diff --git a/pagure/static/atwho/jquery.atwho-1.4.1.css b/pagure/static/atwho/jquery.atwho-1.4.1.css new file mode 100644 index 0000000..a073908 --- /dev/null +++ b/pagure/static/atwho/jquery.atwho-1.4.1.css @@ -0,0 +1,49 @@ +.atwho-view { + position:absolute; + top: 0; + left: 0; + display: none; + margin-top: 18px; + background: white; + color: black; + border: 1px solid #DDD; + border-radius: 3px; + box-shadow: 0 0 5px rgba(0,0,0,0.1); + min-width: 120px; + max-height: 200px; + overflow: auto; + z-index: 11110 !important; +} + +.atwho-view .cur { + background: #3366FF; + color: white; +} +.atwho-view .cur small { + color: white; +} +.atwho-view strong { + color: #3366FF; +} +.atwho-view .cur strong { + color: white; + font:bold; +} +.atwho-view ul { + /* width: 100px; */ + list-style:none; + padding:0; + margin:auto; +} +.atwho-view ul li { + display: block; + padding: 5px 10px; + border-bottom: 1px solid #DDD; + cursor: pointer; + /* border-top: 1px solid #C8C8C8; */ +} +.atwho-view small { + font-size: smaller; + color: #777; + font-weight: normal; +} diff --git a/pagure/static/atwho/jquery.atwho-1.4.1.js b/pagure/static/atwho/jquery.atwho-1.4.1.js new file mode 100644 index 0000000..7f53f12 --- /dev/null +++ b/pagure/static/atwho/jquery.atwho-1.4.1.js @@ -0,0 +1,1158 @@ +/*! jquery.atwho - v1.4.0 %> +* Copyright (c) 2015 chord.luo ; +* homepage: http://ichord.github.com/At.js +* Licensed MIT +*/ +(function (root, factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module unless amdModuleId is set + define(["jquery"], function (a0) { + return (factory(a0)); + }); + } else if (typeof exports === 'object') { + // Node. Does not work with strict CommonJS, but + // only CommonJS-like environments that support module.exports, + // like Node. + module.exports = factory(require("jquery")); + } else { + factory(jQuery); + } +}(this, function (jquery) { + +var $, Api, App, Controller, DEFAULT_CALLBACKS, EditableController, KEY_CODE, Model, TextareaController, View, + slice = [].slice, + extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, + hasProp = {}.hasOwnProperty; + +$ = jquery; + +App = (function() { + function App(inputor) { + this.currentFlag = null; + this.controllers = {}; + this.aliasMaps = {}; + this.$inputor = $(inputor); + this.setupRootElement(); + this.listen(); + } + + App.prototype.createContainer = function(doc) { + var ref; + if ((ref = this.$el) != null) { + ref.remove(); + } + return $(doc.body).append(this.$el = $("
")); + }; + + App.prototype.setupRootElement = function(iframe, asRoot) { + var error; + if (asRoot == null) { + asRoot = false; + } + if (iframe) { + this.window = iframe.contentWindow; + this.document = iframe.contentDocument || this.window.document; + this.iframe = iframe; + } else { + this.document = this.$inputor[0].ownerDocument; + this.window = this.document.defaultView || this.document.parentWindow; + try { + this.iframe = this.window.frameElement; + } catch (_error) { + error = _error; + this.iframe = null; + if ($.fn.atwho.debug) { + throw new Error("iframe auto-discovery is failed.\nPlease use `setIframe` to set the target iframe manually.\n" + error); + } + } + } + return this.createContainer((this.iframeAsRoot = asRoot) ? this.document : document); + }; + + App.prototype.controller = function(at) { + var c, current, currentFlag, ref; + if (this.aliasMaps[at]) { + current = this.controllers[this.aliasMaps[at]]; + } else { + ref = this.controllers; + for (currentFlag in ref) { + c = ref[currentFlag]; + if (currentFlag === at) { + current = c; + break; + } + } + } + if (current) { + return current; + } else { + return this.controllers[this.currentFlag]; + } + }; + + App.prototype.setContextFor = function(at) { + this.currentFlag = at; + return this; + }; + + App.prototype.reg = function(flag, setting) { + var base, controller; + controller = (base = this.controllers)[flag] || (base[flag] = this.$inputor.is('[contentEditable]') ? new EditableController(this, flag) : new TextareaController(this, flag)); + if (setting.alias) { + this.aliasMaps[setting.alias] = flag; + } + controller.init(setting); + return this; + }; + + App.prototype.listen = function() { + return this.$inputor.on('compositionstart', (function(_this) { + return function(e) { + var ref; + if ((ref = _this.controller()) != null) { + ref.view.hide(); + } + _this.isComposing = true; + return null; + }; + })(this)).on('compositionend', (function(_this) { + return function(e) { + _this.isComposing = false; + return null; + }; + })(this)).on('keyup.atwhoInner', (function(_this) { + return function(e) { + return _this.onKeyup(e); + }; + })(this)).on('keydown.atwhoInner', (function(_this) { + return function(e) { + return _this.onKeydown(e); + }; + })(this)).on('blur.atwhoInner', (function(_this) { + return function(e) { + var c; + if (c = _this.controller()) { + c.expectedQueryCBId = null; + return c.view.hide(e, c.getOpt("displayTimeout")); + } + }; + })(this)).on('click.atwhoInner', (function(_this) { + return function(e) { + return _this.dispatch(e); + }; + })(this)).on('scroll.atwhoInner', (function(_this) { + return function() { + var lastScrollTop; + lastScrollTop = _this.$inputor.scrollTop(); + return function(e) { + var currentScrollTop, ref; + currentScrollTop = e.target.scrollTop; + if (lastScrollTop !== currentScrollTop) { + if ((ref = _this.controller()) != null) { + ref.view.hide(e); + } + } + lastScrollTop = currentScrollTop; + return true; + }; + }; + })(this)()); + }; + + App.prototype.shutdown = function() { + var _, c, ref; + ref = this.controllers; + for (_ in ref) { + c = ref[_]; + c.destroy(); + delete this.controllers[_]; + } + this.$inputor.off('.atwhoInner'); + return this.$el.remove(); + }; + + App.prototype.dispatch = function(e) { + var _, c, ref, results; + ref = this.controllers; + results = []; + for (_ in ref) { + c = ref[_]; + results.push(c.lookUp(e)); + } + return results; + }; + + App.prototype.onKeyup = function(e) { + var ref; + switch (e.keyCode) { + case KEY_CODE.ESC: + e.preventDefault(); + if ((ref = this.controller()) != null) { + ref.view.hide(); + } + break; + case KEY_CODE.DOWN: + case KEY_CODE.UP: + case KEY_CODE.CTRL: + case KEY_CODE.ENTER: + $.noop(); + break; + case KEY_CODE.P: + case KEY_CODE.N: + if (!e.ctrlKey) { + this.dispatch(e); + } + break; + default: + this.dispatch(e); + } + }; + + App.prototype.onKeydown = function(e) { + var ref, view; + view = (ref = this.controller()) != null ? ref.view : void 0; + if (!(view && view.visible())) { + return; + } + switch (e.keyCode) { + case KEY_CODE.ESC: + e.preventDefault(); + view.hide(e); + break; + case KEY_CODE.UP: + e.preventDefault(); + view.prev(); + break; + case KEY_CODE.DOWN: + e.preventDefault(); + view.next(); + break; + case KEY_CODE.P: + if (!e.ctrlKey) { + return; + } + e.preventDefault(); + view.prev(); + break; + case KEY_CODE.N: + if (!e.ctrlKey) { + return; + } + e.preventDefault(); + view.next(); + break; + case KEY_CODE.TAB: + case KEY_CODE.ENTER: + case KEY_CODE.SPACE: + if (!view.visible()) { + return; + } + if (!this.controller().getOpt('spaceSelectsMatch') && e.keyCode === KEY_CODE.SPACE) { + return; + } + if (!this.controller().getOpt('tabSelectsMatch') && e.keyCode === KEY_CODE.TAB) { + return; + } + if (view.highlighted()) { + e.preventDefault(); + view.choose(e); + } else { + view.hide(e); + } + break; + default: + $.noop(); + } + }; + + return App; + +})(); + +Controller = (function() { + Controller.prototype.uid = function() { + return (Math.random().toString(16) + "000000000").substr(2, 8) + (new Date().getTime()); + }; + + function Controller(app1, at1) { + this.app = app1; + this.at = at1; + this.$inputor = this.app.$inputor; + this.id = this.$inputor[0].id || this.uid(); + this.expectedQueryCBId = null; + this.setting = null; + this.query = null; + this.pos = 0; + this.range = null; + if ((this.$el = $("#atwho-ground-" + this.id, this.app.$el)).length === 0) { + this.app.$el.append(this.$el = $("
")); + } + this.model = new Model(this); + this.view = new View(this); + } + + Controller.prototype.init = function(setting) { + this.setting = $.extend({}, this.setting || $.fn.atwho["default"], setting); + this.view.init(); + return this.model.reload(this.setting.data); + }; + + Controller.prototype.destroy = function() { + this.trigger('beforeDestroy'); + this.model.destroy(); + this.view.destroy(); + return this.$el.remove(); + }; + + Controller.prototype.callDefault = function() { + var args, error, funcName; + funcName = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : []; + try { + return DEFAULT_CALLBACKS[funcName].apply(this, args); + } catch (_error) { + error = _error; + return $.error(error + " Or maybe At.js doesn't have function " + funcName); + } + }; + + Controller.prototype.trigger = function(name, data) { + var alias, eventName; + if (data == null) { + data = []; + } + data.push(this); + alias = this.getOpt('alias'); + eventName = alias ? name + "-" + alias + ".atwho" : name + ".atwho"; + return this.$inputor.trigger(eventName, data); + }; + + Controller.prototype.callbacks = function(funcName) { + return this.getOpt("callbacks")[funcName] || DEFAULT_CALLBACKS[funcName]; + }; + + Controller.prototype.getOpt = function(at, default_value) { + var e; + try { + return this.setting[at]; + } catch (_error) { + e = _error; + return null; + } + }; + + Controller.prototype.insertContentFor = function($li) { + var data, tpl; + tpl = this.getOpt('insertTpl'); + data = $.extend({}, $li.data('item-data'), { + 'atwho-at': this.at + }); + return this.callbacks("tplEval").call(this, tpl, data, "onInsert"); + }; + + Controller.prototype.renderView = function(data) { + var searchKey; + searchKey = this.getOpt("searchKey"); + data = this.callbacks("sorter").call(this, this.query.text, data.slice(0, 1001), searchKey); + return this.view.render(data.slice(0, this.getOpt('limit'))); + }; + + Controller.arrayToDefaultHash = function(data) { + var i, item, len, results; + if (!$.isArray(data)) { + return data; + } + results = []; + for (i = 0, len = data.length; i < len; i++) { + item = data[i]; + if ($.isPlainObject(item)) { + results.push(item); + } else { + results.push({ + name: item + }); + } + } + return results; + }; + + Controller.prototype.lookUp = function(e) { + var query, wait; + if (e && e.type === 'click' && !this.getOpt('lookUpOnClick')) { + return; + } + if (this.getOpt('suspendOnComposing') && this.app.isComposing) { + return; + } + query = this.catchQuery(e); + if (!query) { + this.expectedQueryCBId = null; + return query; + } + this.app.setContextFor(this.at); + if (wait = this.getOpt('delay')) { + this._delayLookUp(query, wait); + } else { + this._lookUp(query); + } + return query; + }; + + Controller.prototype._delayLookUp = function(query, wait) { + var now, remaining; + now = Date.now ? Date.now() : new Date().getTime(); + this.previousCallTime || (this.previousCallTime = now); + remaining = wait - (now - this.previousCallTime); + if ((0 < remaining && remaining < wait)) { + this.previousCallTime = now; + this._stopDelayedCall(); + return this.delayedCallTimeout = setTimeout((function(_this) { + return function() { + _this.previousCallTime = 0; + _this.delayedCallTimeout = null; + return _this._lookUp(query); + }; + })(this), wait); + } else { + this._stopDelayedCall(); + if (this.previousCallTime !== now) { + this.previousCallTime = 0; + } + return this._lookUp(query); + } + }; + + Controller.prototype._stopDelayedCall = function() { + if (this.delayedCallTimeout) { + clearTimeout(this.delayedCallTimeout); + return this.delayedCallTimeout = null; + } + }; + + Controller.prototype._generateQueryCBId = function() { + return {}; + }; + + Controller.prototype._lookUp = function(query) { + var _callback; + _callback = function(queryCBId, data) { + if (queryCBId !== this.expectedQueryCBId) { + return; + } + if (data && data.length > 0) { + return this.renderView(this.constructor.arrayToDefaultHash(data)); + } else { + return this.view.hide(); + } + }; + this.expectedQueryCBId = this._generateQueryCBId(); + return this.model.query(query.text, $.proxy(_callback, this, this.expectedQueryCBId)); + }; + + return Controller; + +})(); + +TextareaController = (function(superClass) { + extend(TextareaController, superClass); + + function TextareaController() { + return TextareaController.__super__.constructor.apply(this, arguments); + } + + TextareaController.prototype.catchQuery = function() { + var caretPos, content, end, isString, query, start, subtext; + content = this.$inputor.val(); + caretPos = this.$inputor.caret('pos', { + iframe: this.app.iframe + }); + subtext = content.slice(0, caretPos); + query = this.callbacks("matcher").call(this, this.at, subtext, this.getOpt('startWithSpace')); + isString = typeof query === 'string'; + if (isString && query.length < this.getOpt('minLen', 0)) { + return; + } + if (isString && query.length <= this.getOpt('maxLen', 20)) { + start = caretPos - query.length; + end = start + query.length; + this.pos = start; + query = { + 'text': query, + 'headPos': start, + 'endPos': end + }; + this.trigger("matched", [this.at, query.text]); + } else { + query = null; + this.view.hide(); + } + return this.query = query; + }; + + TextareaController.prototype.rect = function() { + var c, iframeOffset, scaleBottom; + if (!(c = this.$inputor.caret('offset', this.pos - 1, { + iframe: this.app.iframe + }))) { + return; + } + if (this.app.iframe && !this.app.iframeAsRoot) { + iframeOffset = $(this.app.iframe).offset(); + c.left += iframeOffset.left; + c.top += iframeOffset.top; + } + scaleBottom = this.app.document.selection ? 0 : 2; + return { + left: c.left, + top: c.top, + bottom: c.top + c.height + scaleBottom + }; + }; + + TextareaController.prototype.insert = function(content, $li) { + var $inputor, source, startStr, suffix, text; + $inputor = this.$inputor; + source = $inputor.val(); + startStr = source.slice(0, Math.max(this.query.headPos - this.at.length, 0)); + suffix = (suffix = this.getOpt('suffix')) === "" ? suffix : suffix || " "; + content += suffix; + text = "" + startStr + content + (source.slice(this.query['endPos'] || 0)); + $inputor.val(text); + $inputor.caret('pos', startStr.length + content.length, { + iframe: this.app.iframe + }); + if (!$inputor.is(':focus')) { + $inputor.focus(); + } + return $inputor.change(); + }; + + return TextareaController; + +})(Controller); + +EditableController = (function(superClass) { + extend(EditableController, superClass); + + function EditableController() { + return EditableController.__super__.constructor.apply(this, arguments); + } + + EditableController.prototype._getRange = function() { + var sel; + sel = this.app.window.getSelection(); + if (sel.rangeCount > 0) { + return sel.getRangeAt(0); + } + }; + + EditableController.prototype._setRange = function(position, node, range) { + if (range == null) { + range = this._getRange(); + } + if (!range) { + return; + } + node = $(node)[0]; + if (position === 'after') { + range.setEndAfter(node); + range.setStartAfter(node); + } else { + range.setEndBefore(node); + range.setStartBefore(node); + } + range.collapse(false); + return this._clearRange(range); + }; + + EditableController.prototype._clearRange = function(range) { + var sel; + if (range == null) { + range = this._getRange(); + } + sel = this.app.window.getSelection(); + if (this.ctrl_a_pressed == null) { + sel.removeAllRanges(); + return sel.addRange(range); + } + }; + + EditableController.prototype._movingEvent = function(e) { + var ref; + return e.type === 'click' || ((ref = e.which) === KEY_CODE.RIGHT || ref === KEY_CODE.LEFT || ref === KEY_CODE.UP || ref === KEY_CODE.DOWN); + }; + + EditableController.prototype._unwrap = function(node) { + var next; + node = $(node).unwrap().get(0); + if ((next = node.nextSibling) && next.nodeValue) { + node.nodeValue += next.nodeValue; + $(next).remove(); + } + return node; + }; + + EditableController.prototype.catchQuery = function(e) { + var $inserted, $query, _range, index, inserted, isString, lastNode, matched, offset, query, query_content, range; + if (!(range = this._getRange())) { + return; + } + if (!range.collapsed) { + return; + } + if (e.which === KEY_CODE.ENTER) { + ($query = $(range.startContainer).closest('.atwho-query')).contents().unwrap(); + if ($query.is(':empty')) { + $query.remove(); + } + ($query = $(".atwho-query", this.app.document)).text($query.text()).contents().last().unwrap(); + this._clearRange(); + return; + } + if (/firefox/i.test(navigator.userAgent)) { + if ($(range.startContainer).is(this.$inputor)) { + this._clearRange(); + return; + } + if (e.which === KEY_CODE.BACKSPACE && range.startContainer.nodeType === document.ELEMENT_NODE && (offset = range.startOffset - 1) >= 0) { + _range = range.cloneRange(); + _range.setStart(range.startContainer, offset); + if ($(_range.cloneContents()).contents().last().is('.atwho-inserted')) { + inserted = $(range.startContainer).contents().get(offset); + this._setRange('after', $(inserted).contents().last()); + } + } else if (e.which === KEY_CODE.LEFT && range.startContainer.nodeType === document.TEXT_NODE) { + $inserted = $(range.startContainer.previousSibling); + if ($inserted.is('.atwho-inserted') && range.startOffset === 0) { + this._setRange('after', $inserted.contents().last()); + } + } + } + $(range.startContainer).closest('.atwho-inserted').addClass('atwho-query').siblings().removeClass('atwho-query'); + if (($query = $(".atwho-query", this.app.document)).length > 0 && $query.is(':empty') && $query.text().length === 0) { + $query.remove(); + } + if (!this._movingEvent(e)) { + $query.removeClass('atwho-inserted'); + } + if ($query.length > 0) { + switch (e.which) { + case KEY_CODE.LEFT: + this._setRange('before', $query.get(0), range); + $query.removeClass('atwho-query'); + return; + case KEY_CODE.RIGHT: + this._setRange('after', $query.get(0).nextSibling, range); + $query.removeClass('atwho-query'); + return; + } + } + if ($query.length > 0 && (query_content = $query.attr('data-atwho-at-query'))) { + $query.empty().html(query_content).attr('data-atwho-at-query', null); + this._setRange('after', $query.get(0), range); + } + _range = range.cloneRange(); + _range.setStart(range.startContainer, 0); + matched = this.callbacks("matcher").call(this, this.at, _range.toString(), this.getOpt('startWithSpace')); + isString = typeof matched === 'string'; + if ($query.length === 0 && isString && (index = range.startOffset - this.at.length - matched.length) >= 0) { + range.setStart(range.startContainer, index); + $query = $('', this.app.document).attr(this.getOpt("editableAtwhoQueryAttrs")).addClass('atwho-query'); + range.surroundContents($query.get(0)); + lastNode = $query.contents().last().get(0); + if (/firefox/i.test(navigator.userAgent)) { + range.setStart(lastNode, lastNode.length); + range.setEnd(lastNode, lastNode.length); + this._clearRange(range); + } else { + this._setRange('after', lastNode, range); + } + } + if (isString && matched.length < this.getOpt('minLen', 0)) { + return; + } + if (isString && matched.length <= this.getOpt('maxLen', 20)) { + query = { + text: matched, + el: $query + }; + this.trigger("matched", [this.at, query.text]); + return this.query = query; + } else { + this.view.hide(); + this.query = { + el: $query + }; + if ($query.text().indexOf(this.at) >= 0) { + if (this._movingEvent(e) && $query.hasClass('atwho-inserted')) { + $query.removeClass('atwho-query'); + } else if (false !== this.callbacks('afterMatchFailed').call(this, this.at, $query)) { + this._setRange("after", this._unwrap($query.text($query.text()).contents().first())); + } + } + return null; + } + }; + + EditableController.prototype.rect = function() { + var $iframe, iframeOffset, rect; + rect = this.query.el.offset(); + if (this.app.iframe && !this.app.iframeAsRoot) { + iframeOffset = ($iframe = $(this.app.iframe)).offset(); + rect.left += iframeOffset.left - this.$inputor.scrollLeft(); + rect.top += iframeOffset.top - this.$inputor.scrollTop(); + } + rect.bottom = rect.top + this.query.el.height(); + return rect; + }; + + EditableController.prototype.insert = function(content, $li) { + var data, range, suffix, suffixNode; + suffix = (suffix = this.getOpt('suffix')) === "" ? suffix : suffix || "\u00A0"; + data = $li.data('item-data'); + this.query.el.removeClass('atwho-query').addClass('atwho-inserted').html(content).attr('data-atwho-at-query', "" + data['atwho-at'] + this.query.text); + if (range = this._getRange()) { + range.setEndAfter(this.query.el[0]); + range.collapse(false); + range.insertNode(suffixNode = this.app.document.createTextNode("\u200D" + suffix)); + this._setRange('after', suffixNode, range); + } + if (!this.$inputor.is(':focus')) { + this.$inputor.focus(); + } + return this.$inputor.change(); + }; + + return EditableController; + +})(Controller); + +Model = (function() { + function Model(context) { + this.context = context; + this.at = this.context.at; + this.storage = this.context.$inputor; + } + + Model.prototype.destroy = function() { + return this.storage.data(this.at, null); + }; + + Model.prototype.saved = function() { + return this.fetch() > 0; + }; + + Model.prototype.query = function(query, callback) { + var _remoteFilter, data, searchKey; + data = this.fetch(); + searchKey = this.context.getOpt("searchKey"); + data = this.context.callbacks('filter').call(this.context, query, data, searchKey) || []; + _remoteFilter = this.context.callbacks('remoteFilter'); + if (data.length > 0 || (!_remoteFilter && data.length === 0)) { + return callback(data); + } else { + return _remoteFilter.call(this.context, query, callback); + } + }; + + Model.prototype.fetch = function() { + return this.storage.data(this.at) || []; + }; + + Model.prototype.save = function(data) { + return this.storage.data(this.at, this.context.callbacks("beforeSave").call(this.context, data || [])); + }; + + Model.prototype.load = function(data) { + if (!(this.saved() || !data)) { + return this._load(data); + } + }; + + Model.prototype.reload = function(data) { + return this._load(data); + }; + + Model.prototype._load = function(data) { + if (typeof data === "string") { + return $.ajax(data, { + dataType: "json" + }).done((function(_this) { + return function(data) { + return _this.save(data); + }; + })(this)); + } else { + return this.save(data); + } + }; + + return Model; + +})(); + +View = (function() { + function View(context) { + this.context = context; + this.$el = $("
    "); + this.timeoutID = null; + this.context.$el.append(this.$el); + this.bindEvent(); + } + + View.prototype.init = function() { + var id; + id = this.context.getOpt("alias") || this.context.at.charCodeAt(0); + return this.$el.attr({ + 'id': "at-view-" + id + }); + }; + + View.prototype.destroy = function() { + return this.$el.remove(); + }; + + View.prototype.bindEvent = function() { + var $menu; + $menu = this.$el.find('ul'); + return $menu.on('mouseenter.atwho-view', 'li', function(e) { + $menu.find('.cur').removeClass('cur'); + return $(e.currentTarget).addClass('cur'); + }).on('click.atwho-view', 'li', (function(_this) { + return function(e) { + $menu.find('.cur').removeClass('cur'); + $(e.currentTarget).addClass('cur'); + _this.choose(e); + return e.preventDefault(); + }; + })(this)); + }; + + View.prototype.visible = function() { + return this.$el.is(":visible"); + }; + + View.prototype.highlighted = function() { + return this.$el.find(".cur").length > 0; + }; + + View.prototype.choose = function(e) { + var $li, content; + if (($li = this.$el.find(".cur")).length) { + content = this.context.insertContentFor($li); + this.context._stopDelayedCall(); + this.context.insert(this.context.callbacks("beforeInsert").call(this.context, content, $li), $li); + this.context.trigger("inserted", [$li, e]); + this.hide(e); + } + if (this.context.getOpt("hideWithoutSuffix")) { + return this.stopShowing = true; + } + }; + + View.prototype.reposition = function(rect) { + var _window, offset, overflowOffset, ref; + _window = this.context.app.iframeAsRoot ? this.context.app.window : window; + if (rect.bottom + this.$el.height() - $(_window).scrollTop() > $(_window).height()) { + rect.bottom = rect.top - this.$el.height(); + } + if (rect.left > (overflowOffset = $(_window).width() - this.$el.width() - 5)) { + rect.left = overflowOffset; + } + offset = { + left: rect.left, + top: rect.bottom + }; + if ((ref = this.context.callbacks("beforeReposition")) != null) { + ref.call(this.context, offset); + } + this.$el.offset(offset); + return this.context.trigger("reposition", [offset]); + }; + + View.prototype.next = function() { + var cur, next; + cur = this.$el.find('.cur').removeClass('cur'); + next = cur.next(); + if (!next.length) { + next = this.$el.find('li:first'); + } + next.addClass('cur'); + return this.scrollTop(Math.max(0, cur.innerHeight() * (next.index() + 2) - this.$el.height())); + }; + + View.prototype.prev = function() { + var cur, prev; + cur = this.$el.find('.cur').removeClass('cur'); + prev = cur.prev(); + if (!prev.length) { + prev = this.$el.find('li:last'); + } + prev.addClass('cur'); + return this.scrollTop(Math.max(0, cur.innerHeight() * (prev.index() + 2) - this.$el.height())); + }; + + View.prototype.scrollTop = function(scrollTop) { + var scrollDuration; + scrollDuration = this.context.getOpt('scrollDuration'); + if (scrollDuration) { + return this.$el.animate({ + scrollTop: scrollTop + }, scrollDuration); + } else { + return this.$el.scrollTop(scrollTop); + } + }; + + View.prototype.show = function() { + var rect; + if (this.stopShowing) { + this.stopShowing = false; + return; + } + if (!this.visible()) { + this.$el.show(); + this.$el.scrollTop(0); + this.context.trigger('shown'); + } + if (rect = this.context.rect()) { + return this.reposition(rect); + } + }; + + View.prototype.hide = function(e, time) { + var callback; + if (!this.visible()) { + return; + } + if (isNaN(time)) { + this.$el.hide(); + return this.context.trigger('hidden', [e]); + } else { + callback = (function(_this) { + return function() { + return _this.hide(); + }; + })(this); + clearTimeout(this.timeoutID); + return this.timeoutID = setTimeout(callback, time); + } + }; + + View.prototype.render = function(list) { + var $li, $ul, i, item, len, li, tpl; + if (!($.isArray(list) && list.length > 0)) { + this.hide(); + return; + } + this.$el.find('ul').empty(); + $ul = this.$el.find('ul'); + tpl = this.context.getOpt('displayTpl'); + for (i = 0, len = list.length; i < len; i++) { + item = list[i]; + item = $.extend({}, item, { + 'atwho-at': this.context.at + }); + li = this.context.callbacks("tplEval").call(this.context, tpl, item, "onDisplay"); + $li = $(this.context.callbacks("highlighter").call(this.context, li, this.context.query.text)); + $li.data("item-data", item); + $ul.append($li); + } + this.show(); + if (this.context.getOpt('highlightFirst')) { + return $ul.find("li:first").addClass("cur"); + } + }; + + return View; + +})(); + +KEY_CODE = { + DOWN: 40, + UP: 38, + ESC: 27, + TAB: 9, + ENTER: 13, + CTRL: 17, + A: 65, + P: 80, + N: 78, + LEFT: 37, + UP: 38, + RIGHT: 39, + DOWN: 40, + BACKSPACE: 8, + SPACE: 32 +}; + +DEFAULT_CALLBACKS = { + beforeSave: function(data) { + return Controller.arrayToDefaultHash(data); + }, + matcher: function(flag, subtext, should_startWithSpace, acceptSpaceBar) { + var _a, _y, match, regexp, space; + flag = flag.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); + if (should_startWithSpace) { + flag = '(?:^|\\s)' + flag; + } + _a = decodeURI("%C3%80"); + _y = decodeURI("%C3%BF"); + space = acceptSpaceBar ? "\ " : ""; + regexp = new RegExp(flag + "([A-Za-z" + _a + "-" + _y + "0-9_" + space + "\'\.\+\-]*)$|" + flag + "([^\\x00-\\xff]*)$", 'gi'); + match = regexp.exec(subtext); + if (match) { + return match[2] || match[1]; + } else { + return null; + } + }, + filter: function(query, data, searchKey) { + var _results, i, item, len; + _results = []; + for (i = 0, len = data.length; i < len; i++) { + item = data[i]; + if (~new String(item[searchKey]).toLowerCase().indexOf(query.toLowerCase())) { + _results.push(item); + } + } + return _results; + }, + remoteFilter: null, + sorter: function(query, items, searchKey) { + var _results, i, item, len; + if (!query) { + return items; + } + _results = []; + for (i = 0, len = items.length; i < len; i++) { + item = items[i]; + item.atwho_order = new String(item[searchKey]).toLowerCase().indexOf(query.toLowerCase()); + if (item.atwho_order > -1) { + _results.push(item); + } + } + return _results.sort(function(a, b) { + return a.atwho_order - b.atwho_order; + }); + }, + tplEval: function(tpl, map) { + var error, template; + template = tpl; + try { + if (typeof tpl !== 'string') { + template = tpl(map); + } + return template.replace(/\$\{([^\}]*)\}/g, function(tag, key, pos) { + return map[key]; + }); + } catch (_error) { + error = _error; + return ""; + } + }, + highlighter: function(li, query) { + var regexp; + if (!query) { + return li; + } + regexp = new RegExp(">\\s*(\\w*?)(" + query.replace("+", "\\+") + ")(\\w*)\\s*<", 'ig'); + return li.replace(regexp, function(str, $1, $2, $3) { + return '> ' + $1 + '' + $2 + '' + $3 + ' <'; + }); + }, + beforeInsert: function(value, $li) { + return value; + }, + beforeReposition: function(offset) { + return offset; + }, + afterMatchFailed: function(at, el) {} +}; + +Api = { + load: function(at, data) { + var c; + if (c = this.controller(at)) { + return c.model.load(data); + } + }, + isSelecting: function() { + var ref; + return !!((ref = this.controller()) != null ? ref.view.visible() : void 0); + }, + hide: function() { + var ref; + return (ref = this.controller()) != null ? ref.view.hide() : void 0; + }, + reposition: function() { + var c; + if (c = this.controller()) { + return c.view.reposition(c.rect()); + } + }, + setIframe: function(iframe, asRoot) { + this.setupRootElement(iframe, asRoot); + return null; + }, + run: function() { + return this.dispatch(); + }, + destroy: function() { + this.shutdown(); + return this.$inputor.data('atwho', null); + } +}; + +$.fn.atwho = function(method) { + var _args, result; + _args = arguments; + result = null; + this.filter('textarea, input, [contenteditable=""], [contenteditable=true]').each(function() { + var $this, app; + if (!(app = ($this = $(this)).data("atwho"))) { + $this.data('atwho', (app = new App(this))); + } + if (typeof method === 'object' || !method) { + return app.reg(method.at, method); + } else if (Api[method] && app) { + return result = Api[method].apply(app, Array.prototype.slice.call(_args, 1)); + } else { + return $.error("Method " + method + " does not exist on jQuery.atwho"); + } + }); + if (result != null) { + return result; + } else { + return this; + } +}; + +$.fn.atwho["default"] = { + at: void 0, + alias: void 0, + data: null, + displayTpl: "
  • ${name}
  • ", + insertTpl: "${atwho-at}${name}", + callbacks: DEFAULT_CALLBACKS, + searchKey: "name", + suffix: void 0, + hideWithoutSuffix: false, + startWithSpace: true, + highlightFirst: true, + limit: 5, + maxLen: 20, + minLen: 0, + displayTimeout: 300, + delay: null, + spaceSelectsMatch: false, + tabSelectsMatch: true, + editableAtwhoQueryAttrs: {}, + scrollDuration: 150, + suspendOnComposing: true, + lookUpOnClick: true +}; + +$.fn.atwho.debug = false; + + +})); diff --git a/pagure/static/atwho/jquery.atwho-1.4.1.min.css b/pagure/static/atwho/jquery.atwho-1.4.1.min.css new file mode 100644 index 0000000..075983d --- /dev/null +++ b/pagure/static/atwho/jquery.atwho-1.4.1.min.css @@ -0,0 +1 @@ +.atwho-view{position:absolute;top:0;left:0;display:none;margin-top:18px;background:#fff;color:#000;border:1px solid #DDD;border-radius:3px;box-shadow:0 0 5px rgba(0,0,0,.1);min-width:120px;max-height:200px;overflow:auto;z-index:11110!important}.atwho-view .cur{background:#36F;color:#fff}.atwho-view .cur small{color:#fff}.atwho-view strong{color:#36F}.atwho-view .cur strong{color:#fff;font:700}.atwho-view ul{list-style:none;padding:0;margin:auto}.atwho-view ul li{display:block;padding:5px 10px;border-bottom:1px solid #DDD;cursor:pointer}.atwho-view small{font-size:smaller;color:#777;font-weight:400} \ No newline at end of file diff --git a/pagure/static/atwho/jquery.atwho-1.4.1.min.js b/pagure/static/atwho/jquery.atwho-1.4.1.min.js new file mode 100644 index 0000000..3488732 --- /dev/null +++ b/pagure/static/atwho/jquery.atwho-1.4.1.min.js @@ -0,0 +1 @@ +!function(a,b){"function"==typeof define&&define.amd?define(["jquery"],function(a){return b(a)}):"object"==typeof exports?module.exports=b(require("jquery")):b(jQuery)}(this,function(a){var b,c,d,e,f,g,h,i,j,k,l=[].slice,m=function(a,b){function c(){this.constructor=a}for(var d in b)n.call(b,d)&&(a[d]=b[d]);return c.prototype=b.prototype,a.prototype=new c,a.__super__=b.prototype,a},n={}.hasOwnProperty;b=a,d=function(){function a(a){this.currentFlag=null,this.controllers={},this.aliasMaps={},this.$inputor=b(a),this.setupRootElement(),this.listen()}return a.prototype.createContainer=function(a){var c;return null!=(c=this.$el)&&c.remove(),b(a.body).append(this.$el=b("
    "))},a.prototype.setupRootElement=function(a,c){var d;if(null==c&&(c=!1),a)this.window=a.contentWindow,this.document=a.contentDocument||this.window.document,this.iframe=a;else{this.document=this.$inputor[0].ownerDocument,this.window=this.document.defaultView||this.document.parentWindow;try{this.iframe=this.window.frameElement}catch(e){if(d=e,this.iframe=null,b.fn.atwho.debug)throw new Error("iframe auto-discovery is failed.\nPlease use `setIframe` to set the target iframe manually.\n"+d)}}return this.createContainer((this.iframeAsRoot=c)?this.document:document)},a.prototype.controller=function(a){var b,c,d,e;if(this.aliasMaps[a])c=this.controllers[this.aliasMaps[a]];else{e=this.controllers;for(d in e)if(b=e[d],d===a){c=b;break}}return c?c:this.controllers[this.currentFlag]},a.prototype.setContextFor=function(a){return this.currentFlag=a,this},a.prototype.reg=function(a,b){var c,d;return d=(c=this.controllers)[a]||(c[a]=this.$inputor.is("[contentEditable]")?new g(this,a):new j(this,a)),b.alias&&(this.aliasMaps[b.alias]=a),d.init(b),this},a.prototype.listen=function(){return this.$inputor.on("compositionstart",function(a){return function(b){var c;return null!=(c=a.controller())&&c.view.hide(),a.isComposing=!0,null}}(this)).on("compositionend",function(a){return function(b){return a.isComposing=!1,null}}(this)).on("keyup.atwhoInner",function(a){return function(b){return a.onKeyup(b)}}(this)).on("keydown.atwhoInner",function(a){return function(b){return a.onKeydown(b)}}(this)).on("blur.atwhoInner",function(a){return function(b){var c;return(c=a.controller())?(c.expectedQueryCBId=null,c.view.hide(b,c.getOpt("displayTimeout"))):void 0}}(this)).on("click.atwhoInner",function(a){return function(b){return a.dispatch(b)}}(this)).on("scroll.atwhoInner",function(a){return function(){var b;return b=a.$inputor.scrollTop(),function(c){var d,e;return d=c.target.scrollTop,b!==d&&null!=(e=a.controller())&&e.view.hide(c),b=d,!0}}}(this)())},a.prototype.shutdown=function(){var a,b,c;c=this.controllers;for(a in c)b=c[a],b.destroy(),delete this.controllers[a];return this.$inputor.off(".atwhoInner"),this.$el.remove()},a.prototype.dispatch=function(a){var b,c,d,e;d=this.controllers,e=[];for(b in d)c=d[b],e.push(c.lookUp(a));return e},a.prototype.onKeyup=function(a){var c;switch(a.keyCode){case h.ESC:a.preventDefault(),null!=(c=this.controller())&&c.view.hide();break;case h.DOWN:case h.UP:case h.CTRL:case h.ENTER:b.noop();break;case h.P:case h.N:a.ctrlKey||this.dispatch(a);break;default:this.dispatch(a)}},a.prototype.onKeydown=function(a){var c,d;if(d=null!=(c=this.controller())?c.view:void 0,d&&d.visible())switch(a.keyCode){case h.ESC:a.preventDefault(),d.hide(a);break;case h.UP:a.preventDefault(),d.prev();break;case h.DOWN:a.preventDefault(),d.next();break;case h.P:if(!a.ctrlKey)return;a.preventDefault(),d.prev();break;case h.N:if(!a.ctrlKey)return;a.preventDefault(),d.next();break;case h.TAB:case h.ENTER:case h.SPACE:if(!d.visible())return;if(!this.controller().getOpt("spaceSelectsMatch")&&a.keyCode===h.SPACE)return;if(!this.controller().getOpt("tabSelectsMatch")&&a.keyCode===h.TAB)return;d.highlighted()?(a.preventDefault(),d.choose(a)):d.hide(a);break;default:b.noop()}},a}(),e=function(){function a(a,c){this.app=a,this.at=c,this.$inputor=this.app.$inputor,this.id=this.$inputor[0].id||this.uid(),this.expectedQueryCBId=null,this.setting=null,this.query=null,this.pos=0,this.range=null,0===(this.$el=b("#atwho-ground-"+this.id,this.app.$el)).length&&this.app.$el.append(this.$el=b("
    ")),this.model=new i(this),this.view=new k(this)}return a.prototype.uid=function(){return(Math.random().toString(16)+"000000000").substr(2,8)+(new Date).getTime()},a.prototype.init=function(a){return this.setting=b.extend({},this.setting||b.fn.atwho["default"],a),this.view.init(),this.model.reload(this.setting.data)},a.prototype.destroy=function(){return this.trigger("beforeDestroy"),this.model.destroy(),this.view.destroy(),this.$el.remove()},a.prototype.callDefault=function(){var a,c,d;d=arguments[0],a=2<=arguments.length?l.call(arguments,1):[];try{return f[d].apply(this,a)}catch(e){return c=e,b.error(c+" Or maybe At.js doesn't have function "+d)}},a.prototype.trigger=function(a,b){var c,d;return null==b&&(b=[]),b.push(this),c=this.getOpt("alias"),d=c?a+"-"+c+".atwho":a+".atwho",this.$inputor.trigger(d,b)},a.prototype.callbacks=function(a){return this.getOpt("callbacks")[a]||f[a]},a.prototype.getOpt=function(a,b){var c;try{return this.setting[a]}catch(d){return c=d,null}},a.prototype.insertContentFor=function(a){var c,d;return d=this.getOpt("insertTpl"),c=b.extend({},a.data("item-data"),{"atwho-at":this.at}),this.callbacks("tplEval").call(this,d,c,"onInsert")},a.prototype.renderView=function(a){var b;return b=this.getOpt("searchKey"),a=this.callbacks("sorter").call(this,this.query.text,a.slice(0,1001),b),this.view.render(a.slice(0,this.getOpt("limit")))},a.arrayToDefaultHash=function(a){var c,d,e,f;if(!b.isArray(a))return a;for(f=[],c=0,e=a.length;e>c;c++)d=a[c],b.isPlainObject(d)?f.push(d):f.push({name:d});return f},a.prototype.lookUp=function(a){var b,c;if((!a||"click"!==a.type||this.getOpt("lookUpOnClick"))&&(!this.getOpt("suspendOnComposing")||!this.app.isComposing))return(b=this.catchQuery(a))?(this.app.setContextFor(this.at),(c=this.getOpt("delay"))?this._delayLookUp(b,c):this._lookUp(b),b):(this.expectedQueryCBId=null,b)},a.prototype._delayLookUp=function(a,b){var c,d;return c=Date.now?Date.now():(new Date).getTime(),this.previousCallTime||(this.previousCallTime=c),d=b-(c-this.previousCallTime),d>0&&b>d?(this.previousCallTime=c,this._stopDelayedCall(),this.delayedCallTimeout=setTimeout(function(b){return function(){return b.previousCallTime=0,b.delayedCallTimeout=null,b._lookUp(a)}}(this),b)):(this._stopDelayedCall(),this.previousCallTime!==c&&(this.previousCallTime=0),this._lookUp(a))},a.prototype._stopDelayedCall=function(){return this.delayedCallTimeout?(clearTimeout(this.delayedCallTimeout),this.delayedCallTimeout=null):void 0},a.prototype._generateQueryCBId=function(){return{}},a.prototype._lookUp=function(a){var c;return c=function(a,b){return a===this.expectedQueryCBId?b&&b.length>0?this.renderView(this.constructor.arrayToDefaultHash(b)):this.view.hide():void 0},this.expectedQueryCBId=this._generateQueryCBId(),this.model.query(a.text,b.proxy(c,this,this.expectedQueryCBId))},a}(),j=function(a){function c(){return c.__super__.constructor.apply(this,arguments)}return m(c,a),c.prototype.catchQuery=function(){var a,b,c,d,e,f,g;return b=this.$inputor.val(),a=this.$inputor.caret("pos",{iframe:this.app.iframe}),g=b.slice(0,a),e=this.callbacks("matcher").call(this,this.at,g,this.getOpt("startWithSpace")),d="string"==typeof e,d&&e.length0?a.getRangeAt(0):void 0},c.prototype._setRange=function(a,c,d){return null==d&&(d=this._getRange()),d?(c=b(c)[0],"after"===a?(d.setEndAfter(c),d.setStartAfter(c)):(d.setEndBefore(c),d.setStartBefore(c)),d.collapse(!1),this._clearRange(d)):void 0},c.prototype._clearRange=function(a){var b;return null==a&&(a=this._getRange()),b=this.app.window.getSelection(),null==this.ctrl_a_pressed?(b.removeAllRanges(),b.addRange(a)):void 0},c.prototype._movingEvent=function(a){var b;return"click"===a.type||(b=a.which)===h.RIGHT||b===h.LEFT||b===h.UP||b===h.DOWN},c.prototype._unwrap=function(a){var c;return a=b(a).unwrap().get(0),(c=a.nextSibling)&&c.nodeValue&&(a.nodeValue+=c.nodeValue,b(c).remove()),a},c.prototype.catchQuery=function(a){var c,d,e,f,g,i,j,k,l,m,n,o;if((o=this._getRange())&&o.collapsed){if(a.which===h.ENTER)return(d=b(o.startContainer).closest(".atwho-query")).contents().unwrap(),d.is(":empty")&&d.remove(),(d=b(".atwho-query",this.app.document)).text(d.text()).contents().last().unwrap(),void this._clearRange();if(/firefox/i.test(navigator.userAgent)){if(b(o.startContainer).is(this.$inputor))return void this._clearRange();a.which===h.BACKSPACE&&o.startContainer.nodeType===document.ELEMENT_NODE&&(l=o.startOffset-1)>=0?(e=o.cloneRange(),e.setStart(o.startContainer,l),b(e.cloneContents()).contents().last().is(".atwho-inserted")&&(g=b(o.startContainer).contents().get(l),this._setRange("after",b(g).contents().last()))):a.which===h.LEFT&&o.startContainer.nodeType===document.TEXT_NODE&&(c=b(o.startContainer.previousSibling),c.is(".atwho-inserted")&&0===o.startOffset&&this._setRange("after",c.contents().last()))}if(b(o.startContainer).closest(".atwho-inserted").addClass("atwho-query").siblings().removeClass("atwho-query"),(d=b(".atwho-query",this.app.document)).length>0&&d.is(":empty")&&0===d.text().length&&d.remove(),this._movingEvent(a)||d.removeClass("atwho-inserted"),d.length>0)switch(a.which){case h.LEFT:return this._setRange("before",d.get(0),o),void d.removeClass("atwho-query");case h.RIGHT:return this._setRange("after",d.get(0).nextSibling,o),void d.removeClass("atwho-query")}if(d.length>0&&(n=d.attr("data-atwho-at-query"))&&(d.empty().html(n).attr("data-atwho-at-query",null),this._setRange("after",d.get(0),o)),e=o.cloneRange(),e.setStart(o.startContainer,0),k=this.callbacks("matcher").call(this,this.at,e.toString(),this.getOpt("startWithSpace")),i="string"==typeof k,0===d.length&&i&&(f=o.startOffset-this.at.length-k.length)>=0&&(o.setStart(o.startContainer,f),d=b("",this.app.document).attr(this.getOpt("editableAtwhoQueryAttrs")).addClass("atwho-query"),o.surroundContents(d.get(0)),j=d.contents().last().get(0),/firefox/i.test(navigator.userAgent)?(o.setStart(j,j.length),o.setEnd(j,j.length),this._clearRange(o)):this._setRange("after",j,o)),!(i&&k.length=0&&(this._movingEvent(a)&&d.hasClass("atwho-inserted")?d.removeClass("atwho-query"):!1!==this.callbacks("afterMatchFailed").call(this,this.at,d)&&this._setRange("after",this._unwrap(d.text(d.text()).contents().first()))),null)}},c.prototype.rect=function(){var a,c,d;return d=this.query.el.offset(),this.app.iframe&&!this.app.iframeAsRoot&&(c=(a=b(this.app.iframe)).offset(),d.left+=c.left-this.$inputor.scrollLeft(),d.top+=c.top-this.$inputor.scrollTop()),d.bottom=d.top+this.query.el.height(),d},c.prototype.insert=function(a,b){var c,d,e,f;return e=""===(e=this.getOpt("suffix"))?e:e||" ",c=b.data("item-data"),this.query.el.removeClass("atwho-query").addClass("atwho-inserted").html(a).attr("data-atwho-at-query",""+c["atwho-at"]+this.query.text),(d=this._getRange())&&(d.setEndAfter(this.query.el[0]),d.collapse(!1),d.insertNode(f=this.app.document.createTextNode("‍"+e)),this._setRange("after",f,d)),this.$inputor.is(":focus")||this.$inputor.focus(),this.$inputor.change()},c}(e),i=function(){function a(a){this.context=a,this.at=this.context.at,this.storage=this.context.$inputor}return a.prototype.destroy=function(){return this.storage.data(this.at,null)},a.prototype.saved=function(){return this.fetch()>0},a.prototype.query=function(a,b){var c,d,e;return d=this.fetch(),e=this.context.getOpt("searchKey"),d=this.context.callbacks("filter").call(this.context,a,d,e)||[],c=this.context.callbacks("remoteFilter"),d.length>0||!c&&0===d.length?b(d):c.call(this.context,a,b)},a.prototype.fetch=function(){return this.storage.data(this.at)||[]},a.prototype.save=function(a){return this.storage.data(this.at,this.context.callbacks("beforeSave").call(this.context,a||[]))},a.prototype.load=function(a){return!this.saved()&&a?this._load(a):void 0},a.prototype.reload=function(a){return this._load(a)},a.prototype._load=function(a){return"string"==typeof a?b.ajax(a,{dataType:"json"}).done(function(a){return function(b){return a.save(b)}}(this)):this.save(a)},a}(),k=function(){function a(a){this.context=a,this.$el=b("
      "),this.timeoutID=null,this.context.$el.append(this.$el),this.bindEvent()}return a.prototype.init=function(){var a;return a=this.context.getOpt("alias")||this.context.at.charCodeAt(0),this.$el.attr({id:"at-view-"+a})},a.prototype.destroy=function(){return this.$el.remove()},a.prototype.bindEvent=function(){var a;return a=this.$el.find("ul"),a.on("mouseenter.atwho-view","li",function(c){return a.find(".cur").removeClass("cur"),b(c.currentTarget).addClass("cur")}).on("click.atwho-view","li",function(c){return function(d){return a.find(".cur").removeClass("cur"),b(d.currentTarget).addClass("cur"),c.choose(d),d.preventDefault()}}(this))},a.prototype.visible=function(){return this.$el.is(":visible")},a.prototype.highlighted=function(){return this.$el.find(".cur").length>0},a.prototype.choose=function(a){var b,c;return(b=this.$el.find(".cur")).length&&(c=this.context.insertContentFor(b),this.context._stopDelayedCall(),this.context.insert(this.context.callbacks("beforeInsert").call(this.context,c,b),b),this.context.trigger("inserted",[b,a]),this.hide(a)),this.context.getOpt("hideWithoutSuffix")?this.stopShowing=!0:void 0},a.prototype.reposition=function(a){var c,d,e,f;return c=this.context.app.iframeAsRoot?this.context.app.window:window,a.bottom+this.$el.height()-b(c).scrollTop()>b(c).height()&&(a.bottom=a.top-this.$el.height()),a.left>(e=b(c).width()-this.$el.width()-5)&&(a.left=e),d={left:a.left,top:a.bottom},null!=(f=this.context.callbacks("beforeReposition"))&&f.call(this.context,d),this.$el.offset(d),this.context.trigger("reposition",[d])},a.prototype.next=function(){var a,b;return a=this.$el.find(".cur").removeClass("cur"),b=a.next(),b.length||(b=this.$el.find("li:first")),b.addClass("cur"),this.scrollTop(Math.max(0,a.innerHeight()*(b.index()+2)-this.$el.height()))},a.prototype.prev=function(){var a,b;return a=this.$el.find(".cur").removeClass("cur"),b=a.prev(),b.length||(b=this.$el.find("li:last")),b.addClass("cur"),this.scrollTop(Math.max(0,a.innerHeight()*(b.index()+2)-this.$el.height()))},a.prototype.scrollTop=function(a){var b;return b=this.context.getOpt("scrollDuration"),b?this.$el.animate({scrollTop:a},b):this.$el.scrollTop(a)},a.prototype.show=function(){var a;return this.stopShowing?void(this.stopShowing=!1):(this.visible()||(this.$el.show(),this.$el.scrollTop(0),this.context.trigger("shown")),(a=this.context.rect())?this.reposition(a):void 0)},a.prototype.hide=function(a,b){var c;if(this.visible())return isNaN(b)?(this.$el.hide(),this.context.trigger("hidden",[a])):(c=function(a){return function(){return a.hide()}}(this),clearTimeout(this.timeoutID),this.timeoutID=setTimeout(c,b))},a.prototype.render=function(a){var c,d,e,f,g,h,i;if(!(b.isArray(a)&&a.length>0))return void this.hide();for(this.$el.find("ul").empty(),d=this.$el.find("ul"),i=this.context.getOpt("displayTpl"),e=0,g=a.length;g>e;e++)f=a[e],f=b.extend({},f,{"atwho-at":this.context.at}),h=this.context.callbacks("tplEval").call(this.context,i,f,"onDisplay"),c=b(this.context.callbacks("highlighter").call(this.context,h,this.context.query.text)),c.data("item-data",f),d.append(c);return this.show(),this.context.getOpt("highlightFirst")?d.find("li:first").addClass("cur"):void 0},a}(),h={DOWN:40,UP:38,ESC:27,TAB:9,ENTER:13,CTRL:17,A:65,P:80,N:78,LEFT:37,UP:38,RIGHT:39,DOWN:40,BACKSPACE:8,SPACE:32},f={beforeSave:function(a){return e.arrayToDefaultHash(a)},matcher:function(a,b,c,d){var e,f,g,h,i;return a=a.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&"),c&&(a="(?:^|\\s)"+a),e=decodeURI("%C3%80"),f=decodeURI("%C3%BF"),i=d?" ":"",h=new RegExp(a+"([A-Za-z"+e+"-"+f+"0-9_"+i+"'.+-]*)$|"+a+"([^\\x00-\\xff]*)$","gi"),g=h.exec(b),g?g[2]||g[1]:null},filter:function(a,b,c){var d,e,f,g;for(d=[],e=0,g=b.length;g>e;e++)f=b[e],~new String(f[c]).toLowerCase().indexOf(a.toLowerCase())&&d.push(f);return d},remoteFilter:null,sorter:function(a,b,c){var d,e,f,g;if(!a)return b;for(d=[],e=0,g=b.length;g>e;e++)f=b[e],f.atwho_order=new String(f[c]).toLowerCase().indexOf(a.toLowerCase()),f.atwho_order>-1&&d.push(f);return d.sort(function(a,b){return a.atwho_order-b.atwho_order})},tplEval:function(a,b){var c,d;d=a;try{return"string"!=typeof a&&(d=a(b)),d.replace(/\$\{([^\}]*)\}/g,function(a,c,d){return b[c]})}catch(e){return c=e,""}},highlighter:function(a,b){var c;return b?(c=new RegExp(">\\s*(\\w*?)("+b.replace("+","\\+")+")(\\w*)\\s*<","ig"),a.replace(c,function(a,b,c,d){return"> "+b+""+c+""+d+" <"})):a},beforeInsert:function(a,b){return a},beforeReposition:function(a){return a},afterMatchFailed:function(a,b){}},c={load:function(a,b){var c;return(c=this.controller(a))?c.model.load(b):void 0},isSelecting:function(){var a;return!!(null!=(a=this.controller())?a.view.visible():void 0)},hide:function(){var a;return null!=(a=this.controller())?a.view.hide():void 0},reposition:function(){var a;return(a=this.controller())?a.view.reposition(a.rect()):void 0},setIframe:function(a,b){return this.setupRootElement(a,b),null},run:function(){return this.dispatch()},destroy:function(){return this.shutdown(),this.$inputor.data("atwho",null)}},b.fn.atwho=function(a){var e,f;return e=arguments,f=null,this.filter('textarea, input, [contenteditable=""], [contenteditable=true]').each(function(){var g,h;return(h=(g=b(this)).data("atwho"))||g.data("atwho",h=new d(this)),"object"!=typeof a&&a?c[a]&&h?f=c[a].apply(h,Array.prototype.slice.call(e,1)):b.error("Method "+a+" does not exist on jQuery.atwho"):h.reg(a.at,a)}),null!=f?f:this},b.fn.atwho["default"]={at:void 0,alias:void 0,data:null,displayTpl:"
    • ${name}
    • ",insertTpl:"${atwho-at}${name}",callbacks:f,searchKey:"name",suffix:void 0,hideWithoutSuffix:!1,startWithSpace:!0,highlightFirst:!0,limit:5,maxLen:20,minLen:0,displayTimeout:300,delay:null,spaceSelectsMatch:!1,tabSelectsMatch:!0,editableAtwhoQueryAttrs:{},scrollDuration:150,suspendOnComposing:!0,lookUpOnClick:!0},b.fn.atwho.debug=!1}); \ No newline at end of file diff --git a/pagure/static/atwho/jquery.atwho.css b/pagure/static/atwho/jquery.atwho.css new file mode 120000 index 0000000..8d3cc6d --- /dev/null +++ b/pagure/static/atwho/jquery.atwho.css @@ -0,0 +1 @@ +jquery.atwho-1.4.1.css \ No newline at end of file diff --git a/pagure/static/atwho/jquery.atwho.js b/pagure/static/atwho/jquery.atwho.js new file mode 120000 index 0000000..6404683 --- /dev/null +++ b/pagure/static/atwho/jquery.atwho.js @@ -0,0 +1 @@ +jquery.atwho-1.4.1.js \ No newline at end of file diff --git a/pagure/static/atwho/jquery.atwho.min.css b/pagure/static/atwho/jquery.atwho.min.css deleted file mode 100644 index f770dc7..0000000 --- a/pagure/static/atwho/jquery.atwho.min.css +++ /dev/null @@ -1 +0,0 @@ -.atwho-view{position:absolute;top:0;left:0;display:none;margin-top:18px;background:#fff;color:#000;border:1px solid #DDD;border-radius:3px;box-shadow:0 0 5px rgba(0,0,0,.1);min-width:120px;z-index:11110!important}.atwho-view .atwho-header{padding:5px;margin:5px;cursor:pointer;border-bottom:solid 1px #eaeff1;color:#6f8092;font-size:11px;font-weight:700}.atwho-view .atwho-header .small{color:#6f8092;float:right;padding-top:2px;margin-right:-5px;font-size:12px;font-weight:400}.atwho-view .atwho-header:hover{cursor:default}.atwho-view .cur{background:#36F;color:#fff}.atwho-view .cur small{color:#fff}.atwho-view strong{color:#36F}.atwho-view .cur strong{color:#fff;font:700}.atwho-view ul{list-style:none;padding:0;margin:auto;max-height:200px;overflow-y:auto}.atwho-view ul li{display:block;padding:5px 10px;border-bottom:1px solid #DDD;cursor:pointer}.atwho-view small{font-size:smaller;color:#777;font-weight:400} \ No newline at end of file diff --git a/pagure/static/atwho/jquery.atwho.min.css b/pagure/static/atwho/jquery.atwho.min.css new file mode 120000 index 0000000..564d968 --- /dev/null +++ b/pagure/static/atwho/jquery.atwho.min.css @@ -0,0 +1 @@ +jquery.atwho-1.4.1.min.css \ No newline at end of file diff --git a/pagure/static/atwho/jquery.atwho.min.js b/pagure/static/atwho/jquery.atwho.min.js deleted file mode 100644 index 71e9a10..0000000 --- a/pagure/static/atwho/jquery.atwho.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(t,e){"function"==typeof define&&define.amd?define(["jquery"],function(t){return e(t)}):"object"==typeof exports?module.exports=e(require("jquery")):e(jQuery)}(this,function(t){var e,i;i={DOWN:40,UP:38,ESC:27,TAB:9,ENTER:13,CTRL:17,A:65,P:80,N:78,LEFT:37,UP:38,RIGHT:39,DOWN:40,BACKSPACE:8,SPACE:32},e={beforeSave:function(t){return r.arrayToDefaultHash(t)},matcher:function(t,e,i,n){var r,o,s,a,h;return t=t.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&"),i&&(t="(?:^|\\s)"+t),r=decodeURI("%C3%80"),o=decodeURI("%C3%BF"),h=n?" ":"",a=new RegExp(t+"([A-Za-z"+r+"-"+o+"0-9_"+h+"'.+-]*)$|"+t+"([^\\x00-\\xff]*)$","gi"),s=a.exec(e),s?s[2]||s[1]:null},filter:function(t,e,i){var n,r,o,s;for(n=[],r=0,s=e.length;s>r;r++)o=e[r],~new String(o[i]).toLowerCase().indexOf(t.toLowerCase())&&n.push(o);return n},remoteFilter:null,sorter:function(t,e,i){var n,r,o,s;if(!t)return e;for(n=[],r=0,s=e.length;s>r;r++)o=e[r],o.atwho_order=new String(o[i]).toLowerCase().indexOf(t.toLowerCase()),o.atwho_order>-1&&n.push(o);return n.sort(function(t,e){return t.atwho_order-e.atwho_order})},tplEval:function(t,e){var i,n,r;r=t;try{return"string"!=typeof t&&(r=t(e)),r.replace(/\$\{([^\}]*)\}/g,function(t,i,n){return e[i]})}catch(n){return i=n,""}},highlighter:function(t,e){var i;return e?(i=new RegExp(">\\s*(\\w*?)("+e.replace("+","\\+")+")(\\w*)\\s*<","ig"),t.replace(i,function(t,e,i,n){return"> "+e+""+i+""+n+" <"})):t},beforeInsert:function(t,e,i){return t},beforeReposition:function(t){return t},afterMatchFailed:function(t,e){}};var n;n=function(){function e(e){this.currentFlag=null,this.controllers={},this.aliasMaps={},this.$inputor=t(e),this.setupRootElement(),this.listen()}return e.prototype.createContainer=function(e){var i;return null!=(i=this.$el)&&i.remove(),t(e.body).append(this.$el=t("
      "))},e.prototype.setupRootElement=function(e,i){var n,r;if(null==i&&(i=!1),e)this.window=e.contentWindow,this.document=e.contentDocument||this.window.document,this.iframe=e;else{this.document=this.$inputor[0].ownerDocument,this.window=this.document.defaultView||this.document.parentWindow;try{this.iframe=this.window.frameElement}catch(r){if(n=r,this.iframe=null,t.fn.atwho.debug)throw new Error("iframe auto-discovery is failed.\nPlease use `setIframe` to set the target iframe manually.\n"+n)}}return this.createContainer((this.iframeAsRoot=i)?this.document:document)},e.prototype.controller=function(t){var e,i,n,r;if(this.aliasMaps[t])i=this.controllers[this.aliasMaps[t]];else{r=this.controllers;for(n in r)if(e=r[n],n===t){i=e;break}}return i?i:this.controllers[this.currentFlag]},e.prototype.setContextFor=function(t){return this.currentFlag=t,this},e.prototype.reg=function(t,e){var i,n;return n=(i=this.controllers)[t]||(i[t]=this.$inputor.is("[contentEditable]")?new l(this,t):new s(this,t)),e.alias&&(this.aliasMaps[e.alias]=t),n.init(e),this},e.prototype.listen=function(){return this.$inputor.on("compositionstart",function(t){return function(e){var i;return null!=(i=t.controller())&&i.view.hide(),t.isComposing=!0,null}}(this)).on("compositionend",function(t){return function(e){return t.isComposing=!1,setTimeout(function(e){return t.dispatch(e)}),null}}(this)).on("keyup.atwhoInner",function(t){return function(e){return t.onKeyup(e)}}(this)).on("keydown.atwhoInner",function(t){return function(e){return t.onKeydown(e)}}(this)).on("blur.atwhoInner",function(t){return function(e){var i;return(i=t.controller())?(i.expectedQueryCBId=null,i.view.hide(e,i.getOpt("displayTimeout"))):void 0}}(this)).on("click.atwhoInner",function(t){return function(e){return t.dispatch(e)}}(this)).on("scroll.atwhoInner",function(t){return function(){var e;return e=t.$inputor.scrollTop(),function(i){var n,r;return n=i.target.scrollTop,e!==n&&null!=(r=t.controller())&&r.view.hide(i),e=n,!0}}}(this)())},e.prototype.shutdown=function(){var t,e,i;i=this.controllers;for(t in i)e=i[t],e.destroy(),delete this.controllers[t];return this.$inputor.off(".atwhoInner"),this.$el.remove()},e.prototype.dispatch=function(t){var e,i,n,r;n=this.controllers,r=[];for(e in n)i=n[e],r.push(i.lookUp(t));return r},e.prototype.onKeyup=function(e){var n;switch(e.keyCode){case i.ESC:e.preventDefault(),null!=(n=this.controller())&&n.view.hide();break;case i.DOWN:case i.UP:case i.CTRL:case i.ENTER:t.noop();break;case i.P:case i.N:e.ctrlKey||this.dispatch(e);break;default:this.dispatch(e)}},e.prototype.onKeydown=function(e){var n,r;if(r=null!=(n=this.controller())?n.view:void 0,r&&r.visible())switch(e.keyCode){case i.ESC:e.preventDefault(),r.hide(e);break;case i.UP:e.preventDefault(),r.prev();break;case i.DOWN:e.preventDefault(),r.next();break;case i.P:if(!e.ctrlKey)return;e.preventDefault(),r.prev();break;case i.N:if(!e.ctrlKey)return;e.preventDefault(),r.next();break;case i.TAB:case i.ENTER:case i.SPACE:if(!r.visible())return;if(!this.controller().getOpt("spaceSelectsMatch")&&e.keyCode===i.SPACE)return;if(!this.controller().getOpt("tabSelectsMatch")&&e.keyCode===i.TAB)return;r.highlighted()?(e.preventDefault(),r.choose(e)):r.hide(e);break;default:t.noop()}},e}();var r,o=[].slice;r=function(){function i(e,i){this.app=e,this.at=i,this.$inputor=this.app.$inputor,this.id=this.$inputor[0].id||this.uid(),this.expectedQueryCBId=null,this.setting=null,this.query=null,this.pos=0,this.range=null,0===(this.$el=t("#atwho-ground-"+this.id,this.app.$el)).length&&this.app.$el.append(this.$el=t("
      ")),this.model=new u(this),this.view=new c(this)}return i.prototype.uid=function(){return(Math.random().toString(16)+"000000000").substr(2,8)+(new Date).getTime()},i.prototype.init=function(e){return this.setting=t.extend({},this.setting||t.fn.atwho["default"],e),this.view.init(),this.model.reload(this.setting.data)},i.prototype.destroy=function(){return this.trigger("beforeDestroy"),this.model.destroy(),this.view.destroy(),this.$el.remove()},i.prototype.callDefault=function(){var i,n,r,s;s=arguments[0],i=2<=arguments.length?o.call(arguments,1):[];try{return e[s].apply(this,i)}catch(r){return n=r,t.error(n+" Or maybe At.js doesn't have function "+s)}},i.prototype.trigger=function(t,e){var i,n;return null==e&&(e=[]),e.push(this),i=this.getOpt("alias"),n=i?t+"-"+i+".atwho":t+".atwho",this.$inputor.trigger(n,e)},i.prototype.callbacks=function(t){return this.getOpt("callbacks")[t]||e[t]},i.prototype.getOpt=function(t,e){var i,n;try{return this.setting[t]}catch(n){return i=n,null}},i.prototype.insertContentFor=function(e){var i,n;return n=this.getOpt("insertTpl"),i=t.extend({},e.data("item-data"),{"atwho-at":this.at}),this.callbacks("tplEval").call(this,n,i,"onInsert")},i.prototype.renderView=function(t){var e;return e=this.getOpt("searchKey"),t=this.callbacks("sorter").call(this,this.query.text,t.slice(0,1001),e),this.view.render(t.slice(0,this.getOpt("limit")))},i.arrayToDefaultHash=function(e){var i,n,r,o;if(!t.isArray(e))return e;for(o=[],i=0,r=e.length;r>i;i++)n=e[i],t.isPlainObject(n)?o.push(n):o.push({name:n});return o},i.prototype.lookUp=function(t){var e,i;if((!t||"click"!==t.type||this.getOpt("lookUpOnClick"))&&(!this.getOpt("suspendOnComposing")||!this.app.isComposing))return(e=this.catchQuery(t))?(this.app.setContextFor(this.at),(i=this.getOpt("delay"))?this._delayLookUp(e,i):this._lookUp(e),e):(this.expectedQueryCBId=null,e)},i.prototype._delayLookUp=function(t,e){var i,n;return i=Date.now?Date.now():(new Date).getTime(),this.previousCallTime||(this.previousCallTime=i),n=e-(i-this.previousCallTime),n>0&&e>n?(this.previousCallTime=i,this._stopDelayedCall(),this.delayedCallTimeout=setTimeout(function(e){return function(){return e.previousCallTime=0,e.delayedCallTimeout=null,e._lookUp(t)}}(this),e)):(this._stopDelayedCall(),this.previousCallTime!==i&&(this.previousCallTime=0),this._lookUp(t))},i.prototype._stopDelayedCall=function(){return this.delayedCallTimeout?(clearTimeout(this.delayedCallTimeout),this.delayedCallTimeout=null):void 0},i.prototype._generateQueryCBId=function(){return{}},i.prototype._lookUp=function(e){var i;return i=function(t,e){return t===this.expectedQueryCBId?e&&e.length>0?this.renderView(this.constructor.arrayToDefaultHash(e)):this.view.hide():void 0},this.expectedQueryCBId=this._generateQueryCBId(),this.model.query(e.text,t.proxy(i,this,this.expectedQueryCBId))},i}();var s,a=function(t,e){function i(){this.constructor=t}for(var n in e)h.call(e,n)&&(t[n]=e[n]);return i.prototype=e.prototype,t.prototype=new i,t.__super__=e.prototype,t},h={}.hasOwnProperty;s=function(e){function i(){return i.__super__.constructor.apply(this,arguments)}return a(i,e),i.prototype.catchQuery=function(){var t,e,i,n,r,o,s;return e=this.$inputor.val(),t=this.$inputor.caret("pos",{iframe:this.app.iframe}),s=e.slice(0,t),r=this.callbacks("matcher").call(this,this.at,s,this.getOpt("startWithSpace"),this.getOpt("acceptSpaceBar")),n="string"==typeof r,n&&r.length0?t.getRangeAt(0):void 0},n.prototype._setRange=function(e,i,n){return null==n&&(n=this._getRange()),n?(i=t(i)[0],"after"===e?(n.setEndAfter(i),n.setStartAfter(i)):(n.setEndBefore(i),n.setStartBefore(i)),n.collapse(!1),this._clearRange(n)):void 0},n.prototype._clearRange=function(t){var e;return null==t&&(t=this._getRange()),e=this.app.window.getSelection(),null==this.ctrl_a_pressed?(e.removeAllRanges(),e.addRange(t)):void 0},n.prototype._movingEvent=function(t){var e;return"click"===t.type||(e=t.which)===i.RIGHT||e===i.LEFT||e===i.UP||e===i.DOWN},n.prototype._unwrap=function(e){var i;return e=t(e).unwrap().get(0),(i=e.nextSibling)&&i.nodeValue&&(e.nodeValue+=i.nodeValue,t(i).remove()),e},n.prototype.catchQuery=function(e){var n,r,o,s,a,h,l,u,c,p,f,d;if((d=this._getRange())&&d.collapsed){if(e.which===i.ENTER)return(r=t(d.startContainer).closest(".atwho-query")).contents().unwrap(),r.is(":empty")&&r.remove(),(r=t(".atwho-query",this.app.document)).text(r.text()).contents().last().unwrap(),void this._clearRange();if(/firefox/i.test(navigator.userAgent)){if(t(d.startContainer).is(this.$inputor))return void this._clearRange();e.which===i.BACKSPACE&&d.startContainer.nodeType===document.ELEMENT_NODE&&(c=d.startOffset-1)>=0?(o=d.cloneRange(),o.setStart(d.startContainer,c),t(o.cloneContents()).contents().last().is(".atwho-inserted")&&(a=t(d.startContainer).contents().get(c),this._setRange("after",t(a).contents().last()))):e.which===i.LEFT&&d.startContainer.nodeType===document.TEXT_NODE&&(n=t(d.startContainer.previousSibling),n.is(".atwho-inserted")&&0===d.startOffset&&this._setRange("after",n.contents().last()))}if(t(d.startContainer).closest(".atwho-inserted").addClass("atwho-query").siblings().removeClass("atwho-query"),(r=t(".atwho-query",this.app.document)).length>0&&r.is(":empty")&&0===r.text().length&&r.remove(),this._movingEvent(e)||r.removeClass("atwho-inserted"),r.length>0)switch(e.which){case i.LEFT:return this._setRange("before",r.get(0),d),void r.removeClass("atwho-query");case i.RIGHT:return this._setRange("after",r.get(0).nextSibling,d),void r.removeClass("atwho-query")}if(r.length>0&&(f=r.attr("data-atwho-at-query"))&&(r.empty().html(f).attr("data-atwho-at-query",null),this._setRange("after",r.get(0),d)),o=d.cloneRange(),o.setStart(d.startContainer,0),u=this.callbacks("matcher").call(this,this.at,o.toString(),this.getOpt("startWithSpace"),this.getOpt("acceptSpaceBar")),h="string"==typeof u,0===r.length&&h&&(s=d.startOffset-this.at.length-u.length)>=0&&(d.setStart(d.startContainer,s),r=t("",this.app.document).attr(this.getOpt("editableAtwhoQueryAttrs")).addClass("atwho-query"),d.surroundContents(r.get(0)),l=r.contents().last().get(0),/firefox/i.test(navigator.userAgent)?(d.setStart(l,l.length),d.setEnd(l,l.length),this._clearRange(d)):this._setRange("after",l,d)),!(h&&u.length=0&&(this._movingEvent(e)&&r.hasClass("atwho-inserted")?r.removeClass("atwho-query"):!1!==this.callbacks("afterMatchFailed").call(this,this.at,r)&&this._setRange("after",this._unwrap(r.text(r.text()).contents().first()))),null)}},n.prototype.rect=function(){var e,i,n;return n=this.query.el.offset(),this.app.iframe&&!this.app.iframeAsRoot&&(i=(e=t(this.app.iframe)).offset(),n.left+=i.left-this.$inputor.scrollLeft(),n.top+=i.top-this.$inputor.scrollTop()),n.bottom=n.top+this.query.el.height(),n},n.prototype.insert=function(t,e){var i,n,r,o;return this.$inputor.is(":focus")||this.$inputor.focus(),r=""===(r=this.getOpt("suffix"))?r:r||" ",i=e.data("item-data"),this.query.el.removeClass("atwho-query").addClass("atwho-inserted").html(t).attr("data-atwho-at-query",""+i["atwho-at"]+this.query.text),(n=this._getRange())&&(n.setEndAfter(this.query.el[0]),n.collapse(!1),n.insertNode(o=this.app.document.createTextNode("‍"+r)),this._setRange("after",o,n)),this.$inputor.is(":focus")||this.$inputor.focus(),this.$inputor.change()},n}(r);var u;u=function(){function e(t){this.context=t,this.at=this.context.at,this.storage=this.context.$inputor}return e.prototype.destroy=function(){return this.storage.data(this.at,null)},e.prototype.saved=function(){return this.fetch()>0},e.prototype.query=function(t,e){var i,n,r;return n=this.fetch(),r=this.context.getOpt("searchKey"),n=this.context.callbacks("filter").call(this.context,t,n,r)||[],i=this.context.callbacks("remoteFilter"),n.length>0||!i&&0===n.length?e(n):i.call(this.context,t,e)},e.prototype.fetch=function(){return this.storage.data(this.at)||[]},e.prototype.save=function(t){return this.storage.data(this.at,this.context.callbacks("beforeSave").call(this.context,t||[]))},e.prototype.load=function(t){return!this.saved()&&t?this._load(t):void 0},e.prototype.reload=function(t){return this._load(t)},e.prototype._load=function(e){return"string"==typeof e?t.ajax(e,{dataType:"json"}).done(function(t){return function(e){return t.save(e)}}(this)):this.save(e)},e}();var c;c=function(){function e(e){this.context=e,this.$el=t("
        "),this.$elUl=this.$el.children(),this.timeoutID=null,this.context.$el.append(this.$el),this.bindEvent()}return e.prototype.init=function(){var t,e;return e=this.context.getOpt("alias")||this.context.at.charCodeAt(0),t=this.context.getOpt("headerTpl"),t&&1===this.$el.children().length&&this.$el.prepend(t),this.$el.attr({id:"at-view-"+e})},e.prototype.destroy=function(){return this.$el.remove()},e.prototype.bindEvent=function(){var e,i,n;return e=this.$el.find("ul"),i=0,n=0,e.on("mousemove.atwho-view","li",function(r){return function(r){var o;if((i!==r.clientX||n!==r.clientY)&&(i=r.clientX,n=r.clientY,o=t(r.currentTarget),!o.hasClass("cur")))return e.find(".cur").removeClass("cur"),o.addClass("cur")}}(this)).on("click.atwho-view","li",function(i){return function(n){return e.find(".cur").removeClass("cur"),t(n.currentTarget).addClass("cur"),i.choose(n),n.preventDefault()}}(this))},e.prototype.visible=function(){return this.$el.is(":visible")},e.prototype.highlighted=function(){return this.$el.find(".cur").length>0},e.prototype.choose=function(t){var e,i;return(e=this.$el.find(".cur")).length&&(i=this.context.insertContentFor(e),this.context._stopDelayedCall(),this.context.insert(this.context.callbacks("beforeInsert").call(this.context,i,e,t),e),this.context.trigger("inserted",[e,t]),this.hide(t)),this.context.getOpt("hideWithoutSuffix")?this.stopShowing=!0:void 0},e.prototype.reposition=function(e){var i,n,r,o;return i=this.context.app.iframeAsRoot?this.context.app.window:window,e.bottom+this.$el.height()-t(i).scrollTop()>t(i).height()&&(e.bottom=e.top-this.$el.height()),e.left>(r=t(i).width()-this.$el.width()-5)&&(e.left=r),n={left:e.left,top:e.bottom},null!=(o=this.context.callbacks("beforeReposition"))&&o.call(this.context,n),this.$el.offset(n),this.context.trigger("reposition",[n])},e.prototype.next=function(){var t,e,i,n;return t=this.$el.find(".cur").removeClass("cur"),e=t.next(),e.length||(e=this.$el.find("li:first")),e.addClass("cur"),i=e[0],n=i.offsetTop+i.offsetHeight+(i.nextSibling?i.nextSibling.offsetHeight:0),this.scrollTop(Math.max(0,n-this.$el.height()))},e.prototype.prev=function(){var t,e,i,n;return t=this.$el.find(".cur").removeClass("cur"),i=t.prev(),i.length||(i=this.$el.find("li:last")),i.addClass("cur"),n=i[0],e=n.offsetTop+n.offsetHeight+(n.nextSibling?n.nextSibling.offsetHeight:0),this.scrollTop(Math.max(0,e-this.$el.height()))},e.prototype.scrollTop=function(t){var e;return e=this.context.getOpt("scrollDuration"),e?this.$elUl.animate({scrollTop:t},e):this.$elUl.scrollTop(t)},e.prototype.show=function(){var t;return this.stopShowing?void(this.stopShowing=!1):(this.visible()||(this.$el.show(),this.$el.scrollTop(0),this.context.trigger("shown")),(t=this.context.rect())?this.reposition(t):void 0)},e.prototype.hide=function(t,e){var i;if(this.visible())return isNaN(e)?(this.$el.hide(),this.context.trigger("hidden",[t])):(i=function(t){return function(){return t.hide()}}(this),clearTimeout(this.timeoutID),this.timeoutID=setTimeout(i,e))},e.prototype.render=function(e){var i,n,r,o,s,a,h;if(!(t.isArray(e)&&e.length>0))return void this.hide();for(this.$el.find("ul").empty(),n=this.$el.find("ul"),h=this.context.getOpt("displayTpl"),r=0,s=e.length;s>r;r++)o=e[r],o=t.extend({},o,{"atwho-at":this.context.at}),a=this.context.callbacks("tplEval").call(this.context,h,o,"onDisplay"),i=t(this.context.callbacks("highlighter").call(this.context,a,this.context.query.text)),i.data("item-data",o),n.append(i);return this.show(),this.context.getOpt("highlightFirst")?n.find("li:first").addClass("cur"):void 0},e}();var p;p={load:function(t,e){var i;return(i=this.controller(t))?i.model.load(e):void 0},isSelecting:function(){var t;return!!(null!=(t=this.controller())?t.view.visible():void 0)},hide:function(){var t;return null!=(t=this.controller())?t.view.hide():void 0},reposition:function(){var t;return(t=this.controller())?t.view.reposition(t.rect()):void 0},setIframe:function(t,e){return this.setupRootElement(t,e),null},run:function(){return this.dispatch()},destroy:function(){return this.shutdown(),this.$inputor.data("atwho",null)}},t.fn.atwho=function(e){var i,r;return i=arguments,r=null,this.filter('textarea, input, [contenteditable=""], [contenteditable=true]').each(function(){var o,s;return(s=(o=t(this)).data("atwho"))||o.data("atwho",s=new n(this)),"object"!=typeof e&&e?p[e]&&s?r=p[e].apply(s,Array.prototype.slice.call(i,1)):t.error("Method "+e+" does not exist on jQuery.atwho"):s.reg(e.at,e)}),null!=r?r:this},t.fn.atwho["default"]={at:void 0,alias:void 0,data:null,displayTpl:"
      • ${name}
      • ",insertTpl:"${atwho-at}${name}",headerTpl:null,callbacks:e,searchKey:"name",suffix:void 0,hideWithoutSuffix:!1,startWithSpace:!0,acceptSpaceBar:!1,highlightFirst:!0,limit:5,maxLen:20,minLen:0,displayTimeout:300,delay:null,spaceSelectsMatch:!1,tabSelectsMatch:!0,editableAtwhoQueryAttrs:{},scrollDuration:150,suspendOnComposing:!0,lookUpOnClick:!0},t.fn.atwho.debug=!1}); \ No newline at end of file diff --git a/pagure/static/atwho/jquery.atwho.min.js b/pagure/static/atwho/jquery.atwho.min.js new file mode 120000 index 0000000..168ae58 --- /dev/null +++ b/pagure/static/atwho/jquery.atwho.min.js @@ -0,0 +1 @@ +jquery.atwho-1.4.1.min.js \ No newline at end of file diff --git a/pagure/static/atwho/jquery.caret-1.5.2.js b/pagure/static/atwho/jquery.caret-1.5.2.js new file mode 100644 index 0000000..c29f029 --- /dev/null +++ b/pagure/static/atwho/jquery.caret-1.5.2.js @@ -0,0 +1,543 @@ +/*! jQuery Caret Plugin - v1.5.2 - 2014-03-25 + * https://github.com/acdvorak/jquery.caret + * Copyright (c) 2012-2014 Andrew C. Dvorak; Licensed MIT */ +(function($, undefined) { + + var _input = document.createElement('input'); + + var _support = { + setSelectionRange: ('setSelectionRange' in _input) || ('selectionStart' in _input), + createTextRange: ('createTextRange' in _input) || ('selection' in document) + }; + + var _rNewlineIE = /\r\n/g, + _rCarriageReturn = /\r/g; + + var _getValue = function(input) { + if (typeof(input.value) !== 'undefined') { + return input.value; + } + return $(input).text(); + }; + + var _setValue = function(input, value) { + if (typeof(input.value) !== 'undefined') { + input.value = value; + } else { + $(input).text(value); + } + }; + + var _getIndex = function(input, pos) { + var norm = _getValue(input).replace(_rCarriageReturn, ''); + var len = norm.length; + + if (typeof(pos) === 'undefined') { + pos = len; + } + + pos = Math.floor(pos); + + // Negative index counts backward from the end of the input/textarea's value + if (pos < 0) { + pos = len + pos; + } + + // Enforce boundaries + if (pos < 0) { pos = 0; } + if (pos > len) { pos = len; } + + return pos; + }; + + var _hasAttr = function(input, attrName) { + return input.hasAttribute ? input.hasAttribute(attrName) : (typeof(input[attrName]) !== 'undefined'); + }; + + /** + * @class + * @constructor + */ + var Range = function(start, end, length, text) { + this.start = start || 0; + this.end = end || 0; + this.length = length || 0; + this.text = text || ''; + }; + + Range.prototype.toString = function() { + return JSON.stringify(this, null, ' '); + }; + + var _getCaretW3 = function(input) { + return input.selectionStart; + }; + + /** + * @see http://stackoverflow.com/q/6943000/467582 + */ + var _getCaretIE = function(input) { + var caret, range, textInputRange, rawValue, len, endRange; + + // Yeah, you have to focus twice for IE 7 and 8. *cries* + input.focus(); + input.focus(); + + range = document.selection.createRange(); + + if (range && range.parentElement() === input) { + rawValue = _getValue(input); + + len = rawValue.length; + + // Create a working TextRange that lives only in the input + textInputRange = input.createTextRange(); + textInputRange.moveToBookmark(range.getBookmark()); + + // Check if the start and end of the selection are at the very end + // of the input, since moveStart/moveEnd doesn't return what we want + // in those cases + endRange = input.createTextRange(); + endRange.collapse(false); + + if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) { + caret = rawValue.replace(_rNewlineIE, '\n').length; + } else { + caret = -textInputRange.moveStart("character", -len); + } + + return caret; + } + + // NOTE: This occurs when you highlight part of a textarea and then click in the middle of the highlighted portion in IE 6-10. + // There doesn't appear to be anything we can do about it. +// alert("Your browser is incredibly stupid. I don't know what else to say."); +// alert(range + '\n\n' + range.parentElement().tagName + '#' + range.parentElement().id); + + return 0; + }; + + /** + * Gets the position of the caret in the given input. + * @param {HTMLInputElement|HTMLTextAreaElement} input input or textarea element + * @returns {Number} + * @see http://stackoverflow.com/questions/263743/how-to-get-cursor-position-in-textarea/263796#263796 + */ + var _getCaret = function(input) { + if (!input) { + return undefined; + } + + // Mozilla, et al. + if (_support.setSelectionRange) { + return _getCaretW3(input); + } + // IE + else if (_support.createTextRange) { + return _getCaretIE(input); + } + + return undefined; + }; + + var _setCaretW3 = function(input, pos) { + input.setSelectionRange(pos, pos); + }; + + var _setCaretIE = function(input, pos) { + var range = input.createTextRange(); + range.move('character', pos); + range.select(); + }; + + /** + * Sets the position of the caret in the given input. + * @param {HTMLInputElement|HTMLTextAreaElement} input input or textarea element + * @param {Number} pos + * @see http://parentnode.org/javascript/working-with-the-cursor-position/ + */ + var _setCaret = function(input, pos) { + input.focus(); + + pos = _getIndex(input, pos); + + // Mozilla, et al. + if (_support.setSelectionRange) { + _setCaretW3(input, pos); + } + // IE + else if (_support.createTextRange) { + _setCaretIE(input, pos); + } + }; + + /** + * Inserts the specified text at the current caret position in the given input. + * @param {HTMLInputElement|HTMLTextAreaElement} input input or textarea element + * @param {String} text + * @see http://parentnode.org/javascript/working-with-the-cursor-position/ + */ + var _insertAtCaret = function(input, text) { + var curPos = _getCaret(input); + + var oldValueNorm = _getValue(input).replace(_rCarriageReturn, ''); + + var newLength = +(curPos + text.length + (oldValueNorm.length - curPos)); + var maxLength = +input.getAttribute('maxlength'); + + if(_hasAttr(input, 'maxlength') && newLength > maxLength) { + var delta = text.length - (newLength - maxLength); + text = text.substr(0, delta); + } + + _setValue(input, oldValueNorm.substr(0, curPos) + text + oldValueNorm.substr(curPos)); + + _setCaret(input, curPos + text.length); + }; + + var _getInputRangeW3 = function(input) { + var range = new Range(); + + range.start = input.selectionStart; + range.end = input.selectionEnd; + + var min = Math.min(range.start, range.end); + var max = Math.max(range.start, range.end); + + range.length = max - min; + range.text = _getValue(input).substring(min, max); + + return range; + }; + + /** @see http://stackoverflow.com/a/3648244/467582 */ + var _getInputRangeIE = function(input) { + var range = new Range(); + + input.focus(); + + var selection = document.selection.createRange(); + + if (selection && selection.parentElement() === input) { + var len, normalizedValue, textInputRange, endRange, start = 0, end = 0; + var rawValue = _getValue(input); + + len = rawValue.length; + normalizedValue = rawValue.replace(/\r\n/g, "\n"); + + // Create a working TextRange that lives only in the input + textInputRange = input.createTextRange(); + textInputRange.moveToBookmark(selection.getBookmark()); + + // Check if the start and end of the selection are at the very end + // of the input, since moveStart/moveEnd doesn't return what we want + // in those cases + endRange = input.createTextRange(); + endRange.collapse(false); + + if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) { + start = end = len; + } else { + start = -textInputRange.moveStart("character", -len); + start += normalizedValue.slice(0, start).split("\n").length - 1; + + if (textInputRange.compareEndPoints("EndToEnd", endRange) > -1) { + end = len; + } else { + end = -textInputRange.moveEnd("character", -len); + end += normalizedValue.slice(0, end).split("\n").length - 1; + } + } + + /// normalize newlines + start -= (rawValue.substring(0, start).split('\r\n').length - 1); + end -= (rawValue.substring(0, end).split('\r\n').length - 1); + /// normalize newlines + + range.start = start; + range.end = end; + range.length = range.end - range.start; + range.text = normalizedValue.substr(range.start, range.length); + } + + return range; + }; + + /** + * Gets the selected text range of the given input. + * @param {HTMLInputElement|HTMLTextAreaElement} input input or textarea element + * @returns {Range} + * @see http://stackoverflow.com/a/263796/467582 + * @see http://stackoverflow.com/a/2966703/467582 + */ + var _getInputRange = function(input) { + if (!input) { + return undefined; + } + + // Mozilla, et al. + if (_support.setSelectionRange) { + return _getInputRangeW3(input); + } + // IE + else if (_support.createTextRange) { + return _getInputRangeIE(input); + } + + return undefined; + }; + + var _setInputRangeW3 = function(input, startPos, endPos) { + input.setSelectionRange(startPos, endPos); + }; + + var _setInputRangeIE = function(input, startPos, endPos) { + var tr = input.createTextRange(); + tr.moveEnd('textedit', -1); + tr.moveStart('character', startPos); + tr.moveEnd('character', endPos - startPos); + tr.select(); + }; + + /** + * Sets the selected text range of (i.e., highlights text in) the given input. + * @param {HTMLInputElement|HTMLTextAreaElement} input input or textarea element + * @param {Number} startPos Zero-based index + * @param {Number} endPos Zero-based index + * @see http://parentnode.org/javascript/working-with-the-cursor-position/ + * @see http://stackoverflow.com/a/2966703/467582 + */ + var _setInputRange = function(input, startPos, endPos) { + startPos = _getIndex(input, startPos); + endPos = _getIndex(input, endPos); + + // Mozilla, et al. + if (_support.setSelectionRange) { + _setInputRangeW3(input, startPos, endPos); + } + // IE + else if (_support.createTextRange) { + _setInputRangeIE(input, startPos, endPos); + } + }; + + /** + * Replaces the currently selected text with the given string. + * @param {HTMLInputElement|HTMLTextAreaElement} input input or textarea element + * @param {String} text New text that will replace the currently selected text. + * @see http://parentnode.org/javascript/working-with-the-cursor-position/ + */ + var _replaceInputRange = function(input, text) { + var $input = $(input); + + var oldValue = $input.val(); + var selection = _getInputRange(input); + + var newLength = +(selection.start + text.length + (oldValue.length - selection.end)); + var maxLength = +$input.attr('maxlength'); + + if($input.is('[maxlength]') && newLength > maxLength) { + var delta = text.length - (newLength - maxLength); + text = text.substr(0, delta); + } + + // Now that we know what the user selected, we can replace it + var startText = oldValue.substr(0, selection.start); + var endText = oldValue.substr(selection.end); + + $input.val(startText + text + endText); + + // Reset the selection + var startPos = selection.start; + var endPos = startPos + text.length; + + _setInputRange(input, selection.length ? startPos : endPos, endPos); + }; + + var _selectAllW3 = function(elem) { + var selection = window.getSelection(); + var range = document.createRange(); + range.selectNodeContents(elem); + selection.removeAllRanges(); + selection.addRange(range); + }; + + var _selectAllIE = function(elem) { + var range = document.body.createTextRange(); + range.moveToElementText(elem); + range.select(); + }; + + /** + * Select all text in the given element. + * @param {HTMLElement} elem Any block or inline element other than a form element. + */ + var _selectAll = function(elem) { + var $elem = $(elem); + if ($elem.is('input, textarea') || elem.select) { + $elem.select(); + return; + } + + // Mozilla, et al. + if (_support.setSelectionRange) { + _selectAllW3(elem); + } + // IE + else if (_support.createTextRange) { + _selectAllIE(elem); + } + }; + + var _deselectAll = function() { + if (document.selection) { + document.selection.empty(); + } + else if (window.getSelection) { + window.getSelection().removeAllRanges(); + } + }; + + $.extend($.fn, { + + /** + * Gets or sets the position of the caret or inserts text at the current caret position in an input or textarea element. + * @returns {Number|jQuery} The current caret position if invoked as a getter (with no arguments) + * or this jQuery object if invoked as a setter or inserter. + * @see http://web.archive.org/web/20080704185920/http://parentnode.org/javascript/working-with-the-cursor-position/ + * @since 1.0.0 + * @example + *
        +         *    // Get position
        +         *    var pos = $('input:first').caret();
        +         * 
        + * @example + *
        +         *    // Set position
        +         *    $('input:first').caret(15);
        +         *    $('input:first').caret(-3);
        +         * 
        + * @example + *
        +         *    // Insert text at current position
        +         *    $('input:first').caret('Some text');
        +         * 
        + */ + caret: function() { + var $inputs = this.filter('input, textarea'); + + // getCaret() + if (arguments.length === 0) { + var input = $inputs.get(0); + return _getCaret(input); + } + // setCaret(position) + else if (typeof arguments[0] === 'number') { + var pos = arguments[0]; + $inputs.each(function(_i, input) { + _setCaret(input, pos); + }); + } + // insertAtCaret(text) + else { + var text = arguments[0]; + $inputs.each(function(_i, input) { + _insertAtCaret(input, text); + }); + } + + return this; + }, + + /** + * Gets or sets the selection range or replaces the currently selected text in an input or textarea element. + * @returns {Range|jQuery} The current selection range if invoked as a getter (with no arguments) + * or this jQuery object if invoked as a setter or replacer. + * @see http://stackoverflow.com/a/2966703/467582 + * @since 1.0.0 + * @example + *
        +         *    // Get selection range
        +         *    var range = $('input:first').range();
        +         * 
        + * @example + *
        +         *    // Set selection range
        +         *    $('input:first').range(15);
        +         *    $('input:first').range(15, 20);
        +         *    $('input:first').range(-3);
        +         *    $('input:first').range(-8, -3);
        +         * 
        + * @example + *
        +         *    // Replace the currently selected text
        +         *    $('input:first').range('Replacement text');
        +         * 
        + */ + range: function() { + var $inputs = this.filter('input, textarea'); + + // getRange() = { start: pos, end: pos } + if (arguments.length === 0) { + var input = $inputs.get(0); + return _getInputRange(input); + } + // setRange(startPos, endPos) + else if (typeof arguments[0] === 'number') { + var startPos = arguments[0]; + var endPos = arguments[1]; + $inputs.each(function(_i, input) { + _setInputRange(input, startPos, endPos); + }); + } + // replaceRange(text) + else { + var text = arguments[0]; + $inputs.each(function(_i, input) { + _replaceInputRange(input, text); + }); + } + + return this; + }, + + /** + * Selects all text in each element of this jQuery object. + * @returns {jQuery} This jQuery object + * @see http://stackoverflow.com/a/11128179/467582 + * @since 1.5.0 + * @example + *
        +         *     // Select the contents of span elements when clicked
        +         *     $('span').on('click', function() { $(this).highlight(); });
        +         * 
        + */ + selectAll: function() { + return this.each(function(_i, elem) { + _selectAll(elem); + }); + } + + }); + + $.extend($, { + /** + * Deselects all text on the page. + * @returns {jQuery} The jQuery function + * @since 1.5.0 + * @example + *
        +         *     // Select some text
        +         *     $('span').selectAll();
        +         *
        +         *     // Deselect the text
        +         *     $.deselectAll();
        +         * 
        + */ + deselectAll: function() { + _deselectAll(); + return this; + } + }); + +}(window.jQuery || window.Zepto || window.$)); diff --git a/pagure/static/atwho/jquery.caret-1.5.2.min.js b/pagure/static/atwho/jquery.caret-1.5.2.min.js new file mode 100644 index 0000000..832a87d --- /dev/null +++ b/pagure/static/atwho/jquery.caret-1.5.2.min.js @@ -0,0 +1,6 @@ +/*! jQuery Caret Plugin - v1.5.2 - 2014-03-25 + * https://github.com/acdvorak/jquery.caret + * Copyright (c) 2012-2014 Andrew C. Dvorak; Licensed MIT */ + +!function(a,b){var c=document.createElement("input"),d={setSelectionRange:"setSelectionRange"in c||"selectionStart"in c,createTextRange:"createTextRange"in c||"selection"in document},e=/\r\n/g,f=/\r/g,g=function(b){return"undefined"!=typeof b.value?b.value:a(b).text()},h=function(b,c){"undefined"!=typeof b.value?b.value=c:a(b).text(c)},i=function(a,b){var c=g(a).replace(f,""),d=c.length;return"undefined"==typeof b&&(b=d),b=Math.floor(b),0>b&&(b=d+b),0>b&&(b=0),b>d&&(b=d),b},j=function(a,b){return a.hasAttribute?a.hasAttribute(b):"undefined"!=typeof a[b]},k=function(a,b,c,d){this.start=a||0,this.end=b||0,this.length=c||0,this.text=d||""};k.prototype.toString=function(){return JSON.stringify(this,null," ")};var l=function(a){return a.selectionStart},m=function(a){var b,c,d,f,h,i;return a.focus(),a.focus(),c=document.selection.createRange(),c&&c.parentElement()===a?(f=g(a),h=f.length,d=a.createTextRange(),d.moveToBookmark(c.getBookmark()),i=a.createTextRange(),i.collapse(!1),b=d.compareEndPoints("StartToEnd",i)>-1?f.replace(e,"\n").length:-d.moveStart("character",-h)):0},n=function(a){return a?d.setSelectionRange?l(a):d.createTextRange?m(a):b:b},o=function(a,b){a.setSelectionRange(b,b)},p=function(a,b){var c=a.createTextRange();c.move("character",b),c.select()},q=function(a,b){a.focus(),b=i(a,b),d.setSelectionRange?o(a,b):d.createTextRange&&p(a,b)},r=function(a,b){var c=n(a),d=g(a).replace(f,""),e=+(c+b.length+(d.length-c)),i=+a.getAttribute("maxlength");if(j(a,"maxlength")&&e>i){var k=b.length-(e-i);b=b.substr(0,k)}h(a,d.substr(0,c)+b+d.substr(c)),q(a,c+b.length)},s=function(a){var b=new k;b.start=a.selectionStart,b.end=a.selectionEnd;var c=Math.min(b.start,b.end),d=Math.max(b.start,b.end);return b.length=d-c,b.text=g(a).substring(c,d),b},t=function(a){var b=new k;a.focus();var c=document.selection.createRange();if(c&&c.parentElement()===a){var d,e,f,h,i=0,j=0,l=g(a);d=l.length,e=l.replace(/\r\n/g,"\n"),f=a.createTextRange(),f.moveToBookmark(c.getBookmark()),h=a.createTextRange(),h.collapse(!1),f.compareEndPoints("StartToEnd",h)>-1?i=j=d:(i=-f.moveStart("character",-d),i+=e.slice(0,i).split("\n").length-1,f.compareEndPoints("EndToEnd",h)>-1?j=d:(j=-f.moveEnd("character",-d),j+=e.slice(0,j).split("\n").length-1)),i-=l.substring(0,i).split("\r\n").length-1,j-=l.substring(0,j).split("\r\n").length-1,b.start=i,b.end=j,b.length=b.end-b.start,b.text=e.substr(b.start,b.length)}return b},u=function(a){return a?d.setSelectionRange?s(a):d.createTextRange?t(a):b:b},v=function(a,b,c){a.setSelectionRange(b,c)},w=function(a,b,c){var d=a.createTextRange();d.moveEnd("textedit",-1),d.moveStart("character",b),d.moveEnd("character",c-b),d.select()},x=function(a,b,c){b=i(a,b),c=i(a,c),d.setSelectionRange?v(a,b,c):d.createTextRange&&w(a,b,c)},y=function(b,c){var d=a(b),e=d.val(),f=u(b),g=+(f.start+c.length+(e.length-f.end)),h=+d.attr("maxlength");if(d.is("[maxlength]")&&g>h){var i=c.length-(g-h);c=c.substr(0,i)}var j=e.substr(0,f.start),k=e.substr(f.end);d.val(j+c+k);var l=f.start,m=l+c.length;x(b,f.length?l:m,m)},z=function(a){var b=window.getSelection(),c=document.createRange();c.selectNodeContents(a),b.removeAllRanges(),b.addRange(c)},A=function(a){var b=document.body.createTextRange();b.moveToElementText(a),b.select()},B=function(b){var c=a(b);return c.is("input, textarea")||b.select?(c.select(),void 0):(d.setSelectionRange?z(b):d.createTextRange&&A(b),void 0)},C=function(){document.selection?document.selection.empty():window.getSelection&&window.getSelection().removeAllRanges()};a.extend(a.fn,{caret:function(){var a=this.filter("input, textarea");if(0===arguments.length){var b=a.get(0);return n(b)}if("number"==typeof arguments[0]){var c=arguments[0];a.each(function(a,b){q(b,c)})}else{var d=arguments[0];a.each(function(a,b){r(b,d)})}return this},range:function(){var a=this.filter("input, textarea");if(0===arguments.length){var b=a.get(0);return u(b)}if("number"==typeof arguments[0]){var c=arguments[0],d=arguments[1];a.each(function(a,b){x(b,c,d)})}else{var e=arguments[0];a.each(function(a,b){y(b,e)})}return this},selectAll:function(){return this.each(function(a,b){B(b)})}}),a.extend(a,{deselectAll:function(){return C(),this}})}(window.jQuery||window.Zepto||window.$); +//# sourceMappingURL=dist/jquery.caret-1.5.2.min.map \ No newline at end of file diff --git a/pagure/static/atwho/jquery.caret.js b/pagure/static/atwho/jquery.caret.js new file mode 120000 index 0000000..a73e1e2 --- /dev/null +++ b/pagure/static/atwho/jquery.caret.js @@ -0,0 +1 @@ +jquery.caret-1.5.2.js \ No newline at end of file diff --git a/pagure/static/atwho/jquery.caret.min.js b/pagure/static/atwho/jquery.caret.min.js deleted file mode 100644 index a25584e..0000000 --- a/pagure/static/atwho/jquery.caret.min.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! jquery.caret 2016-02-27 */ -!function(a,b){"function"==typeof define&&define.amd?define(["jquery"],function(c){return a.returnExportsGlobal=b(c)}):"object"==typeof exports?module.exports=b(require("jquery")):b(jQuery)}(this,function(a){"use strict";var b,c,d,e,f,g,h,i,j,k,l;k="caret",b=function(){function b(a){this.$inputor=a,this.domInputor=this.$inputor[0]}return b.prototype.setPos=function(a){var b,c,d,e;return(e=j.getSelection())&&(d=0,c=!1,(b=function(a,f){var g,i,j,k,l,m;for(l=f.childNodes,m=[],j=0,k=l.length;k>j&&(g=l[j],!c);j++)if(3===g.nodeType){if(d+g.length>=a){c=!0,i=h.createRange(),i.setStart(g,a-d),e.removeAllRanges(),e.addRange(i);break}m.push(d+=g.length)}else m.push(b(a,g));return m})(a,this.domInputor)),this.domInputor},b.prototype.getIEPosition=function(){return this.getPosition()},b.prototype.getPosition=function(){var a,b;return b=this.getOffset(),a=this.$inputor.offset(),b.left-=a.left,b.top-=a.top,b},b.prototype.getOldIEPos=function(){var a,b;return b=h.selection.createRange(),a=h.body.createTextRange(),a.moveToElementText(this.domInputor),a.setEndPoint("EndToEnd",b),a.text.length},b.prototype.getPos=function(){var a,b,c;return(c=this.range())?(a=c.cloneRange(),a.selectNodeContents(this.domInputor),a.setEnd(c.endContainer,c.endOffset),b=a.toString().length,a.detach(),b):h.selection?this.getOldIEPos():void 0},b.prototype.getOldIEOffset=function(){var a,b;return a=h.selection.createRange().duplicate(),a.moveStart("character",-1),b=a.getBoundingClientRect(),{height:b.bottom-b.top,left:b.left,top:b.top}},b.prototype.getOffset=function(){var b,c,d,e,f;return j.getSelection&&(d=this.range())?(d.endOffset-1>0&&d.endContainer!==this.domInputor&&(b=d.cloneRange(),b.setStart(d.endContainer,d.endOffset-1),b.setEnd(d.endContainer,d.endOffset),e=b.getBoundingClientRect(),c={height:e.height,left:e.left+e.width,top:e.top},b.detach()),c&&0!==(null!=c?c.height:void 0)||(b=d.cloneRange(),f=a(h.createTextNode("|")),b.insertNode(f[0]),b.selectNode(f[0]),e=b.getBoundingClientRect(),c={height:e.height,left:e.left,top:e.top},f.remove(),b.detach())):h.selection&&(c=this.getOldIEOffset()),c&&(c.top+=a(j).scrollTop(),c.left+=a(j).scrollLeft()),c},b.prototype.range=function(){var a;if(j.getSelection)return a=j.getSelection(),a.rangeCount>0?a.getRangeAt(0):null},b}(),c=function(){function b(a){this.$inputor=a,this.domInputor=this.$inputor[0]}return b.prototype.getIEPos=function(){var a,b,c,d,e,f,g;return b=this.domInputor,f=h.selection.createRange(),e=0,f&&f.parentElement()===b&&(d=b.value.replace(/\r\n/g,"\n"),c=d.length,g=b.createTextRange(),g.moveToBookmark(f.getBookmark()),a=b.createTextRange(),a.collapse(!1),e=g.compareEndPoints("StartToEnd",a)>-1?c:-g.moveStart("character",-c)),e},b.prototype.getPos=function(){return h.selection?this.getIEPos():this.domInputor.selectionStart},b.prototype.setPos=function(a){var b,c;return b=this.domInputor,h.selection?(c=b.createTextRange(),c.move("character",a),c.select()):b.setSelectionRange&&b.setSelectionRange(a,a),b},b.prototype.getIEOffset=function(a){var b,c,d,e;return c=this.domInputor.createTextRange(),a||(a=this.getPos()),c.move("character",a),d=c.boundingLeft,e=c.boundingTop,b=c.boundingHeight,{left:d,top:e,height:b}},b.prototype.getOffset=function(b){var c,d,e;return c=this.$inputor,h.selection?(d=this.getIEOffset(b),d.top+=a(j).scrollTop()+c.scrollTop(),d.left+=a(j).scrollLeft()+c.scrollLeft(),d):(d=c.offset(),e=this.getPosition(b),d={left:d.left+e.left-c.scrollLeft(),top:d.top+e.top-c.scrollTop(),height:e.height})},b.prototype.getPosition=function(a){var b,c,e,f,g,h,i;return b=this.$inputor,f=function(a){return a=a.replace(/<|>|`|"|&/g,"?").replace(/\r\n|\r|\n/g,"
        "),/firefox/i.test(navigator.userAgent)&&(a=a.replace(/\s/g," ")),a},void 0===a&&(a=this.getPos()),i=b.val().slice(0,a),e=b.val().slice(a),g=""+f(i)+"",g+="|",g+=""+f(e)+"",h=new d(b),c=h.create(g).rect()},b.prototype.getIEPosition=function(a){var b,c,d,e,f;return d=this.getIEOffset(a),c=this.$inputor.offset(),e=d.left-c.left,f=d.top-c.top,b=d.height,{left:e,top:f,height:b}},b}(),d=function(){function b(a){this.$inputor=a}return b.prototype.css_attr=["borderBottomWidth","borderLeftWidth","borderRightWidth","borderTopStyle","borderRightStyle","borderBottomStyle","borderLeftStyle","borderTopWidth","boxSizing","fontFamily","fontSize","fontWeight","height","letterSpacing","lineHeight","marginBottom","marginLeft","marginRight","marginTop","outlineWidth","overflow","overflowX","overflowY","paddingBottom","paddingLeft","paddingRight","paddingTop","textAlign","textOverflow","textTransform","whiteSpace","wordBreak","wordWrap"],b.prototype.mirrorCss=function(){var b,c=this;return b={position:"absolute",left:-9999,top:0,zIndex:-2e4},"TEXTAREA"===this.$inputor.prop("tagName")&&this.css_attr.push("width"),a.each(this.css_attr,function(a,d){return b[d]=c.$inputor.css(d)}),b},b.prototype.create=function(b){return this.$mirror=a("
        "),this.$mirror.css(this.mirrorCss()),this.$mirror.html(b),this.$inputor.after(this.$mirror),this},b.prototype.rect=function(){var a,b,c;return a=this.$mirror.find("#caret"),b=a.position(),c={left:b.left,top:b.top,height:a.height()},this.$mirror.remove(),c},b}(),e={contentEditable:function(a){return!(!a[0].contentEditable||"true"!==a[0].contentEditable)}},g={pos:function(a){return a||0===a?this.setPos(a):this.getPos()},position:function(a){return h.selection?this.getIEPosition(a):this.getPosition(a)},offset:function(a){var b;return b=this.getOffset(a)}},h=null,j=null,i=null,l=function(a){var b;return(b=null!=a?a.iframe:void 0)?(i=b,j=b.contentWindow,h=b.contentDocument||j.document):(i=void 0,j=window,h=document)},f=function(a){var b;h=a[0].ownerDocument,j=h.defaultView||h.parentWindow;try{return i=j.frameElement}catch(c){b=c}},a.fn.caret=function(d,f,h){var i;return g[d]?(a.isPlainObject(f)?(l(f),f=void 0):l(h),i=e.contentEditable(this)?new b(this):new c(this),g[d].apply(i,[f])):a.error("Method "+d+" does not exist on jQuery.caret")},a.fn.caret.EditableCaret=b,a.fn.caret.InputCaret=c,a.fn.caret.Utils=e,a.fn.caret.apis=g}); \ No newline at end of file diff --git a/pagure/static/atwho/jquery.caret.min.js b/pagure/static/atwho/jquery.caret.min.js new file mode 120000 index 0000000..9878694 --- /dev/null +++ b/pagure/static/atwho/jquery.caret.min.js @@ -0,0 +1 @@ +jquery.caret-1.5.2.min.js \ No newline at end of file diff --git a/pagure/static/codemirror/codemirror-5.18.2.css b/pagure/static/codemirror/codemirror-5.18.2.css new file mode 100644 index 0000000..18b0bf7 --- /dev/null +++ b/pagure/static/codemirror/codemirror-5.18.2.css @@ -0,0 +1,347 @@ +/* BASICS */ + +.CodeMirror { + /* Set height, width, borders, and global font properties here */ + font-family: monospace; + height: 300px; + color: black; +} + +/* PADDING */ + +.CodeMirror-lines { + padding: 4px 0; /* Vertical padding around content */ +} +.CodeMirror pre { + padding: 0 4px; /* Horizontal padding of content */ +} + +.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { + background-color: white; /* The little square between H and V scrollbars */ +} + +/* GUTTER */ + +.CodeMirror-gutters { + border-right: 1px solid #ddd; + background-color: #f7f7f7; + white-space: nowrap; +} +.CodeMirror-linenumbers {} +.CodeMirror-linenumber { + padding: 0 3px 0 5px; + min-width: 20px; + text-align: right; + color: #999; + white-space: nowrap; +} + +.CodeMirror-guttermarker { color: black; } +.CodeMirror-guttermarker-subtle { color: #999; } + +/* CURSOR */ + +.CodeMirror-cursor { + border-left: 1px solid black; + border-right: none; + width: 0; +} +/* Shown when moving in bi-directional text */ +.CodeMirror div.CodeMirror-secondarycursor { + border-left: 1px solid silver; +} +.cm-fat-cursor .CodeMirror-cursor { + width: auto; + border: 0 !important; + background: #7e7; +} +.cm-fat-cursor div.CodeMirror-cursors { + z-index: 1; +} + +.cm-animate-fat-cursor { + width: auto; + border: 0; + -webkit-animation: blink 1.06s steps(1) infinite; + -moz-animation: blink 1.06s steps(1) infinite; + animation: blink 1.06s steps(1) infinite; + background-color: #7e7; +} +@-moz-keyframes blink { + 0% {} + 50% { background-color: transparent; } + 100% {} +} +@-webkit-keyframes blink { + 0% {} + 50% { background-color: transparent; } + 100% {} +} +@keyframes blink { + 0% {} + 50% { background-color: transparent; } + 100% {} +} + +/* Can style cursor different in overwrite (non-insert) mode */ +.CodeMirror-overwrite .CodeMirror-cursor {} + +.cm-tab { display: inline-block; text-decoration: inherit; } + +.CodeMirror-rulers { + position: absolute; + left: 0; right: 0; top: -50px; bottom: -20px; + overflow: hidden; +} +.CodeMirror-ruler { + border-left: 1px solid #ccc; + top: 0; bottom: 0; + position: absolute; +} + +/* DEFAULT THEME */ + +.cm-s-default .cm-header {color: blue;} +.cm-s-default .cm-quote {color: #090;} +.cm-negative {color: #d44;} +.cm-positive {color: #292;} +.cm-header, .cm-strong {font-weight: bold;} +.cm-em {font-style: italic;} +.cm-link {text-decoration: underline;} +.cm-strikethrough {text-decoration: line-through;} + +.cm-s-default .cm-keyword {color: #708;} +.cm-s-default .cm-atom {color: #219;} +.cm-s-default .cm-number {color: #164;} +.cm-s-default .cm-def {color: #00f;} +.cm-s-default .cm-variable, +.cm-s-default .cm-punctuation, +.cm-s-default .cm-property, +.cm-s-default .cm-operator {} +.cm-s-default .cm-variable-2 {color: #05a;} +.cm-s-default .cm-variable-3 {color: #085;} +.cm-s-default .cm-comment {color: #a50;} +.cm-s-default .cm-string {color: #a11;} +.cm-s-default .cm-string-2 {color: #f50;} +.cm-s-default .cm-meta {color: #555;} +.cm-s-default .cm-qualifier {color: #555;} +.cm-s-default .cm-builtin {color: #30a;} +.cm-s-default .cm-bracket {color: #997;} +.cm-s-default .cm-tag {color: #170;} +.cm-s-default .cm-attribute {color: #00c;} +.cm-s-default .cm-hr {color: #999;} +.cm-s-default .cm-link {color: #00c;} + +.cm-s-default .cm-error {color: #f00;} +.cm-invalidchar {color: #f00;} + +.CodeMirror-composing { border-bottom: 2px solid; } + +/* Default styles for common addons */ + +div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;} +div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;} +.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); } +.CodeMirror-activeline-background {background: #e8f2ff;} + +/* STOP */ + +/* The rest of this file contains styles related to the mechanics of + the editor. You probably shouldn't touch them. */ + +.CodeMirror { + position: relative; + overflow: hidden; + background: white; +} + +.CodeMirror-scroll { + overflow: scroll !important; /* Things will break if this is overridden */ + /* 30px is the magic margin used to hide the element's real scrollbars */ + /* See overflow: hidden in .CodeMirror */ + margin-bottom: -30px; margin-right: -30px; + padding-bottom: 30px; + height: 100%; + outline: none; /* Prevent dragging from highlighting the element */ + position: relative; +} +.CodeMirror-sizer { + position: relative; + border-right: 30px solid transparent; +} + +/* The fake, visible scrollbars. Used to force redraw during scrolling + before actual scrolling happens, thus preventing shaking and + flickering artifacts. */ +.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { + position: absolute; + z-index: 6; + display: none; +} +.CodeMirror-vscrollbar { + right: 0; top: 0; + overflow-x: hidden; + overflow-y: scroll; +} +.CodeMirror-hscrollbar { + bottom: 0; left: 0; + overflow-y: hidden; + overflow-x: scroll; +} +.CodeMirror-scrollbar-filler { + right: 0; bottom: 0; +} +.CodeMirror-gutter-filler { + left: 0; bottom: 0; +} + +.CodeMirror-gutters { + position: absolute; left: 0; top: 0; + min-height: 100%; + z-index: 3; +} +.CodeMirror-gutter { + white-space: normal; + height: 100%; + display: inline-block; + vertical-align: top; + margin-bottom: -30px; + /* Hack to make IE7 behave */ + *zoom:1; + *display:inline; +} +.CodeMirror-gutter-wrapper { + position: absolute; + z-index: 4; + background: none !important; + border: none !important; +} +.CodeMirror-gutter-background { + position: absolute; + top: 0; bottom: 0; + z-index: 4; +} +.CodeMirror-gutter-elt { + position: absolute; + cursor: default; + z-index: 4; +} +.CodeMirror-gutter-wrapper { + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; +} + +.CodeMirror-lines { + cursor: text; + min-height: 1px; /* prevents collapsing before first draw */ +} +.CodeMirror pre { + /* Reset some styles that the rest of the page might have set */ + -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0; + border-width: 0; + background: transparent; + font-family: inherit; + font-size: inherit; + margin: 0; + white-space: pre; + word-wrap: normal; + line-height: inherit; + color: inherit; + z-index: 2; + position: relative; + overflow: visible; + -webkit-tap-highlight-color: transparent; + -webkit-font-variant-ligatures: none; + font-variant-ligatures: none; +} +.CodeMirror-wrap pre { + word-wrap: break-word; + white-space: pre-wrap; + word-break: normal; +} + +.CodeMirror-linebackground { + position: absolute; + left: 0; right: 0; top: 0; bottom: 0; + z-index: 0; +} + +.CodeMirror-linewidget { + position: relative; + z-index: 2; + overflow: auto; +} + +.CodeMirror-widget {} + +.CodeMirror-code { + outline: none; +} + +/* Force content-box sizing for the elements where we expect it */ +.CodeMirror-scroll, +.CodeMirror-sizer, +.CodeMirror-gutter, +.CodeMirror-gutters, +.CodeMirror-linenumber { + -moz-box-sizing: content-box; + box-sizing: content-box; +} + +.CodeMirror-measure { + position: absolute; + width: 100%; + height: 0; + overflow: hidden; + visibility: hidden; +} + +.CodeMirror-cursor { + position: absolute; + pointer-events: none; +} +.CodeMirror-measure pre { position: static; } + +div.CodeMirror-cursors { + visibility: hidden; + position: relative; + z-index: 3; +} +div.CodeMirror-dragcursors { + visibility: visible; +} + +.CodeMirror-focused div.CodeMirror-cursors { + visibility: visible; +} + +.CodeMirror-selected { background: #d9d9d9; } +.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; } +.CodeMirror-crosshair { cursor: crosshair; } +.CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; } +.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; } + +.cm-searching { + background: #ffa; + background: rgba(255, 255, 0, .4); +} + +/* IE7 hack to prevent it from returning funny offsetTops on the spans */ +.CodeMirror span { *vertical-align: text-bottom; } + +/* Used to force a border model for a node */ +.cm-force-border { padding-right: .1px; } + +@media print { + /* Hide the cursor when printing */ + .CodeMirror div.CodeMirror-cursors { + visibility: hidden; + } +} + +/* See issue #2901 */ +.cm-tab-wrap-hack:after { content: ''; } + +/* Help users use markselection to safely style text background */ +span.CodeMirror-selectedtext { background: none; } diff --git a/pagure/static/codemirror/codemirror-5.18.2.js b/pagure/static/codemirror/codemirror-5.18.2.js new file mode 100644 index 0000000..1071bb9 --- /dev/null +++ b/pagure/static/codemirror/codemirror-5.18.2.js @@ -0,0 +1,8961 @@ +// CodeMirror, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + +// This is CodeMirror (http://codemirror.net), a code editor +// implemented in JavaScript on top of the browser's DOM. +// +// You can find some technical background for some of the code below +// at http://marijnhaverbeke.nl/blog/#cm-internals . + +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + module.exports = mod(); + else if (typeof define == "function" && define.amd) // AMD + return define([], mod); + else // Plain browser env + (this || window).CodeMirror = mod(); +})(function() { + "use strict"; + + // BROWSER SNIFFING + + // Kludges for bugs and behavior differences that can't be feature + // detected are enabled based on userAgent etc sniffing. + var userAgent = navigator.userAgent; + var platform = navigator.platform; + + var gecko = /gecko\/\d/i.test(userAgent); + var ie_upto10 = /MSIE \d/.test(userAgent); + var ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(userAgent); + var ie = ie_upto10 || ie_11up; + var ie_version = ie && (ie_upto10 ? document.documentMode || 6 : ie_11up[1]); + var webkit = /WebKit\//.test(userAgent); + var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(userAgent); + var chrome = /Chrome\//.test(userAgent); + var presto = /Opera\//.test(userAgent); + var safari = /Apple Computer/.test(navigator.vendor); + var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(userAgent); + var phantom = /PhantomJS/.test(userAgent); + + var ios = /AppleWebKit/.test(userAgent) && /Mobile\/\w+/.test(userAgent); + // This is woefully incomplete. Suggestions for alternative methods welcome. + var mobile = ios || /Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(userAgent); + var mac = ios || /Mac/.test(platform); + var chromeOS = /\bCrOS\b/.test(userAgent); + var windows = /win/i.test(platform); + + var presto_version = presto && userAgent.match(/Version\/(\d*\.\d*)/); + if (presto_version) presto_version = Number(presto_version[1]); + if (presto_version && presto_version >= 15) { presto = false; webkit = true; } + // Some browsers use the wrong event properties to signal cmd/ctrl on OS X + var flipCtrlCmd = mac && (qtwebkit || presto && (presto_version == null || presto_version < 12.11)); + var captureRightClick = gecko || (ie && ie_version >= 9); + + // Optimize some code when these features are not used. + var sawReadOnlySpans = false, sawCollapsedSpans = false; + + // EDITOR CONSTRUCTOR + + // A CodeMirror instance represents an editor. This is the object + // that user code is usually dealing with. + + function CodeMirror(place, options) { + if (!(this instanceof CodeMirror)) return new CodeMirror(place, options); + + this.options = options = options ? copyObj(options) : {}; + // Determine effective options based on given values and defaults. + copyObj(defaults, options, false); + setGuttersForLineNumbers(options); + + var doc = options.value; + if (typeof doc == "string") doc = new Doc(doc, options.mode, null, options.lineSeparator); + this.doc = doc; + + var input = new CodeMirror.inputStyles[options.inputStyle](this); + var display = this.display = new Display(place, doc, input); + display.wrapper.CodeMirror = this; + updateGutters(this); + themeChanged(this); + if (options.lineWrapping) + this.display.wrapper.className += " CodeMirror-wrap"; + if (options.autofocus && !mobile) display.input.focus(); + initScrollbars(this); + + this.state = { + keyMaps: [], // stores maps added by addKeyMap + overlays: [], // highlighting overlays, as added by addOverlay + modeGen: 0, // bumped when mode/overlay changes, used to invalidate highlighting info + overwrite: false, + delayingBlurEvent: false, + focused: false, + suppressEdits: false, // used to disable editing during key handlers when in readOnly mode + pasteIncoming: false, cutIncoming: false, // help recognize paste/cut edits in input.poll + selectingText: false, + draggingText: false, + highlight: new Delayed(), // stores highlight worker timeout + keySeq: null, // Unfinished key sequence + specialChars: null + }; + + var cm = this; + + // Override magic textarea content restore that IE sometimes does + // on our hidden textarea on reload + if (ie && ie_version < 11) setTimeout(function() { cm.display.input.reset(true); }, 20); + + registerEventHandlers(this); + ensureGlobalHandlers(); + + startOperation(this); + this.curOp.forceUpdate = true; + attachDoc(this, doc); + + if ((options.autofocus && !mobile) || cm.hasFocus()) + setTimeout(bind(onFocus, this), 20); + else + onBlur(this); + + for (var opt in optionHandlers) if (optionHandlers.hasOwnProperty(opt)) + optionHandlers[opt](this, options[opt], Init); + maybeUpdateLineNumberWidth(this); + if (options.finishInit) options.finishInit(this); + for (var i = 0; i < initHooks.length; ++i) initHooks[i](this); + endOperation(this); + // Suppress optimizelegibility in Webkit, since it breaks text + // measuring on line wrapping boundaries. + if (webkit && options.lineWrapping && + getComputedStyle(display.lineDiv).textRendering == "optimizelegibility") + display.lineDiv.style.textRendering = "auto"; + } + + // DISPLAY CONSTRUCTOR + + // The display handles the DOM integration, both for input reading + // and content drawing. It holds references to DOM nodes and + // display-related state. + + function Display(place, doc, input) { + var d = this; + this.input = input; + + // Covers bottom-right square when both scrollbars are present. + d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler"); + d.scrollbarFiller.setAttribute("cm-not-content", "true"); + // Covers bottom of gutter when coverGutterNextToScrollbar is on + // and h scrollbar is present. + d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler"); + d.gutterFiller.setAttribute("cm-not-content", "true"); + // Will contain the actual code, positioned to cover the viewport. + d.lineDiv = elt("div", null, "CodeMirror-code"); + // Elements are added to these to represent selection and cursors. + d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1"); + d.cursorDiv = elt("div", null, "CodeMirror-cursors"); + // A visibility: hidden element used to find the size of things. + d.measure = elt("div", null, "CodeMirror-measure"); + // When lines outside of the viewport are measured, they are drawn in this. + d.lineMeasure = elt("div", null, "CodeMirror-measure"); + // Wraps everything that needs to exist inside the vertically-padded coordinate system + d.lineSpace = elt("div", [d.measure, d.lineMeasure, d.selectionDiv, d.cursorDiv, d.lineDiv], + null, "position: relative; outline: none"); + // Moved around its parent to cover visible view. + d.mover = elt("div", [elt("div", [d.lineSpace], "CodeMirror-lines")], null, "position: relative"); + // Set to the height of the document, allowing scrolling. + d.sizer = elt("div", [d.mover], "CodeMirror-sizer"); + d.sizerWidth = null; + // Behavior of elts with overflow: auto and padding is + // inconsistent across browsers. This is used to ensure the + // scrollable area is big enough. + d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerGap + "px; width: 1px;"); + // Will contain the gutters, if any. + d.gutters = elt("div", null, "CodeMirror-gutters"); + d.lineGutter = null; + // Actual scrollable element. + d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll"); + d.scroller.setAttribute("tabIndex", "-1"); + // The element in which the editor lives. + d.wrapper = elt("div", [d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror"); + + // Work around IE7 z-index bug (not perfect, hence IE7 not really being supported) + if (ie && ie_version < 8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; } + if (!webkit && !(gecko && mobile)) d.scroller.draggable = true; + + if (place) { + if (place.appendChild) place.appendChild(d.wrapper); + else place(d.wrapper); + } + + // Current rendered range (may be bigger than the view window). + d.viewFrom = d.viewTo = doc.first; + d.reportedViewFrom = d.reportedViewTo = doc.first; + // Information about the rendered lines. + d.view = []; + d.renderedView = null; + // Holds info about a single rendered line when it was rendered + // for measurement, while not in view. + d.externalMeasured = null; + // Empty space (in pixels) above the view + d.viewOffset = 0; + d.lastWrapHeight = d.lastWrapWidth = 0; + d.updateLineNumbers = null; + + d.nativeBarWidth = d.barHeight = d.barWidth = 0; + d.scrollbarsClipped = false; + + // Used to only resize the line number gutter when necessary (when + // the amount of lines crosses a boundary that makes its width change) + d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null; + // Set to true when a non-horizontal-scrolling line widget is + // added. As an optimization, line widget aligning is skipped when + // this is false. + d.alignWidgets = false; + + d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null; + + // Tracks the maximum line length so that the horizontal scrollbar + // can be kept static when scrolling. + d.maxLine = null; + d.maxLineLength = 0; + d.maxLineChanged = false; + + // Used for measuring wheel scrolling granularity + d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null; + + // True when shift is held down. + d.shift = false; + + // Used to track whether anything happened since the context menu + // was opened. + d.selForContextMenu = null; + + d.activeTouch = null; + + input.init(d); + } + + // STATE UPDATES + + // Used to get the editor into a consistent state again when options change. + + function loadMode(cm) { + cm.doc.mode = CodeMirror.getMode(cm.options, cm.doc.modeOption); + resetModeState(cm); + } + + function resetModeState(cm) { + cm.doc.iter(function(line) { + if (line.stateAfter) line.stateAfter = null; + if (line.styles) line.styles = null; + }); + cm.doc.frontier = cm.doc.first; + startWorker(cm, 100); + cm.state.modeGen++; + if (cm.curOp) regChange(cm); + } + + function wrappingChanged(cm) { + if (cm.options.lineWrapping) { + addClass(cm.display.wrapper, "CodeMirror-wrap"); + cm.display.sizer.style.minWidth = ""; + cm.display.sizerWidth = null; + } else { + rmClass(cm.display.wrapper, "CodeMirror-wrap"); + findMaxLine(cm); + } + estimateLineHeights(cm); + regChange(cm); + clearCaches(cm); + setTimeout(function(){updateScrollbars(cm);}, 100); + } + + // Returns a function that estimates the height of a line, to use as + // first approximation until the line becomes visible (and is thus + // properly measurable). + function estimateHeight(cm) { + var th = textHeight(cm.display), wrapping = cm.options.lineWrapping; + var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3); + return function(line) { + if (lineIsHidden(cm.doc, line)) return 0; + + var widgetsHeight = 0; + if (line.widgets) for (var i = 0; i < line.widgets.length; i++) { + if (line.widgets[i].height) widgetsHeight += line.widgets[i].height; + } + + if (wrapping) + return widgetsHeight + (Math.ceil(line.text.length / perLine) || 1) * th; + else + return widgetsHeight + th; + }; + } + + function estimateLineHeights(cm) { + var doc = cm.doc, est = estimateHeight(cm); + doc.iter(function(line) { + var estHeight = est(line); + if (estHeight != line.height) updateLineHeight(line, estHeight); + }); + } + + function themeChanged(cm) { + cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") + + cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-"); + clearCaches(cm); + } + + function guttersChanged(cm) { + updateGutters(cm); + regChange(cm); + setTimeout(function(){alignHorizontally(cm);}, 20); + } + + // Rebuild the gutter elements, ensure the margin to the left of the + // code matches their width. + function updateGutters(cm) { + var gutters = cm.display.gutters, specs = cm.options.gutters; + removeChildren(gutters); + for (var i = 0; i < specs.length; ++i) { + var gutterClass = specs[i]; + var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + gutterClass)); + if (gutterClass == "CodeMirror-linenumbers") { + cm.display.lineGutter = gElt; + gElt.style.width = (cm.display.lineNumWidth || 1) + "px"; + } + } + gutters.style.display = i ? "" : "none"; + updateGutterSpace(cm); + } + + function updateGutterSpace(cm) { + var width = cm.display.gutters.offsetWidth; + cm.display.sizer.style.marginLeft = width + "px"; + } + + // Compute the character length of a line, taking into account + // collapsed ranges (see markText) that might hide parts, and join + // other lines onto it. + function lineLength(line) { + if (line.height == 0) return 0; + var len = line.text.length, merged, cur = line; + while (merged = collapsedSpanAtStart(cur)) { + var found = merged.find(0, true); + cur = found.from.line; + len += found.from.ch - found.to.ch; + } + cur = line; + while (merged = collapsedSpanAtEnd(cur)) { + var found = merged.find(0, true); + len -= cur.text.length - found.from.ch; + cur = found.to.line; + len += cur.text.length - found.to.ch; + } + return len; + } + + // Find the longest line in the document. + function findMaxLine(cm) { + var d = cm.display, doc = cm.doc; + d.maxLine = getLine(doc, doc.first); + d.maxLineLength = lineLength(d.maxLine); + d.maxLineChanged = true; + doc.iter(function(line) { + var len = lineLength(line); + if (len > d.maxLineLength) { + d.maxLineLength = len; + d.maxLine = line; + } + }); + } + + // Make sure the gutters options contains the element + // "CodeMirror-linenumbers" when the lineNumbers option is true. + function setGuttersForLineNumbers(options) { + var found = indexOf(options.gutters, "CodeMirror-linenumbers"); + if (found == -1 && options.lineNumbers) { + options.gutters = options.gutters.concat(["CodeMirror-linenumbers"]); + } else if (found > -1 && !options.lineNumbers) { + options.gutters = options.gutters.slice(0); + options.gutters.splice(found, 1); + } + } + + // SCROLLBARS + + // Prepare DOM reads needed to update the scrollbars. Done in one + // shot to minimize update/measure roundtrips. + function measureForScrollbars(cm) { + var d = cm.display, gutterW = d.gutters.offsetWidth; + var docH = Math.round(cm.doc.height + paddingVert(cm.display)); + return { + clientHeight: d.scroller.clientHeight, + viewHeight: d.wrapper.clientHeight, + scrollWidth: d.scroller.scrollWidth, clientWidth: d.scroller.clientWidth, + viewWidth: d.wrapper.clientWidth, + barLeft: cm.options.fixedGutter ? gutterW : 0, + docHeight: docH, + scrollHeight: docH + scrollGap(cm) + d.barHeight, + nativeBarWidth: d.nativeBarWidth, + gutterWidth: gutterW + }; + } + + function NativeScrollbars(place, scroll, cm) { + this.cm = cm; + var vert = this.vert = elt("div", [elt("div", null, null, "min-width: 1px")], "CodeMirror-vscrollbar"); + var horiz = this.horiz = elt("div", [elt("div", null, null, "height: 100%; min-height: 1px")], "CodeMirror-hscrollbar"); + place(vert); place(horiz); + + on(vert, "scroll", function() { + if (vert.clientHeight) scroll(vert.scrollTop, "vertical"); + }); + on(horiz, "scroll", function() { + if (horiz.clientWidth) scroll(horiz.scrollLeft, "horizontal"); + }); + + this.checkedZeroWidth = false; + // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8). + if (ie && ie_version < 8) this.horiz.style.minHeight = this.vert.style.minWidth = "18px"; + } + + NativeScrollbars.prototype = copyObj({ + update: function(measure) { + var needsH = measure.scrollWidth > measure.clientWidth + 1; + var needsV = measure.scrollHeight > measure.clientHeight + 1; + var sWidth = measure.nativeBarWidth; + + if (needsV) { + this.vert.style.display = "block"; + this.vert.style.bottom = needsH ? sWidth + "px" : "0"; + var totalHeight = measure.viewHeight - (needsH ? sWidth : 0); + // A bug in IE8 can cause this value to be negative, so guard it. + this.vert.firstChild.style.height = + Math.max(0, measure.scrollHeight - measure.clientHeight + totalHeight) + "px"; + } else { + this.vert.style.display = ""; + this.vert.firstChild.style.height = "0"; + } + + if (needsH) { + this.horiz.style.display = "block"; + this.horiz.style.right = needsV ? sWidth + "px" : "0"; + this.horiz.style.left = measure.barLeft + "px"; + var totalWidth = measure.viewWidth - measure.barLeft - (needsV ? sWidth : 0); + this.horiz.firstChild.style.width = + (measure.scrollWidth - measure.clientWidth + totalWidth) + "px"; + } else { + this.horiz.style.display = ""; + this.horiz.firstChild.style.width = "0"; + } + + if (!this.checkedZeroWidth && measure.clientHeight > 0) { + if (sWidth == 0) this.zeroWidthHack(); + this.checkedZeroWidth = true; + } + + return {right: needsV ? sWidth : 0, bottom: needsH ? sWidth : 0}; + }, + setScrollLeft: function(pos) { + if (this.horiz.scrollLeft != pos) this.horiz.scrollLeft = pos; + if (this.disableHoriz) this.enableZeroWidthBar(this.horiz, this.disableHoriz); + }, + setScrollTop: function(pos) { + if (this.vert.scrollTop != pos) this.vert.scrollTop = pos; + if (this.disableVert) this.enableZeroWidthBar(this.vert, this.disableVert); + }, + zeroWidthHack: function() { + var w = mac && !mac_geMountainLion ? "12px" : "18px"; + this.horiz.style.height = this.vert.style.width = w; + this.horiz.style.pointerEvents = this.vert.style.pointerEvents = "none"; + this.disableHoriz = new Delayed; + this.disableVert = new Delayed; + }, + enableZeroWidthBar: function(bar, delay) { + bar.style.pointerEvents = "auto"; + function maybeDisable() { + // To find out whether the scrollbar is still visible, we + // check whether the element under the pixel in the bottom + // left corner of the scrollbar box is the scrollbar box + // itself (when the bar is still visible) or its filler child + // (when the bar is hidden). If it is still visible, we keep + // it enabled, if it's hidden, we disable pointer events. + var box = bar.getBoundingClientRect(); + var elt = document.elementFromPoint(box.left + 1, box.bottom - 1); + if (elt != bar) bar.style.pointerEvents = "none"; + else delay.set(1000, maybeDisable); + } + delay.set(1000, maybeDisable); + }, + clear: function() { + var parent = this.horiz.parentNode; + parent.removeChild(this.horiz); + parent.removeChild(this.vert); + } + }, NativeScrollbars.prototype); + + function NullScrollbars() {} + + NullScrollbars.prototype = copyObj({ + update: function() { return {bottom: 0, right: 0}; }, + setScrollLeft: function() {}, + setScrollTop: function() {}, + clear: function() {} + }, NullScrollbars.prototype); + + CodeMirror.scrollbarModel = {"native": NativeScrollbars, "null": NullScrollbars}; + + function initScrollbars(cm) { + if (cm.display.scrollbars) { + cm.display.scrollbars.clear(); + if (cm.display.scrollbars.addClass) + rmClass(cm.display.wrapper, cm.display.scrollbars.addClass); + } + + cm.display.scrollbars = new CodeMirror.scrollbarModel[cm.options.scrollbarStyle](function(node) { + cm.display.wrapper.insertBefore(node, cm.display.scrollbarFiller); + // Prevent clicks in the scrollbars from killing focus + on(node, "mousedown", function() { + if (cm.state.focused) setTimeout(function() { cm.display.input.focus(); }, 0); + }); + node.setAttribute("cm-not-content", "true"); + }, function(pos, axis) { + if (axis == "horizontal") setScrollLeft(cm, pos); + else setScrollTop(cm, pos); + }, cm); + if (cm.display.scrollbars.addClass) + addClass(cm.display.wrapper, cm.display.scrollbars.addClass); + } + + function updateScrollbars(cm, measure) { + if (!measure) measure = measureForScrollbars(cm); + var startWidth = cm.display.barWidth, startHeight = cm.display.barHeight; + updateScrollbarsInner(cm, measure); + for (var i = 0; i < 4 && startWidth != cm.display.barWidth || startHeight != cm.display.barHeight; i++) { + if (startWidth != cm.display.barWidth && cm.options.lineWrapping) + updateHeightsInViewport(cm); + updateScrollbarsInner(cm, measureForScrollbars(cm)); + startWidth = cm.display.barWidth; startHeight = cm.display.barHeight; + } + } + + // Re-synchronize the fake scrollbars with the actual size of the + // content. + function updateScrollbarsInner(cm, measure) { + var d = cm.display; + var sizes = d.scrollbars.update(measure); + + d.sizer.style.paddingRight = (d.barWidth = sizes.right) + "px"; + d.sizer.style.paddingBottom = (d.barHeight = sizes.bottom) + "px"; + d.heightForcer.style.borderBottom = sizes.bottom + "px solid transparent" + + if (sizes.right && sizes.bottom) { + d.scrollbarFiller.style.display = "block"; + d.scrollbarFiller.style.height = sizes.bottom + "px"; + d.scrollbarFiller.style.width = sizes.right + "px"; + } else d.scrollbarFiller.style.display = ""; + if (sizes.bottom && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) { + d.gutterFiller.style.display = "block"; + d.gutterFiller.style.height = sizes.bottom + "px"; + d.gutterFiller.style.width = measure.gutterWidth + "px"; + } else d.gutterFiller.style.display = ""; + } + + // Compute the lines that are visible in a given viewport (defaults + // the the current scroll position). viewport may contain top, + // height, and ensure (see op.scrollToPos) properties. + function visibleLines(display, doc, viewport) { + var top = viewport && viewport.top != null ? Math.max(0, viewport.top) : display.scroller.scrollTop; + top = Math.floor(top - paddingTop(display)); + var bottom = viewport && viewport.bottom != null ? viewport.bottom : top + display.wrapper.clientHeight; + + var from = lineAtHeight(doc, top), to = lineAtHeight(doc, bottom); + // Ensure is a {from: {line, ch}, to: {line, ch}} object, and + // forces those lines into the viewport (if possible). + if (viewport && viewport.ensure) { + var ensureFrom = viewport.ensure.from.line, ensureTo = viewport.ensure.to.line; + if (ensureFrom < from) { + from = ensureFrom; + to = lineAtHeight(doc, heightAtLine(getLine(doc, ensureFrom)) + display.wrapper.clientHeight); + } else if (Math.min(ensureTo, doc.lastLine()) >= to) { + from = lineAtHeight(doc, heightAtLine(getLine(doc, ensureTo)) - display.wrapper.clientHeight); + to = ensureTo; + } + } + return {from: from, to: Math.max(to, from + 1)}; + } + + // LINE NUMBERS + + // Re-align line numbers and gutter marks to compensate for + // horizontal scrolling. + function alignHorizontally(cm) { + var display = cm.display, view = display.view; + if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) return; + var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft; + var gutterW = display.gutters.offsetWidth, left = comp + "px"; + for (var i = 0; i < view.length; i++) if (!view[i].hidden) { + if (cm.options.fixedGutter) { + if (view[i].gutter) + view[i].gutter.style.left = left; + if (view[i].gutterBackground) + view[i].gutterBackground.style.left = left; + } + var align = view[i].alignable; + if (align) for (var j = 0; j < align.length; j++) + align[j].style.left = left; + } + if (cm.options.fixedGutter) + display.gutters.style.left = (comp + gutterW) + "px"; + } + + // Used to ensure that the line number gutter is still the right + // size for the current document size. Returns true when an update + // is needed. + function maybeUpdateLineNumberWidth(cm) { + if (!cm.options.lineNumbers) return false; + var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display; + if (last.length != display.lineNumChars) { + var test = display.measure.appendChild(elt("div", [elt("div", last)], + "CodeMirror-linenumber CodeMirror-gutter-elt")); + var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW; + display.lineGutter.style.width = ""; + display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding) + 1; + display.lineNumWidth = display.lineNumInnerWidth + padding; + display.lineNumChars = display.lineNumInnerWidth ? last.length : -1; + display.lineGutter.style.width = display.lineNumWidth + "px"; + updateGutterSpace(cm); + return true; + } + return false; + } + + function lineNumberFor(options, i) { + return String(options.lineNumberFormatter(i + options.firstLineNumber)); + } + + // Computes display.scroller.scrollLeft + display.gutters.offsetWidth, + // but using getBoundingClientRect to get a sub-pixel-accurate + // result. + function compensateForHScroll(display) { + return display.scroller.getBoundingClientRect().left - display.sizer.getBoundingClientRect().left; + } + + // DISPLAY DRAWING + + function DisplayUpdate(cm, viewport, force) { + var display = cm.display; + + this.viewport = viewport; + // Store some values that we'll need later (but don't want to force a relayout for) + this.visible = visibleLines(display, cm.doc, viewport); + this.editorIsHidden = !display.wrapper.offsetWidth; + this.wrapperHeight = display.wrapper.clientHeight; + this.wrapperWidth = display.wrapper.clientWidth; + this.oldDisplayWidth = displayWidth(cm); + this.force = force; + this.dims = getDimensions(cm); + this.events = []; + } + + DisplayUpdate.prototype.signal = function(emitter, type) { + if (hasHandler(emitter, type)) + this.events.push(arguments); + }; + DisplayUpdate.prototype.finish = function() { + for (var i = 0; i < this.events.length; i++) + signal.apply(null, this.events[i]); + }; + + function maybeClipScrollbars(cm) { + var display = cm.display; + if (!display.scrollbarsClipped && display.scroller.offsetWidth) { + display.nativeBarWidth = display.scroller.offsetWidth - display.scroller.clientWidth; + display.heightForcer.style.height = scrollGap(cm) + "px"; + display.sizer.style.marginBottom = -display.nativeBarWidth + "px"; + display.sizer.style.borderRightWidth = scrollGap(cm) + "px"; + display.scrollbarsClipped = true; + } + } + + // Does the actual updating of the line display. Bails out + // (returning false) when there is nothing to be done and forced is + // false. + function updateDisplayIfNeeded(cm, update) { + var display = cm.display, doc = cm.doc; + + if (update.editorIsHidden) { + resetView(cm); + return false; + } + + // Bail out if the visible area is already rendered and nothing changed. + if (!update.force && + update.visible.from >= display.viewFrom && update.visible.to <= display.viewTo && + (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo) && + display.renderedView == display.view && countDirtyView(cm) == 0) + return false; + + if (maybeUpdateLineNumberWidth(cm)) { + resetView(cm); + update.dims = getDimensions(cm); + } + + // Compute a suitable new viewport (from & to) + var end = doc.first + doc.size; + var from = Math.max(update.visible.from - cm.options.viewportMargin, doc.first); + var to = Math.min(end, update.visible.to + cm.options.viewportMargin); + if (display.viewFrom < from && from - display.viewFrom < 20) from = Math.max(doc.first, display.viewFrom); + if (display.viewTo > to && display.viewTo - to < 20) to = Math.min(end, display.viewTo); + if (sawCollapsedSpans) { + from = visualLineNo(cm.doc, from); + to = visualLineEndNo(cm.doc, to); + } + + var different = from != display.viewFrom || to != display.viewTo || + display.lastWrapHeight != update.wrapperHeight || display.lastWrapWidth != update.wrapperWidth; + adjustView(cm, from, to); + + display.viewOffset = heightAtLine(getLine(cm.doc, display.viewFrom)); + // Position the mover div to align with the current scroll position + cm.display.mover.style.top = display.viewOffset + "px"; + + var toUpdate = countDirtyView(cm); + if (!different && toUpdate == 0 && !update.force && display.renderedView == display.view && + (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo)) + return false; + + // For big changes, we hide the enclosing element during the + // update, since that speeds up the operations on most browsers. + var focused = activeElt(); + if (toUpdate > 4) display.lineDiv.style.display = "none"; + patchDisplay(cm, display.updateLineNumbers, update.dims); + if (toUpdate > 4) display.lineDiv.style.display = ""; + display.renderedView = display.view; + // There might have been a widget with a focused element that got + // hidden or updated, if so re-focus it. + if (focused && activeElt() != focused && focused.offsetHeight) focused.focus(); + + // Prevent selection and cursors from interfering with the scroll + // width and height. + removeChildren(display.cursorDiv); + removeChildren(display.selectionDiv); + display.gutters.style.height = display.sizer.style.minHeight = 0; + + if (different) { + display.lastWrapHeight = update.wrapperHeight; + display.lastWrapWidth = update.wrapperWidth; + startWorker(cm, 400); + } + + display.updateLineNumbers = null; + + return true; + } + + function postUpdateDisplay(cm, update) { + var viewport = update.viewport; + + for (var first = true;; first = false) { + if (!first || !cm.options.lineWrapping || update.oldDisplayWidth == displayWidth(cm)) { + // Clip forced viewport to actual scrollable area. + if (viewport && viewport.top != null) + viewport = {top: Math.min(cm.doc.height + paddingVert(cm.display) - displayHeight(cm), viewport.top)}; + // Updated line heights might result in the drawn area not + // actually covering the viewport. Keep looping until it does. + update.visible = visibleLines(cm.display, cm.doc, viewport); + if (update.visible.from >= cm.display.viewFrom && update.visible.to <= cm.display.viewTo) + break; + } + if (!updateDisplayIfNeeded(cm, update)) break; + updateHeightsInViewport(cm); + var barMeasure = measureForScrollbars(cm); + updateSelection(cm); + updateScrollbars(cm, barMeasure); + setDocumentHeight(cm, barMeasure); + } + + update.signal(cm, "update", cm); + if (cm.display.viewFrom != cm.display.reportedViewFrom || cm.display.viewTo != cm.display.reportedViewTo) { + update.signal(cm, "viewportChange", cm, cm.display.viewFrom, cm.display.viewTo); + cm.display.reportedViewFrom = cm.display.viewFrom; cm.display.reportedViewTo = cm.display.viewTo; + } + } + + function updateDisplaySimple(cm, viewport) { + var update = new DisplayUpdate(cm, viewport); + if (updateDisplayIfNeeded(cm, update)) { + updateHeightsInViewport(cm); + postUpdateDisplay(cm, update); + var barMeasure = measureForScrollbars(cm); + updateSelection(cm); + updateScrollbars(cm, barMeasure); + setDocumentHeight(cm, barMeasure); + update.finish(); + } + } + + function setDocumentHeight(cm, measure) { + cm.display.sizer.style.minHeight = measure.docHeight + "px"; + cm.display.heightForcer.style.top = measure.docHeight + "px"; + cm.display.gutters.style.height = (measure.docHeight + cm.display.barHeight + scrollGap(cm)) + "px"; + } + + // Read the actual heights of the rendered lines, and update their + // stored heights to match. + function updateHeightsInViewport(cm) { + var display = cm.display; + var prevBottom = display.lineDiv.offsetTop; + for (var i = 0; i < display.view.length; i++) { + var cur = display.view[i], height; + if (cur.hidden) continue; + if (ie && ie_version < 8) { + var bot = cur.node.offsetTop + cur.node.offsetHeight; + height = bot - prevBottom; + prevBottom = bot; + } else { + var box = cur.node.getBoundingClientRect(); + height = box.bottom - box.top; + } + var diff = cur.line.height - height; + if (height < 2) height = textHeight(display); + if (diff > .001 || diff < -.001) { + updateLineHeight(cur.line, height); + updateWidgetHeight(cur.line); + if (cur.rest) for (var j = 0; j < cur.rest.length; j++) + updateWidgetHeight(cur.rest[j]); + } + } + } + + // Read and store the height of line widgets associated with the + // given line. + function updateWidgetHeight(line) { + if (line.widgets) for (var i = 0; i < line.widgets.length; ++i) + line.widgets[i].height = line.widgets[i].node.parentNode.offsetHeight; + } + + // Do a bulk-read of the DOM positions and sizes needed to draw the + // view, so that we don't interleave reading and writing to the DOM. + function getDimensions(cm) { + var d = cm.display, left = {}, width = {}; + var gutterLeft = d.gutters.clientLeft; + for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) { + left[cm.options.gutters[i]] = n.offsetLeft + n.clientLeft + gutterLeft; + width[cm.options.gutters[i]] = n.clientWidth; + } + return {fixedPos: compensateForHScroll(d), + gutterTotalWidth: d.gutters.offsetWidth, + gutterLeft: left, + gutterWidth: width, + wrapperWidth: d.wrapper.clientWidth}; + } + + // Sync the actual display DOM structure with display.view, removing + // nodes for lines that are no longer in view, and creating the ones + // that are not there yet, and updating the ones that are out of + // date. + function patchDisplay(cm, updateNumbersFrom, dims) { + var display = cm.display, lineNumbers = cm.options.lineNumbers; + var container = display.lineDiv, cur = container.firstChild; + + function rm(node) { + var next = node.nextSibling; + // Works around a throw-scroll bug in OS X Webkit + if (webkit && mac && cm.display.currentWheelTarget == node) + node.style.display = "none"; + else + node.parentNode.removeChild(node); + return next; + } + + var view = display.view, lineN = display.viewFrom; + // Loop over the elements in the view, syncing cur (the DOM nodes + // in display.lineDiv) with the view as we go. + for (var i = 0; i < view.length; i++) { + var lineView = view[i]; + if (lineView.hidden) { + } else if (!lineView.node || lineView.node.parentNode != container) { // Not drawn yet + var node = buildLineElement(cm, lineView, lineN, dims); + container.insertBefore(node, cur); + } else { // Already drawn + while (cur != lineView.node) cur = rm(cur); + var updateNumber = lineNumbers && updateNumbersFrom != null && + updateNumbersFrom <= lineN && lineView.lineNumber; + if (lineView.changes) { + if (indexOf(lineView.changes, "gutter") > -1) updateNumber = false; + updateLineForChanges(cm, lineView, lineN, dims); + } + if (updateNumber) { + removeChildren(lineView.lineNumber); + lineView.lineNumber.appendChild(document.createTextNode(lineNumberFor(cm.options, lineN))); + } + cur = lineView.node.nextSibling; + } + lineN += lineView.size; + } + while (cur) cur = rm(cur); + } + + // When an aspect of a line changes, a string is added to + // lineView.changes. This updates the relevant part of the line's + // DOM structure. + function updateLineForChanges(cm, lineView, lineN, dims) { + for (var j = 0; j < lineView.changes.length; j++) { + var type = lineView.changes[j]; + if (type == "text") updateLineText(cm, lineView); + else if (type == "gutter") updateLineGutter(cm, lineView, lineN, dims); + else if (type == "class") updateLineClasses(lineView); + else if (type == "widget") updateLineWidgets(cm, lineView, dims); + } + lineView.changes = null; + } + + // Lines with gutter elements, widgets or a background class need to + // be wrapped, and have the extra elements added to the wrapper div + function ensureLineWrapped(lineView) { + if (lineView.node == lineView.text) { + lineView.node = elt("div", null, null, "position: relative"); + if (lineView.text.parentNode) + lineView.text.parentNode.replaceChild(lineView.node, lineView.text); + lineView.node.appendChild(lineView.text); + if (ie && ie_version < 8) lineView.node.style.zIndex = 2; + } + return lineView.node; + } + + function updateLineBackground(lineView) { + var cls = lineView.bgClass ? lineView.bgClass + " " + (lineView.line.bgClass || "") : lineView.line.bgClass; + if (cls) cls += " CodeMirror-linebackground"; + if (lineView.background) { + if (cls) lineView.background.className = cls; + else { lineView.background.parentNode.removeChild(lineView.background); lineView.background = null; } + } else if (cls) { + var wrap = ensureLineWrapped(lineView); + lineView.background = wrap.insertBefore(elt("div", null, cls), wrap.firstChild); + } + } + + // Wrapper around buildLineContent which will reuse the structure + // in display.externalMeasured when possible. + function getLineContent(cm, lineView) { + var ext = cm.display.externalMeasured; + if (ext && ext.line == lineView.line) { + cm.display.externalMeasured = null; + lineView.measure = ext.measure; + return ext.built; + } + return buildLineContent(cm, lineView); + } + + // Redraw the line's text. Interacts with the background and text + // classes because the mode may output tokens that influence these + // classes. + function updateLineText(cm, lineView) { + var cls = lineView.text.className; + var built = getLineContent(cm, lineView); + if (lineView.text == lineView.node) lineView.node = built.pre; + lineView.text.parentNode.replaceChild(built.pre, lineView.text); + lineView.text = built.pre; + if (built.bgClass != lineView.bgClass || built.textClass != lineView.textClass) { + lineView.bgClass = built.bgClass; + lineView.textClass = built.textClass; + updateLineClasses(lineView); + } else if (cls) { + lineView.text.className = cls; + } + } + + function updateLineClasses(lineView) { + updateLineBackground(lineView); + if (lineView.line.wrapClass) + ensureLineWrapped(lineView).className = lineView.line.wrapClass; + else if (lineView.node != lineView.text) + lineView.node.className = ""; + var textClass = lineView.textClass ? lineView.textClass + " " + (lineView.line.textClass || "") : lineView.line.textClass; + lineView.text.className = textClass || ""; + } + + function updateLineGutter(cm, lineView, lineN, dims) { + if (lineView.gutter) { + lineView.node.removeChild(lineView.gutter); + lineView.gutter = null; + } + if (lineView.gutterBackground) { + lineView.node.removeChild(lineView.gutterBackground); + lineView.gutterBackground = null; + } + if (lineView.line.gutterClass) { + var wrap = ensureLineWrapped(lineView); + lineView.gutterBackground = elt("div", null, "CodeMirror-gutter-background " + lineView.line.gutterClass, + "left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + + "px; width: " + dims.gutterTotalWidth + "px"); + wrap.insertBefore(lineView.gutterBackground, lineView.text); + } + var markers = lineView.line.gutterMarkers; + if (cm.options.lineNumbers || markers) { + var wrap = ensureLineWrapped(lineView); + var gutterWrap = lineView.gutter = elt("div", null, "CodeMirror-gutter-wrapper", "left: " + + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px"); + cm.display.input.setUneditable(gutterWrap); + wrap.insertBefore(gutterWrap, lineView.text); + if (lineView.line.gutterClass) + gutterWrap.className += " " + lineView.line.gutterClass; + if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"])) + lineView.lineNumber = gutterWrap.appendChild( + elt("div", lineNumberFor(cm.options, lineN), + "CodeMirror-linenumber CodeMirror-gutter-elt", + "left: " + dims.gutterLeft["CodeMirror-linenumbers"] + "px; width: " + + cm.display.lineNumInnerWidth + "px")); + if (markers) for (var k = 0; k < cm.options.gutters.length; ++k) { + var id = cm.options.gutters[k], found = markers.hasOwnProperty(id) && markers[id]; + if (found) + gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt", "left: " + + dims.gutterLeft[id] + "px; width: " + dims.gutterWidth[id] + "px")); + } + } + } + + function updateLineWidgets(cm, lineView, dims) { + if (lineView.alignable) lineView.alignable = null; + for (var node = lineView.node.firstChild, next; node; node = next) { + var next = node.nextSibling; + if (node.className == "CodeMirror-linewidget") + lineView.node.removeChild(node); + } + insertLineWidgets(cm, lineView, dims); + } + + // Build a line's DOM representation from scratch + function buildLineElement(cm, lineView, lineN, dims) { + var built = getLineContent(cm, lineView); + lineView.text = lineView.node = built.pre; + if (built.bgClass) lineView.bgClass = built.bgClass; + if (built.textClass) lineView.textClass = built.textClass; + + updateLineClasses(lineView); + updateLineGutter(cm, lineView, lineN, dims); + insertLineWidgets(cm, lineView, dims); + return lineView.node; + } + + // A lineView may contain multiple logical lines (when merged by + // collapsed spans). The widgets for all of them need to be drawn. + function insertLineWidgets(cm, lineView, dims) { + insertLineWidgetsFor(cm, lineView.line, lineView, dims, true); + if (lineView.rest) for (var i = 0; i < lineView.rest.length; i++) + insertLineWidgetsFor(cm, lineView.rest[i], lineView, dims, false); + } + + function insertLineWidgetsFor(cm, line, lineView, dims, allowAbove) { + if (!line.widgets) return; + var wrap = ensureLineWrapped(lineView); + for (var i = 0, ws = line.widgets; i < ws.length; ++i) { + var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget"); + if (!widget.handleMouseEvents) node.setAttribute("cm-ignore-events", "true"); + positionLineWidget(widget, node, lineView, dims); + cm.display.input.setUneditable(node); + if (allowAbove && widget.above) + wrap.insertBefore(node, lineView.gutter || lineView.text); + else + wrap.appendChild(node); + signalLater(widget, "redraw"); + } + } + + function positionLineWidget(widget, node, lineView, dims) { + if (widget.noHScroll) { + (lineView.alignable || (lineView.alignable = [])).push(node); + var width = dims.wrapperWidth; + node.style.left = dims.fixedPos + "px"; + if (!widget.coverGutter) { + width -= dims.gutterTotalWidth; + node.style.paddingLeft = dims.gutterTotalWidth + "px"; + } + node.style.width = width + "px"; + } + if (widget.coverGutter) { + node.style.zIndex = 5; + node.style.position = "relative"; + if (!widget.noHScroll) node.style.marginLeft = -dims.gutterTotalWidth + "px"; + } + } + + // POSITION OBJECT + + // A Pos instance represents a position within the text. + var Pos = CodeMirror.Pos = function(line, ch) { + if (!(this instanceof Pos)) return new Pos(line, ch); + this.line = line; this.ch = ch; + }; + + // Compare two positions, return 0 if they are the same, a negative + // number when a is less, and a positive number otherwise. + var cmp = CodeMirror.cmpPos = function(a, b) { return a.line - b.line || a.ch - b.ch; }; + + function copyPos(x) {return Pos(x.line, x.ch);} + function maxPos(a, b) { return cmp(a, b) < 0 ? b : a; } + function minPos(a, b) { return cmp(a, b) < 0 ? a : b; } + + // INPUT HANDLING + + function ensureFocus(cm) { + if (!cm.state.focused) { cm.display.input.focus(); onFocus(cm); } + } + + // This will be set to a {lineWise: bool, text: [string]} object, so + // that, when pasting, we know what kind of selections the copied + // text was made out of. + var lastCopied = null; + + function applyTextInput(cm, inserted, deleted, sel, origin) { + var doc = cm.doc; + cm.display.shift = false; + if (!sel) sel = doc.sel; + + var paste = cm.state.pasteIncoming || origin == "paste"; + var textLines = doc.splitLines(inserted), multiPaste = null + // When pasing N lines into N selections, insert one line per selection + if (paste && sel.ranges.length > 1) { + if (lastCopied && lastCopied.text.join("\n") == inserted) { + if (sel.ranges.length % lastCopied.text.length == 0) { + multiPaste = []; + for (var i = 0; i < lastCopied.text.length; i++) + multiPaste.push(doc.splitLines(lastCopied.text[i])); + } + } else if (textLines.length == sel.ranges.length) { + multiPaste = map(textLines, function(l) { return [l]; }); + } + } + + // Normal behavior is to insert the new text into every selection + for (var i = sel.ranges.length - 1; i >= 0; i--) { + var range = sel.ranges[i]; + var from = range.from(), to = range.to(); + if (range.empty()) { + if (deleted && deleted > 0) // Handle deletion + from = Pos(from.line, from.ch - deleted); + else if (cm.state.overwrite && !paste) // Handle overwrite + to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + lst(textLines).length)); + else if (lastCopied && lastCopied.lineWise && lastCopied.text.join("\n") == inserted) + from = to = Pos(from.line, 0) + } + var updateInput = cm.curOp.updateInput; + var changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i % multiPaste.length] : textLines, + origin: origin || (paste ? "paste" : cm.state.cutIncoming ? "cut" : "+input")}; + makeChange(cm.doc, changeEvent); + signalLater(cm, "inputRead", cm, changeEvent); + } + if (inserted && !paste) + triggerElectric(cm, inserted); + + ensureCursorVisible(cm); + cm.curOp.updateInput = updateInput; + cm.curOp.typing = true; + cm.state.pasteIncoming = cm.state.cutIncoming = false; + } + + function handlePaste(e, cm) { + var pasted = e.clipboardData && e.clipboardData.getData("Text"); + if (pasted) { + e.preventDefault(); + if (!cm.isReadOnly() && !cm.options.disableInput) + runInOp(cm, function() { applyTextInput(cm, pasted, 0, null, "paste"); }); + return true; + } + } + + function triggerElectric(cm, inserted) { + // When an 'electric' character is inserted, immediately trigger a reindent + if (!cm.options.electricChars || !cm.options.smartIndent) return; + var sel = cm.doc.sel; + + for (var i = sel.ranges.length - 1; i >= 0; i--) { + var range = sel.ranges[i]; + if (range.head.ch > 100 || (i && sel.ranges[i - 1].head.line == range.head.line)) continue; + var mode = cm.getModeAt(range.head); + var indented = false; + if (mode.electricChars) { + for (var j = 0; j < mode.electricChars.length; j++) + if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) { + indented = indentLine(cm, range.head.line, "smart"); + break; + } + } else if (mode.electricInput) { + if (mode.electricInput.test(getLine(cm.doc, range.head.line).text.slice(0, range.head.ch))) + indented = indentLine(cm, range.head.line, "smart"); + } + if (indented) signalLater(cm, "electricInput", cm, range.head.line); + } + } + + function copyableRanges(cm) { + var text = [], ranges = []; + for (var i = 0; i < cm.doc.sel.ranges.length; i++) { + var line = cm.doc.sel.ranges[i].head.line; + var lineRange = {anchor: Pos(line, 0), head: Pos(line + 1, 0)}; + ranges.push(lineRange); + text.push(cm.getRange(lineRange.anchor, lineRange.head)); + } + return {text: text, ranges: ranges}; + } + + function disableBrowserMagic(field, spellcheck) { + field.setAttribute("autocorrect", "off"); + field.setAttribute("autocapitalize", "off"); + field.setAttribute("spellcheck", !!spellcheck); + } + + // TEXTAREA INPUT STYLE + + function TextareaInput(cm) { + this.cm = cm; + // See input.poll and input.reset + this.prevInput = ""; + + // Flag that indicates whether we expect input to appear real soon + // now (after some event like 'keypress' or 'input') and are + // polling intensively. + this.pollingFast = false; + // Self-resetting timeout for the poller + this.polling = new Delayed(); + // Tracks when input.reset has punted to just putting a short + // string into the textarea instead of the full selection. + this.inaccurateSelection = false; + // Used to work around IE issue with selection being forgotten when focus moves away from textarea + this.hasSelection = false; + this.composing = null; + }; + + function hiddenTextarea() { + var te = elt("textarea", null, null, "position: absolute; bottom: -1em; padding: 0; width: 1px; height: 1em; outline: none"); + var div = elt("div", [te], null, "overflow: hidden; position: relative; width: 3px; height: 0px;"); + // The textarea is kept positioned near the cursor to prevent the + // fact that it'll be scrolled into view on input from scrolling + // our fake cursor out of view. On webkit, when wrap=off, paste is + // very slow. So make the area wide instead. + if (webkit) te.style.width = "1000px"; + else te.setAttribute("wrap", "off"); + // If border: 0; -- iOS fails to open keyboard (issue #1287) + if (ios) te.style.border = "1px solid black"; + disableBrowserMagic(te); + return div; + } + + TextareaInput.prototype = copyObj({ + init: function(display) { + var input = this, cm = this.cm; + + // Wraps and hides input textarea + var div = this.wrapper = hiddenTextarea(); + // The semihidden textarea that is focused when the editor is + // focused, and receives input. + var te = this.textarea = div.firstChild; + display.wrapper.insertBefore(div, display.wrapper.firstChild); + + // Needed to hide big blue blinking cursor on Mobile Safari (doesn't seem to work in iOS 8 anymore) + if (ios) te.style.width = "0px"; + + on(te, "input", function() { + if (ie && ie_version >= 9 && input.hasSelection) input.hasSelection = null; + input.poll(); + }); + + on(te, "paste", function(e) { + if (signalDOMEvent(cm, e) || handlePaste(e, cm)) return + + cm.state.pasteIncoming = true; + input.fastPoll(); + }); + + function prepareCopyCut(e) { + if (signalDOMEvent(cm, e)) return + if (cm.somethingSelected()) { + lastCopied = {lineWise: false, text: cm.getSelections()}; + if (input.inaccurateSelection) { + input.prevInput = ""; + input.inaccurateSelection = false; + te.value = lastCopied.text.join("\n"); + selectInput(te); + } + } else if (!cm.options.lineWiseCopyCut) { + return; + } else { + var ranges = copyableRanges(cm); + lastCopied = {lineWise: true, text: ranges.text}; + if (e.type == "cut") { + cm.setSelections(ranges.ranges, null, sel_dontScroll); + } else { + input.prevInput = ""; + te.value = ranges.text.join("\n"); + selectInput(te); + } + } + if (e.type == "cut") cm.state.cutIncoming = true; + } + on(te, "cut", prepareCopyCut); + on(te, "copy", prepareCopyCut); + + on(display.scroller, "paste", function(e) { + if (eventInWidget(display, e) || signalDOMEvent(cm, e)) return; + cm.state.pasteIncoming = true; + input.focus(); + }); + + // Prevent normal selection in the editor (we handle our own) + on(display.lineSpace, "selectstart", function(e) { + if (!eventInWidget(display, e)) e_preventDefault(e); + }); + + on(te, "compositionstart", function() { + var start = cm.getCursor("from"); + if (input.composing) input.composing.range.clear() + input.composing = { + start: start, + range: cm.markText(start, cm.getCursor("to"), {className: "CodeMirror-composing"}) + }; + }); + on(te, "compositionend", function() { + if (input.composing) { + input.poll(); + input.composing.range.clear(); + input.composing = null; + } + }); + }, + + prepareSelection: function() { + // Redraw the selection and/or cursor + var cm = this.cm, display = cm.display, doc = cm.doc; + var result = prepareSelection(cm); + + // Move the hidden textarea near the cursor to prevent scrolling artifacts + if (cm.options.moveInputWithCursor) { + var headPos = cursorCoords(cm, doc.sel.primary().head, "div"); + var wrapOff = display.wrapper.getBoundingClientRect(), lineOff = display.lineDiv.getBoundingClientRect(); + result.teTop = Math.max(0, Math.min(display.wrapper.clientHeight - 10, + headPos.top + lineOff.top - wrapOff.top)); + result.teLeft = Math.max(0, Math.min(display.wrapper.clientWidth - 10, + headPos.left + lineOff.left - wrapOff.left)); + } + + return result; + }, + + showSelection: function(drawn) { + var cm = this.cm, display = cm.display; + removeChildrenAndAdd(display.cursorDiv, drawn.cursors); + removeChildrenAndAdd(display.selectionDiv, drawn.selection); + if (drawn.teTop != null) { + this.wrapper.style.top = drawn.teTop + "px"; + this.wrapper.style.left = drawn.teLeft + "px"; + } + }, + + // Reset the input to correspond to the selection (or to be empty, + // when not typing and nothing is selected) + reset: function(typing) { + if (this.contextMenuPending) return; + var minimal, selected, cm = this.cm, doc = cm.doc; + if (cm.somethingSelected()) { + this.prevInput = ""; + var range = doc.sel.primary(); + minimal = hasCopyEvent && + (range.to().line - range.from().line > 100 || (selected = cm.getSelection()).length > 1000); + var content = minimal ? "-" : selected || cm.getSelection(); + this.textarea.value = content; + if (cm.state.focused) selectInput(this.textarea); + if (ie && ie_version >= 9) this.hasSelection = content; + } else if (!typing) { + this.prevInput = this.textarea.value = ""; + if (ie && ie_version >= 9) this.hasSelection = null; + } + this.inaccurateSelection = minimal; + }, + + getField: function() { return this.textarea; }, + + supportsTouch: function() { return false; }, + + focus: function() { + if (this.cm.options.readOnly != "nocursor" && (!mobile || activeElt() != this.textarea)) { + try { this.textarea.focus(); } + catch (e) {} // IE8 will throw if the textarea is display: none or not in DOM + } + }, + + blur: function() { this.textarea.blur(); }, + + resetPosition: function() { + this.wrapper.style.top = this.wrapper.style.left = 0; + }, + + receivedFocus: function() { this.slowPoll(); }, + + // Poll for input changes, using the normal rate of polling. This + // runs as long as the editor is focused. + slowPoll: function() { + var input = this; + if (input.pollingFast) return; + input.polling.set(this.cm.options.pollInterval, function() { + input.poll(); + if (input.cm.state.focused) input.slowPoll(); + }); + }, + + // When an event has just come in that is likely to add or change + // something in the input textarea, we poll faster, to ensure that + // the change appears on the screen quickly. + fastPoll: function() { + var missed = false, input = this; + input.pollingFast = true; + function p() { + var changed = input.poll(); + if (!changed && !missed) {missed = true; input.polling.set(60, p);} + else {input.pollingFast = false; input.slowPoll();} + } + input.polling.set(20, p); + }, + + // Read input from the textarea, and update the document to match. + // When something is selected, it is present in the textarea, and + // selected (unless it is huge, in which case a placeholder is + // used). When nothing is selected, the cursor sits after previously + // seen text (can be empty), which is stored in prevInput (we must + // not reset the textarea when typing, because that breaks IME). + poll: function() { + var cm = this.cm, input = this.textarea, prevInput = this.prevInput; + // Since this is called a *lot*, try to bail out as cheaply as + // possible when it is clear that nothing happened. hasSelection + // will be the case when there is a lot of text in the textarea, + // in which case reading its value would be expensive. + if (this.contextMenuPending || !cm.state.focused || + (hasSelection(input) && !prevInput && !this.composing) || + cm.isReadOnly() || cm.options.disableInput || cm.state.keySeq) + return false; + + var text = input.value; + // If nothing changed, bail. + if (text == prevInput && !cm.somethingSelected()) return false; + // Work around nonsensical selection resetting in IE9/10, and + // inexplicable appearance of private area unicode characters on + // some key combos in Mac (#2689). + if (ie && ie_version >= 9 && this.hasSelection === text || + mac && /[\uf700-\uf7ff]/.test(text)) { + cm.display.input.reset(); + return false; + } + + if (cm.doc.sel == cm.display.selForContextMenu) { + var first = text.charCodeAt(0); + if (first == 0x200b && !prevInput) prevInput = "\u200b"; + if (first == 0x21da) { this.reset(); return this.cm.execCommand("undo"); } + } + // Find the part of the input that is actually new + var same = 0, l = Math.min(prevInput.length, text.length); + while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) ++same; + + var self = this; + runInOp(cm, function() { + applyTextInput(cm, text.slice(same), prevInput.length - same, + null, self.composing ? "*compose" : null); + + // Don't leave long text in the textarea, since it makes further polling slow + if (text.length > 1000 || text.indexOf("\n") > -1) input.value = self.prevInput = ""; + else self.prevInput = text; + + if (self.composing) { + self.composing.range.clear(); + self.composing.range = cm.markText(self.composing.start, cm.getCursor("to"), + {className: "CodeMirror-composing"}); + } + }); + return true; + }, + + ensurePolled: function() { + if (this.pollingFast && this.poll()) this.pollingFast = false; + }, + + onKeyPress: function() { + if (ie && ie_version >= 9) this.hasSelection = null; + this.fastPoll(); + }, + + onContextMenu: function(e) { + var input = this, cm = input.cm, display = cm.display, te = input.textarea; + var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop; + if (!pos || presto) return; // Opera is difficult. + + // Reset the current text selection only if the click is done outside of the selection + // and 'resetSelectionOnContextMenu' option is true. + var reset = cm.options.resetSelectionOnContextMenu; + if (reset && cm.doc.sel.contains(pos) == -1) + operation(cm, setSelection)(cm.doc, simpleSelection(pos), sel_dontScroll); + + var oldCSS = te.style.cssText, oldWrapperCSS = input.wrapper.style.cssText; + input.wrapper.style.cssText = "position: absolute" + var wrapperBox = input.wrapper.getBoundingClientRect() + te.style.cssText = "position: absolute; width: 30px; height: 30px; top: " + (e.clientY - wrapperBox.top - 5) + + "px; left: " + (e.clientX - wrapperBox.left - 5) + "px; z-index: 1000; background: " + + (ie ? "rgba(255, 255, 255, .05)" : "transparent") + + "; outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);"; + if (webkit) var oldScrollY = window.scrollY; // Work around Chrome issue (#2712) + display.input.focus(); + if (webkit) window.scrollTo(null, oldScrollY); + display.input.reset(); + // Adds "Select all" to context menu in FF + if (!cm.somethingSelected()) te.value = input.prevInput = " "; + input.contextMenuPending = true; + display.selForContextMenu = cm.doc.sel; + clearTimeout(display.detectingSelectAll); + + // Select-all will be greyed out if there's nothing to select, so + // this adds a zero-width space so that we can later check whether + // it got selected. + function prepareSelectAllHack() { + if (te.selectionStart != null) { + var selected = cm.somethingSelected(); + var extval = "\u200b" + (selected ? te.value : ""); + te.value = "\u21da"; // Used to catch context-menu undo + te.value = extval; + input.prevInput = selected ? "" : "\u200b"; + te.selectionStart = 1; te.selectionEnd = extval.length; + // Re-set this, in case some other handler touched the + // selection in the meantime. + display.selForContextMenu = cm.doc.sel; + } + } + function rehide() { + input.contextMenuPending = false; + input.wrapper.style.cssText = oldWrapperCSS + te.style.cssText = oldCSS; + if (ie && ie_version < 9) display.scrollbars.setScrollTop(display.scroller.scrollTop = scrollPos); + + // Try to detect the user choosing select-all + if (te.selectionStart != null) { + if (!ie || (ie && ie_version < 9)) prepareSelectAllHack(); + var i = 0, poll = function() { + if (display.selForContextMenu == cm.doc.sel && te.selectionStart == 0 && + te.selectionEnd > 0 && input.prevInput == "\u200b") + operation(cm, commands.selectAll)(cm); + else if (i++ < 10) display.detectingSelectAll = setTimeout(poll, 500); + else display.input.reset(); + }; + display.detectingSelectAll = setTimeout(poll, 200); + } + } + + if (ie && ie_version >= 9) prepareSelectAllHack(); + if (captureRightClick) { + e_stop(e); + var mouseup = function() { + off(window, "mouseup", mouseup); + setTimeout(rehide, 20); + }; + on(window, "mouseup", mouseup); + } else { + setTimeout(rehide, 50); + } + }, + + readOnlyChanged: function(val) { + if (!val) this.reset(); + }, + + setUneditable: nothing, + + needsContentAttribute: false + }, TextareaInput.prototype); + + // CONTENTEDITABLE INPUT STYLE + + function ContentEditableInput(cm) { + this.cm = cm; + this.lastAnchorNode = this.lastAnchorOffset = this.lastFocusNode = this.lastFocusOffset = null; + this.polling = new Delayed(); + this.gracePeriod = false; + } + + ContentEditableInput.prototype = copyObj({ + init: function(display) { + var input = this, cm = input.cm; + var div = input.div = display.lineDiv; + disableBrowserMagic(div, cm.options.spellcheck); + + on(div, "paste", function(e) { + if (signalDOMEvent(cm, e) || handlePaste(e, cm)) return + // IE doesn't fire input events, so we schedule a read for the pasted content in this way + if (ie_version <= 11) setTimeout(operation(cm, function() { + if (!input.pollContent()) regChange(cm); + }), 20) + }) + + on(div, "compositionstart", function(e) { + var data = e.data; + input.composing = {sel: cm.doc.sel, data: data, startData: data}; + if (!data) return; + var prim = cm.doc.sel.primary(); + var line = cm.getLine(prim.head.line); + var found = line.indexOf(data, Math.max(0, prim.head.ch - data.length)); + if (found > -1 && found <= prim.head.ch) + input.composing.sel = simpleSelection(Pos(prim.head.line, found), + Pos(prim.head.line, found + data.length)); + }); + on(div, "compositionupdate", function(e) { + input.composing.data = e.data; + }); + on(div, "compositionend", function(e) { + var ours = input.composing; + if (!ours) return; + if (e.data != ours.startData && !/\u200b/.test(e.data)) + ours.data = e.data; + // Need a small delay to prevent other code (input event, + // selection polling) from doing damage when fired right after + // compositionend. + setTimeout(function() { + if (!ours.handled) + input.applyComposition(ours); + if (input.composing == ours) + input.composing = null; + }, 50); + }); + + on(div, "touchstart", function() { + input.forceCompositionEnd(); + }); + + on(div, "input", function() { + if (input.composing) return; + if (cm.isReadOnly() || !input.pollContent()) + runInOp(input.cm, function() {regChange(cm);}); + }); + + function onCopyCut(e) { + if (signalDOMEvent(cm, e)) return + if (cm.somethingSelected()) { + lastCopied = {lineWise: false, text: cm.getSelections()}; + if (e.type == "cut") cm.replaceSelection("", null, "cut"); + } else if (!cm.options.lineWiseCopyCut) { + return; + } else { + var ranges = copyableRanges(cm); + lastCopied = {lineWise: true, text: ranges.text}; + if (e.type == "cut") { + cm.operation(function() { + cm.setSelections(ranges.ranges, 0, sel_dontScroll); + cm.replaceSelection("", null, "cut"); + }); + } + } + if (e.clipboardData) { + e.clipboardData.clearData(); + var content = lastCopied.text.join("\n") + // iOS exposes the clipboard API, but seems to discard content inserted into it + e.clipboardData.setData("Text", content); + if (e.clipboardData.getData("Text") == content) { + e.preventDefault(); + return + } + } + // Old-fashioned briefly-focus-a-textarea hack + var kludge = hiddenTextarea(), te = kludge.firstChild; + cm.display.lineSpace.insertBefore(kludge, cm.display.lineSpace.firstChild); + te.value = lastCopied.text.join("\n"); + var hadFocus = document.activeElement; + selectInput(te); + setTimeout(function() { + cm.display.lineSpace.removeChild(kludge); + hadFocus.focus(); + if (hadFocus == div) input.showPrimarySelection() + }, 50); + } + on(div, "copy", onCopyCut); + on(div, "cut", onCopyCut); + }, + + prepareSelection: function() { + var result = prepareSelection(this.cm, false); + result.focus = this.cm.state.focused; + return result; + }, + + showSelection: function(info, takeFocus) { + if (!info || !this.cm.display.view.length) return; + if (info.focus || takeFocus) this.showPrimarySelection(); + this.showMultipleSelections(info); + }, + + showPrimarySelection: function() { + var sel = window.getSelection(), prim = this.cm.doc.sel.primary(); + var curAnchor = domToPos(this.cm, sel.anchorNode, sel.anchorOffset); + var curFocus = domToPos(this.cm, sel.focusNode, sel.focusOffset); + if (curAnchor && !curAnchor.bad && curFocus && !curFocus.bad && + cmp(minPos(curAnchor, curFocus), prim.from()) == 0 && + cmp(maxPos(curAnchor, curFocus), prim.to()) == 0) + return; + + var start = posToDOM(this.cm, prim.from()); + var end = posToDOM(this.cm, prim.to()); + if (!start && !end) return; + + var view = this.cm.display.view; + var old = sel.rangeCount && sel.getRangeAt(0); + if (!start) { + start = {node: view[0].measure.map[2], offset: 0}; + } else if (!end) { // FIXME dangerously hacky + var measure = view[view.length - 1].measure; + var map = measure.maps ? measure.maps[measure.maps.length - 1] : measure.map; + end = {node: map[map.length - 1], offset: map[map.length - 2] - map[map.length - 3]}; + } + + try { var rng = range(start.node, start.offset, end.offset, end.node); } + catch(e) {} // Our model of the DOM might be outdated, in which case the range we try to set can be impossible + if (rng) { + if (!gecko && this.cm.state.focused) { + sel.collapse(start.node, start.offset); + if (!rng.collapsed) sel.addRange(rng); + } else { + sel.removeAllRanges(); + sel.addRange(rng); + } + if (old && sel.anchorNode == null) sel.addRange(old); + else if (gecko) this.startGracePeriod(); + } + this.rememberSelection(); + }, + + startGracePeriod: function() { + var input = this; + clearTimeout(this.gracePeriod); + this.gracePeriod = setTimeout(function() { + input.gracePeriod = false; + if (input.selectionChanged()) + input.cm.operation(function() { input.cm.curOp.selectionChanged = true; }); + }, 20); + }, + + showMultipleSelections: function(info) { + removeChildrenAndAdd(this.cm.display.cursorDiv, info.cursors); + removeChildrenAndAdd(this.cm.display.selectionDiv, info.selection); + }, + + rememberSelection: function() { + var sel = window.getSelection(); + this.lastAnchorNode = sel.anchorNode; this.lastAnchorOffset = sel.anchorOffset; + this.lastFocusNode = sel.focusNode; this.lastFocusOffset = sel.focusOffset; + }, + + selectionInEditor: function() { + var sel = window.getSelection(); + if (!sel.rangeCount) return false; + var node = sel.getRangeAt(0).commonAncestorContainer; + return contains(this.div, node); + }, + + focus: function() { + if (this.cm.options.readOnly != "nocursor") this.div.focus(); + }, + blur: function() { this.div.blur(); }, + getField: function() { return this.div; }, + + supportsTouch: function() { return true; }, + + receivedFocus: function() { + var input = this; + if (this.selectionInEditor()) + this.pollSelection(); + else + runInOp(this.cm, function() { input.cm.curOp.selectionChanged = true; }); + + function poll() { + if (input.cm.state.focused) { + input.pollSelection(); + input.polling.set(input.cm.options.pollInterval, poll); + } + } + this.polling.set(this.cm.options.pollInterval, poll); + }, + + selectionChanged: function() { + var sel = window.getSelection(); + return sel.anchorNode != this.lastAnchorNode || sel.anchorOffset != this.lastAnchorOffset || + sel.focusNode != this.lastFocusNode || sel.focusOffset != this.lastFocusOffset; + }, + + pollSelection: function() { + if (!this.composing && !this.gracePeriod && this.selectionChanged()) { + var sel = window.getSelection(), cm = this.cm; + this.rememberSelection(); + var anchor = domToPos(cm, sel.anchorNode, sel.anchorOffset); + var head = domToPos(cm, sel.focusNode, sel.focusOffset); + if (anchor && head) runInOp(cm, function() { + setSelection(cm.doc, simpleSelection(anchor, head), sel_dontScroll); + if (anchor.bad || head.bad) cm.curOp.selectionChanged = true; + }); + } + }, + + pollContent: function() { + var cm = this.cm, display = cm.display, sel = cm.doc.sel.primary(); + var from = sel.from(), to = sel.to(); + if (from.line < display.viewFrom || to.line > display.viewTo - 1) return false; + + var fromIndex; + if (from.line == display.viewFrom || (fromIndex = findViewIndex(cm, from.line)) == 0) { + var fromLine = lineNo(display.view[0].line); + var fromNode = display.view[0].node; + } else { + var fromLine = lineNo(display.view[fromIndex].line); + var fromNode = display.view[fromIndex - 1].node.nextSibling; + } + var toIndex = findViewIndex(cm, to.line); + if (toIndex == display.view.length - 1) { + var toLine = display.viewTo - 1; + var toNode = display.lineDiv.lastChild; + } else { + var toLine = lineNo(display.view[toIndex + 1].line) - 1; + var toNode = display.view[toIndex + 1].node.previousSibling; + } + + var newText = cm.doc.splitLines(domTextBetween(cm, fromNode, toNode, fromLine, toLine)); + var oldText = getBetween(cm.doc, Pos(fromLine, 0), Pos(toLine, getLine(cm.doc, toLine).text.length)); + while (newText.length > 1 && oldText.length > 1) { + if (lst(newText) == lst(oldText)) { newText.pop(); oldText.pop(); toLine--; } + else if (newText[0] == oldText[0]) { newText.shift(); oldText.shift(); fromLine++; } + else break; + } + + var cutFront = 0, cutEnd = 0; + var newTop = newText[0], oldTop = oldText[0], maxCutFront = Math.min(newTop.length, oldTop.length); + while (cutFront < maxCutFront && newTop.charCodeAt(cutFront) == oldTop.charCodeAt(cutFront)) + ++cutFront; + var newBot = lst(newText), oldBot = lst(oldText); + var maxCutEnd = Math.min(newBot.length - (newText.length == 1 ? cutFront : 0), + oldBot.length - (oldText.length == 1 ? cutFront : 0)); + while (cutEnd < maxCutEnd && + newBot.charCodeAt(newBot.length - cutEnd - 1) == oldBot.charCodeAt(oldBot.length - cutEnd - 1)) + ++cutEnd; + + newText[newText.length - 1] = newBot.slice(0, newBot.length - cutEnd); + newText[0] = newText[0].slice(cutFront); + + var chFrom = Pos(fromLine, cutFront); + var chTo = Pos(toLine, oldText.length ? lst(oldText).length - cutEnd : 0); + if (newText.length > 1 || newText[0] || cmp(chFrom, chTo)) { + replaceRange(cm.doc, newText, chFrom, chTo, "+input"); + return true; + } + }, + + ensurePolled: function() { + this.forceCompositionEnd(); + }, + reset: function() { + this.forceCompositionEnd(); + }, + forceCompositionEnd: function() { + if (!this.composing || this.composing.handled) return; + this.applyComposition(this.composing); + this.composing.handled = true; + this.div.blur(); + this.div.focus(); + }, + applyComposition: function(composing) { + if (this.cm.isReadOnly()) + operation(this.cm, regChange)(this.cm) + else if (composing.data && composing.data != composing.startData) + operation(this.cm, applyTextInput)(this.cm, composing.data, 0, composing.sel); + }, + + setUneditable: function(node) { + node.contentEditable = "false" + }, + + onKeyPress: function(e) { + e.preventDefault(); + if (!this.cm.isReadOnly()) + operation(this.cm, applyTextInput)(this.cm, String.fromCharCode(e.charCode == null ? e.keyCode : e.charCode), 0); + }, + + readOnlyChanged: function(val) { + this.div.contentEditable = String(val != "nocursor") + }, + + onContextMenu: nothing, + resetPosition: nothing, + + needsContentAttribute: true + }, ContentEditableInput.prototype); + + function posToDOM(cm, pos) { + var view = findViewForLine(cm, pos.line); + if (!view || view.hidden) return null; + var line = getLine(cm.doc, pos.line); + var info = mapFromLineView(view, line, pos.line); + + var order = getOrder(line), side = "left"; + if (order) { + var partPos = getBidiPartAt(order, pos.ch); + side = partPos % 2 ? "right" : "left"; + } + var result = nodeAndOffsetInLineMap(info.map, pos.ch, side); + result.offset = result.collapse == "right" ? result.end : result.start; + return result; + } + + function badPos(pos, bad) { if (bad) pos.bad = true; return pos; } + + function domToPos(cm, node, offset) { + var lineNode; + if (node == cm.display.lineDiv) { + lineNode = cm.display.lineDiv.childNodes[offset]; + if (!lineNode) return badPos(cm.clipPos(Pos(cm.display.viewTo - 1)), true); + node = null; offset = 0; + } else { + for (lineNode = node;; lineNode = lineNode.parentNode) { + if (!lineNode || lineNode == cm.display.lineDiv) return null; + if (lineNode.parentNode && lineNode.parentNode == cm.display.lineDiv) break; + } + } + for (var i = 0; i < cm.display.view.length; i++) { + var lineView = cm.display.view[i]; + if (lineView.node == lineNode) + return locateNodeInLineView(lineView, node, offset); + } + } + + function locateNodeInLineView(lineView, node, offset) { + var wrapper = lineView.text.firstChild, bad = false; + if (!node || !contains(wrapper, node)) return badPos(Pos(lineNo(lineView.line), 0), true); + if (node == wrapper) { + bad = true; + node = wrapper.childNodes[offset]; + offset = 0; + if (!node) { + var line = lineView.rest ? lst(lineView.rest) : lineView.line; + return badPos(Pos(lineNo(line), line.text.length), bad); + } + } + + var textNode = node.nodeType == 3 ? node : null, topNode = node; + if (!textNode && node.childNodes.length == 1 && node.firstChild.nodeType == 3) { + textNode = node.firstChild; + if (offset) offset = textNode.nodeValue.length; + } + while (topNode.parentNode != wrapper) topNode = topNode.parentNode; + var measure = lineView.measure, maps = measure.maps; + + function find(textNode, topNode, offset) { + for (var i = -1; i < (maps ? maps.length : 0); i++) { + var map = i < 0 ? measure.map : maps[i]; + for (var j = 0; j < map.length; j += 3) { + var curNode = map[j + 2]; + if (curNode == textNode || curNode == topNode) { + var line = lineNo(i < 0 ? lineView.line : lineView.rest[i]); + var ch = map[j] + offset; + if (offset < 0 || curNode != textNode) ch = map[j + (offset ? 1 : 0)]; + return Pos(line, ch); + } + } + } + } + var found = find(textNode, topNode, offset); + if (found) return badPos(found, bad); + + // FIXME this is all really shaky. might handle the few cases it needs to handle, but likely to cause problems + for (var after = topNode.nextSibling, dist = textNode ? textNode.nodeValue.length - offset : 0; after; after = after.nextSibling) { + found = find(after, after.firstChild, 0); + if (found) + return badPos(Pos(found.line, found.ch - dist), bad); + else + dist += after.textContent.length; + } + for (var before = topNode.previousSibling, dist = offset; before; before = before.previousSibling) { + found = find(before, before.firstChild, -1); + if (found) + return badPos(Pos(found.line, found.ch + dist), bad); + else + dist += before.textContent.length; + } + } + + function domTextBetween(cm, from, to, fromLine, toLine) { + var text = "", closing = false, lineSep = cm.doc.lineSeparator(); + function recognizeMarker(id) { return function(marker) { return marker.id == id; }; } + function walk(node) { + if (node.nodeType == 1) { + var cmText = node.getAttribute("cm-text"); + if (cmText != null) { + if (cmText == "") cmText = node.textContent.replace(/\u200b/g, ""); + text += cmText; + return; + } + var markerID = node.getAttribute("cm-marker"), range; + if (markerID) { + var found = cm.findMarks(Pos(fromLine, 0), Pos(toLine + 1, 0), recognizeMarker(+markerID)); + if (found.length && (range = found[0].find())) + text += getBetween(cm.doc, range.from, range.to).join(lineSep); + return; + } + if (node.getAttribute("contenteditable") == "false") return; + for (var i = 0; i < node.childNodes.length; i++) + walk(node.childNodes[i]); + if (/^(pre|div|p)$/i.test(node.nodeName)) + closing = true; + } else if (node.nodeType == 3) { + var val = node.nodeValue; + if (!val) return; + if (closing) { + text += lineSep; + closing = false; + } + text += val; + } + } + for (;;) { + walk(from); + if (from == to) break; + from = from.nextSibling; + } + return text; + } + + CodeMirror.inputStyles = {"textarea": TextareaInput, "contenteditable": ContentEditableInput}; + + // SELECTION / CURSOR + + // Selection objects are immutable. A new one is created every time + // the selection changes. A selection is one or more non-overlapping + // (and non-touching) ranges, sorted, and an integer that indicates + // which one is the primary selection (the one that's scrolled into + // view, that getCursor returns, etc). + function Selection(ranges, primIndex) { + this.ranges = ranges; + this.primIndex = primIndex; + } + + Selection.prototype = { + primary: function() { return this.ranges[this.primIndex]; }, + equals: function(other) { + if (other == this) return true; + if (other.primIndex != this.primIndex || other.ranges.length != this.ranges.length) return false; + for (var i = 0; i < this.ranges.length; i++) { + var here = this.ranges[i], there = other.ranges[i]; + if (cmp(here.anchor, there.anchor) != 0 || cmp(here.head, there.head) != 0) return false; + } + return true; + }, + deepCopy: function() { + for (var out = [], i = 0; i < this.ranges.length; i++) + out[i] = new Range(copyPos(this.ranges[i].anchor), copyPos(this.ranges[i].head)); + return new Selection(out, this.primIndex); + }, + somethingSelected: function() { + for (var i = 0; i < this.ranges.length; i++) + if (!this.ranges[i].empty()) return true; + return false; + }, + contains: function(pos, end) { + if (!end) end = pos; + for (var i = 0; i < this.ranges.length; i++) { + var range = this.ranges[i]; + if (cmp(end, range.from()) >= 0 && cmp(pos, range.to()) <= 0) + return i; + } + return -1; + } + }; + + function Range(anchor, head) { + this.anchor = anchor; this.head = head; + } + + Range.prototype = { + from: function() { return minPos(this.anchor, this.head); }, + to: function() { return maxPos(this.anchor, this.head); }, + empty: function() { + return this.head.line == this.anchor.line && this.head.ch == this.anchor.ch; + } + }; + + // Take an unsorted, potentially overlapping set of ranges, and + // build a selection out of it. 'Consumes' ranges array (modifying + // it). + function normalizeSelection(ranges, primIndex) { + var prim = ranges[primIndex]; + ranges.sort(function(a, b) { return cmp(a.from(), b.from()); }); + primIndex = indexOf(ranges, prim); + for (var i = 1; i < ranges.length; i++) { + var cur = ranges[i], prev = ranges[i - 1]; + if (cmp(prev.to(), cur.from()) >= 0) { + var from = minPos(prev.from(), cur.from()), to = maxPos(prev.to(), cur.to()); + var inv = prev.empty() ? cur.from() == cur.head : prev.from() == prev.head; + if (i <= primIndex) --primIndex; + ranges.splice(--i, 2, new Range(inv ? to : from, inv ? from : to)); + } + } + return new Selection(ranges, primIndex); + } + + function simpleSelection(anchor, head) { + return new Selection([new Range(anchor, head || anchor)], 0); + } + + // Most of the external API clips given positions to make sure they + // actually exist within the document. + function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1));} + function clipPos(doc, pos) { + if (pos.line < doc.first) return Pos(doc.first, 0); + var last = doc.first + doc.size - 1; + if (pos.line > last) return Pos(last, getLine(doc, last).text.length); + return clipToLen(pos, getLine(doc, pos.line).text.length); + } + function clipToLen(pos, linelen) { + var ch = pos.ch; + if (ch == null || ch > linelen) return Pos(pos.line, linelen); + else if (ch < 0) return Pos(pos.line, 0); + else return pos; + } + function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size;} + function clipPosArray(doc, array) { + for (var out = [], i = 0; i < array.length; i++) out[i] = clipPos(doc, array[i]); + return out; + } + + // SELECTION UPDATES + + // The 'scroll' parameter given to many of these indicated whether + // the new cursor position should be scrolled into view after + // modifying the selection. + + // If shift is held or the extend flag is set, extends a range to + // include a given position (and optionally a second position). + // Otherwise, simply returns the range between the given positions. + // Used for cursor motion and such. + function extendRange(doc, range, head, other) { + if (doc.cm && doc.cm.display.shift || doc.extend) { + var anchor = range.anchor; + if (other) { + var posBefore = cmp(head, anchor) < 0; + if (posBefore != (cmp(other, anchor) < 0)) { + anchor = head; + head = other; + } else if (posBefore != (cmp(head, other) < 0)) { + head = other; + } + } + return new Range(anchor, head); + } else { + return new Range(other || head, head); + } + } + + // Extend the primary selection range, discard the rest. + function extendSelection(doc, head, other, options) { + setSelection(doc, new Selection([extendRange(doc, doc.sel.primary(), head, other)], 0), options); + } + + // Extend all selections (pos is an array of selections with length + // equal the number of selections) + function extendSelections(doc, heads, options) { + for (var out = [], i = 0; i < doc.sel.ranges.length; i++) + out[i] = extendRange(doc, doc.sel.ranges[i], heads[i], null); + var newSel = normalizeSelection(out, doc.sel.primIndex); + setSelection(doc, newSel, options); + } + + // Updates a single range in the selection. + function replaceOneSelection(doc, i, range, options) { + var ranges = doc.sel.ranges.slice(0); + ranges[i] = range; + setSelection(doc, normalizeSelection(ranges, doc.sel.primIndex), options); + } + + // Reset the selection to a single range. + function setSimpleSelection(doc, anchor, head, options) { + setSelection(doc, simpleSelection(anchor, head), options); + } + + // Give beforeSelectionChange handlers a change to influence a + // selection update. + function filterSelectionChange(doc, sel, options) { + var obj = { + ranges: sel.ranges, + update: function(ranges) { + this.ranges = []; + for (var i = 0; i < ranges.length; i++) + this.ranges[i] = new Range(clipPos(doc, ranges[i].anchor), + clipPos(doc, ranges[i].head)); + }, + origin: options && options.origin + }; + signal(doc, "beforeSelectionChange", doc, obj); + if (doc.cm) signal(doc.cm, "beforeSelectionChange", doc.cm, obj); + if (obj.ranges != sel.ranges) return normalizeSelection(obj.ranges, obj.ranges.length - 1); + else return sel; + } + + function setSelectionReplaceHistory(doc, sel, options) { + var done = doc.history.done, last = lst(done); + if (last && last.ranges) { + done[done.length - 1] = sel; + setSelectionNoUndo(doc, sel, options); + } else { + setSelection(doc, sel, options); + } + } + + // Set a new selection. + function setSelection(doc, sel, options) { + setSelectionNoUndo(doc, sel, options); + addSelectionToHistory(doc, doc.sel, doc.cm ? doc.cm.curOp.id : NaN, options); + } + + function setSelectionNoUndo(doc, sel, options) { + if (hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange")) + sel = filterSelectionChange(doc, sel, options); + + var bias = options && options.bias || + (cmp(sel.primary().head, doc.sel.primary().head) < 0 ? -1 : 1); + setSelectionInner(doc, skipAtomicInSelection(doc, sel, bias, true)); + + if (!(options && options.scroll === false) && doc.cm) + ensureCursorVisible(doc.cm); + } + + function setSelectionInner(doc, sel) { + if (sel.equals(doc.sel)) return; + + doc.sel = sel; + + if (doc.cm) { + doc.cm.curOp.updateInput = doc.cm.curOp.selectionChanged = true; + signalCursorActivity(doc.cm); + } + signalLater(doc, "cursorActivity", doc); + } + + // Verify that the selection does not partially select any atomic + // marked ranges. + function reCheckSelection(doc) { + setSelectionInner(doc, skipAtomicInSelection(doc, doc.sel, null, false), sel_dontScroll); + } + + // Return a selection that does not partially select any atomic + // ranges. + function skipAtomicInSelection(doc, sel, bias, mayClear) { + var out; + for (var i = 0; i < sel.ranges.length; i++) { + var range = sel.ranges[i]; + var old = sel.ranges.length == doc.sel.ranges.length && doc.sel.ranges[i]; + var newAnchor = skipAtomic(doc, range.anchor, old && old.anchor, bias, mayClear); + var newHead = skipAtomic(doc, range.head, old && old.head, bias, mayClear); + if (out || newAnchor != range.anchor || newHead != range.head) { + if (!out) out = sel.ranges.slice(0, i); + out[i] = new Range(newAnchor, newHead); + } + } + return out ? normalizeSelection(out, sel.primIndex) : sel; + } + + function skipAtomicInner(doc, pos, oldPos, dir, mayClear) { + var line = getLine(doc, pos.line); + if (line.markedSpans) for (var i = 0; i < line.markedSpans.length; ++i) { + var sp = line.markedSpans[i], m = sp.marker; + if ((sp.from == null || (m.inclusiveLeft ? sp.from <= pos.ch : sp.from < pos.ch)) && + (sp.to == null || (m.inclusiveRight ? sp.to >= pos.ch : sp.to > pos.ch))) { + if (mayClear) { + signal(m, "beforeCursorEnter"); + if (m.explicitlyCleared) { + if (!line.markedSpans) break; + else {--i; continue;} + } + } + if (!m.atomic) continue; + + if (oldPos) { + var near = m.find(dir < 0 ? 1 : -1), diff; + if (dir < 0 ? m.inclusiveRight : m.inclusiveLeft) + near = movePos(doc, near, -dir, near && near.line == pos.line ? line : null); + if (near && near.line == pos.line && (diff = cmp(near, oldPos)) && (dir < 0 ? diff < 0 : diff > 0)) + return skipAtomicInner(doc, near, pos, dir, mayClear); + } + + var far = m.find(dir < 0 ? -1 : 1); + if (dir < 0 ? m.inclusiveLeft : m.inclusiveRight) + far = movePos(doc, far, dir, far.line == pos.line ? line : null); + return far ? skipAtomicInner(doc, far, pos, dir, mayClear) : null; + } + } + return pos; + } + + // Ensure a given position is not inside an atomic range. + function skipAtomic(doc, pos, oldPos, bias, mayClear) { + var dir = bias || 1; + var found = skipAtomicInner(doc, pos, oldPos, dir, mayClear) || + (!mayClear && skipAtomicInner(doc, pos, oldPos, dir, true)) || + skipAtomicInner(doc, pos, oldPos, -dir, mayClear) || + (!mayClear && skipAtomicInner(doc, pos, oldPos, -dir, true)); + if (!found) { + doc.cantEdit = true; + return Pos(doc.first, 0); + } + return found; + } + + function movePos(doc, pos, dir, line) { + if (dir < 0 && pos.ch == 0) { + if (pos.line > doc.first) return clipPos(doc, Pos(pos.line - 1)); + else return null; + } else if (dir > 0 && pos.ch == (line || getLine(doc, pos.line)).text.length) { + if (pos.line < doc.first + doc.size - 1) return Pos(pos.line + 1, 0); + else return null; + } else { + return new Pos(pos.line, pos.ch + dir); + } + } + + // SELECTION DRAWING + + function updateSelection(cm) { + cm.display.input.showSelection(cm.display.input.prepareSelection()); + } + + function prepareSelection(cm, primary) { + var doc = cm.doc, result = {}; + var curFragment = result.cursors = document.createDocumentFragment(); + var selFragment = result.selection = document.createDocumentFragment(); + + for (var i = 0; i < doc.sel.ranges.length; i++) { + if (primary === false && i == doc.sel.primIndex) continue; + var range = doc.sel.ranges[i]; + if (range.from().line >= cm.display.viewTo || range.to().line < cm.display.viewFrom) continue; + var collapsed = range.empty(); + if (collapsed || cm.options.showCursorWhenSelecting) + drawSelectionCursor(cm, range.head, curFragment); + if (!collapsed) + drawSelectionRange(cm, range, selFragment); + } + return result; + } + + // Draws a cursor for the given range + function drawSelectionCursor(cm, head, output) { + var pos = cursorCoords(cm, head, "div", null, null, !cm.options.singleCursorHeightPerLine); + + var cursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor")); + cursor.style.left = pos.left + "px"; + cursor.style.top = pos.top + "px"; + cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px"; + + if (pos.other) { + // Secondary cursor, shown when on a 'jump' in bi-directional text + var otherCursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor")); + otherCursor.style.display = ""; + otherCursor.style.left = pos.other.left + "px"; + otherCursor.style.top = pos.other.top + "px"; + otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px"; + } + } + + // Draws the given range as a highlighted selection + function drawSelectionRange(cm, range, output) { + var display = cm.display, doc = cm.doc; + var fragment = document.createDocumentFragment(); + var padding = paddingH(cm.display), leftSide = padding.left; + var rightSide = Math.max(display.sizerWidth, displayWidth(cm) - display.sizer.offsetLeft) - padding.right; + + function add(left, top, width, bottom) { + if (top < 0) top = 0; + top = Math.round(top); + bottom = Math.round(bottom); + fragment.appendChild(elt("div", null, "CodeMirror-selected", "position: absolute; left: " + left + + "px; top: " + top + "px; width: " + (width == null ? rightSide - left : width) + + "px; height: " + (bottom - top) + "px")); + } + + function drawForLine(line, fromArg, toArg) { + var lineObj = getLine(doc, line); + var lineLen = lineObj.text.length; + var start, end; + function coords(ch, bias) { + return charCoords(cm, Pos(line, ch), "div", lineObj, bias); + } + + iterateBidiSections(getOrder(lineObj), fromArg || 0, toArg == null ? lineLen : toArg, function(from, to, dir) { + var leftPos = coords(from, "left"), rightPos, left, right; + if (from == to) { + rightPos = leftPos; + left = right = leftPos.left; + } else { + rightPos = coords(to - 1, "right"); + if (dir == "rtl") { var tmp = leftPos; leftPos = rightPos; rightPos = tmp; } + left = leftPos.left; + right = rightPos.right; + } + if (fromArg == null && from == 0) left = leftSide; + if (rightPos.top - leftPos.top > 3) { // Different lines, draw top part + add(left, leftPos.top, null, leftPos.bottom); + left = leftSide; + if (leftPos.bottom < rightPos.top) add(left, leftPos.bottom, null, rightPos.top); + } + if (toArg == null && to == lineLen) right = rightSide; + if (!start || leftPos.top < start.top || leftPos.top == start.top && leftPos.left < start.left) + start = leftPos; + if (!end || rightPos.bottom > end.bottom || rightPos.bottom == end.bottom && rightPos.right > end.right) + end = rightPos; + if (left < leftSide + 1) left = leftSide; + add(left, rightPos.top, right - left, rightPos.bottom); + }); + return {start: start, end: end}; + } + + var sFrom = range.from(), sTo = range.to(); + if (sFrom.line == sTo.line) { + drawForLine(sFrom.line, sFrom.ch, sTo.ch); + } else { + var fromLine = getLine(doc, sFrom.line), toLine = getLine(doc, sTo.line); + var singleVLine = visualLine(fromLine) == visualLine(toLine); + var leftEnd = drawForLine(sFrom.line, sFrom.ch, singleVLine ? fromLine.text.length + 1 : null).end; + var rightStart = drawForLine(sTo.line, singleVLine ? 0 : null, sTo.ch).start; + if (singleVLine) { + if (leftEnd.top < rightStart.top - 2) { + add(leftEnd.right, leftEnd.top, null, leftEnd.bottom); + add(leftSide, rightStart.top, rightStart.left, rightStart.bottom); + } else { + add(leftEnd.right, leftEnd.top, rightStart.left - leftEnd.right, leftEnd.bottom); + } + } + if (leftEnd.bottom < rightStart.top) + add(leftSide, leftEnd.bottom, null, rightStart.top); + } + + output.appendChild(fragment); + } + + // Cursor-blinking + function restartBlink(cm) { + if (!cm.state.focused) return; + var display = cm.display; + clearInterval(display.blinker); + var on = true; + display.cursorDiv.style.visibility = ""; + if (cm.options.cursorBlinkRate > 0) + display.blinker = setInterval(function() { + display.cursorDiv.style.visibility = (on = !on) ? "" : "hidden"; + }, cm.options.cursorBlinkRate); + else if (cm.options.cursorBlinkRate < 0) + display.cursorDiv.style.visibility = "hidden"; + } + + // HIGHLIGHT WORKER + + function startWorker(cm, time) { + if (cm.doc.mode.startState && cm.doc.frontier < cm.display.viewTo) + cm.state.highlight.set(time, bind(highlightWorker, cm)); + } + + function highlightWorker(cm) { + var doc = cm.doc; + if (doc.frontier < doc.first) doc.frontier = doc.first; + if (doc.frontier >= cm.display.viewTo) return; + var end = +new Date + cm.options.workTime; + var state = copyState(doc.mode, getStateBefore(cm, doc.frontier)); + var changedLines = []; + + doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.viewTo + 500), function(line) { + if (doc.frontier >= cm.display.viewFrom) { // Visible + var oldStyles = line.styles, tooLong = line.text.length > cm.options.maxHighlightLength; + var highlighted = highlightLine(cm, line, tooLong ? copyState(doc.mode, state) : state, true); + line.styles = highlighted.styles; + var oldCls = line.styleClasses, newCls = highlighted.classes; + if (newCls) line.styleClasses = newCls; + else if (oldCls) line.styleClasses = null; + var ischange = !oldStyles || oldStyles.length != line.styles.length || + oldCls != newCls && (!oldCls || !newCls || oldCls.bgClass != newCls.bgClass || oldCls.textClass != newCls.textClass); + for (var i = 0; !ischange && i < oldStyles.length; ++i) ischange = oldStyles[i] != line.styles[i]; + if (ischange) changedLines.push(doc.frontier); + line.stateAfter = tooLong ? state : copyState(doc.mode, state); + } else { + if (line.text.length <= cm.options.maxHighlightLength) + processLine(cm, line.text, state); + line.stateAfter = doc.frontier % 5 == 0 ? copyState(doc.mode, state) : null; + } + ++doc.frontier; + if (+new Date > end) { + startWorker(cm, cm.options.workDelay); + return true; + } + }); + if (changedLines.length) runInOp(cm, function() { + for (var i = 0; i < changedLines.length; i++) + regLineChange(cm, changedLines[i], "text"); + }); + } + + // Finds the line to start with when starting a parse. Tries to + // find a line with a stateAfter, so that it can start with a + // valid state. If that fails, it returns the line with the + // smallest indentation, which tends to need the least context to + // parse correctly. + function findStartLine(cm, n, precise) { + var minindent, minline, doc = cm.doc; + var lim = precise ? -1 : n - (cm.doc.mode.innerMode ? 1000 : 100); + for (var search = n; search > lim; --search) { + if (search <= doc.first) return doc.first; + var line = getLine(doc, search - 1); + if (line.stateAfter && (!precise || search <= doc.frontier)) return search; + var indented = countColumn(line.text, null, cm.options.tabSize); + if (minline == null || minindent > indented) { + minline = search - 1; + minindent = indented; + } + } + return minline; + } + + function getStateBefore(cm, n, precise) { + var doc = cm.doc, display = cm.display; + if (!doc.mode.startState) return true; + var pos = findStartLine(cm, n, precise), state = pos > doc.first && getLine(doc, pos-1).stateAfter; + if (!state) state = startState(doc.mode); + else state = copyState(doc.mode, state); + doc.iter(pos, n, function(line) { + processLine(cm, line.text, state); + var save = pos == n - 1 || pos % 5 == 0 || pos >= display.viewFrom && pos < display.viewTo; + line.stateAfter = save ? copyState(doc.mode, state) : null; + ++pos; + }); + if (precise) doc.frontier = pos; + return state; + } + + // POSITION MEASUREMENT + + function paddingTop(display) {return display.lineSpace.offsetTop;} + function paddingVert(display) {return display.mover.offsetHeight - display.lineSpace.offsetHeight;} + function paddingH(display) { + if (display.cachedPaddingH) return display.cachedPaddingH; + var e = removeChildrenAndAdd(display.measure, elt("pre", "x")); + var style = window.getComputedStyle ? window.getComputedStyle(e) : e.currentStyle; + var data = {left: parseInt(style.paddingLeft), right: parseInt(style.paddingRight)}; + if (!isNaN(data.left) && !isNaN(data.right)) display.cachedPaddingH = data; + return data; + } + + function scrollGap(cm) { return scrollerGap - cm.display.nativeBarWidth; } + function displayWidth(cm) { + return cm.display.scroller.clientWidth - scrollGap(cm) - cm.display.barWidth; + } + function displayHeight(cm) { + return cm.display.scroller.clientHeight - scrollGap(cm) - cm.display.barHeight; + } + + // Ensure the lineView.wrapping.heights array is populated. This is + // an array of bottom offsets for the lines that make up a drawn + // line. When lineWrapping is on, there might be more than one + // height. + function ensureLineHeights(cm, lineView, rect) { + var wrapping = cm.options.lineWrapping; + var curWidth = wrapping && displayWidth(cm); + if (!lineView.measure.heights || wrapping && lineView.measure.width != curWidth) { + var heights = lineView.measure.heights = []; + if (wrapping) { + lineView.measure.width = curWidth; + var rects = lineView.text.firstChild.getClientRects(); + for (var i = 0; i < rects.length - 1; i++) { + var cur = rects[i], next = rects[i + 1]; + if (Math.abs(cur.bottom - next.bottom) > 2) + heights.push((cur.bottom + next.top) / 2 - rect.top); + } + } + heights.push(rect.bottom - rect.top); + } + } + + // Find a line map (mapping character offsets to text nodes) and a + // measurement cache for the given line number. (A line view might + // contain multiple lines when collapsed ranges are present.) + function mapFromLineView(lineView, line, lineN) { + if (lineView.line == line) + return {map: lineView.measure.map, cache: lineView.measure.cache}; + for (var i = 0; i < lineView.rest.length; i++) + if (lineView.rest[i] == line) + return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i]}; + for (var i = 0; i < lineView.rest.length; i++) + if (lineNo(lineView.rest[i]) > lineN) + return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i], before: true}; + } + + // Render a line into the hidden node display.externalMeasured. Used + // when measurement is needed for a line that's not in the viewport. + function updateExternalMeasurement(cm, line) { + line = visualLine(line); + var lineN = lineNo(line); + var view = cm.display.externalMeasured = new LineView(cm.doc, line, lineN); + view.lineN = lineN; + var built = view.built = buildLineContent(cm, view); + view.text = built.pre; + removeChildrenAndAdd(cm.display.lineMeasure, built.pre); + return view; + } + + // Get a {top, bottom, left, right} box (in line-local coordinates) + // for a given character. + function measureChar(cm, line, ch, bias) { + return measureCharPrepared(cm, prepareMeasureForLine(cm, line), ch, bias); + } + + // Find a line view that corresponds to the given line number. + function findViewForLine(cm, lineN) { + if (lineN >= cm.display.viewFrom && lineN < cm.display.viewTo) + return cm.display.view[findViewIndex(cm, lineN)]; + var ext = cm.display.externalMeasured; + if (ext && lineN >= ext.lineN && lineN < ext.lineN + ext.size) + return ext; + } + + // Measurement can be split in two steps, the set-up work that + // applies to the whole line, and the measurement of the actual + // character. Functions like coordsChar, that need to do a lot of + // measurements in a row, can thus ensure that the set-up work is + // only done once. + function prepareMeasureForLine(cm, line) { + var lineN = lineNo(line); + var view = findViewForLine(cm, lineN); + if (view && !view.text) { + view = null; + } else if (view && view.changes) { + updateLineForChanges(cm, view, lineN, getDimensions(cm)); + cm.curOp.forceUpdate = true; + } + if (!view) + view = updateExternalMeasurement(cm, line); + + var info = mapFromLineView(view, line, lineN); + return { + line: line, view: view, rect: null, + map: info.map, cache: info.cache, before: info.before, + hasHeights: false + }; + } + + // Given a prepared measurement object, measures the position of an + // actual character (or fetches it from the cache). + function measureCharPrepared(cm, prepared, ch, bias, varHeight) { + if (prepared.before) ch = -1; + var key = ch + (bias || ""), found; + if (prepared.cache.hasOwnProperty(key)) { + found = prepared.cache[key]; + } else { + if (!prepared.rect) + prepared.rect = prepared.view.text.getBoundingClientRect(); + if (!prepared.hasHeights) { + ensureLineHeights(cm, prepared.view, prepared.rect); + prepared.hasHeights = true; + } + found = measureCharInner(cm, prepared, ch, bias); + if (!found.bogus) prepared.cache[key] = found; + } + return {left: found.left, right: found.right, + top: varHeight ? found.rtop : found.top, + bottom: varHeight ? found.rbottom : found.bottom}; + } + + var nullRect = {left: 0, right: 0, top: 0, bottom: 0}; + + function nodeAndOffsetInLineMap(map, ch, bias) { + var node, start, end, collapse; + // First, search the line map for the text node corresponding to, + // or closest to, the target character. + for (var i = 0; i < map.length; i += 3) { + var mStart = map[i], mEnd = map[i + 1]; + if (ch < mStart) { + start = 0; end = 1; + collapse = "left"; + } else if (ch < mEnd) { + start = ch - mStart; + end = start + 1; + } else if (i == map.length - 3 || ch == mEnd && map[i + 3] > ch) { + end = mEnd - mStart; + start = end - 1; + if (ch >= mEnd) collapse = "right"; + } + if (start != null) { + node = map[i + 2]; + if (mStart == mEnd && bias == (node.insertLeft ? "left" : "right")) + collapse = bias; + if (bias == "left" && start == 0) + while (i && map[i - 2] == map[i - 3] && map[i - 1].insertLeft) { + node = map[(i -= 3) + 2]; + collapse = "left"; + } + if (bias == "right" && start == mEnd - mStart) + while (i < map.length - 3 && map[i + 3] == map[i + 4] && !map[i + 5].insertLeft) { + node = map[(i += 3) + 2]; + collapse = "right"; + } + break; + } + } + return {node: node, start: start, end: end, collapse: collapse, coverStart: mStart, coverEnd: mEnd}; + } + + function getUsefulRect(rects, bias) { + var rect = nullRect + if (bias == "left") for (var i = 0; i < rects.length; i++) { + if ((rect = rects[i]).left != rect.right) break + } else for (var i = rects.length - 1; i >= 0; i--) { + if ((rect = rects[i]).left != rect.right) break + } + return rect + } + + function measureCharInner(cm, prepared, ch, bias) { + var place = nodeAndOffsetInLineMap(prepared.map, ch, bias); + var node = place.node, start = place.start, end = place.end, collapse = place.collapse; + + var rect; + if (node.nodeType == 3) { // If it is a text node, use a range to retrieve the coordinates. + for (var i = 0; i < 4; i++) { // Retry a maximum of 4 times when nonsense rectangles are returned + while (start && isExtendingChar(prepared.line.text.charAt(place.coverStart + start))) --start; + while (place.coverStart + end < place.coverEnd && isExtendingChar(prepared.line.text.charAt(place.coverStart + end))) ++end; + if (ie && ie_version < 9 && start == 0 && end == place.coverEnd - place.coverStart) + rect = node.parentNode.getBoundingClientRect(); + else + rect = getUsefulRect(range(node, start, end).getClientRects(), bias) + if (rect.left || rect.right || start == 0) break; + end = start; + start = start - 1; + collapse = "right"; + } + if (ie && ie_version < 11) rect = maybeUpdateRectForZooming(cm.display.measure, rect); + } else { // If it is a widget, simply get the box for the whole widget. + if (start > 0) collapse = bias = "right"; + var rects; + if (cm.options.lineWrapping && (rects = node.getClientRects()).length > 1) + rect = rects[bias == "right" ? rects.length - 1 : 0]; + else + rect = node.getBoundingClientRect(); + } + if (ie && ie_version < 9 && !start && (!rect || !rect.left && !rect.right)) { + var rSpan = node.parentNode.getClientRects()[0]; + if (rSpan) + rect = {left: rSpan.left, right: rSpan.left + charWidth(cm.display), top: rSpan.top, bottom: rSpan.bottom}; + else + rect = nullRect; + } + + var rtop = rect.top - prepared.rect.top, rbot = rect.bottom - prepared.rect.top; + var mid = (rtop + rbot) / 2; + var heights = prepared.view.measure.heights; + for (var i = 0; i < heights.length - 1; i++) + if (mid < heights[i]) break; + var top = i ? heights[i - 1] : 0, bot = heights[i]; + var result = {left: (collapse == "right" ? rect.right : rect.left) - prepared.rect.left, + right: (collapse == "left" ? rect.left : rect.right) - prepared.rect.left, + top: top, bottom: bot}; + if (!rect.left && !rect.right) result.bogus = true; + if (!cm.options.singleCursorHeightPerLine) { result.rtop = rtop; result.rbottom = rbot; } + + return result; + } + + // Work around problem with bounding client rects on ranges being + // returned incorrectly when zoomed on IE10 and below. + function maybeUpdateRectForZooming(measure, rect) { + if (!window.screen || screen.logicalXDPI == null || + screen.logicalXDPI == screen.deviceXDPI || !hasBadZoomedRects(measure)) + return rect; + var scaleX = screen.logicalXDPI / screen.deviceXDPI; + var scaleY = screen.logicalYDPI / screen.deviceYDPI; + return {left: rect.left * scaleX, right: rect.right * scaleX, + top: rect.top * scaleY, bottom: rect.bottom * scaleY}; + } + + function clearLineMeasurementCacheFor(lineView) { + if (lineView.measure) { + lineView.measure.cache = {}; + lineView.measure.heights = null; + if (lineView.rest) for (var i = 0; i < lineView.rest.length; i++) + lineView.measure.caches[i] = {}; + } + } + + function clearLineMeasurementCache(cm) { + cm.display.externalMeasure = null; + removeChildren(cm.display.lineMeasure); + for (var i = 0; i < cm.display.view.length; i++) + clearLineMeasurementCacheFor(cm.display.view[i]); + } + + function clearCaches(cm) { + clearLineMeasurementCache(cm); + cm.display.cachedCharWidth = cm.display.cachedTextHeight = cm.display.cachedPaddingH = null; + if (!cm.options.lineWrapping) cm.display.maxLineChanged = true; + cm.display.lineNumChars = null; + } + + function pageScrollX() { return window.pageXOffset || (document.documentElement || document.body).scrollLeft; } + function pageScrollY() { return window.pageYOffset || (document.documentElement || document.body).scrollTop; } + + // Converts a {top, bottom, left, right} box from line-local + // coordinates into another coordinate system. Context may be one of + // "line", "div" (display.lineDiv), "local"/null (editor), "window", + // or "page". + function intoCoordSystem(cm, lineObj, rect, context) { + if (lineObj.widgets) for (var i = 0; i < lineObj.widgets.length; ++i) if (lineObj.widgets[i].above) { + var size = widgetHeight(lineObj.widgets[i]); + rect.top += size; rect.bottom += size; + } + if (context == "line") return rect; + if (!context) context = "local"; + var yOff = heightAtLine(lineObj); + if (context == "local") yOff += paddingTop(cm.display); + else yOff -= cm.display.viewOffset; + if (context == "page" || context == "window") { + var lOff = cm.display.lineSpace.getBoundingClientRect(); + yOff += lOff.top + (context == "window" ? 0 : pageScrollY()); + var xOff = lOff.left + (context == "window" ? 0 : pageScrollX()); + rect.left += xOff; rect.right += xOff; + } + rect.top += yOff; rect.bottom += yOff; + return rect; + } + + // Coverts a box from "div" coords to another coordinate system. + // Context may be "window", "page", "div", or "local"/null. + function fromCoordSystem(cm, coords, context) { + if (context == "div") return coords; + var left = coords.left, top = coords.top; + // First move into "page" coordinate system + if (context == "page") { + left -= pageScrollX(); + top -= pageScrollY(); + } else if (context == "local" || !context) { + var localBox = cm.display.sizer.getBoundingClientRect(); + left += localBox.left; + top += localBox.top; + } + + var lineSpaceBox = cm.display.lineSpace.getBoundingClientRect(); + return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top}; + } + + function charCoords(cm, pos, context, lineObj, bias) { + if (!lineObj) lineObj = getLine(cm.doc, pos.line); + return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, bias), context); + } + + // Returns a box for a given cursor position, which may have an + // 'other' property containing the position of the secondary cursor + // on a bidi boundary. + function cursorCoords(cm, pos, context, lineObj, preparedMeasure, varHeight) { + lineObj = lineObj || getLine(cm.doc, pos.line); + if (!preparedMeasure) preparedMeasure = prepareMeasureForLine(cm, lineObj); + function get(ch, right) { + var m = measureCharPrepared(cm, preparedMeasure, ch, right ? "right" : "left", varHeight); + if (right) m.left = m.right; else m.right = m.left; + return intoCoordSystem(cm, lineObj, m, context); + } + function getBidi(ch, partPos) { + var part = order[partPos], right = part.level % 2; + if (ch == bidiLeft(part) && partPos && part.level < order[partPos - 1].level) { + part = order[--partPos]; + ch = bidiRight(part) - (part.level % 2 ? 0 : 1); + right = true; + } else if (ch == bidiRight(part) && partPos < order.length - 1 && part.level < order[partPos + 1].level) { + part = order[++partPos]; + ch = bidiLeft(part) - part.level % 2; + right = false; + } + if (right && ch == part.to && ch > part.from) return get(ch - 1); + return get(ch, right); + } + var order = getOrder(lineObj), ch = pos.ch; + if (!order) return get(ch); + var partPos = getBidiPartAt(order, ch); + var val = getBidi(ch, partPos); + if (bidiOther != null) val.other = getBidi(ch, bidiOther); + return val; + } + + // Used to cheaply estimate the coordinates for a position. Used for + // intermediate scroll updates. + function estimateCoords(cm, pos) { + var left = 0, pos = clipPos(cm.doc, pos); + if (!cm.options.lineWrapping) left = charWidth(cm.display) * pos.ch; + var lineObj = getLine(cm.doc, pos.line); + var top = heightAtLine(lineObj) + paddingTop(cm.display); + return {left: left, right: left, top: top, bottom: top + lineObj.height}; + } + + // Positions returned by coordsChar contain some extra information. + // xRel is the relative x position of the input coordinates compared + // to the found position (so xRel > 0 means the coordinates are to + // the right of the character position, for example). When outside + // is true, that means the coordinates lie outside the line's + // vertical range. + function PosWithInfo(line, ch, outside, xRel) { + var pos = Pos(line, ch); + pos.xRel = xRel; + if (outside) pos.outside = true; + return pos; + } + + // Compute the character position closest to the given coordinates. + // Input must be lineSpace-local ("div" coordinate system). + function coordsChar(cm, x, y) { + var doc = cm.doc; + y += cm.display.viewOffset; + if (y < 0) return PosWithInfo(doc.first, 0, true, -1); + var lineN = lineAtHeight(doc, y), last = doc.first + doc.size - 1; + if (lineN > last) + return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, true, 1); + if (x < 0) x = 0; + + var lineObj = getLine(doc, lineN); + for (;;) { + var found = coordsCharInner(cm, lineObj, lineN, x, y); + var merged = collapsedSpanAtEnd(lineObj); + var mergedPos = merged && merged.find(0, true); + if (merged && (found.ch > mergedPos.from.ch || found.ch == mergedPos.from.ch && found.xRel > 0)) + lineN = lineNo(lineObj = mergedPos.to.line); + else + return found; + } + } + + function coordsCharInner(cm, lineObj, lineNo, x, y) { + var innerOff = y - heightAtLine(lineObj); + var wrongLine = false, adjust = 2 * cm.display.wrapper.clientWidth; + var preparedMeasure = prepareMeasureForLine(cm, lineObj); + + function getX(ch) { + var sp = cursorCoords(cm, Pos(lineNo, ch), "line", lineObj, preparedMeasure); + wrongLine = true; + if (innerOff > sp.bottom) return sp.left - adjust; + else if (innerOff < sp.top) return sp.left + adjust; + else wrongLine = false; + return sp.left; + } + + var bidi = getOrder(lineObj), dist = lineObj.text.length; + var from = lineLeft(lineObj), to = lineRight(lineObj); + var fromX = getX(from), fromOutside = wrongLine, toX = getX(to), toOutside = wrongLine; + + if (x > toX) return PosWithInfo(lineNo, to, toOutside, 1); + // Do a binary search between these bounds. + for (;;) { + if (bidi ? to == from || to == moveVisually(lineObj, from, 1) : to - from <= 1) { + var ch = x < fromX || x - fromX <= toX - x ? from : to; + var outside = ch == from ? fromOutside : toOutside + var xDiff = x - (ch == from ? fromX : toX); + // This is a kludge to handle the case where the coordinates + // are after a line-wrapped line. We should replace it with a + // more general handling of cursor positions around line + // breaks. (Issue #4078) + if (toOutside && !bidi && !/\s/.test(lineObj.text.charAt(ch)) && xDiff > 0 && + ch < lineObj.text.length && preparedMeasure.view.measure.heights.length > 1) { + var charSize = measureCharPrepared(cm, preparedMeasure, ch, "right"); + if (innerOff <= charSize.bottom && innerOff >= charSize.top && Math.abs(x - charSize.right) < xDiff) { + outside = false + ch++ + xDiff = x - charSize.right + } + } + while (isExtendingChar(lineObj.text.charAt(ch))) ++ch; + var pos = PosWithInfo(lineNo, ch, outside, xDiff < -1 ? -1 : xDiff > 1 ? 1 : 0); + return pos; + } + var step = Math.ceil(dist / 2), middle = from + step; + if (bidi) { + middle = from; + for (var i = 0; i < step; ++i) middle = moveVisually(lineObj, middle, 1); + } + var middleX = getX(middle); + if (middleX > x) {to = middle; toX = middleX; if (toOutside = wrongLine) toX += 1000; dist = step;} + else {from = middle; fromX = middleX; fromOutside = wrongLine; dist -= step;} + } + } + + var measureText; + // Compute the default text height. + function textHeight(display) { + if (display.cachedTextHeight != null) return display.cachedTextHeight; + if (measureText == null) { + measureText = elt("pre"); + // Measure a bunch of lines, for browsers that compute + // fractional heights. + for (var i = 0; i < 49; ++i) { + measureText.appendChild(document.createTextNode("x")); + measureText.appendChild(elt("br")); + } + measureText.appendChild(document.createTextNode("x")); + } + removeChildrenAndAdd(display.measure, measureText); + var height = measureText.offsetHeight / 50; + if (height > 3) display.cachedTextHeight = height; + removeChildren(display.measure); + return height || 1; + } + + // Compute the default character width. + function charWidth(display) { + if (display.cachedCharWidth != null) return display.cachedCharWidth; + var anchor = elt("span", "xxxxxxxxxx"); + var pre = elt("pre", [anchor]); + removeChildrenAndAdd(display.measure, pre); + var rect = anchor.getBoundingClientRect(), width = (rect.right - rect.left) / 10; + if (width > 2) display.cachedCharWidth = width; + return width || 10; + } + + // OPERATIONS + + // Operations are used to wrap a series of changes to the editor + // state in such a way that each change won't have to update the + // cursor and display (which would be awkward, slow, and + // error-prone). Instead, display updates are batched and then all + // combined and executed at once. + + var operationGroup = null; + + var nextOpId = 0; + // Start a new operation. + function startOperation(cm) { + cm.curOp = { + cm: cm, + viewChanged: false, // Flag that indicates that lines might need to be redrawn + startHeight: cm.doc.height, // Used to detect need to update scrollbar + forceUpdate: false, // Used to force a redraw + updateInput: null, // Whether to reset the input textarea + typing: false, // Whether this reset should be careful to leave existing text (for compositing) + changeObjs: null, // Accumulated changes, for firing change events + cursorActivityHandlers: null, // Set of handlers to fire cursorActivity on + cursorActivityCalled: 0, // Tracks which cursorActivity handlers have been called already + selectionChanged: false, // Whether the selection needs to be redrawn + updateMaxLine: false, // Set when the widest line needs to be determined anew + scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet + scrollToPos: null, // Used to scroll to a specific position + focus: false, + id: ++nextOpId // Unique ID + }; + if (operationGroup) { + operationGroup.ops.push(cm.curOp); + } else { + cm.curOp.ownsGroup = operationGroup = { + ops: [cm.curOp], + delayedCallbacks: [] + }; + } + } + + function fireCallbacksForOps(group) { + // Calls delayed callbacks and cursorActivity handlers until no + // new ones appear + var callbacks = group.delayedCallbacks, i = 0; + do { + for (; i < callbacks.length; i++) + callbacks[i].call(null); + for (var j = 0; j < group.ops.length; j++) { + var op = group.ops[j]; + if (op.cursorActivityHandlers) + while (op.cursorActivityCalled < op.cursorActivityHandlers.length) + op.cursorActivityHandlers[op.cursorActivityCalled++].call(null, op.cm); + } + } while (i < callbacks.length); + } + + // Finish an operation, updating the display and signalling delayed events + function endOperation(cm) { + var op = cm.curOp, group = op.ownsGroup; + if (!group) return; + + try { fireCallbacksForOps(group); } + finally { + operationGroup = null; + for (var i = 0; i < group.ops.length; i++) + group.ops[i].cm.curOp = null; + endOperations(group); + } + } + + // The DOM updates done when an operation finishes are batched so + // that the minimum number of relayouts are required. + function endOperations(group) { + var ops = group.ops; + for (var i = 0; i < ops.length; i++) // Read DOM + endOperation_R1(ops[i]); + for (var i = 0; i < ops.length; i++) // Write DOM (maybe) + endOperation_W1(ops[i]); + for (var i = 0; i < ops.length; i++) // Read DOM + endOperation_R2(ops[i]); + for (var i = 0; i < ops.length; i++) // Write DOM (maybe) + endOperation_W2(ops[i]); + for (var i = 0; i < ops.length; i++) // Read DOM + endOperation_finish(ops[i]); + } + + function endOperation_R1(op) { + var cm = op.cm, display = cm.display; + maybeClipScrollbars(cm); + if (op.updateMaxLine) findMaxLine(cm); + + op.mustUpdate = op.viewChanged || op.forceUpdate || op.scrollTop != null || + op.scrollToPos && (op.scrollToPos.from.line < display.viewFrom || + op.scrollToPos.to.line >= display.viewTo) || + display.maxLineChanged && cm.options.lineWrapping; + op.update = op.mustUpdate && + new DisplayUpdate(cm, op.mustUpdate && {top: op.scrollTop, ensure: op.scrollToPos}, op.forceUpdate); + } + + function endOperation_W1(op) { + op.updatedDisplay = op.mustUpdate && updateDisplayIfNeeded(op.cm, op.update); + } + + function endOperation_R2(op) { + var cm = op.cm, display = cm.display; + if (op.updatedDisplay) updateHeightsInViewport(cm); + + op.barMeasure = measureForScrollbars(cm); + + // If the max line changed since it was last measured, measure it, + // and ensure the document's width matches it. + // updateDisplay_W2 will use these properties to do the actual resizing + if (display.maxLineChanged && !cm.options.lineWrapping) { + op.adjustWidthTo = measureChar(cm, display.maxLine, display.maxLine.text.length).left + 3; + cm.display.sizerWidth = op.adjustWidthTo; + op.barMeasure.scrollWidth = + Math.max(display.scroller.clientWidth, display.sizer.offsetLeft + op.adjustWidthTo + scrollGap(cm) + cm.display.barWidth); + op.maxScrollLeft = Math.max(0, display.sizer.offsetLeft + op.adjustWidthTo - displayWidth(cm)); + } + + if (op.updatedDisplay || op.selectionChanged) + op.preparedSelection = display.input.prepareSelection(op.focus); + } + + function endOperation_W2(op) { + var cm = op.cm; + + if (op.adjustWidthTo != null) { + cm.display.sizer.style.minWidth = op.adjustWidthTo + "px"; + if (op.maxScrollLeft < cm.doc.scrollLeft) + setScrollLeft(cm, Math.min(cm.display.scroller.scrollLeft, op.maxScrollLeft), true); + cm.display.maxLineChanged = false; + } + + var takeFocus = op.focus && op.focus == activeElt() && (!document.hasFocus || document.hasFocus()) + if (op.preparedSelection) + cm.display.input.showSelection(op.preparedSelection, takeFocus); + if (op.updatedDisplay || op.startHeight != cm.doc.height) + updateScrollbars(cm, op.barMeasure); + if (op.updatedDisplay) + setDocumentHeight(cm, op.barMeasure); + + if (op.selectionChanged) restartBlink(cm); + + if (cm.state.focused && op.updateInput) + cm.display.input.reset(op.typing); + if (takeFocus) ensureFocus(op.cm); + } + + function endOperation_finish(op) { + var cm = op.cm, display = cm.display, doc = cm.doc; + + if (op.updatedDisplay) postUpdateDisplay(cm, op.update); + + // Abort mouse wheel delta measurement, when scrolling explicitly + if (display.wheelStartX != null && (op.scrollTop != null || op.scrollLeft != null || op.scrollToPos)) + display.wheelStartX = display.wheelStartY = null; + + // Propagate the scroll position to the actual DOM scroller + if (op.scrollTop != null && (display.scroller.scrollTop != op.scrollTop || op.forceScroll)) { + doc.scrollTop = Math.max(0, Math.min(display.scroller.scrollHeight - display.scroller.clientHeight, op.scrollTop)); + display.scrollbars.setScrollTop(doc.scrollTop); + display.scroller.scrollTop = doc.scrollTop; + } + if (op.scrollLeft != null && (display.scroller.scrollLeft != op.scrollLeft || op.forceScroll)) { + doc.scrollLeft = Math.max(0, Math.min(display.scroller.scrollWidth - display.scroller.clientWidth, op.scrollLeft)); + display.scrollbars.setScrollLeft(doc.scrollLeft); + display.scroller.scrollLeft = doc.scrollLeft; + alignHorizontally(cm); + } + // If we need to scroll a specific position into view, do so. + if (op.scrollToPos) { + var coords = scrollPosIntoView(cm, clipPos(doc, op.scrollToPos.from), + clipPos(doc, op.scrollToPos.to), op.scrollToPos.margin); + if (op.scrollToPos.isCursor && cm.state.focused) maybeScrollWindow(cm, coords); + } + + // Fire events for markers that are hidden/unidden by editing or + // undoing + var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers; + if (hidden) for (var i = 0; i < hidden.length; ++i) + if (!hidden[i].lines.length) signal(hidden[i], "hide"); + if (unhidden) for (var i = 0; i < unhidden.length; ++i) + if (unhidden[i].lines.length) signal(unhidden[i], "unhide"); + + if (display.wrapper.offsetHeight) + doc.scrollTop = cm.display.scroller.scrollTop; + + // Fire change events, and delayed event handlers + if (op.changeObjs) + signal(cm, "changes", cm, op.changeObjs); + if (op.update) + op.update.finish(); + } + + // Run the given function in an operation + function runInOp(cm, f) { + if (cm.curOp) return f(); + startOperation(cm); + try { return f(); } + finally { endOperation(cm); } + } + // Wraps a function in an operation. Returns the wrapped function. + function operation(cm, f) { + return function() { + if (cm.curOp) return f.apply(cm, arguments); + startOperation(cm); + try { return f.apply(cm, arguments); } + finally { endOperation(cm); } + }; + } + // Used to add methods to editor and doc instances, wrapping them in + // operations. + function methodOp(f) { + return function() { + if (this.curOp) return f.apply(this, arguments); + startOperation(this); + try { return f.apply(this, arguments); } + finally { endOperation(this); } + }; + } + function docMethodOp(f) { + return function() { + var cm = this.cm; + if (!cm || cm.curOp) return f.apply(this, arguments); + startOperation(cm); + try { return f.apply(this, arguments); } + finally { endOperation(cm); } + }; + } + + // VIEW TRACKING + + // These objects are used to represent the visible (currently drawn) + // part of the document. A LineView may correspond to multiple + // logical lines, if those are connected by collapsed ranges. + function LineView(doc, line, lineN) { + // The starting line + this.line = line; + // Continuing lines, if any + this.rest = visualLineContinued(line); + // Number of logical lines in this visual line + this.size = this.rest ? lineNo(lst(this.rest)) - lineN + 1 : 1; + this.node = this.text = null; + this.hidden = lineIsHidden(doc, line); + } + + // Create a range of LineView objects for the given lines. + function buildViewArray(cm, from, to) { + var array = [], nextPos; + for (var pos = from; pos < to; pos = nextPos) { + var view = new LineView(cm.doc, getLine(cm.doc, pos), pos); + nextPos = pos + view.size; + array.push(view); + } + return array; + } + + // Updates the display.view data structure for a given change to the + // document. From and to are in pre-change coordinates. Lendiff is + // the amount of lines added or subtracted by the change. This is + // used for changes that span multiple lines, or change the way + // lines are divided into visual lines. regLineChange (below) + // registers single-line changes. + function regChange(cm, from, to, lendiff) { + if (from == null) from = cm.doc.first; + if (to == null) to = cm.doc.first + cm.doc.size; + if (!lendiff) lendiff = 0; + + var display = cm.display; + if (lendiff && to < display.viewTo && + (display.updateLineNumbers == null || display.updateLineNumbers > from)) + display.updateLineNumbers = from; + + cm.curOp.viewChanged = true; + + if (from >= display.viewTo) { // Change after + if (sawCollapsedSpans && visualLineNo(cm.doc, from) < display.viewTo) + resetView(cm); + } else if (to <= display.viewFrom) { // Change before + if (sawCollapsedSpans && visualLineEndNo(cm.doc, to + lendiff) > display.viewFrom) { + resetView(cm); + } else { + display.viewFrom += lendiff; + display.viewTo += lendiff; + } + } else if (from <= display.viewFrom && to >= display.viewTo) { // Full overlap + resetView(cm); + } else if (from <= display.viewFrom) { // Top overlap + var cut = viewCuttingPoint(cm, to, to + lendiff, 1); + if (cut) { + display.view = display.view.slice(cut.index); + display.viewFrom = cut.lineN; + display.viewTo += lendiff; + } else { + resetView(cm); + } + } else if (to >= display.viewTo) { // Bottom overlap + var cut = viewCuttingPoint(cm, from, from, -1); + if (cut) { + display.view = display.view.slice(0, cut.index); + display.viewTo = cut.lineN; + } else { + resetView(cm); + } + } else { // Gap in the middle + var cutTop = viewCuttingPoint(cm, from, from, -1); + var cutBot = viewCuttingPoint(cm, to, to + lendiff, 1); + if (cutTop && cutBot) { + display.view = display.view.slice(0, cutTop.index) + .concat(buildViewArray(cm, cutTop.lineN, cutBot.lineN)) + .concat(display.view.slice(cutBot.index)); + display.viewTo += lendiff; + } else { + resetView(cm); + } + } + + var ext = display.externalMeasured; + if (ext) { + if (to < ext.lineN) + ext.lineN += lendiff; + else if (from < ext.lineN + ext.size) + display.externalMeasured = null; + } + } + + // Register a change to a single line. Type must be one of "text", + // "gutter", "class", "widget" + function regLineChange(cm, line, type) { + cm.curOp.viewChanged = true; + var display = cm.display, ext = cm.display.externalMeasured; + if (ext && line >= ext.lineN && line < ext.lineN + ext.size) + display.externalMeasured = null; + + if (line < display.viewFrom || line >= display.viewTo) return; + var lineView = display.view[findViewIndex(cm, line)]; + if (lineView.node == null) return; + var arr = lineView.changes || (lineView.changes = []); + if (indexOf(arr, type) == -1) arr.push(type); + } + + // Clear the view. + function resetView(cm) { + cm.display.viewFrom = cm.display.viewTo = cm.doc.first; + cm.display.view = []; + cm.display.viewOffset = 0; + } + + // Find the view element corresponding to a given line. Return null + // when the line isn't visible. + function findViewIndex(cm, n) { + if (n >= cm.display.viewTo) return null; + n -= cm.display.viewFrom; + if (n < 0) return null; + var view = cm.display.view; + for (var i = 0; i < view.length; i++) { + n -= view[i].size; + if (n < 0) return i; + } + } + + function viewCuttingPoint(cm, oldN, newN, dir) { + var index = findViewIndex(cm, oldN), diff, view = cm.display.view; + if (!sawCollapsedSpans || newN == cm.doc.first + cm.doc.size) + return {index: index, lineN: newN}; + for (var i = 0, n = cm.display.viewFrom; i < index; i++) + n += view[i].size; + if (n != oldN) { + if (dir > 0) { + if (index == view.length - 1) return null; + diff = (n + view[index].size) - oldN; + index++; + } else { + diff = n - oldN; + } + oldN += diff; newN += diff; + } + while (visualLineNo(cm.doc, newN) != newN) { + if (index == (dir < 0 ? 0 : view.length - 1)) return null; + newN += dir * view[index - (dir < 0 ? 1 : 0)].size; + index += dir; + } + return {index: index, lineN: newN}; + } + + // Force the view to cover a given range, adding empty view element + // or clipping off existing ones as needed. + function adjustView(cm, from, to) { + var display = cm.display, view = display.view; + if (view.length == 0 || from >= display.viewTo || to <= display.viewFrom) { + display.view = buildViewArray(cm, from, to); + display.viewFrom = from; + } else { + if (display.viewFrom > from) + display.view = buildViewArray(cm, from, display.viewFrom).concat(display.view); + else if (display.viewFrom < from) + display.view = display.view.slice(findViewIndex(cm, from)); + display.viewFrom = from; + if (display.viewTo < to) + display.view = display.view.concat(buildViewArray(cm, display.viewTo, to)); + else if (display.viewTo > to) + display.view = display.view.slice(0, findViewIndex(cm, to)); + } + display.viewTo = to; + } + + // Count the number of lines in the view whose DOM representation is + // out of date (or nonexistent). + function countDirtyView(cm) { + var view = cm.display.view, dirty = 0; + for (var i = 0; i < view.length; i++) { + var lineView = view[i]; + if (!lineView.hidden && (!lineView.node || lineView.changes)) ++dirty; + } + return dirty; + } + + // EVENT HANDLERS + + // Attach the necessary event handlers when initializing the editor + function registerEventHandlers(cm) { + var d = cm.display; + on(d.scroller, "mousedown", operation(cm, onMouseDown)); + // Older IE's will not fire a second mousedown for a double click + if (ie && ie_version < 11) + on(d.scroller, "dblclick", operation(cm, function(e) { + if (signalDOMEvent(cm, e)) return; + var pos = posFromMouse(cm, e); + if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) return; + e_preventDefault(e); + var word = cm.findWordAt(pos); + extendSelection(cm.doc, word.anchor, word.head); + })); + else + on(d.scroller, "dblclick", function(e) { signalDOMEvent(cm, e) || e_preventDefault(e); }); + // Some browsers fire contextmenu *after* opening the menu, at + // which point we can't mess with it anymore. Context menu is + // handled in onMouseDown for these browsers. + if (!captureRightClick) on(d.scroller, "contextmenu", function(e) {onContextMenu(cm, e);}); + + // Used to suppress mouse event handling when a touch happens + var touchFinished, prevTouch = {end: 0}; + function finishTouch() { + if (d.activeTouch) { + touchFinished = setTimeout(function() {d.activeTouch = null;}, 1000); + prevTouch = d.activeTouch; + prevTouch.end = +new Date; + } + }; + function isMouseLikeTouchEvent(e) { + if (e.touches.length != 1) return false; + var touch = e.touches[0]; + return touch.radiusX <= 1 && touch.radiusY <= 1; + } + function farAway(touch, other) { + if (other.left == null) return true; + var dx = other.left - touch.left, dy = other.top - touch.top; + return dx * dx + dy * dy > 20 * 20; + } + on(d.scroller, "touchstart", function(e) { + if (!signalDOMEvent(cm, e) && !isMouseLikeTouchEvent(e)) { + clearTimeout(touchFinished); + var now = +new Date; + d.activeTouch = {start: now, moved: false, + prev: now - prevTouch.end <= 300 ? prevTouch : null}; + if (e.touches.length == 1) { + d.activeTouch.left = e.touches[0].pageX; + d.activeTouch.top = e.touches[0].pageY; + } + } + }); + on(d.scroller, "touchmove", function() { + if (d.activeTouch) d.activeTouch.moved = true; + }); + on(d.scroller, "touchend", function(e) { + var touch = d.activeTouch; + if (touch && !eventInWidget(d, e) && touch.left != null && + !touch.moved && new Date - touch.start < 300) { + var pos = cm.coordsChar(d.activeTouch, "page"), range; + if (!touch.prev || farAway(touch, touch.prev)) // Single tap + range = new Range(pos, pos); + else if (!touch.prev.prev || farAway(touch, touch.prev.prev)) // Double tap + range = cm.findWordAt(pos); + else // Triple tap + range = new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0))); + cm.setSelection(range.anchor, range.head); + cm.focus(); + e_preventDefault(e); + } + finishTouch(); + }); + on(d.scroller, "touchcancel", finishTouch); + + // Sync scrolling between fake scrollbars and real scrollable + // area, ensure viewport is updated when scrolling. + on(d.scroller, "scroll", function() { + if (d.scroller.clientHeight) { + setScrollTop(cm, d.scroller.scrollTop); + setScrollLeft(cm, d.scroller.scrollLeft, true); + signal(cm, "scroll", cm); + } + }); + + // Listen to wheel events in order to try and update the viewport on time. + on(d.scroller, "mousewheel", function(e){onScrollWheel(cm, e);}); + on(d.scroller, "DOMMouseScroll", function(e){onScrollWheel(cm, e);}); + + // Prevent wrapper from ever scrolling + on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; }); + + d.dragFunctions = { + enter: function(e) {if (!signalDOMEvent(cm, e)) e_stop(e);}, + over: function(e) {if (!signalDOMEvent(cm, e)) { onDragOver(cm, e); e_stop(e); }}, + start: function(e){onDragStart(cm, e);}, + drop: operation(cm, onDrop), + leave: function(e) {if (!signalDOMEvent(cm, e)) { clearDragCursor(cm); }} + }; + + var inp = d.input.getField(); + on(inp, "keyup", function(e) { onKeyUp.call(cm, e); }); + on(inp, "keydown", operation(cm, onKeyDown)); + on(inp, "keypress", operation(cm, onKeyPress)); + on(inp, "focus", bind(onFocus, cm)); + on(inp, "blur", bind(onBlur, cm)); + } + + function dragDropChanged(cm, value, old) { + var wasOn = old && old != CodeMirror.Init; + if (!value != !wasOn) { + var funcs = cm.display.dragFunctions; + var toggle = value ? on : off; + toggle(cm.display.scroller, "dragstart", funcs.start); + toggle(cm.display.scroller, "dragenter", funcs.enter); + toggle(cm.display.scroller, "dragover", funcs.over); + toggle(cm.display.scroller, "dragleave", funcs.leave); + toggle(cm.display.scroller, "drop", funcs.drop); + } + } + + // Called when the window resizes + function onResize(cm) { + var d = cm.display; + if (d.lastWrapHeight == d.wrapper.clientHeight && d.lastWrapWidth == d.wrapper.clientWidth) + return; + // Might be a text scaling operation, clear size caches. + d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null; + d.scrollbarsClipped = false; + cm.setSize(); + } + + // MOUSE EVENTS + + // Return true when the given mouse event happened in a widget + function eventInWidget(display, e) { + for (var n = e_target(e); n != display.wrapper; n = n.parentNode) { + if (!n || (n.nodeType == 1 && n.getAttribute("cm-ignore-events") == "true") || + (n.parentNode == display.sizer && n != display.mover)) + return true; + } + } + + // Given a mouse event, find the corresponding position. If liberal + // is false, it checks whether a gutter or scrollbar was clicked, + // and returns null if it was. forRect is used by rectangular + // selections, and tries to estimate a character position even for + // coordinates beyond the right of the text. + function posFromMouse(cm, e, liberal, forRect) { + var display = cm.display; + if (!liberal && e_target(e).getAttribute("cm-not-content") == "true") return null; + + var x, y, space = display.lineSpace.getBoundingClientRect(); + // Fails unpredictably on IE[67] when mouse is dragged around quickly. + try { x = e.clientX - space.left; y = e.clientY - space.top; } + catch (e) { return null; } + var coords = coordsChar(cm, x, y), line; + if (forRect && coords.xRel == 1 && (line = getLine(cm.doc, coords.line).text).length == coords.ch) { + var colDiff = countColumn(line, line.length, cm.options.tabSize) - line.length; + coords = Pos(coords.line, Math.max(0, Math.round((x - paddingH(cm.display).left) / charWidth(cm.display)) - colDiff)); + } + return coords; + } + + // A mouse down can be a single click, double click, triple click, + // start of selection drag, start of text drag, new cursor + // (ctrl-click), rectangle drag (alt-drag), or xwin + // middle-click-paste. Or it might be a click on something we should + // not interfere with, such as a scrollbar or widget. + function onMouseDown(e) { + var cm = this, display = cm.display; + if (signalDOMEvent(cm, e) || display.activeTouch && display.input.supportsTouch()) return; + display.shift = e.shiftKey; + + if (eventInWidget(display, e)) { + if (!webkit) { + // Briefly turn off draggability, to allow widgets to do + // normal dragging things. + display.scroller.draggable = false; + setTimeout(function(){display.scroller.draggable = true;}, 100); + } + return; + } + if (clickInGutter(cm, e)) return; + var start = posFromMouse(cm, e); + window.focus(); + + switch (e_button(e)) { + case 1: + // #3261: make sure, that we're not starting a second selection + if (cm.state.selectingText) + cm.state.selectingText(e); + else if (start) + leftButtonDown(cm, e, start); + else if (e_target(e) == display.scroller) + e_preventDefault(e); + break; + case 2: + if (webkit) cm.state.lastMiddleDown = +new Date; + if (start) extendSelection(cm.doc, start); + setTimeout(function() {display.input.focus();}, 20); + e_preventDefault(e); + break; + case 3: + if (captureRightClick) onContextMenu(cm, e); + else delayBlurEvent(cm); + break; + } + } + + var lastClick, lastDoubleClick; + function leftButtonDown(cm, e, start) { + if (ie) setTimeout(bind(ensureFocus, cm), 0); + else cm.curOp.focus = activeElt(); + + var now = +new Date, type; + if (lastDoubleClick && lastDoubleClick.time > now - 400 && cmp(lastDoubleClick.pos, start) == 0) { + type = "triple"; + } else if (lastClick && lastClick.time > now - 400 && cmp(lastClick.pos, start) == 0) { + type = "double"; + lastDoubleClick = {time: now, pos: start}; + } else { + type = "single"; + lastClick = {time: now, pos: start}; + } + + var sel = cm.doc.sel, modifier = mac ? e.metaKey : e.ctrlKey, contained; + if (cm.options.dragDrop && dragAndDrop && !cm.isReadOnly() && + type == "single" && (contained = sel.contains(start)) > -1 && + (cmp((contained = sel.ranges[contained]).from(), start) < 0 || start.xRel > 0) && + (cmp(contained.to(), start) > 0 || start.xRel < 0)) + leftButtonStartDrag(cm, e, start, modifier); + else + leftButtonSelect(cm, e, start, type, modifier); + } + + // Start a text drag. When it ends, see if any dragging actually + // happen, and treat as a click if it didn't. + function leftButtonStartDrag(cm, e, start, modifier) { + var display = cm.display, startTime = +new Date; + var dragEnd = operation(cm, function(e2) { + if (webkit) display.scroller.draggable = false; + cm.state.draggingText = false; + off(document, "mouseup", dragEnd); + off(display.scroller, "drop", dragEnd); + if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) { + e_preventDefault(e2); + if (!modifier && +new Date - 200 < startTime) + extendSelection(cm.doc, start); + // Work around unexplainable focus problem in IE9 (#2127) and Chrome (#3081) + if (webkit || ie && ie_version == 9) + setTimeout(function() {document.body.focus(); display.input.focus();}, 20); + else + display.input.focus(); + } + }); + // Let the drag handler handle this. + if (webkit) display.scroller.draggable = true; + cm.state.draggingText = dragEnd; + dragEnd.copy = mac ? e.altKey : e.ctrlKey + // IE's approach to draggable + if (display.scroller.dragDrop) display.scroller.dragDrop(); + on(document, "mouseup", dragEnd); + on(display.scroller, "drop", dragEnd); + } + + // Normal selection, as opposed to text dragging. + function leftButtonSelect(cm, e, start, type, addNew) { + var display = cm.display, doc = cm.doc; + e_preventDefault(e); + + var ourRange, ourIndex, startSel = doc.sel, ranges = startSel.ranges; + if (addNew && !e.shiftKey) { + ourIndex = doc.sel.contains(start); + if (ourIndex > -1) + ourRange = ranges[ourIndex]; + else + ourRange = new Range(start, start); + } else { + ourRange = doc.sel.primary(); + ourIndex = doc.sel.primIndex; + } + + if (chromeOS ? e.shiftKey && e.metaKey : e.altKey) { + type = "rect"; + if (!addNew) ourRange = new Range(start, start); + start = posFromMouse(cm, e, true, true); + ourIndex = -1; + } else if (type == "double") { + var word = cm.findWordAt(start); + if (cm.display.shift || doc.extend) + ourRange = extendRange(doc, ourRange, word.anchor, word.head); + else + ourRange = word; + } else if (type == "triple") { + var line = new Range(Pos(start.line, 0), clipPos(doc, Pos(start.line + 1, 0))); + if (cm.display.shift || doc.extend) + ourRange = extendRange(doc, ourRange, line.anchor, line.head); + else + ourRange = line; + } else { + ourRange = extendRange(doc, ourRange, start); + } + + if (!addNew) { + ourIndex = 0; + setSelection(doc, new Selection([ourRange], 0), sel_mouse); + startSel = doc.sel; + } else if (ourIndex == -1) { + ourIndex = ranges.length; + setSelection(doc, normalizeSelection(ranges.concat([ourRange]), ourIndex), + {scroll: false, origin: "*mouse"}); + } else if (ranges.length > 1 && ranges[ourIndex].empty() && type == "single" && !e.shiftKey) { + setSelection(doc, normalizeSelection(ranges.slice(0, ourIndex).concat(ranges.slice(ourIndex + 1)), 0), + {scroll: false, origin: "*mouse"}); + startSel = doc.sel; + } else { + replaceOneSelection(doc, ourIndex, ourRange, sel_mouse); + } + + var lastPos = start; + function extendTo(pos) { + if (cmp(lastPos, pos) == 0) return; + lastPos = pos; + + if (type == "rect") { + var ranges = [], tabSize = cm.options.tabSize; + var startCol = countColumn(getLine(doc, start.line).text, start.ch, tabSize); + var posCol = countColumn(getLine(doc, pos.line).text, pos.ch, tabSize); + var left = Math.min(startCol, posCol), right = Math.max(startCol, posCol); + for (var line = Math.min(start.line, pos.line), end = Math.min(cm.lastLine(), Math.max(start.line, pos.line)); + line <= end; line++) { + var text = getLine(doc, line).text, leftPos = findColumn(text, left, tabSize); + if (left == right) + ranges.push(new Range(Pos(line, leftPos), Pos(line, leftPos))); + else if (text.length > leftPos) + ranges.push(new Range(Pos(line, leftPos), Pos(line, findColumn(text, right, tabSize)))); + } + if (!ranges.length) ranges.push(new Range(start, start)); + setSelection(doc, normalizeSelection(startSel.ranges.slice(0, ourIndex).concat(ranges), ourIndex), + {origin: "*mouse", scroll: false}); + cm.scrollIntoView(pos); + } else { + var oldRange = ourRange; + var anchor = oldRange.anchor, head = pos; + if (type != "single") { + if (type == "double") + var range = cm.findWordAt(pos); + else + var range = new Range(Pos(pos.line, 0), clipPos(doc, Pos(pos.line + 1, 0))); + if (cmp(range.anchor, anchor) > 0) { + head = range.head; + anchor = minPos(oldRange.from(), range.anchor); + } else { + head = range.anchor; + anchor = maxPos(oldRange.to(), range.head); + } + } + var ranges = startSel.ranges.slice(0); + ranges[ourIndex] = new Range(clipPos(doc, anchor), head); + setSelection(doc, normalizeSelection(ranges, ourIndex), sel_mouse); + } + } + + var editorSize = display.wrapper.getBoundingClientRect(); + // Used to ensure timeout re-tries don't fire when another extend + // happened in the meantime (clearTimeout isn't reliable -- at + // least on Chrome, the timeouts still happen even when cleared, + // if the clear happens after their scheduled firing time). + var counter = 0; + + function extend(e) { + var curCount = ++counter; + var cur = posFromMouse(cm, e, true, type == "rect"); + if (!cur) return; + if (cmp(cur, lastPos) != 0) { + cm.curOp.focus = activeElt(); + extendTo(cur); + var visible = visibleLines(display, doc); + if (cur.line >= visible.to || cur.line < visible.from) + setTimeout(operation(cm, function(){if (counter == curCount) extend(e);}), 150); + } else { + var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0; + if (outside) setTimeout(operation(cm, function() { + if (counter != curCount) return; + display.scroller.scrollTop += outside; + extend(e); + }), 50); + } + } + + function done(e) { + cm.state.selectingText = false; + counter = Infinity; + e_preventDefault(e); + display.input.focus(); + off(document, "mousemove", move); + off(document, "mouseup", up); + doc.history.lastSelOrigin = null; + } + + var move = operation(cm, function(e) { + if (!e_button(e)) done(e); + else extend(e); + }); + var up = operation(cm, done); + cm.state.selectingText = up; + on(document, "mousemove", move); + on(document, "mouseup", up); + } + + // Determines whether an event happened in the gutter, and fires the + // handlers for the corresponding event. + function gutterEvent(cm, e, type, prevent) { + try { var mX = e.clientX, mY = e.clientY; } + catch(e) { return false; } + if (mX >= Math.floor(cm.display.gutters.getBoundingClientRect().right)) return false; + if (prevent) e_preventDefault(e); + + var display = cm.display; + var lineBox = display.lineDiv.getBoundingClientRect(); + + if (mY > lineBox.bottom || !hasHandler(cm, type)) return e_defaultPrevented(e); + mY -= lineBox.top - display.viewOffset; + + for (var i = 0; i < cm.options.gutters.length; ++i) { + var g = display.gutters.childNodes[i]; + if (g && g.getBoundingClientRect().right >= mX) { + var line = lineAtHeight(cm.doc, mY); + var gutter = cm.options.gutters[i]; + signal(cm, type, cm, line, gutter, e); + return e_defaultPrevented(e); + } + } + } + + function clickInGutter(cm, e) { + return gutterEvent(cm, e, "gutterClick", true); + } + + // Kludge to work around strange IE behavior where it'll sometimes + // re-fire a series of drag-related events right after the drop (#1551) + var lastDrop = 0; + + function onDrop(e) { + var cm = this; + clearDragCursor(cm); + if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) + return; + e_preventDefault(e); + if (ie) lastDrop = +new Date; + var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files; + if (!pos || cm.isReadOnly()) return; + // Might be a file drop, in which case we simply extract the text + // and insert it. + if (files && files.length && window.FileReader && window.File) { + var n = files.length, text = Array(n), read = 0; + var loadFile = function(file, i) { + if (cm.options.allowDropFileTypes && + indexOf(cm.options.allowDropFileTypes, file.type) == -1) + return; + + var reader = new FileReader; + reader.onload = operation(cm, function() { + var content = reader.result; + if (/[\x00-\x08\x0e-\x1f]{2}/.test(content)) content = ""; + text[i] = content; + if (++read == n) { + pos = clipPos(cm.doc, pos); + var change = {from: pos, to: pos, + text: cm.doc.splitLines(text.join(cm.doc.lineSeparator())), + origin: "paste"}; + makeChange(cm.doc, change); + setSelectionReplaceHistory(cm.doc, simpleSelection(pos, changeEnd(change))); + } + }); + reader.readAsText(file); + }; + for (var i = 0; i < n; ++i) loadFile(files[i], i); + } else { // Normal drop + // Don't do a replace if the drop happened inside of the selected text. + if (cm.state.draggingText && cm.doc.sel.contains(pos) > -1) { + cm.state.draggingText(e); + // Ensure the editor is re-focused + setTimeout(function() {cm.display.input.focus();}, 20); + return; + } + try { + var text = e.dataTransfer.getData("Text"); + if (text) { + if (cm.state.draggingText && !cm.state.draggingText.copy) + var selected = cm.listSelections(); + setSelectionNoUndo(cm.doc, simpleSelection(pos, pos)); + if (selected) for (var i = 0; i < selected.length; ++i) + replaceRange(cm.doc, "", selected[i].anchor, selected[i].head, "drag"); + cm.replaceSelection(text, "around", "paste"); + cm.display.input.focus(); + } + } + catch(e){} + } + } + + function onDragStart(cm, e) { + if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return; } + if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) return; + + e.dataTransfer.setData("Text", cm.getSelection()); + e.dataTransfer.effectAllowed = "copyMove" + + // Use dummy image instead of default browsers image. + // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there. + if (e.dataTransfer.setDragImage && !safari) { + var img = elt("img", null, null, "position: fixed; left: 0; top: 0;"); + img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="; + if (presto) { + img.width = img.height = 1; + cm.display.wrapper.appendChild(img); + // Force a relayout, or Opera won't use our image for some obscure reason + img._top = img.offsetTop; + } + e.dataTransfer.setDragImage(img, 0, 0); + if (presto) img.parentNode.removeChild(img); + } + } + + function onDragOver(cm, e) { + var pos = posFromMouse(cm, e); + if (!pos) return; + var frag = document.createDocumentFragment(); + drawSelectionCursor(cm, pos, frag); + if (!cm.display.dragCursor) { + cm.display.dragCursor = elt("div", null, "CodeMirror-cursors CodeMirror-dragcursors"); + cm.display.lineSpace.insertBefore(cm.display.dragCursor, cm.display.cursorDiv); + } + removeChildrenAndAdd(cm.display.dragCursor, frag); + } + + function clearDragCursor(cm) { + if (cm.display.dragCursor) { + cm.display.lineSpace.removeChild(cm.display.dragCursor); + cm.display.dragCursor = null; + } + } + + // SCROLL EVENTS + + // Sync the scrollable area and scrollbars, ensure the viewport + // covers the visible area. + function setScrollTop(cm, val) { + if (Math.abs(cm.doc.scrollTop - val) < 2) return; + cm.doc.scrollTop = val; + if (!gecko) updateDisplaySimple(cm, {top: val}); + if (cm.display.scroller.scrollTop != val) cm.display.scroller.scrollTop = val; + cm.display.scrollbars.setScrollTop(val); + if (gecko) updateDisplaySimple(cm); + startWorker(cm, 100); + } + // Sync scroller and scrollbar, ensure the gutter elements are + // aligned. + function setScrollLeft(cm, val, isScroller) { + if (isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) return; + val = Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth); + cm.doc.scrollLeft = val; + alignHorizontally(cm); + if (cm.display.scroller.scrollLeft != val) cm.display.scroller.scrollLeft = val; + cm.display.scrollbars.setScrollLeft(val); + } + + // Since the delta values reported on mouse wheel events are + // unstandardized between browsers and even browser versions, and + // generally horribly unpredictable, this code starts by measuring + // the scroll effect that the first few mouse wheel events have, + // and, from that, detects the way it can convert deltas to pixel + // offsets afterwards. + // + // The reason we want to know the amount a wheel event will scroll + // is that it gives us a chance to update the display before the + // actual scrolling happens, reducing flickering. + + var wheelSamples = 0, wheelPixelsPerUnit = null; + // Fill in a browser-detected starting value on browsers where we + // know one. These don't have to be accurate -- the result of them + // being wrong would just be a slight flicker on the first wheel + // scroll (if it is large enough). + if (ie) wheelPixelsPerUnit = -.53; + else if (gecko) wheelPixelsPerUnit = 15; + else if (chrome) wheelPixelsPerUnit = -.7; + else if (safari) wheelPixelsPerUnit = -1/3; + + var wheelEventDelta = function(e) { + var dx = e.wheelDeltaX, dy = e.wheelDeltaY; + if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) dx = e.detail; + if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) dy = e.detail; + else if (dy == null) dy = e.wheelDelta; + return {x: dx, y: dy}; + }; + CodeMirror.wheelEventPixels = function(e) { + var delta = wheelEventDelta(e); + delta.x *= wheelPixelsPerUnit; + delta.y *= wheelPixelsPerUnit; + return delta; + }; + + function onScrollWheel(cm, e) { + var delta = wheelEventDelta(e), dx = delta.x, dy = delta.y; + + var display = cm.display, scroll = display.scroller; + // Quit if there's nothing to scroll here + var canScrollX = scroll.scrollWidth > scroll.clientWidth; + var canScrollY = scroll.scrollHeight > scroll.clientHeight; + if (!(dx && canScrollX || dy && canScrollY)) return; + + // Webkit browsers on OS X abort momentum scrolls when the target + // of the scroll event is removed from the scrollable element. + // This hack (see related code in patchDisplay) makes sure the + // element is kept around. + if (dy && mac && webkit) { + outer: for (var cur = e.target, view = display.view; cur != scroll; cur = cur.parentNode) { + for (var i = 0; i < view.length; i++) { + if (view[i].node == cur) { + cm.display.currentWheelTarget = cur; + break outer; + } + } + } + } + + // On some browsers, horizontal scrolling will cause redraws to + // happen before the gutter has been realigned, causing it to + // wriggle around in a most unseemly way. When we have an + // estimated pixels/delta value, we just handle horizontal + // scrolling entirely here. It'll be slightly off from native, but + // better than glitching out. + if (dx && !gecko && !presto && wheelPixelsPerUnit != null) { + if (dy && canScrollY) + setScrollTop(cm, Math.max(0, Math.min(scroll.scrollTop + dy * wheelPixelsPerUnit, scroll.scrollHeight - scroll.clientHeight))); + setScrollLeft(cm, Math.max(0, Math.min(scroll.scrollLeft + dx * wheelPixelsPerUnit, scroll.scrollWidth - scroll.clientWidth))); + // Only prevent default scrolling if vertical scrolling is + // actually possible. Otherwise, it causes vertical scroll + // jitter on OSX trackpads when deltaX is small and deltaY + // is large (issue #3579) + if (!dy || (dy && canScrollY)) + e_preventDefault(e); + display.wheelStartX = null; // Abort measurement, if in progress + return; + } + + // 'Project' the visible viewport to cover the area that is being + // scrolled into view (if we know enough to estimate it). + if (dy && wheelPixelsPerUnit != null) { + var pixels = dy * wheelPixelsPerUnit; + var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight; + if (pixels < 0) top = Math.max(0, top + pixels - 50); + else bot = Math.min(cm.doc.height, bot + pixels + 50); + updateDisplaySimple(cm, {top: top, bottom: bot}); + } + + if (wheelSamples < 20) { + if (display.wheelStartX == null) { + display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop; + display.wheelDX = dx; display.wheelDY = dy; + setTimeout(function() { + if (display.wheelStartX == null) return; + var movedX = scroll.scrollLeft - display.wheelStartX; + var movedY = scroll.scrollTop - display.wheelStartY; + var sample = (movedY && display.wheelDY && movedY / display.wheelDY) || + (movedX && display.wheelDX && movedX / display.wheelDX); + display.wheelStartX = display.wheelStartY = null; + if (!sample) return; + wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1); + ++wheelSamples; + }, 200); + } else { + display.wheelDX += dx; display.wheelDY += dy; + } + } + } + + // KEY EVENTS + + // Run a handler that was bound to a key. + function doHandleBinding(cm, bound, dropShift) { + if (typeof bound == "string") { + bound = commands[bound]; + if (!bound) return false; + } + // Ensure previous input has been read, so that the handler sees a + // consistent view of the document + cm.display.input.ensurePolled(); + var prevShift = cm.display.shift, done = false; + try { + if (cm.isReadOnly()) cm.state.suppressEdits = true; + if (dropShift) cm.display.shift = false; + done = bound(cm) != Pass; + } finally { + cm.display.shift = prevShift; + cm.state.suppressEdits = false; + } + return done; + } + + function lookupKeyForEditor(cm, name, handle) { + for (var i = 0; i < cm.state.keyMaps.length; i++) { + var result = lookupKey(name, cm.state.keyMaps[i], handle, cm); + if (result) return result; + } + return (cm.options.extraKeys && lookupKey(name, cm.options.extraKeys, handle, cm)) + || lookupKey(name, cm.options.keyMap, handle, cm); + } + + var stopSeq = new Delayed; + function dispatchKey(cm, name, e, handle) { + var seq = cm.state.keySeq; + if (seq) { + if (isModifierKey(name)) return "handled"; + stopSeq.set(50, function() { + if (cm.state.keySeq == seq) { + cm.state.keySeq = null; + cm.display.input.reset(); + } + }); + name = seq + " " + name; + } + var result = lookupKeyForEditor(cm, name, handle); + + if (result == "multi") + cm.state.keySeq = name; + if (result == "handled") + signalLater(cm, "keyHandled", cm, name, e); + + if (result == "handled" || result == "multi") { + e_preventDefault(e); + restartBlink(cm); + } + + if (seq && !result && /\'$/.test(name)) { + e_preventDefault(e); + return true; + } + return !!result; + } + + // Handle a key from the keydown event. + function handleKeyBinding(cm, e) { + var name = keyName(e, true); + if (!name) return false; + + if (e.shiftKey && !cm.state.keySeq) { + // First try to resolve full name (including 'Shift-'). Failing + // that, see if there is a cursor-motion command (starting with + // 'go') bound to the keyname without 'Shift-'. + return dispatchKey(cm, "Shift-" + name, e, function(b) {return doHandleBinding(cm, b, true);}) + || dispatchKey(cm, name, e, function(b) { + if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion) + return doHandleBinding(cm, b); + }); + } else { + return dispatchKey(cm, name, e, function(b) { return doHandleBinding(cm, b); }); + } + } + + // Handle a key from the keypress event + function handleCharBinding(cm, e, ch) { + return dispatchKey(cm, "'" + ch + "'", e, + function(b) { return doHandleBinding(cm, b, true); }); + } + + var lastStoppedKey = null; + function onKeyDown(e) { + var cm = this; + cm.curOp.focus = activeElt(); + if (signalDOMEvent(cm, e)) return; + // IE does strange things with escape. + if (ie && ie_version < 11 && e.keyCode == 27) e.returnValue = false; + var code = e.keyCode; + cm.display.shift = code == 16 || e.shiftKey; + var handled = handleKeyBinding(cm, e); + if (presto) { + lastStoppedKey = handled ? code : null; + // Opera has no cut event... we try to at least catch the key combo + if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey)) + cm.replaceSelection("", null, "cut"); + } + + // Turn mouse into crosshair when Alt is held on Mac. + if (code == 18 && !/\bCodeMirror-crosshair\b/.test(cm.display.lineDiv.className)) + showCrossHair(cm); + } + + function showCrossHair(cm) { + var lineDiv = cm.display.lineDiv; + addClass(lineDiv, "CodeMirror-crosshair"); + + function up(e) { + if (e.keyCode == 18 || !e.altKey) { + rmClass(lineDiv, "CodeMirror-crosshair"); + off(document, "keyup", up); + off(document, "mouseover", up); + } + } + on(document, "keyup", up); + on(document, "mouseover", up); + } + + function onKeyUp(e) { + if (e.keyCode == 16) this.doc.sel.shift = false; + signalDOMEvent(this, e); + } + + function onKeyPress(e) { + var cm = this; + if (eventInWidget(cm.display, e) || signalDOMEvent(cm, e) || e.ctrlKey && !e.altKey || mac && e.metaKey) return; + var keyCode = e.keyCode, charCode = e.charCode; + if (presto && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;} + if ((presto && (!e.which || e.which < 10)) && handleKeyBinding(cm, e)) return; + var ch = String.fromCharCode(charCode == null ? keyCode : charCode); + if (handleCharBinding(cm, e, ch)) return; + cm.display.input.onKeyPress(e); + } + + // FOCUS/BLUR EVENTS + + function delayBlurEvent(cm) { + cm.state.delayingBlurEvent = true; + setTimeout(function() { + if (cm.state.delayingBlurEvent) { + cm.state.delayingBlurEvent = false; + onBlur(cm); + } + }, 100); + } + + function onFocus(cm) { + if (cm.state.delayingBlurEvent) cm.state.delayingBlurEvent = false; + + if (cm.options.readOnly == "nocursor") return; + if (!cm.state.focused) { + signal(cm, "focus", cm); + cm.state.focused = true; + addClass(cm.display.wrapper, "CodeMirror-focused"); + // This test prevents this from firing when a context + // menu is closed (since the input reset would kill the + // select-all detection hack) + if (!cm.curOp && cm.display.selForContextMenu != cm.doc.sel) { + cm.display.input.reset(); + if (webkit) setTimeout(function() { cm.display.input.reset(true); }, 20); // Issue #1730 + } + cm.display.input.receivedFocus(); + } + restartBlink(cm); + } + function onBlur(cm) { + if (cm.state.delayingBlurEvent) return; + + if (cm.state.focused) { + signal(cm, "blur", cm); + cm.state.focused = false; + rmClass(cm.display.wrapper, "CodeMirror-focused"); + } + clearInterval(cm.display.blinker); + setTimeout(function() {if (!cm.state.focused) cm.display.shift = false;}, 150); + } + + // CONTEXT MENU HANDLING + + // To make the context menu work, we need to briefly unhide the + // textarea (making it as unobtrusive as possible) to let the + // right-click take effect on it. + function onContextMenu(cm, e) { + if (eventInWidget(cm.display, e) || contextMenuInGutter(cm, e)) return; + if (signalDOMEvent(cm, e, "contextmenu")) return; + cm.display.input.onContextMenu(e); + } + + function contextMenuInGutter(cm, e) { + if (!hasHandler(cm, "gutterContextMenu")) return false; + return gutterEvent(cm, e, "gutterContextMenu", false); + } + + // UPDATING + + // Compute the position of the end of a change (its 'to' property + // refers to the pre-change end). + var changeEnd = CodeMirror.changeEnd = function(change) { + if (!change.text) return change.to; + return Pos(change.from.line + change.text.length - 1, + lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0)); + }; + + // Adjust a position to refer to the post-change position of the + // same text, or the end of the change if the change covers it. + function adjustForChange(pos, change) { + if (cmp(pos, change.from) < 0) return pos; + if (cmp(pos, change.to) <= 0) return changeEnd(change); + + var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch; + if (pos.line == change.to.line) ch += changeEnd(change).ch - change.to.ch; + return Pos(line, ch); + } + + function computeSelAfterChange(doc, change) { + var out = []; + for (var i = 0; i < doc.sel.ranges.length; i++) { + var range = doc.sel.ranges[i]; + out.push(new Range(adjustForChange(range.anchor, change), + adjustForChange(range.head, change))); + } + return normalizeSelection(out, doc.sel.primIndex); + } + + function offsetPos(pos, old, nw) { + if (pos.line == old.line) + return Pos(nw.line, pos.ch - old.ch + nw.ch); + else + return Pos(nw.line + (pos.line - old.line), pos.ch); + } + + // Used by replaceSelections to allow moving the selection to the + // start or around the replaced test. Hint may be "start" or "around". + function computeReplacedSel(doc, changes, hint) { + var out = []; + var oldPrev = Pos(doc.first, 0), newPrev = oldPrev; + for (var i = 0; i < changes.length; i++) { + var change = changes[i]; + var from = offsetPos(change.from, oldPrev, newPrev); + var to = offsetPos(changeEnd(change), oldPrev, newPrev); + oldPrev = change.to; + newPrev = to; + if (hint == "around") { + var range = doc.sel.ranges[i], inv = cmp(range.head, range.anchor) < 0; + out[i] = new Range(inv ? to : from, inv ? from : to); + } else { + out[i] = new Range(from, from); + } + } + return new Selection(out, doc.sel.primIndex); + } + + // Allow "beforeChange" event handlers to influence a change + function filterChange(doc, change, update) { + var obj = { + canceled: false, + from: change.from, + to: change.to, + text: change.text, + origin: change.origin, + cancel: function() { this.canceled = true; } + }; + if (update) obj.update = function(from, to, text, origin) { + if (from) this.from = clipPos(doc, from); + if (to) this.to = clipPos(doc, to); + if (text) this.text = text; + if (origin !== undefined) this.origin = origin; + }; + signal(doc, "beforeChange", doc, obj); + if (doc.cm) signal(doc.cm, "beforeChange", doc.cm, obj); + + if (obj.canceled) return null; + return {from: obj.from, to: obj.to, text: obj.text, origin: obj.origin}; + } + + // Apply a change to a document, and add it to the document's + // history, and propagating it to all linked documents. + function makeChange(doc, change, ignoreReadOnly) { + if (doc.cm) { + if (!doc.cm.curOp) return operation(doc.cm, makeChange)(doc, change, ignoreReadOnly); + if (doc.cm.state.suppressEdits) return; + } + + if (hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")) { + change = filterChange(doc, change, true); + if (!change) return; + } + + // Possibly split or suppress the update based on the presence + // of read-only spans in its range. + var split = sawReadOnlySpans && !ignoreReadOnly && removeReadOnlyRanges(doc, change.from, change.to); + if (split) { + for (var i = split.length - 1; i >= 0; --i) + makeChangeInner(doc, {from: split[i].from, to: split[i].to, text: i ? [""] : change.text}); + } else { + makeChangeInner(doc, change); + } + } + + function makeChangeInner(doc, change) { + if (change.text.length == 1 && change.text[0] == "" && cmp(change.from, change.to) == 0) return; + var selAfter = computeSelAfterChange(doc, change); + addChangeToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN); + + makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change)); + var rebased = []; + + linkedDocs(doc, function(doc, sharedHist) { + if (!sharedHist && indexOf(rebased, doc.history) == -1) { + rebaseHist(doc.history, change); + rebased.push(doc.history); + } + makeChangeSingleDoc(doc, change, null, stretchSpansOverChange(doc, change)); + }); + } + + // Revert a change stored in a document's history. + function makeChangeFromHistory(doc, type, allowSelectionOnly) { + if (doc.cm && doc.cm.state.suppressEdits && !allowSelectionOnly) return; + + var hist = doc.history, event, selAfter = doc.sel; + var source = type == "undo" ? hist.done : hist.undone, dest = type == "undo" ? hist.undone : hist.done; + + // Verify that there is a useable event (so that ctrl-z won't + // needlessly clear selection events) + for (var i = 0; i < source.length; i++) { + event = source[i]; + if (allowSelectionOnly ? event.ranges && !event.equals(doc.sel) : !event.ranges) + break; + } + if (i == source.length) return; + hist.lastOrigin = hist.lastSelOrigin = null; + + for (;;) { + event = source.pop(); + if (event.ranges) { + pushSelectionToHistory(event, dest); + if (allowSelectionOnly && !event.equals(doc.sel)) { + setSelection(doc, event, {clearRedo: false}); + return; + } + selAfter = event; + } + else break; + } + + // Build up a reverse change object to add to the opposite history + // stack (redo when undoing, and vice versa). + var antiChanges = []; + pushSelectionToHistory(selAfter, dest); + dest.push({changes: antiChanges, generation: hist.generation}); + hist.generation = event.generation || ++hist.maxGeneration; + + var filter = hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange"); + + for (var i = event.changes.length - 1; i >= 0; --i) { + var change = event.changes[i]; + change.origin = type; + if (filter && !filterChange(doc, change, false)) { + source.length = 0; + return; + } + + antiChanges.push(historyChangeFromChange(doc, change)); + + var after = i ? computeSelAfterChange(doc, change) : lst(source); + makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change)); + if (!i && doc.cm) doc.cm.scrollIntoView({from: change.from, to: changeEnd(change)}); + var rebased = []; + + // Propagate to the linked documents + linkedDocs(doc, function(doc, sharedHist) { + if (!sharedHist && indexOf(rebased, doc.history) == -1) { + rebaseHist(doc.history, change); + rebased.push(doc.history); + } + makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change)); + }); + } + } + + // Sub-views need their line numbers shifted when text is added + // above or below them in the parent document. + function shiftDoc(doc, distance) { + if (distance == 0) return; + doc.first += distance; + doc.sel = new Selection(map(doc.sel.ranges, function(range) { + return new Range(Pos(range.anchor.line + distance, range.anchor.ch), + Pos(range.head.line + distance, range.head.ch)); + }), doc.sel.primIndex); + if (doc.cm) { + regChange(doc.cm, doc.first, doc.first - distance, distance); + for (var d = doc.cm.display, l = d.viewFrom; l < d.viewTo; l++) + regLineChange(doc.cm, l, "gutter"); + } + } + + // More lower-level change function, handling only a single document + // (not linked ones). + function makeChangeSingleDoc(doc, change, selAfter, spans) { + if (doc.cm && !doc.cm.curOp) + return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans); + + if (change.to.line < doc.first) { + shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line)); + return; + } + if (change.from.line > doc.lastLine()) return; + + // Clip the change to the size of this doc + if (change.from.line < doc.first) { + var shift = change.text.length - 1 - (doc.first - change.from.line); + shiftDoc(doc, shift); + change = {from: Pos(doc.first, 0), to: Pos(change.to.line + shift, change.to.ch), + text: [lst(change.text)], origin: change.origin}; + } + var last = doc.lastLine(); + if (change.to.line > last) { + change = {from: change.from, to: Pos(last, getLine(doc, last).text.length), + text: [change.text[0]], origin: change.origin}; + } + + change.removed = getBetween(doc, change.from, change.to); + + if (!selAfter) selAfter = computeSelAfterChange(doc, change); + if (doc.cm) makeChangeSingleDocInEditor(doc.cm, change, spans); + else updateDoc(doc, change, spans); + setSelectionNoUndo(doc, selAfter, sel_dontScroll); + } + + // Handle the interaction of a change to a document with the editor + // that this document is part of. + function makeChangeSingleDocInEditor(cm, change, spans) { + var doc = cm.doc, display = cm.display, from = change.from, to = change.to; + + var recomputeMaxLength = false, checkWidthStart = from.line; + if (!cm.options.lineWrapping) { + checkWidthStart = lineNo(visualLine(getLine(doc, from.line))); + doc.iter(checkWidthStart, to.line + 1, function(line) { + if (line == display.maxLine) { + recomputeMaxLength = true; + return true; + } + }); + } + + if (doc.sel.contains(change.from, change.to) > -1) + signalCursorActivity(cm); + + updateDoc(doc, change, spans, estimateHeight(cm)); + + if (!cm.options.lineWrapping) { + doc.iter(checkWidthStart, from.line + change.text.length, function(line) { + var len = lineLength(line); + if (len > display.maxLineLength) { + display.maxLine = line; + display.maxLineLength = len; + display.maxLineChanged = true; + recomputeMaxLength = false; + } + }); + if (recomputeMaxLength) cm.curOp.updateMaxLine = true; + } + + // Adjust frontier, schedule worker + doc.frontier = Math.min(doc.frontier, from.line); + startWorker(cm, 400); + + var lendiff = change.text.length - (to.line - from.line) - 1; + // Remember that these lines changed, for updating the display + if (change.full) + regChange(cm); + else if (from.line == to.line && change.text.length == 1 && !isWholeLineUpdate(cm.doc, change)) + regLineChange(cm, from.line, "text"); + else + regChange(cm, from.line, to.line + 1, lendiff); + + var changesHandler = hasHandler(cm, "changes"), changeHandler = hasHandler(cm, "change"); + if (changeHandler || changesHandler) { + var obj = { + from: from, to: to, + text: change.text, + removed: change.removed, + origin: change.origin + }; + if (changeHandler) signalLater(cm, "change", cm, obj); + if (changesHandler) (cm.curOp.changeObjs || (cm.curOp.changeObjs = [])).push(obj); + } + cm.display.selForContextMenu = null; + } + + function replaceRange(doc, code, from, to, origin) { + if (!to) to = from; + if (cmp(to, from) < 0) { var tmp = to; to = from; from = tmp; } + if (typeof code == "string") code = doc.splitLines(code); + makeChange(doc, {from: from, to: to, text: code, origin: origin}); + } + + // SCROLLING THINGS INTO VIEW + + // If an editor sits on the top or bottom of the window, partially + // scrolled out of view, this ensures that the cursor is visible. + function maybeScrollWindow(cm, coords) { + if (signalDOMEvent(cm, "scrollCursorIntoView")) return; + + var display = cm.display, box = display.sizer.getBoundingClientRect(), doScroll = null; + if (coords.top + box.top < 0) doScroll = true; + else if (coords.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) doScroll = false; + if (doScroll != null && !phantom) { + var scrollNode = elt("div", "\u200b", null, "position: absolute; top: " + + (coords.top - display.viewOffset - paddingTop(cm.display)) + "px; height: " + + (coords.bottom - coords.top + scrollGap(cm) + display.barHeight) + "px; left: " + + coords.left + "px; width: 2px;"); + cm.display.lineSpace.appendChild(scrollNode); + scrollNode.scrollIntoView(doScroll); + cm.display.lineSpace.removeChild(scrollNode); + } + } + + // Scroll a given position into view (immediately), verifying that + // it actually became visible (as line heights are accurately + // measured, the position of something may 'drift' during drawing). + function scrollPosIntoView(cm, pos, end, margin) { + if (margin == null) margin = 0; + for (var limit = 0; limit < 5; limit++) { + var changed = false, coords = cursorCoords(cm, pos); + var endCoords = !end || end == pos ? coords : cursorCoords(cm, end); + var scrollPos = calculateScrollPos(cm, Math.min(coords.left, endCoords.left), + Math.min(coords.top, endCoords.top) - margin, + Math.max(coords.left, endCoords.left), + Math.max(coords.bottom, endCoords.bottom) + margin); + var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft; + if (scrollPos.scrollTop != null) { + setScrollTop(cm, scrollPos.scrollTop); + if (Math.abs(cm.doc.scrollTop - startTop) > 1) changed = true; + } + if (scrollPos.scrollLeft != null) { + setScrollLeft(cm, scrollPos.scrollLeft); + if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) changed = true; + } + if (!changed) break; + } + return coords; + } + + // Scroll a given set of coordinates into view (immediately). + function scrollIntoView(cm, x1, y1, x2, y2) { + var scrollPos = calculateScrollPos(cm, x1, y1, x2, y2); + if (scrollPos.scrollTop != null) setScrollTop(cm, scrollPos.scrollTop); + if (scrollPos.scrollLeft != null) setScrollLeft(cm, scrollPos.scrollLeft); + } + + // Calculate a new scroll position needed to scroll the given + // rectangle into view. Returns an object with scrollTop and + // scrollLeft properties. When these are undefined, the + // vertical/horizontal position does not need to be adjusted. + function calculateScrollPos(cm, x1, y1, x2, y2) { + var display = cm.display, snapMargin = textHeight(cm.display); + if (y1 < 0) y1 = 0; + var screentop = cm.curOp && cm.curOp.scrollTop != null ? cm.curOp.scrollTop : display.scroller.scrollTop; + var screen = displayHeight(cm), result = {}; + if (y2 - y1 > screen) y2 = y1 + screen; + var docBottom = cm.doc.height + paddingVert(display); + var atTop = y1 < snapMargin, atBottom = y2 > docBottom - snapMargin; + if (y1 < screentop) { + result.scrollTop = atTop ? 0 : y1; + } else if (y2 > screentop + screen) { + var newTop = Math.min(y1, (atBottom ? docBottom : y2) - screen); + if (newTop != screentop) result.scrollTop = newTop; + } + + var screenleft = cm.curOp && cm.curOp.scrollLeft != null ? cm.curOp.scrollLeft : display.scroller.scrollLeft; + var screenw = displayWidth(cm) - (cm.options.fixedGutter ? display.gutters.offsetWidth : 0); + var tooWide = x2 - x1 > screenw; + if (tooWide) x2 = x1 + screenw; + if (x1 < 10) + result.scrollLeft = 0; + else if (x1 < screenleft) + result.scrollLeft = Math.max(0, x1 - (tooWide ? 0 : 10)); + else if (x2 > screenw + screenleft - 3) + result.scrollLeft = x2 + (tooWide ? 0 : 10) - screenw; + return result; + } + + // Store a relative adjustment to the scroll position in the current + // operation (to be applied when the operation finishes). + function addToScrollPos(cm, left, top) { + if (left != null || top != null) resolveScrollToPos(cm); + if (left != null) + cm.curOp.scrollLeft = (cm.curOp.scrollLeft == null ? cm.doc.scrollLeft : cm.curOp.scrollLeft) + left; + if (top != null) + cm.curOp.scrollTop = (cm.curOp.scrollTop == null ? cm.doc.scrollTop : cm.curOp.scrollTop) + top; + } + + // Make sure that at the end of the operation the current cursor is + // shown. + function ensureCursorVisible(cm) { + resolveScrollToPos(cm); + var cur = cm.getCursor(), from = cur, to = cur; + if (!cm.options.lineWrapping) { + from = cur.ch ? Pos(cur.line, cur.ch - 1) : cur; + to = Pos(cur.line, cur.ch + 1); + } + cm.curOp.scrollToPos = {from: from, to: to, margin: cm.options.cursorScrollMargin, isCursor: true}; + } + + // When an operation has its scrollToPos property set, and another + // scroll action is applied before the end of the operation, this + // 'simulates' scrolling that position into view in a cheap way, so + // that the effect of intermediate scroll commands is not ignored. + function resolveScrollToPos(cm) { + var range = cm.curOp.scrollToPos; + if (range) { + cm.curOp.scrollToPos = null; + var from = estimateCoords(cm, range.from), to = estimateCoords(cm, range.to); + var sPos = calculateScrollPos(cm, Math.min(from.left, to.left), + Math.min(from.top, to.top) - range.margin, + Math.max(from.right, to.right), + Math.max(from.bottom, to.bottom) + range.margin); + cm.scrollTo(sPos.scrollLeft, sPos.scrollTop); + } + } + + // API UTILITIES + + // Indent the given line. The how parameter can be "smart", + // "add"/null, "subtract", or "prev". When aggressive is false + // (typically set to true for forced single-line indents), empty + // lines are not indented, and places where the mode returns Pass + // are left alone. + function indentLine(cm, n, how, aggressive) { + var doc = cm.doc, state; + if (how == null) how = "add"; + if (how == "smart") { + // Fall back to "prev" when the mode doesn't have an indentation + // method. + if (!doc.mode.indent) how = "prev"; + else state = getStateBefore(cm, n); + } + + var tabSize = cm.options.tabSize; + var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize); + if (line.stateAfter) line.stateAfter = null; + var curSpaceString = line.text.match(/^\s*/)[0], indentation; + if (!aggressive && !/\S/.test(line.text)) { + indentation = 0; + how = "not"; + } else if (how == "smart") { + indentation = doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text); + if (indentation == Pass || indentation > 150) { + if (!aggressive) return; + how = "prev"; + } + } + if (how == "prev") { + if (n > doc.first) indentation = countColumn(getLine(doc, n-1).text, null, tabSize); + else indentation = 0; + } else if (how == "add") { + indentation = curSpace + cm.options.indentUnit; + } else if (how == "subtract") { + indentation = curSpace - cm.options.indentUnit; + } else if (typeof how == "number") { + indentation = curSpace + how; + } + indentation = Math.max(0, indentation); + + var indentString = "", pos = 0; + if (cm.options.indentWithTabs) + for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t";} + if (pos < indentation) indentString += spaceStr(indentation - pos); + + if (indentString != curSpaceString) { + replaceRange(doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input"); + line.stateAfter = null; + return true; + } else { + // Ensure that, if the cursor was in the whitespace at the start + // of the line, it is moved to the end of that space. + for (var i = 0; i < doc.sel.ranges.length; i++) { + var range = doc.sel.ranges[i]; + if (range.head.line == n && range.head.ch < curSpaceString.length) { + var pos = Pos(n, curSpaceString.length); + replaceOneSelection(doc, i, new Range(pos, pos)); + break; + } + } + } + } + + // Utility for applying a change to a line by handle or number, + // returning the number and optionally registering the line as + // changed. + function changeLine(doc, handle, changeType, op) { + var no = handle, line = handle; + if (typeof handle == "number") line = getLine(doc, clipLine(doc, handle)); + else no = lineNo(handle); + if (no == null) return null; + if (op(line, no) && doc.cm) regLineChange(doc.cm, no, changeType); + return line; + } + + // Helper for deleting text near the selection(s), used to implement + // backspace, delete, and similar functionality. + function deleteNearSelection(cm, compute) { + var ranges = cm.doc.sel.ranges, kill = []; + // Build up a set of ranges to kill first, merging overlapping + // ranges. + for (var i = 0; i < ranges.length; i++) { + var toKill = compute(ranges[i]); + while (kill.length && cmp(toKill.from, lst(kill).to) <= 0) { + var replaced = kill.pop(); + if (cmp(replaced.from, toKill.from) < 0) { + toKill.from = replaced.from; + break; + } + } + kill.push(toKill); + } + // Next, remove those actual ranges. + runInOp(cm, function() { + for (var i = kill.length - 1; i >= 0; i--) + replaceRange(cm.doc, "", kill[i].from, kill[i].to, "+delete"); + ensureCursorVisible(cm); + }); + } + + // Used for horizontal relative motion. Dir is -1 or 1 (left or + // right), unit can be "char", "column" (like char, but doesn't + // cross line boundaries), "word" (across next word), or "group" (to + // the start of next group of word or non-word-non-whitespace + // chars). The visually param controls whether, in right-to-left + // text, direction 1 means to move towards the next index in the + // string, or towards the character to the right of the current + // position. The resulting position will have a hitSide=true + // property if it reached the end of the document. + function findPosH(doc, pos, dir, unit, visually) { + var line = pos.line, ch = pos.ch, origDir = dir; + var lineObj = getLine(doc, line); + function findNextLine() { + var l = line + dir; + if (l < doc.first || l >= doc.first + doc.size) return false + line = l; + return lineObj = getLine(doc, l); + } + function moveOnce(boundToLine) { + var next = (visually ? moveVisually : moveLogically)(lineObj, ch, dir, true); + if (next == null) { + if (!boundToLine && findNextLine()) { + if (visually) ch = (dir < 0 ? lineRight : lineLeft)(lineObj); + else ch = dir < 0 ? lineObj.text.length : 0; + } else return false + } else ch = next; + return true; + } + + if (unit == "char") { + moveOnce() + } else if (unit == "column") { + moveOnce(true) + } else if (unit == "word" || unit == "group") { + var sawType = null, group = unit == "group"; + var helper = doc.cm && doc.cm.getHelper(pos, "wordChars"); + for (var first = true;; first = false) { + if (dir < 0 && !moveOnce(!first)) break; + var cur = lineObj.text.charAt(ch) || "\n"; + var type = isWordChar(cur, helper) ? "w" + : group && cur == "\n" ? "n" + : !group || /\s/.test(cur) ? null + : "p"; + if (group && !first && !type) type = "s"; + if (sawType && sawType != type) { + if (dir < 0) {dir = 1; moveOnce();} + break; + } + + if (type) sawType = type; + if (dir > 0 && !moveOnce(!first)) break; + } + } + var result = skipAtomic(doc, Pos(line, ch), pos, origDir, true); + if (!cmp(pos, result)) result.hitSide = true; + return result; + } + + // For relative vertical movement. Dir may be -1 or 1. Unit can be + // "page" or "line". The resulting position will have a hitSide=true + // property if it reached the end of the document. + function findPosV(cm, pos, dir, unit) { + var doc = cm.doc, x = pos.left, y; + if (unit == "page") { + var pageSize = Math.min(cm.display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight); + y = pos.top + dir * (pageSize - (dir < 0 ? 1.5 : .5) * textHeight(cm.display)); + } else if (unit == "line") { + y = dir > 0 ? pos.bottom + 3 : pos.top - 3; + } + for (;;) { + var target = coordsChar(cm, x, y); + if (!target.outside) break; + if (dir < 0 ? y <= 0 : y >= doc.height) { target.hitSide = true; break; } + y += dir * 5; + } + return target; + } + + // EDITOR METHODS + + // The publicly visible API. Note that methodOp(f) means + // 'wrap f in an operation, performed on its `this` parameter'. + + // This is not the complete set of editor methods. Most of the + // methods defined on the Doc type are also injected into + // CodeMirror.prototype, for backwards compatibility and + // convenience. + + CodeMirror.prototype = { + constructor: CodeMirror, + focus: function(){window.focus(); this.display.input.focus();}, + + setOption: function(option, value) { + var options = this.options, old = options[option]; + if (options[option] == value && option != "mode") return; + options[option] = value; + if (optionHandlers.hasOwnProperty(option)) + operation(this, optionHandlers[option])(this, value, old); + }, + + getOption: function(option) {return this.options[option];}, + getDoc: function() {return this.doc;}, + + addKeyMap: function(map, bottom) { + this.state.keyMaps[bottom ? "push" : "unshift"](getKeyMap(map)); + }, + removeKeyMap: function(map) { + var maps = this.state.keyMaps; + for (var i = 0; i < maps.length; ++i) + if (maps[i] == map || maps[i].name == map) { + maps.splice(i, 1); + return true; + } + }, + + addOverlay: methodOp(function(spec, options) { + var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec); + if (mode.startState) throw new Error("Overlays may not be stateful."); + insertSorted(this.state.overlays, + {mode: mode, modeSpec: spec, opaque: options && options.opaque, + priority: (options && options.priority) || 0}, + function(overlay) { return overlay.priority }) + this.state.modeGen++; + regChange(this); + }), + removeOverlay: methodOp(function(spec) { + var overlays = this.state.overlays; + for (var i = 0; i < overlays.length; ++i) { + var cur = overlays[i].modeSpec; + if (cur == spec || typeof spec == "string" && cur.name == spec) { + overlays.splice(i, 1); + this.state.modeGen++; + regChange(this); + return; + } + } + }), + + indentLine: methodOp(function(n, dir, aggressive) { + if (typeof dir != "string" && typeof dir != "number") { + if (dir == null) dir = this.options.smartIndent ? "smart" : "prev"; + else dir = dir ? "add" : "subtract"; + } + if (isLine(this.doc, n)) indentLine(this, n, dir, aggressive); + }), + indentSelection: methodOp(function(how) { + var ranges = this.doc.sel.ranges, end = -1; + for (var i = 0; i < ranges.length; i++) { + var range = ranges[i]; + if (!range.empty()) { + var from = range.from(), to = range.to(); + var start = Math.max(end, from.line); + end = Math.min(this.lastLine(), to.line - (to.ch ? 0 : 1)) + 1; + for (var j = start; j < end; ++j) + indentLine(this, j, how); + var newRanges = this.doc.sel.ranges; + if (from.ch == 0 && ranges.length == newRanges.length && newRanges[i].from().ch > 0) + replaceOneSelection(this.doc, i, new Range(from, newRanges[i].to()), sel_dontScroll); + } else if (range.head.line > end) { + indentLine(this, range.head.line, how, true); + end = range.head.line; + if (i == this.doc.sel.primIndex) ensureCursorVisible(this); + } + } + }), + + // Fetch the parser token for a given character. Useful for hacks + // that want to inspect the mode state (say, for completion). + getTokenAt: function(pos, precise) { + return takeToken(this, pos, precise); + }, + + getLineTokens: function(line, precise) { + return takeToken(this, Pos(line), precise, true); + }, + + getTokenTypeAt: function(pos) { + pos = clipPos(this.doc, pos); + var styles = getLineStyles(this, getLine(this.doc, pos.line)); + var before = 0, after = (styles.length - 1) / 2, ch = pos.ch; + var type; + if (ch == 0) type = styles[2]; + else for (;;) { + var mid = (before + after) >> 1; + if ((mid ? styles[mid * 2 - 1] : 0) >= ch) after = mid; + else if (styles[mid * 2 + 1] < ch) before = mid + 1; + else { type = styles[mid * 2 + 2]; break; } + } + var cut = type ? type.indexOf("cm-overlay ") : -1; + return cut < 0 ? type : cut == 0 ? null : type.slice(0, cut - 1); + }, + + getModeAt: function(pos) { + var mode = this.doc.mode; + if (!mode.innerMode) return mode; + return CodeMirror.innerMode(mode, this.getTokenAt(pos).state).mode; + }, + + getHelper: function(pos, type) { + return this.getHelpers(pos, type)[0]; + }, + + getHelpers: function(pos, type) { + var found = []; + if (!helpers.hasOwnProperty(type)) return found; + var help = helpers[type], mode = this.getModeAt(pos); + if (typeof mode[type] == "string") { + if (help[mode[type]]) found.push(help[mode[type]]); + } else if (mode[type]) { + for (var i = 0; i < mode[type].length; i++) { + var val = help[mode[type][i]]; + if (val) found.push(val); + } + } else if (mode.helperType && help[mode.helperType]) { + found.push(help[mode.helperType]); + } else if (help[mode.name]) { + found.push(help[mode.name]); + } + for (var i = 0; i < help._global.length; i++) { + var cur = help._global[i]; + if (cur.pred(mode, this) && indexOf(found, cur.val) == -1) + found.push(cur.val); + } + return found; + }, + + getStateAfter: function(line, precise) { + var doc = this.doc; + line = clipLine(doc, line == null ? doc.first + doc.size - 1: line); + return getStateBefore(this, line + 1, precise); + }, + + cursorCoords: function(start, mode) { + var pos, range = this.doc.sel.primary(); + if (start == null) pos = range.head; + else if (typeof start == "object") pos = clipPos(this.doc, start); + else pos = start ? range.from() : range.to(); + return cursorCoords(this, pos, mode || "page"); + }, + + charCoords: function(pos, mode) { + return charCoords(this, clipPos(this.doc, pos), mode || "page"); + }, + + coordsChar: function(coords, mode) { + coords = fromCoordSystem(this, coords, mode || "page"); + return coordsChar(this, coords.left, coords.top); + }, + + lineAtHeight: function(height, mode) { + height = fromCoordSystem(this, {top: height, left: 0}, mode || "page").top; + return lineAtHeight(this.doc, height + this.display.viewOffset); + }, + heightAtLine: function(line, mode) { + var end = false, lineObj; + if (typeof line == "number") { + var last = this.doc.first + this.doc.size - 1; + if (line < this.doc.first) line = this.doc.first; + else if (line > last) { line = last; end = true; } + lineObj = getLine(this.doc, line); + } else { + lineObj = line; + } + return intoCoordSystem(this, lineObj, {top: 0, left: 0}, mode || "page").top + + (end ? this.doc.height - heightAtLine(lineObj) : 0); + }, + + defaultTextHeight: function() { return textHeight(this.display); }, + defaultCharWidth: function() { return charWidth(this.display); }, + + setGutterMarker: methodOp(function(line, gutterID, value) { + return changeLine(this.doc, line, "gutter", function(line) { + var markers = line.gutterMarkers || (line.gutterMarkers = {}); + markers[gutterID] = value; + if (!value && isEmpty(markers)) line.gutterMarkers = null; + return true; + }); + }), + + clearGutter: methodOp(function(gutterID) { + var cm = this, doc = cm.doc, i = doc.first; + doc.iter(function(line) { + if (line.gutterMarkers && line.gutterMarkers[gutterID]) { + line.gutterMarkers[gutterID] = null; + regLineChange(cm, i, "gutter"); + if (isEmpty(line.gutterMarkers)) line.gutterMarkers = null; + } + ++i; + }); + }), + + lineInfo: function(line) { + if (typeof line == "number") { + if (!isLine(this.doc, line)) return null; + var n = line; + line = getLine(this.doc, line); + if (!line) return null; + } else { + var n = lineNo(line); + if (n == null) return null; + } + return {line: n, handle: line, text: line.text, gutterMarkers: line.gutterMarkers, + textClass: line.textClass, bgClass: line.bgClass, wrapClass: line.wrapClass, + widgets: line.widgets}; + }, + + getViewport: function() { return {from: this.display.viewFrom, to: this.display.viewTo};}, + + addWidget: function(pos, node, scroll, vert, horiz) { + var display = this.display; + pos = cursorCoords(this, clipPos(this.doc, pos)); + var top = pos.bottom, left = pos.left; + node.style.position = "absolute"; + node.setAttribute("cm-ignore-events", "true"); + this.display.input.setUneditable(node); + display.sizer.appendChild(node); + if (vert == "over") { + top = pos.top; + } else if (vert == "above" || vert == "near") { + var vspace = Math.max(display.wrapper.clientHeight, this.doc.height), + hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth); + // Default to positioning above (if specified and possible); otherwise default to positioning below + if ((vert == 'above' || pos.bottom + node.offsetHeight > vspace) && pos.top > node.offsetHeight) + top = pos.top - node.offsetHeight; + else if (pos.bottom + node.offsetHeight <= vspace) + top = pos.bottom; + if (left + node.offsetWidth > hspace) + left = hspace - node.offsetWidth; + } + node.style.top = top + "px"; + node.style.left = node.style.right = ""; + if (horiz == "right") { + left = display.sizer.clientWidth - node.offsetWidth; + node.style.right = "0px"; + } else { + if (horiz == "left") left = 0; + else if (horiz == "middle") left = (display.sizer.clientWidth - node.offsetWidth) / 2; + node.style.left = left + "px"; + } + if (scroll) + scrollIntoView(this, left, top, left + node.offsetWidth, top + node.offsetHeight); + }, + + triggerOnKeyDown: methodOp(onKeyDown), + triggerOnKeyPress: methodOp(onKeyPress), + triggerOnKeyUp: onKeyUp, + + execCommand: function(cmd) { + if (commands.hasOwnProperty(cmd)) + return commands[cmd].call(null, this); + }, + + triggerElectric: methodOp(function(text) { triggerElectric(this, text); }), + + findPosH: function(from, amount, unit, visually) { + var dir = 1; + if (amount < 0) { dir = -1; amount = -amount; } + for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) { + cur = findPosH(this.doc, cur, dir, unit, visually); + if (cur.hitSide) break; + } + return cur; + }, + + moveH: methodOp(function(dir, unit) { + var cm = this; + cm.extendSelectionsBy(function(range) { + if (cm.display.shift || cm.doc.extend || range.empty()) + return findPosH(cm.doc, range.head, dir, unit, cm.options.rtlMoveVisually); + else + return dir < 0 ? range.from() : range.to(); + }, sel_move); + }), + + deleteH: methodOp(function(dir, unit) { + var sel = this.doc.sel, doc = this.doc; + if (sel.somethingSelected()) + doc.replaceSelection("", null, "+delete"); + else + deleteNearSelection(this, function(range) { + var other = findPosH(doc, range.head, dir, unit, false); + return dir < 0 ? {from: other, to: range.head} : {from: range.head, to: other}; + }); + }), + + findPosV: function(from, amount, unit, goalColumn) { + var dir = 1, x = goalColumn; + if (amount < 0) { dir = -1; amount = -amount; } + for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) { + var coords = cursorCoords(this, cur, "div"); + if (x == null) x = coords.left; + else coords.left = x; + cur = findPosV(this, coords, dir, unit); + if (cur.hitSide) break; + } + return cur; + }, + + moveV: methodOp(function(dir, unit) { + var cm = this, doc = this.doc, goals = []; + var collapse = !cm.display.shift && !doc.extend && doc.sel.somethingSelected(); + doc.extendSelectionsBy(function(range) { + if (collapse) + return dir < 0 ? range.from() : range.to(); + var headPos = cursorCoords(cm, range.head, "div"); + if (range.goalColumn != null) headPos.left = range.goalColumn; + goals.push(headPos.left); + var pos = findPosV(cm, headPos, dir, unit); + if (unit == "page" && range == doc.sel.primary()) + addToScrollPos(cm, null, charCoords(cm, pos, "div").top - headPos.top); + return pos; + }, sel_move); + if (goals.length) for (var i = 0; i < doc.sel.ranges.length; i++) + doc.sel.ranges[i].goalColumn = goals[i]; + }), + + // Find the word at the given position (as returned by coordsChar). + findWordAt: function(pos) { + var doc = this.doc, line = getLine(doc, pos.line).text; + var start = pos.ch, end = pos.ch; + if (line) { + var helper = this.getHelper(pos, "wordChars"); + if ((pos.xRel < 0 || end == line.length) && start) --start; else ++end; + var startChar = line.charAt(start); + var check = isWordChar(startChar, helper) + ? function(ch) { return isWordChar(ch, helper); } + : /\s/.test(startChar) ? function(ch) {return /\s/.test(ch);} + : function(ch) {return !/\s/.test(ch) && !isWordChar(ch);}; + while (start > 0 && check(line.charAt(start - 1))) --start; + while (end < line.length && check(line.charAt(end))) ++end; + } + return new Range(Pos(pos.line, start), Pos(pos.line, end)); + }, + + toggleOverwrite: function(value) { + if (value != null && value == this.state.overwrite) return; + if (this.state.overwrite = !this.state.overwrite) + addClass(this.display.cursorDiv, "CodeMirror-overwrite"); + else + rmClass(this.display.cursorDiv, "CodeMirror-overwrite"); + + signal(this, "overwriteToggle", this, this.state.overwrite); + }, + hasFocus: function() { return this.display.input.getField() == activeElt(); }, + isReadOnly: function() { return !!(this.options.readOnly || this.doc.cantEdit); }, + + scrollTo: methodOp(function(x, y) { + if (x != null || y != null) resolveScrollToPos(this); + if (x != null) this.curOp.scrollLeft = x; + if (y != null) this.curOp.scrollTop = y; + }), + getScrollInfo: function() { + var scroller = this.display.scroller; + return {left: scroller.scrollLeft, top: scroller.scrollTop, + height: scroller.scrollHeight - scrollGap(this) - this.display.barHeight, + width: scroller.scrollWidth - scrollGap(this) - this.display.barWidth, + clientHeight: displayHeight(this), clientWidth: displayWidth(this)}; + }, + + scrollIntoView: methodOp(function(range, margin) { + if (range == null) { + range = {from: this.doc.sel.primary().head, to: null}; + if (margin == null) margin = this.options.cursorScrollMargin; + } else if (typeof range == "number") { + range = {from: Pos(range, 0), to: null}; + } else if (range.from == null) { + range = {from: range, to: null}; + } + if (!range.to) range.to = range.from; + range.margin = margin || 0; + + if (range.from.line != null) { + resolveScrollToPos(this); + this.curOp.scrollToPos = range; + } else { + var sPos = calculateScrollPos(this, Math.min(range.from.left, range.to.left), + Math.min(range.from.top, range.to.top) - range.margin, + Math.max(range.from.right, range.to.right), + Math.max(range.from.bottom, range.to.bottom) + range.margin); + this.scrollTo(sPos.scrollLeft, sPos.scrollTop); + } + }), + + setSize: methodOp(function(width, height) { + var cm = this; + function interpret(val) { + return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val; + } + if (width != null) cm.display.wrapper.style.width = interpret(width); + if (height != null) cm.display.wrapper.style.height = interpret(height); + if (cm.options.lineWrapping) clearLineMeasurementCache(this); + var lineNo = cm.display.viewFrom; + cm.doc.iter(lineNo, cm.display.viewTo, function(line) { + if (line.widgets) for (var i = 0; i < line.widgets.length; i++) + if (line.widgets[i].noHScroll) { regLineChange(cm, lineNo, "widget"); break; } + ++lineNo; + }); + cm.curOp.forceUpdate = true; + signal(cm, "refresh", this); + }), + + operation: function(f){return runInOp(this, f);}, + + refresh: methodOp(function() { + var oldHeight = this.display.cachedTextHeight; + regChange(this); + this.curOp.forceUpdate = true; + clearCaches(this); + this.scrollTo(this.doc.scrollLeft, this.doc.scrollTop); + updateGutterSpace(this); + if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5) + estimateLineHeights(this); + signal(this, "refresh", this); + }), + + swapDoc: methodOp(function(doc) { + var old = this.doc; + old.cm = null; + attachDoc(this, doc); + clearCaches(this); + this.display.input.reset(); + this.scrollTo(doc.scrollLeft, doc.scrollTop); + this.curOp.forceScroll = true; + signalLater(this, "swapDoc", this, old); + return old; + }), + + getInputField: function(){return this.display.input.getField();}, + getWrapperElement: function(){return this.display.wrapper;}, + getScrollerElement: function(){return this.display.scroller;}, + getGutterElement: function(){return this.display.gutters;} + }; + eventMixin(CodeMirror); + + // OPTION DEFAULTS + + // The default configuration options. + var defaults = CodeMirror.defaults = {}; + // Functions to run when options are changed. + var optionHandlers = CodeMirror.optionHandlers = {}; + + function option(name, deflt, handle, notOnInit) { + CodeMirror.defaults[name] = deflt; + if (handle) optionHandlers[name] = + notOnInit ? function(cm, val, old) {if (old != Init) handle(cm, val, old);} : handle; + } + + // Passed to option handlers when there is no old value. + var Init = CodeMirror.Init = {toString: function(){return "CodeMirror.Init";}}; + + // These two are, on init, called from the constructor because they + // have to be initialized before the editor can start at all. + option("value", "", function(cm, val) { + cm.setValue(val); + }, true); + option("mode", null, function(cm, val) { + cm.doc.modeOption = val; + loadMode(cm); + }, true); + + option("indentUnit", 2, loadMode, true); + option("indentWithTabs", false); + option("smartIndent", true); + option("tabSize", 4, function(cm) { + resetModeState(cm); + clearCaches(cm); + regChange(cm); + }, true); + option("lineSeparator", null, function(cm, val) { + cm.doc.lineSep = val; + if (!val) return; + var newBreaks = [], lineNo = cm.doc.first; + cm.doc.iter(function(line) { + for (var pos = 0;;) { + var found = line.text.indexOf(val, pos); + if (found == -1) break; + pos = found + val.length; + newBreaks.push(Pos(lineNo, found)); + } + lineNo++; + }); + for (var i = newBreaks.length - 1; i >= 0; i--) + replaceRange(cm.doc, val, newBreaks[i], Pos(newBreaks[i].line, newBreaks[i].ch + val.length)) + }); + option("specialChars", /[\u0000-\u001f\u007f\u00ad\u200b-\u200f\u2028\u2029\ufeff]/g, function(cm, val, old) { + cm.state.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g"); + if (old != CodeMirror.Init) cm.refresh(); + }); + option("specialCharPlaceholder", defaultSpecialCharPlaceholder, function(cm) {cm.refresh();}, true); + option("electricChars", true); + option("inputStyle", mobile ? "contenteditable" : "textarea", function() { + throw new Error("inputStyle can not (yet) be changed in a running editor"); // FIXME + }, true); + option("spellcheck", false, function(cm, val) { + cm.getInputField().spellcheck = val + }, true); + option("rtlMoveVisually", !windows); + option("wholeLineUpdateBefore", true); + + option("theme", "default", function(cm) { + themeChanged(cm); + guttersChanged(cm); + }, true); + option("keyMap", "default", function(cm, val, old) { + var next = getKeyMap(val); + var prev = old != CodeMirror.Init && getKeyMap(old); + if (prev && prev.detach) prev.detach(cm, next); + if (next.attach) next.attach(cm, prev || null); + }); + option("extraKeys", null); + + option("lineWrapping", false, wrappingChanged, true); + option("gutters", [], function(cm) { + setGuttersForLineNumbers(cm.options); + guttersChanged(cm); + }, true); + option("fixedGutter", true, function(cm, val) { + cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0"; + cm.refresh(); + }, true); + option("coverGutterNextToScrollbar", false, function(cm) {updateScrollbars(cm);}, true); + option("scrollbarStyle", "native", function(cm) { + initScrollbars(cm); + updateScrollbars(cm); + cm.display.scrollbars.setScrollTop(cm.doc.scrollTop); + cm.display.scrollbars.setScrollLeft(cm.doc.scrollLeft); + }, true); + option("lineNumbers", false, function(cm) { + setGuttersForLineNumbers(cm.options); + guttersChanged(cm); + }, true); + option("firstLineNumber", 1, guttersChanged, true); + option("lineNumberFormatter", function(integer) {return integer;}, guttersChanged, true); + option("showCursorWhenSelecting", false, updateSelection, true); + + option("resetSelectionOnContextMenu", true); + option("lineWiseCopyCut", true); + + option("readOnly", false, function(cm, val) { + if (val == "nocursor") { + onBlur(cm); + cm.display.input.blur(); + cm.display.disabled = true; + } else { + cm.display.disabled = false; + } + cm.display.input.readOnlyChanged(val) + }); + option("disableInput", false, function(cm, val) {if (!val) cm.display.input.reset();}, true); + option("dragDrop", true, dragDropChanged); + option("allowDropFileTypes", null); + + option("cursorBlinkRate", 530); + option("cursorScrollMargin", 0); + option("cursorHeight", 1, updateSelection, true); + option("singleCursorHeightPerLine", true, updateSelection, true); + option("workTime", 100); + option("workDelay", 100); + option("flattenSpans", true, resetModeState, true); + option("addModeClass", false, resetModeState, true); + option("pollInterval", 100); + option("undoDepth", 200, function(cm, val){cm.doc.history.undoDepth = val;}); + option("historyEventDelay", 1250); + option("viewportMargin", 10, function(cm){cm.refresh();}, true); + option("maxHighlightLength", 10000, resetModeState, true); + option("moveInputWithCursor", true, function(cm, val) { + if (!val) cm.display.input.resetPosition(); + }); + + option("tabindex", null, function(cm, val) { + cm.display.input.getField().tabIndex = val || ""; + }); + option("autofocus", null); + + // MODE DEFINITION AND QUERYING + + // Known modes, by name and by MIME + var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {}; + + // Extra arguments are stored as the mode's dependencies, which is + // used by (legacy) mechanisms like loadmode.js to automatically + // load a mode. (Preferred mechanism is the require/define calls.) + CodeMirror.defineMode = function(name, mode) { + if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name; + if (arguments.length > 2) + mode.dependencies = Array.prototype.slice.call(arguments, 2); + modes[name] = mode; + }; + + CodeMirror.defineMIME = function(mime, spec) { + mimeModes[mime] = spec; + }; + + // Given a MIME type, a {name, ...options} config object, or a name + // string, return a mode config object. + CodeMirror.resolveMode = function(spec) { + if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) { + spec = mimeModes[spec]; + } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) { + var found = mimeModes[spec.name]; + if (typeof found == "string") found = {name: found}; + spec = createObj(found, spec); + spec.name = found.name; + } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) { + return CodeMirror.resolveMode("application/xml"); + } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+json$/.test(spec)) { + return CodeMirror.resolveMode("application/json"); + } + if (typeof spec == "string") return {name: spec}; + else return spec || {name: "null"}; + }; + + // Given a mode spec (anything that resolveMode accepts), find and + // initialize an actual mode object. + CodeMirror.getMode = function(options, spec) { + var spec = CodeMirror.resolveMode(spec); + var mfactory = modes[spec.name]; + if (!mfactory) return CodeMirror.getMode(options, "text/plain"); + var modeObj = mfactory(options, spec); + if (modeExtensions.hasOwnProperty(spec.name)) { + var exts = modeExtensions[spec.name]; + for (var prop in exts) { + if (!exts.hasOwnProperty(prop)) continue; + if (modeObj.hasOwnProperty(prop)) modeObj["_" + prop] = modeObj[prop]; + modeObj[prop] = exts[prop]; + } + } + modeObj.name = spec.name; + if (spec.helperType) modeObj.helperType = spec.helperType; + if (spec.modeProps) for (var prop in spec.modeProps) + modeObj[prop] = spec.modeProps[prop]; + + return modeObj; + }; + + // Minimal default mode. + CodeMirror.defineMode("null", function() { + return {token: function(stream) {stream.skipToEnd();}}; + }); + CodeMirror.defineMIME("text/plain", "null"); + + // This can be used to attach properties to mode objects from + // outside the actual mode definition. + var modeExtensions = CodeMirror.modeExtensions = {}; + CodeMirror.extendMode = function(mode, properties) { + var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {}); + copyObj(properties, exts); + }; + + // EXTENSIONS + + CodeMirror.defineExtension = function(name, func) { + CodeMirror.prototype[name] = func; + }; + CodeMirror.defineDocExtension = function(name, func) { + Doc.prototype[name] = func; + }; + CodeMirror.defineOption = option; + + var initHooks = []; + CodeMirror.defineInitHook = function(f) {initHooks.push(f);}; + + var helpers = CodeMirror.helpers = {}; + CodeMirror.registerHelper = function(type, name, value) { + if (!helpers.hasOwnProperty(type)) helpers[type] = CodeMirror[type] = {_global: []}; + helpers[type][name] = value; + }; + CodeMirror.registerGlobalHelper = function(type, name, predicate, value) { + CodeMirror.registerHelper(type, name, value); + helpers[type]._global.push({pred: predicate, val: value}); + }; + + // MODE STATE HANDLING + + // Utility functions for working with state. Exported because nested + // modes need to do this for their inner modes. + + var copyState = CodeMirror.copyState = function(mode, state) { + if (state === true) return state; + if (mode.copyState) return mode.copyState(state); + var nstate = {}; + for (var n in state) { + var val = state[n]; + if (val instanceof Array) val = val.concat([]); + nstate[n] = val; + } + return nstate; + }; + + var startState = CodeMirror.startState = function(mode, a1, a2) { + return mode.startState ? mode.startState(a1, a2) : true; + }; + + // Given a mode and a state (for that mode), find the inner mode and + // state at the position that the state refers to. + CodeMirror.innerMode = function(mode, state) { + while (mode.innerMode) { + var info = mode.innerMode(state); + if (!info || info.mode == mode) break; + state = info.state; + mode = info.mode; + } + return info || {mode: mode, state: state}; + }; + + // STANDARD COMMANDS + + // Commands are parameter-less actions that can be performed on an + // editor, mostly used for keybindings. + var commands = CodeMirror.commands = { + selectAll: function(cm) {cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()), sel_dontScroll);}, + singleSelection: function(cm) { + cm.setSelection(cm.getCursor("anchor"), cm.getCursor("head"), sel_dontScroll); + }, + killLine: function(cm) { + deleteNearSelection(cm, function(range) { + if (range.empty()) { + var len = getLine(cm.doc, range.head.line).text.length; + if (range.head.ch == len && range.head.line < cm.lastLine()) + return {from: range.head, to: Pos(range.head.line + 1, 0)}; + else + return {from: range.head, to: Pos(range.head.line, len)}; + } else { + return {from: range.from(), to: range.to()}; + } + }); + }, + deleteLine: function(cm) { + deleteNearSelection(cm, function(range) { + return {from: Pos(range.from().line, 0), + to: clipPos(cm.doc, Pos(range.to().line + 1, 0))}; + }); + }, + delLineLeft: function(cm) { + deleteNearSelection(cm, function(range) { + return {from: Pos(range.from().line, 0), to: range.from()}; + }); + }, + delWrappedLineLeft: function(cm) { + deleteNearSelection(cm, function(range) { + var top = cm.charCoords(range.head, "div").top + 5; + var leftPos = cm.coordsChar({left: 0, top: top}, "div"); + return {from: leftPos, to: range.from()}; + }); + }, + delWrappedLineRight: function(cm) { + deleteNearSelection(cm, function(range) { + var top = cm.charCoords(range.head, "div").top + 5; + var rightPos = cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div"); + return {from: range.from(), to: rightPos }; + }); + }, + undo: function(cm) {cm.undo();}, + redo: function(cm) {cm.redo();}, + undoSelection: function(cm) {cm.undoSelection();}, + redoSelection: function(cm) {cm.redoSelection();}, + goDocStart: function(cm) {cm.extendSelection(Pos(cm.firstLine(), 0));}, + goDocEnd: function(cm) {cm.extendSelection(Pos(cm.lastLine()));}, + goLineStart: function(cm) { + cm.extendSelectionsBy(function(range) { return lineStart(cm, range.head.line); }, + {origin: "+move", bias: 1}); + }, + goLineStartSmart: function(cm) { + cm.extendSelectionsBy(function(range) { + return lineStartSmart(cm, range.head); + }, {origin: "+move", bias: 1}); + }, + goLineEnd: function(cm) { + cm.extendSelectionsBy(function(range) { return lineEnd(cm, range.head.line); }, + {origin: "+move", bias: -1}); + }, + goLineRight: function(cm) { + cm.extendSelectionsBy(function(range) { + var top = cm.charCoords(range.head, "div").top + 5; + return cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div"); + }, sel_move); + }, + goLineLeft: function(cm) { + cm.extendSelectionsBy(function(range) { + var top = cm.charCoords(range.head, "div").top + 5; + return cm.coordsChar({left: 0, top: top}, "div"); + }, sel_move); + }, + goLineLeftSmart: function(cm) { + cm.extendSelectionsBy(function(range) { + var top = cm.charCoords(range.head, "div").top + 5; + var pos = cm.coordsChar({left: 0, top: top}, "div"); + if (pos.ch < cm.getLine(pos.line).search(/\S/)) return lineStartSmart(cm, range.head); + return pos; + }, sel_move); + }, + goLineUp: function(cm) {cm.moveV(-1, "line");}, + goLineDown: function(cm) {cm.moveV(1, "line");}, + goPageUp: function(cm) {cm.moveV(-1, "page");}, + goPageDown: function(cm) {cm.moveV(1, "page");}, + goCharLeft: function(cm) {cm.moveH(-1, "char");}, + goCharRight: function(cm) {cm.moveH(1, "char");}, + goColumnLeft: function(cm) {cm.moveH(-1, "column");}, + goColumnRight: function(cm) {cm.moveH(1, "column");}, + goWordLeft: function(cm) {cm.moveH(-1, "word");}, + goGroupRight: function(cm) {cm.moveH(1, "group");}, + goGroupLeft: function(cm) {cm.moveH(-1, "group");}, + goWordRight: function(cm) {cm.moveH(1, "word");}, + delCharBefore: function(cm) {cm.deleteH(-1, "char");}, + delCharAfter: function(cm) {cm.deleteH(1, "char");}, + delWordBefore: function(cm) {cm.deleteH(-1, "word");}, + delWordAfter: function(cm) {cm.deleteH(1, "word");}, + delGroupBefore: function(cm) {cm.deleteH(-1, "group");}, + delGroupAfter: function(cm) {cm.deleteH(1, "group");}, + indentAuto: function(cm) {cm.indentSelection("smart");}, + indentMore: function(cm) {cm.indentSelection("add");}, + indentLess: function(cm) {cm.indentSelection("subtract");}, + insertTab: function(cm) {cm.replaceSelection("\t");}, + insertSoftTab: function(cm) { + var spaces = [], ranges = cm.listSelections(), tabSize = cm.options.tabSize; + for (var i = 0; i < ranges.length; i++) { + var pos = ranges[i].from(); + var col = countColumn(cm.getLine(pos.line), pos.ch, tabSize); + spaces.push(spaceStr(tabSize - col % tabSize)); + } + cm.replaceSelections(spaces); + }, + defaultTab: function(cm) { + if (cm.somethingSelected()) cm.indentSelection("add"); + else cm.execCommand("insertTab"); + }, + transposeChars: function(cm) { + runInOp(cm, function() { + var ranges = cm.listSelections(), newSel = []; + for (var i = 0; i < ranges.length; i++) { + var cur = ranges[i].head, line = getLine(cm.doc, cur.line).text; + if (line) { + if (cur.ch == line.length) cur = new Pos(cur.line, cur.ch - 1); + if (cur.ch > 0) { + cur = new Pos(cur.line, cur.ch + 1); + cm.replaceRange(line.charAt(cur.ch - 1) + line.charAt(cur.ch - 2), + Pos(cur.line, cur.ch - 2), cur, "+transpose"); + } else if (cur.line > cm.doc.first) { + var prev = getLine(cm.doc, cur.line - 1).text; + if (prev) + cm.replaceRange(line.charAt(0) + cm.doc.lineSeparator() + + prev.charAt(prev.length - 1), + Pos(cur.line - 1, prev.length - 1), Pos(cur.line, 1), "+transpose"); + } + } + newSel.push(new Range(cur, cur)); + } + cm.setSelections(newSel); + }); + }, + newlineAndIndent: function(cm) { + runInOp(cm, function() { + var len = cm.listSelections().length; + for (var i = 0; i < len; i++) { + var range = cm.listSelections()[i]; + cm.replaceRange(cm.doc.lineSeparator(), range.anchor, range.head, "+input"); + cm.indentLine(range.from().line + 1, null, true); + } + ensureCursorVisible(cm); + }); + }, + openLine: function(cm) {cm.replaceSelection("\n", "start")}, + toggleOverwrite: function(cm) {cm.toggleOverwrite();} + }; + + + // STANDARD KEYMAPS + + var keyMap = CodeMirror.keyMap = {}; + + keyMap.basic = { + "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown", + "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown", + "Delete": "delCharAfter", "Backspace": "delCharBefore", "Shift-Backspace": "delCharBefore", + "Tab": "defaultTab", "Shift-Tab": "indentAuto", + "Enter": "newlineAndIndent", "Insert": "toggleOverwrite", + "Esc": "singleSelection" + }; + // Note that the save and find-related commands aren't defined by + // default. User code or addons can define them. Unknown commands + // are simply ignored. + keyMap.pcDefault = { + "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo", + "Ctrl-Home": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Up": "goLineUp", "Ctrl-Down": "goLineDown", + "Ctrl-Left": "goGroupLeft", "Ctrl-Right": "goGroupRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd", + "Ctrl-Backspace": "delGroupBefore", "Ctrl-Delete": "delGroupAfter", "Ctrl-S": "save", "Ctrl-F": "find", + "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll", + "Ctrl-[": "indentLess", "Ctrl-]": "indentMore", + "Ctrl-U": "undoSelection", "Shift-Ctrl-U": "redoSelection", "Alt-U": "redoSelection", + fallthrough: "basic" + }; + // Very basic readline/emacs-style bindings, which are standard on Mac. + keyMap.emacsy = { + "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown", + "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd", + "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore", + "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars", + "Ctrl-O": "openLine" + }; + keyMap.macDefault = { + "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo", + "Cmd-Home": "goDocStart", "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft", + "Alt-Right": "goGroupRight", "Cmd-Left": "goLineLeft", "Cmd-Right": "goLineRight", "Alt-Backspace": "delGroupBefore", + "Ctrl-Alt-Backspace": "delGroupAfter", "Alt-Delete": "delGroupAfter", "Cmd-S": "save", "Cmd-F": "find", + "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll", + "Cmd-[": "indentLess", "Cmd-]": "indentMore", "Cmd-Backspace": "delWrappedLineLeft", "Cmd-Delete": "delWrappedLineRight", + "Cmd-U": "undoSelection", "Shift-Cmd-U": "redoSelection", "Ctrl-Up": "goDocStart", "Ctrl-Down": "goDocEnd", + fallthrough: ["basic", "emacsy"] + }; + keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault; + + // KEYMAP DISPATCH + + function normalizeKeyName(name) { + var parts = name.split(/-(?!$)/), name = parts[parts.length - 1]; + var alt, ctrl, shift, cmd; + for (var i = 0; i < parts.length - 1; i++) { + var mod = parts[i]; + if (/^(cmd|meta|m)$/i.test(mod)) cmd = true; + else if (/^a(lt)?$/i.test(mod)) alt = true; + else if (/^(c|ctrl|control)$/i.test(mod)) ctrl = true; + else if (/^s(hift)$/i.test(mod)) shift = true; + else throw new Error("Unrecognized modifier name: " + mod); + } + if (alt) name = "Alt-" + name; + if (ctrl) name = "Ctrl-" + name; + if (cmd) name = "Cmd-" + name; + if (shift) name = "Shift-" + name; + return name; + } + + // This is a kludge to keep keymaps mostly working as raw objects + // (backwards compatibility) while at the same time support features + // like normalization and multi-stroke key bindings. It compiles a + // new normalized keymap, and then updates the old object to reflect + // this. + CodeMirror.normalizeKeyMap = function(keymap) { + var copy = {}; + for (var keyname in keymap) if (keymap.hasOwnProperty(keyname)) { + var value = keymap[keyname]; + if (/^(name|fallthrough|(de|at)tach)$/.test(keyname)) continue; + if (value == "...") { delete keymap[keyname]; continue; } + + var keys = map(keyname.split(" "), normalizeKeyName); + for (var i = 0; i < keys.length; i++) { + var val, name; + if (i == keys.length - 1) { + name = keys.join(" "); + val = value; + } else { + name = keys.slice(0, i + 1).join(" "); + val = "..."; + } + var prev = copy[name]; + if (!prev) copy[name] = val; + else if (prev != val) throw new Error("Inconsistent bindings for " + name); + } + delete keymap[keyname]; + } + for (var prop in copy) keymap[prop] = copy[prop]; + return keymap; + }; + + var lookupKey = CodeMirror.lookupKey = function(key, map, handle, context) { + map = getKeyMap(map); + var found = map.call ? map.call(key, context) : map[key]; + if (found === false) return "nothing"; + if (found === "...") return "multi"; + if (found != null && handle(found)) return "handled"; + + if (map.fallthrough) { + if (Object.prototype.toString.call(map.fallthrough) != "[object Array]") + return lookupKey(key, map.fallthrough, handle, context); + for (var i = 0; i < map.fallthrough.length; i++) { + var result = lookupKey(key, map.fallthrough[i], handle, context); + if (result) return result; + } + } + }; + + // Modifier key presses don't count as 'real' key presses for the + // purpose of keymap fallthrough. + var isModifierKey = CodeMirror.isModifierKey = function(value) { + var name = typeof value == "string" ? value : keyNames[value.keyCode]; + return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod"; + }; + + // Look up the name of a key as indicated by an event object. + var keyName = CodeMirror.keyName = function(event, noShift) { + if (presto && event.keyCode == 34 && event["char"]) return false; + var base = keyNames[event.keyCode], name = base; + if (name == null || event.altGraphKey) return false; + if (event.altKey && base != "Alt") name = "Alt-" + name; + if ((flipCtrlCmd ? event.metaKey : event.ctrlKey) && base != "Ctrl") name = "Ctrl-" + name; + if ((flipCtrlCmd ? event.ctrlKey : event.metaKey) && base != "Cmd") name = "Cmd-" + name; + if (!noShift && event.shiftKey && base != "Shift") name = "Shift-" + name; + return name; + }; + + function getKeyMap(val) { + return typeof val == "string" ? keyMap[val] : val; + } + + // FROMTEXTAREA + + CodeMirror.fromTextArea = function(textarea, options) { + options = options ? copyObj(options) : {}; + options.value = textarea.value; + if (!options.tabindex && textarea.tabIndex) + options.tabindex = textarea.tabIndex; + if (!options.placeholder && textarea.placeholder) + options.placeholder = textarea.placeholder; + // Set autofocus to true if this textarea is focused, or if it has + // autofocus and no other element is focused. + if (options.autofocus == null) { + var hasFocus = activeElt(); + options.autofocus = hasFocus == textarea || + textarea.getAttribute("autofocus") != null && hasFocus == document.body; + } + + function save() {textarea.value = cm.getValue();} + if (textarea.form) { + on(textarea.form, "submit", save); + // Deplorable hack to make the submit method do the right thing. + if (!options.leaveSubmitMethodAlone) { + var form = textarea.form, realSubmit = form.submit; + try { + var wrappedSubmit = form.submit = function() { + save(); + form.submit = realSubmit; + form.submit(); + form.submit = wrappedSubmit; + }; + } catch(e) {} + } + } + + options.finishInit = function(cm) { + cm.save = save; + cm.getTextArea = function() { return textarea; }; + cm.toTextArea = function() { + cm.toTextArea = isNaN; // Prevent this from being ran twice + save(); + textarea.parentNode.removeChild(cm.getWrapperElement()); + textarea.style.display = ""; + if (textarea.form) { + off(textarea.form, "submit", save); + if (typeof textarea.form.submit == "function") + textarea.form.submit = realSubmit; + } + }; + }; + + textarea.style.display = "none"; + var cm = CodeMirror(function(node) { + textarea.parentNode.insertBefore(node, textarea.nextSibling); + }, options); + return cm; + }; + + // STRING STREAM + + // Fed to the mode parsers, provides helper functions to make + // parsers more succinct. + + var StringStream = CodeMirror.StringStream = function(string, tabSize) { + this.pos = this.start = 0; + this.string = string; + this.tabSize = tabSize || 8; + this.lastColumnPos = this.lastColumnValue = 0; + this.lineStart = 0; + }; + + StringStream.prototype = { + eol: function() {return this.pos >= this.string.length;}, + sol: function() {return this.pos == this.lineStart;}, + peek: function() {return this.string.charAt(this.pos) || undefined;}, + next: function() { + if (this.pos < this.string.length) + return this.string.charAt(this.pos++); + }, + eat: function(match) { + var ch = this.string.charAt(this.pos); + if (typeof match == "string") var ok = ch == match; + else var ok = ch && (match.test ? match.test(ch) : match(ch)); + if (ok) {++this.pos; return ch;} + }, + eatWhile: function(match) { + var start = this.pos; + while (this.eat(match)){} + return this.pos > start; + }, + eatSpace: function() { + var start = this.pos; + while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos; + return this.pos > start; + }, + skipToEnd: function() {this.pos = this.string.length;}, + skipTo: function(ch) { + var found = this.string.indexOf(ch, this.pos); + if (found > -1) {this.pos = found; return true;} + }, + backUp: function(n) {this.pos -= n;}, + column: function() { + if (this.lastColumnPos < this.start) { + this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue); + this.lastColumnPos = this.start; + } + return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0); + }, + indentation: function() { + return countColumn(this.string, null, this.tabSize) - + (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0); + }, + match: function(pattern, consume, caseInsensitive) { + if (typeof pattern == "string") { + var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;}; + var substr = this.string.substr(this.pos, pattern.length); + if (cased(substr) == cased(pattern)) { + if (consume !== false) this.pos += pattern.length; + return true; + } + } else { + var match = this.string.slice(this.pos).match(pattern); + if (match && match.index > 0) return null; + if (match && consume !== false) this.pos += match[0].length; + return match; + } + }, + current: function(){return this.string.slice(this.start, this.pos);}, + hideFirstChars: function(n, inner) { + this.lineStart += n; + try { return inner(); } + finally { this.lineStart -= n; } + } + }; + + // TEXTMARKERS + + // Created with markText and setBookmark methods. A TextMarker is a + // handle that can be used to clear or find a marked position in the + // document. Line objects hold arrays (markedSpans) containing + // {from, to, marker} object pointing to such marker objects, and + // indicating that such a marker is present on that line. Multiple + // lines may point to the same marker when it spans across lines. + // The spans will have null for their from/to properties when the + // marker continues beyond the start/end of the line. Markers have + // links back to the lines they currently touch. + + var nextMarkerId = 0; + + var TextMarker = CodeMirror.TextMarker = function(doc, type) { + this.lines = []; + this.type = type; + this.doc = doc; + this.id = ++nextMarkerId; + }; + eventMixin(TextMarker); + + // Clear the marker. + TextMarker.prototype.clear = function() { + if (this.explicitlyCleared) return; + var cm = this.doc.cm, withOp = cm && !cm.curOp; + if (withOp) startOperation(cm); + if (hasHandler(this, "clear")) { + var found = this.find(); + if (found) signalLater(this, "clear", found.from, found.to); + } + var min = null, max = null; + for (var i = 0; i < this.lines.length; ++i) { + var line = this.lines[i]; + var span = getMarkedSpanFor(line.markedSpans, this); + if (cm && !this.collapsed) regLineChange(cm, lineNo(line), "text"); + else if (cm) { + if (span.to != null) max = lineNo(line); + if (span.from != null) min = lineNo(line); + } + line.markedSpans = removeMarkedSpan(line.markedSpans, span); + if (span.from == null && this.collapsed && !lineIsHidden(this.doc, line) && cm) + updateLineHeight(line, textHeight(cm.display)); + } + if (cm && this.collapsed && !cm.options.lineWrapping) for (var i = 0; i < this.lines.length; ++i) { + var visual = visualLine(this.lines[i]), len = lineLength(visual); + if (len > cm.display.maxLineLength) { + cm.display.maxLine = visual; + cm.display.maxLineLength = len; + cm.display.maxLineChanged = true; + } + } + + if (min != null && cm && this.collapsed) regChange(cm, min, max + 1); + this.lines.length = 0; + this.explicitlyCleared = true; + if (this.atomic && this.doc.cantEdit) { + this.doc.cantEdit = false; + if (cm) reCheckSelection(cm.doc); + } + if (cm) signalLater(cm, "markerCleared", cm, this); + if (withOp) endOperation(cm); + if (this.parent) this.parent.clear(); + }; + + // Find the position of the marker in the document. Returns a {from, + // to} object by default. Side can be passed to get a specific side + // -- 0 (both), -1 (left), or 1 (right). When lineObj is true, the + // Pos objects returned contain a line object, rather than a line + // number (used to prevent looking up the same line twice). + TextMarker.prototype.find = function(side, lineObj) { + if (side == null && this.type == "bookmark") side = 1; + var from, to; + for (var i = 0; i < this.lines.length; ++i) { + var line = this.lines[i]; + var span = getMarkedSpanFor(line.markedSpans, this); + if (span.from != null) { + from = Pos(lineObj ? line : lineNo(line), span.from); + if (side == -1) return from; + } + if (span.to != null) { + to = Pos(lineObj ? line : lineNo(line), span.to); + if (side == 1) return to; + } + } + return from && {from: from, to: to}; + }; + + // Signals that the marker's widget changed, and surrounding layout + // should be recomputed. + TextMarker.prototype.changed = function() { + var pos = this.find(-1, true), widget = this, cm = this.doc.cm; + if (!pos || !cm) return; + runInOp(cm, function() { + var line = pos.line, lineN = lineNo(pos.line); + var view = findViewForLine(cm, lineN); + if (view) { + clearLineMeasurementCacheFor(view); + cm.curOp.selectionChanged = cm.curOp.forceUpdate = true; + } + cm.curOp.updateMaxLine = true; + if (!lineIsHidden(widget.doc, line) && widget.height != null) { + var oldHeight = widget.height; + widget.height = null; + var dHeight = widgetHeight(widget) - oldHeight; + if (dHeight) + updateLineHeight(line, line.height + dHeight); + } + }); + }; + + TextMarker.prototype.attachLine = function(line) { + if (!this.lines.length && this.doc.cm) { + var op = this.doc.cm.curOp; + if (!op.maybeHiddenMarkers || indexOf(op.maybeHiddenMarkers, this) == -1) + (op.maybeUnhiddenMarkers || (op.maybeUnhiddenMarkers = [])).push(this); + } + this.lines.push(line); + }; + TextMarker.prototype.detachLine = function(line) { + this.lines.splice(indexOf(this.lines, line), 1); + if (!this.lines.length && this.doc.cm) { + var op = this.doc.cm.curOp; + (op.maybeHiddenMarkers || (op.maybeHiddenMarkers = [])).push(this); + } + }; + + // Collapsed markers have unique ids, in order to be able to order + // them, which is needed for uniquely determining an outer marker + // when they overlap (they may nest, but not partially overlap). + var nextMarkerId = 0; + + // Create a marker, wire it up to the right lines, and + function markText(doc, from, to, options, type) { + // Shared markers (across linked documents) are handled separately + // (markTextShared will call out to this again, once per + // document). + if (options && options.shared) return markTextShared(doc, from, to, options, type); + // Ensure we are in an operation. + if (doc.cm && !doc.cm.curOp) return operation(doc.cm, markText)(doc, from, to, options, type); + + var marker = new TextMarker(doc, type), diff = cmp(from, to); + if (options) copyObj(options, marker, false); + // Don't connect empty markers unless clearWhenEmpty is false + if (diff > 0 || diff == 0 && marker.clearWhenEmpty !== false) + return marker; + if (marker.replacedWith) { + // Showing up as a widget implies collapsed (widget replaces text) + marker.collapsed = true; + marker.widgetNode = elt("span", [marker.replacedWith], "CodeMirror-widget"); + if (!options.handleMouseEvents) marker.widgetNode.setAttribute("cm-ignore-events", "true"); + if (options.insertLeft) marker.widgetNode.insertLeft = true; + } + if (marker.collapsed) { + if (conflictingCollapsedRange(doc, from.line, from, to, marker) || + from.line != to.line && conflictingCollapsedRange(doc, to.line, from, to, marker)) + throw new Error("Inserting collapsed marker partially overlapping an existing one"); + sawCollapsedSpans = true; + } + + if (marker.addToHistory) + addChangeToHistory(doc, {from: from, to: to, origin: "markText"}, doc.sel, NaN); + + var curLine = from.line, cm = doc.cm, updateMaxLine; + doc.iter(curLine, to.line + 1, function(line) { + if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(line) == cm.display.maxLine) + updateMaxLine = true; + if (marker.collapsed && curLine != from.line) updateLineHeight(line, 0); + addMarkedSpan(line, new MarkedSpan(marker, + curLine == from.line ? from.ch : null, + curLine == to.line ? to.ch : null)); + ++curLine; + }); + // lineIsHidden depends on the presence of the spans, so needs a second pass + if (marker.collapsed) doc.iter(from.line, to.line + 1, function(line) { + if (lineIsHidden(doc, line)) updateLineHeight(line, 0); + }); + + if (marker.clearOnEnter) on(marker, "beforeCursorEnter", function() { marker.clear(); }); + + if (marker.readOnly) { + sawReadOnlySpans = true; + if (doc.history.done.length || doc.history.undone.length) + doc.clearHistory(); + } + if (marker.collapsed) { + marker.id = ++nextMarkerId; + marker.atomic = true; + } + if (cm) { + // Sync editor state + if (updateMaxLine) cm.curOp.updateMaxLine = true; + if (marker.collapsed) + regChange(cm, from.line, to.line + 1); + else if (marker.className || marker.title || marker.startStyle || marker.endStyle || marker.css) + for (var i = from.line; i <= to.line; i++) regLineChange(cm, i, "text"); + if (marker.atomic) reCheckSelection(cm.doc); + signalLater(cm, "markerAdded", cm, marker); + } + return marker; + } + + // SHARED TEXTMARKERS + + // A shared marker spans multiple linked documents. It is + // implemented as a meta-marker-object controlling multiple normal + // markers. + var SharedTextMarker = CodeMirror.SharedTextMarker = function(markers, primary) { + this.markers = markers; + this.primary = primary; + for (var i = 0; i < markers.length; ++i) + markers[i].parent = this; + }; + eventMixin(SharedTextMarker); + + SharedTextMarker.prototype.clear = function() { + if (this.explicitlyCleared) return; + this.explicitlyCleared = true; + for (var i = 0; i < this.markers.length; ++i) + this.markers[i].clear(); + signalLater(this, "clear"); + }; + SharedTextMarker.prototype.find = function(side, lineObj) { + return this.primary.find(side, lineObj); + }; + + function markTextShared(doc, from, to, options, type) { + options = copyObj(options); + options.shared = false; + var markers = [markText(doc, from, to, options, type)], primary = markers[0]; + var widget = options.widgetNode; + linkedDocs(doc, function(doc) { + if (widget) options.widgetNode = widget.cloneNode(true); + markers.push(markText(doc, clipPos(doc, from), clipPos(doc, to), options, type)); + for (var i = 0; i < doc.linked.length; ++i) + if (doc.linked[i].isParent) return; + primary = lst(markers); + }); + return new SharedTextMarker(markers, primary); + } + + function findSharedMarkers(doc) { + return doc.findMarks(Pos(doc.first, 0), doc.clipPos(Pos(doc.lastLine())), + function(m) { return m.parent; }); + } + + function copySharedMarkers(doc, markers) { + for (var i = 0; i < markers.length; i++) { + var marker = markers[i], pos = marker.find(); + var mFrom = doc.clipPos(pos.from), mTo = doc.clipPos(pos.to); + if (cmp(mFrom, mTo)) { + var subMark = markText(doc, mFrom, mTo, marker.primary, marker.primary.type); + marker.markers.push(subMark); + subMark.parent = marker; + } + } + } + + function detachSharedMarkers(markers) { + for (var i = 0; i < markers.length; i++) { + var marker = markers[i], linked = [marker.primary.doc];; + linkedDocs(marker.primary.doc, function(d) { linked.push(d); }); + for (var j = 0; j < marker.markers.length; j++) { + var subMarker = marker.markers[j]; + if (indexOf(linked, subMarker.doc) == -1) { + subMarker.parent = null; + marker.markers.splice(j--, 1); + } + } + } + } + + // TEXTMARKER SPANS + + function MarkedSpan(marker, from, to) { + this.marker = marker; + this.from = from; this.to = to; + } + + // Search an array of spans for a span matching the given marker. + function getMarkedSpanFor(spans, marker) { + if (spans) for (var i = 0; i < spans.length; ++i) { + var span = spans[i]; + if (span.marker == marker) return span; + } + } + // Remove a span from an array, returning undefined if no spans are + // left (we don't store arrays for lines without spans). + function removeMarkedSpan(spans, span) { + for (var r, i = 0; i < spans.length; ++i) + if (spans[i] != span) (r || (r = [])).push(spans[i]); + return r; + } + // Add a span to a line. + function addMarkedSpan(line, span) { + line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span]; + span.marker.attachLine(line); + } + + // Used for the algorithm that adjusts markers for a change in the + // document. These functions cut an array of spans at a given + // character position, returning an array of remaining chunks (or + // undefined if nothing remains). + function markedSpansBefore(old, startCh, isInsert) { + if (old) for (var i = 0, nw; i < old.length; ++i) { + var span = old[i], marker = span.marker; + var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh); + if (startsBefore || span.from == startCh && marker.type == "bookmark" && (!isInsert || !span.marker.insertLeft)) { + var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh); + (nw || (nw = [])).push(new MarkedSpan(marker, span.from, endsAfter ? null : span.to)); + } + } + return nw; + } + function markedSpansAfter(old, endCh, isInsert) { + if (old) for (var i = 0, nw; i < old.length; ++i) { + var span = old[i], marker = span.marker; + var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh); + if (endsAfter || span.from == endCh && marker.type == "bookmark" && (!isInsert || span.marker.insertLeft)) { + var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh); + (nw || (nw = [])).push(new MarkedSpan(marker, startsBefore ? null : span.from - endCh, + span.to == null ? null : span.to - endCh)); + } + } + return nw; + } + + // Given a change object, compute the new set of marker spans that + // cover the line in which the change took place. Removes spans + // entirely within the change, reconnects spans belonging to the + // same marker that appear on both sides of the change, and cuts off + // spans partially within the change. Returns an array of span + // arrays with one element for each line in (after) the change. + function stretchSpansOverChange(doc, change) { + if (change.full) return null; + var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans; + var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans; + if (!oldFirst && !oldLast) return null; + + var startCh = change.from.ch, endCh = change.to.ch, isInsert = cmp(change.from, change.to) == 0; + // Get the spans that 'stick out' on both sides + var first = markedSpansBefore(oldFirst, startCh, isInsert); + var last = markedSpansAfter(oldLast, endCh, isInsert); + + // Next, merge those two ends + var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0); + if (first) { + // Fix up .to properties of first + for (var i = 0; i < first.length; ++i) { + var span = first[i]; + if (span.to == null) { + var found = getMarkedSpanFor(last, span.marker); + if (!found) span.to = startCh; + else if (sameLine) span.to = found.to == null ? null : found.to + offset; + } + } + } + if (last) { + // Fix up .from in last (or move them into first in case of sameLine) + for (var i = 0; i < last.length; ++i) { + var span = last[i]; + if (span.to != null) span.to += offset; + if (span.from == null) { + var found = getMarkedSpanFor(first, span.marker); + if (!found) { + span.from = offset; + if (sameLine) (first || (first = [])).push(span); + } + } else { + span.from += offset; + if (sameLine) (first || (first = [])).push(span); + } + } + } + // Make sure we didn't create any zero-length spans + if (first) first = clearEmptySpans(first); + if (last && last != first) last = clearEmptySpans(last); + + var newMarkers = [first]; + if (!sameLine) { + // Fill gap with whole-line-spans + var gap = change.text.length - 2, gapMarkers; + if (gap > 0 && first) + for (var i = 0; i < first.length; ++i) + if (first[i].to == null) + (gapMarkers || (gapMarkers = [])).push(new MarkedSpan(first[i].marker, null, null)); + for (var i = 0; i < gap; ++i) + newMarkers.push(gapMarkers); + newMarkers.push(last); + } + return newMarkers; + } + + // Remove spans that are empty and don't have a clearWhenEmpty + // option of false. + function clearEmptySpans(spans) { + for (var i = 0; i < spans.length; ++i) { + var span = spans[i]; + if (span.from != null && span.from == span.to && span.marker.clearWhenEmpty !== false) + spans.splice(i--, 1); + } + if (!spans.length) return null; + return spans; + } + + // Used for un/re-doing changes from the history. Combines the + // result of computing the existing spans with the set of spans that + // existed in the history (so that deleting around a span and then + // undoing brings back the span). + function mergeOldSpans(doc, change) { + var old = getOldSpans(doc, change); + var stretched = stretchSpansOverChange(doc, change); + if (!old) return stretched; + if (!stretched) return old; + + for (var i = 0; i < old.length; ++i) { + var oldCur = old[i], stretchCur = stretched[i]; + if (oldCur && stretchCur) { + spans: for (var j = 0; j < stretchCur.length; ++j) { + var span = stretchCur[j]; + for (var k = 0; k < oldCur.length; ++k) + if (oldCur[k].marker == span.marker) continue spans; + oldCur.push(span); + } + } else if (stretchCur) { + old[i] = stretchCur; + } + } + return old; + } + + // Used to 'clip' out readOnly ranges when making a change. + function removeReadOnlyRanges(doc, from, to) { + var markers = null; + doc.iter(from.line, to.line + 1, function(line) { + if (line.markedSpans) for (var i = 0; i < line.markedSpans.length; ++i) { + var mark = line.markedSpans[i].marker; + if (mark.readOnly && (!markers || indexOf(markers, mark) == -1)) + (markers || (markers = [])).push(mark); + } + }); + if (!markers) return null; + var parts = [{from: from, to: to}]; + for (var i = 0; i < markers.length; ++i) { + var mk = markers[i], m = mk.find(0); + for (var j = 0; j < parts.length; ++j) { + var p = parts[j]; + if (cmp(p.to, m.from) < 0 || cmp(p.from, m.to) > 0) continue; + var newParts = [j, 1], dfrom = cmp(p.from, m.from), dto = cmp(p.to, m.to); + if (dfrom < 0 || !mk.inclusiveLeft && !dfrom) + newParts.push({from: p.from, to: m.from}); + if (dto > 0 || !mk.inclusiveRight && !dto) + newParts.push({from: m.to, to: p.to}); + parts.splice.apply(parts, newParts); + j += newParts.length - 1; + } + } + return parts; + } + + // Connect or disconnect spans from a line. + function detachMarkedSpans(line) { + var spans = line.markedSpans; + if (!spans) return; + for (var i = 0; i < spans.length; ++i) + spans[i].marker.detachLine(line); + line.markedSpans = null; + } + function attachMarkedSpans(line, spans) { + if (!spans) return; + for (var i = 0; i < spans.length; ++i) + spans[i].marker.attachLine(line); + line.markedSpans = spans; + } + + // Helpers used when computing which overlapping collapsed span + // counts as the larger one. + function extraLeft(marker) { return marker.inclusiveLeft ? -1 : 0; } + function extraRight(marker) { return marker.inclusiveRight ? 1 : 0; } + + // Returns a number indicating which of two overlapping collapsed + // spans is larger (and thus includes the other). Falls back to + // comparing ids when the spans cover exactly the same range. + function compareCollapsedMarkers(a, b) { + var lenDiff = a.lines.length - b.lines.length; + if (lenDiff != 0) return lenDiff; + var aPos = a.find(), bPos = b.find(); + var fromCmp = cmp(aPos.from, bPos.from) || extraLeft(a) - extraLeft(b); + if (fromCmp) return -fromCmp; + var toCmp = cmp(aPos.to, bPos.to) || extraRight(a) - extraRight(b); + if (toCmp) return toCmp; + return b.id - a.id; + } + + // Find out whether a line ends or starts in a collapsed span. If + // so, return the marker for that span. + function collapsedSpanAtSide(line, start) { + var sps = sawCollapsedSpans && line.markedSpans, found; + if (sps) for (var sp, i = 0; i < sps.length; ++i) { + sp = sps[i]; + if (sp.marker.collapsed && (start ? sp.from : sp.to) == null && + (!found || compareCollapsedMarkers(found, sp.marker) < 0)) + found = sp.marker; + } + return found; + } + function collapsedSpanAtStart(line) { return collapsedSpanAtSide(line, true); } + function collapsedSpanAtEnd(line) { return collapsedSpanAtSide(line, false); } + + // Test whether there exists a collapsed span that partially + // overlaps (covers the start or end, but not both) of a new span. + // Such overlap is not allowed. + function conflictingCollapsedRange(doc, lineNo, from, to, marker) { + var line = getLine(doc, lineNo); + var sps = sawCollapsedSpans && line.markedSpans; + if (sps) for (var i = 0; i < sps.length; ++i) { + var sp = sps[i]; + if (!sp.marker.collapsed) continue; + var found = sp.marker.find(0); + var fromCmp = cmp(found.from, from) || extraLeft(sp.marker) - extraLeft(marker); + var toCmp = cmp(found.to, to) || extraRight(sp.marker) - extraRight(marker); + if (fromCmp >= 0 && toCmp <= 0 || fromCmp <= 0 && toCmp >= 0) continue; + if (fromCmp <= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.to, from) >= 0 : cmp(found.to, from) > 0) || + fromCmp >= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.from, to) <= 0 : cmp(found.from, to) < 0)) + return true; + } + } + + // A visual line is a line as drawn on the screen. Folding, for + // example, can cause multiple logical lines to appear on the same + // visual line. This finds the start of the visual line that the + // given line is part of (usually that is the line itself). + function visualLine(line) { + var merged; + while (merged = collapsedSpanAtStart(line)) + line = merged.find(-1, true).line; + return line; + } + + // Returns an array of logical lines that continue the visual line + // started by the argument, or undefined if there are no such lines. + function visualLineContinued(line) { + var merged, lines; + while (merged = collapsedSpanAtEnd(line)) { + line = merged.find(1, true).line; + (lines || (lines = [])).push(line); + } + return lines; + } + + // Get the line number of the start of the visual line that the + // given line number is part of. + function visualLineNo(doc, lineN) { + var line = getLine(doc, lineN), vis = visualLine(line); + if (line == vis) return lineN; + return lineNo(vis); + } + // Get the line number of the start of the next visual line after + // the given line. + function visualLineEndNo(doc, lineN) { + if (lineN > doc.lastLine()) return lineN; + var line = getLine(doc, lineN), merged; + if (!lineIsHidden(doc, line)) return lineN; + while (merged = collapsedSpanAtEnd(line)) + line = merged.find(1, true).line; + return lineNo(line) + 1; + } + + // Compute whether a line is hidden. Lines count as hidden when they + // are part of a visual line that starts with another line, or when + // they are entirely covered by collapsed, non-widget span. + function lineIsHidden(doc, line) { + var sps = sawCollapsedSpans && line.markedSpans; + if (sps) for (var sp, i = 0; i < sps.length; ++i) { + sp = sps[i]; + if (!sp.marker.collapsed) continue; + if (sp.from == null) return true; + if (sp.marker.widgetNode) continue; + if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp)) + return true; + } + } + function lineIsHiddenInner(doc, line, span) { + if (span.to == null) { + var end = span.marker.find(1, true); + return lineIsHiddenInner(doc, end.line, getMarkedSpanFor(end.line.markedSpans, span.marker)); + } + if (span.marker.inclusiveRight && span.to == line.text.length) + return true; + for (var sp, i = 0; i < line.markedSpans.length; ++i) { + sp = line.markedSpans[i]; + if (sp.marker.collapsed && !sp.marker.widgetNode && sp.from == span.to && + (sp.to == null || sp.to != span.from) && + (sp.marker.inclusiveLeft || span.marker.inclusiveRight) && + lineIsHiddenInner(doc, line, sp)) return true; + } + } + + // LINE WIDGETS + + // Line widgets are block elements displayed above or below a line. + + var LineWidget = CodeMirror.LineWidget = function(doc, node, options) { + if (options) for (var opt in options) if (options.hasOwnProperty(opt)) + this[opt] = options[opt]; + this.doc = doc; + this.node = node; + }; + eventMixin(LineWidget); + + function adjustScrollWhenAboveVisible(cm, line, diff) { + if (heightAtLine(line) < ((cm.curOp && cm.curOp.scrollTop) || cm.doc.scrollTop)) + addToScrollPos(cm, null, diff); + } + + LineWidget.prototype.clear = function() { + var cm = this.doc.cm, ws = this.line.widgets, line = this.line, no = lineNo(line); + if (no == null || !ws) return; + for (var i = 0; i < ws.length; ++i) if (ws[i] == this) ws.splice(i--, 1); + if (!ws.length) line.widgets = null; + var height = widgetHeight(this); + updateLineHeight(line, Math.max(0, line.height - height)); + if (cm) runInOp(cm, function() { + adjustScrollWhenAboveVisible(cm, line, -height); + regLineChange(cm, no, "widget"); + }); + }; + LineWidget.prototype.changed = function() { + var oldH = this.height, cm = this.doc.cm, line = this.line; + this.height = null; + var diff = widgetHeight(this) - oldH; + if (!diff) return; + updateLineHeight(line, line.height + diff); + if (cm) runInOp(cm, function() { + cm.curOp.forceUpdate = true; + adjustScrollWhenAboveVisible(cm, line, diff); + }); + }; + + function widgetHeight(widget) { + if (widget.height != null) return widget.height; + var cm = widget.doc.cm; + if (!cm) return 0; + if (!contains(document.body, widget.node)) { + var parentStyle = "position: relative;"; + if (widget.coverGutter) + parentStyle += "margin-left: -" + cm.display.gutters.offsetWidth + "px;"; + if (widget.noHScroll) + parentStyle += "width: " + cm.display.wrapper.clientWidth + "px;"; + removeChildrenAndAdd(cm.display.measure, elt("div", [widget.node], null, parentStyle)); + } + return widget.height = widget.node.parentNode.offsetHeight; + } + + function addLineWidget(doc, handle, node, options) { + var widget = new LineWidget(doc, node, options); + var cm = doc.cm; + if (cm && widget.noHScroll) cm.display.alignWidgets = true; + changeLine(doc, handle, "widget", function(line) { + var widgets = line.widgets || (line.widgets = []); + if (widget.insertAt == null) widgets.push(widget); + else widgets.splice(Math.min(widgets.length - 1, Math.max(0, widget.insertAt)), 0, widget); + widget.line = line; + if (cm && !lineIsHidden(doc, line)) { + var aboveVisible = heightAtLine(line) < doc.scrollTop; + updateLineHeight(line, line.height + widgetHeight(widget)); + if (aboveVisible) addToScrollPos(cm, null, widget.height); + cm.curOp.forceUpdate = true; + } + return true; + }); + return widget; + } + + // LINE DATA STRUCTURE + + // Line objects. These hold state related to a line, including + // highlighting info (the styles array). + var Line = CodeMirror.Line = function(text, markedSpans, estimateHeight) { + this.text = text; + attachMarkedSpans(this, markedSpans); + this.height = estimateHeight ? estimateHeight(this) : 1; + }; + eventMixin(Line); + Line.prototype.lineNo = function() { return lineNo(this); }; + + // Change the content (text, markers) of a line. Automatically + // invalidates cached information and tries to re-estimate the + // line's height. + function updateLine(line, text, markedSpans, estimateHeight) { + line.text = text; + if (line.stateAfter) line.stateAfter = null; + if (line.styles) line.styles = null; + if (line.order != null) line.order = null; + detachMarkedSpans(line); + attachMarkedSpans(line, markedSpans); + var estHeight = estimateHeight ? estimateHeight(line) : 1; + if (estHeight != line.height) updateLineHeight(line, estHeight); + } + + // Detach a line from the document tree and its markers. + function cleanUpLine(line) { + line.parent = null; + detachMarkedSpans(line); + } + + function extractLineClasses(type, output) { + if (type) for (;;) { + var lineClass = type.match(/(?:^|\s+)line-(background-)?(\S+)/); + if (!lineClass) break; + type = type.slice(0, lineClass.index) + type.slice(lineClass.index + lineClass[0].length); + var prop = lineClass[1] ? "bgClass" : "textClass"; + if (output[prop] == null) + output[prop] = lineClass[2]; + else if (!(new RegExp("(?:^|\s)" + lineClass[2] + "(?:$|\s)")).test(output[prop])) + output[prop] += " " + lineClass[2]; + } + return type; + } + + function callBlankLine(mode, state) { + if (mode.blankLine) return mode.blankLine(state); + if (!mode.innerMode) return; + var inner = CodeMirror.innerMode(mode, state); + if (inner.mode.blankLine) return inner.mode.blankLine(inner.state); + } + + function readToken(mode, stream, state, inner) { + for (var i = 0; i < 10; i++) { + if (inner) inner[0] = CodeMirror.innerMode(mode, state).mode; + var style = mode.token(stream, state); + if (stream.pos > stream.start) return style; + } + throw new Error("Mode " + mode.name + " failed to advance stream."); + } + + // Utility for getTokenAt and getLineTokens + function takeToken(cm, pos, precise, asArray) { + function getObj(copy) { + return {start: stream.start, end: stream.pos, + string: stream.current(), + type: style || null, + state: copy ? copyState(doc.mode, state) : state}; + } + + var doc = cm.doc, mode = doc.mode, style; + pos = clipPos(doc, pos); + var line = getLine(doc, pos.line), state = getStateBefore(cm, pos.line, precise); + var stream = new StringStream(line.text, cm.options.tabSize), tokens; + if (asArray) tokens = []; + while ((asArray || stream.pos < pos.ch) && !stream.eol()) { + stream.start = stream.pos; + style = readToken(mode, stream, state); + if (asArray) tokens.push(getObj(true)); + } + return asArray ? tokens : getObj(); + } + + // Run the given mode's parser over a line, calling f for each token. + function runMode(cm, text, mode, state, f, lineClasses, forceToEnd) { + var flattenSpans = mode.flattenSpans; + if (flattenSpans == null) flattenSpans = cm.options.flattenSpans; + var curStart = 0, curStyle = null; + var stream = new StringStream(text, cm.options.tabSize), style; + var inner = cm.options.addModeClass && [null]; + if (text == "") extractLineClasses(callBlankLine(mode, state), lineClasses); + while (!stream.eol()) { + if (stream.pos > cm.options.maxHighlightLength) { + flattenSpans = false; + if (forceToEnd) processLine(cm, text, state, stream.pos); + stream.pos = text.length; + style = null; + } else { + style = extractLineClasses(readToken(mode, stream, state, inner), lineClasses); + } + if (inner) { + var mName = inner[0].name; + if (mName) style = "m-" + (style ? mName + " " + style : mName); + } + if (!flattenSpans || curStyle != style) { + while (curStart < stream.start) { + curStart = Math.min(stream.start, curStart + 50000); + f(curStart, curStyle); + } + curStyle = style; + } + stream.start = stream.pos; + } + while (curStart < stream.pos) { + // Webkit seems to refuse to render text nodes longer than 57444 characters + var pos = Math.min(stream.pos, curStart + 50000); + f(pos, curStyle); + curStart = pos; + } + } + + // Compute a style array (an array starting with a mode generation + // -- for invalidation -- followed by pairs of end positions and + // style strings), which is used to highlight the tokens on the + // line. + function highlightLine(cm, line, state, forceToEnd) { + // A styles array always starts with a number identifying the + // mode/overlays that it is based on (for easy invalidation). + var st = [cm.state.modeGen], lineClasses = {}; + // Compute the base array of styles + runMode(cm, line.text, cm.doc.mode, state, function(end, style) { + st.push(end, style); + }, lineClasses, forceToEnd); + + // Run overlays, adjust style array. + for (var o = 0; o < cm.state.overlays.length; ++o) { + var overlay = cm.state.overlays[o], i = 1, at = 0; + runMode(cm, line.text, overlay.mode, true, function(end, style) { + var start = i; + // Ensure there's a token end at the current position, and that i points at it + while (at < end) { + var i_end = st[i]; + if (i_end > end) + st.splice(i, 1, end, st[i+1], i_end); + i += 2; + at = Math.min(end, i_end); + } + if (!style) return; + if (overlay.opaque) { + st.splice(start, i - start, end, "cm-overlay " + style); + i = start + 2; + } else { + for (; start < i; start += 2) { + var cur = st[start+1]; + st[start+1] = (cur ? cur + " " : "") + "cm-overlay " + style; + } + } + }, lineClasses); + } + + return {styles: st, classes: lineClasses.bgClass || lineClasses.textClass ? lineClasses : null}; + } + + function getLineStyles(cm, line, updateFrontier) { + if (!line.styles || line.styles[0] != cm.state.modeGen) { + var state = getStateBefore(cm, lineNo(line)); + var result = highlightLine(cm, line, line.text.length > cm.options.maxHighlightLength ? copyState(cm.doc.mode, state) : state); + line.stateAfter = state; + line.styles = result.styles; + if (result.classes) line.styleClasses = result.classes; + else if (line.styleClasses) line.styleClasses = null; + if (updateFrontier === cm.doc.frontier) cm.doc.frontier++; + } + return line.styles; + } + + // Lightweight form of highlight -- proceed over this line and + // update state, but don't save a style array. Used for lines that + // aren't currently visible. + function processLine(cm, text, state, startAt) { + var mode = cm.doc.mode; + var stream = new StringStream(text, cm.options.tabSize); + stream.start = stream.pos = startAt || 0; + if (text == "") callBlankLine(mode, state); + while (!stream.eol()) { + readToken(mode, stream, state); + stream.start = stream.pos; + } + } + + // Convert a style as returned by a mode (either null, or a string + // containing one or more styles) to a CSS style. This is cached, + // and also looks for line-wide styles. + var styleToClassCache = {}, styleToClassCacheWithMode = {}; + function interpretTokenStyle(style, options) { + if (!style || /^\s*$/.test(style)) return null; + var cache = options.addModeClass ? styleToClassCacheWithMode : styleToClassCache; + return cache[style] || + (cache[style] = style.replace(/\S+/g, "cm-$&")); + } + + // Render the DOM representation of the text of a line. Also builds + // up a 'line map', which points at the DOM nodes that represent + // specific stretches of text, and is used by the measuring code. + // The returned object contains the DOM node, this map, and + // information about line-wide styles that were set by the mode. + function buildLineContent(cm, lineView) { + // The padding-right forces the element to have a 'border', which + // is needed on Webkit to be able to get line-level bounding + // rectangles for it (in measureChar). + var content = elt("span", null, null, webkit ? "padding-right: .1px" : null); + var builder = {pre: elt("pre", [content], "CodeMirror-line"), content: content, + col: 0, pos: 0, cm: cm, + trailingSpace: false, + splitSpaces: (ie || webkit) && cm.getOption("lineWrapping")}; + lineView.measure = {}; + + // Iterate over the logical lines that make up this visual line. + for (var i = 0; i <= (lineView.rest ? lineView.rest.length : 0); i++) { + var line = i ? lineView.rest[i - 1] : lineView.line, order; + builder.pos = 0; + builder.addToken = buildToken; + // Optionally wire in some hacks into the token-rendering + // algorithm, to deal with browser quirks. + if (hasBadBidiRects(cm.display.measure) && (order = getOrder(line))) + builder.addToken = buildTokenBadBidi(builder.addToken, order); + builder.map = []; + var allowFrontierUpdate = lineView != cm.display.externalMeasured && lineNo(line); + insertLineContent(line, builder, getLineStyles(cm, line, allowFrontierUpdate)); + if (line.styleClasses) { + if (line.styleClasses.bgClass) + builder.bgClass = joinClasses(line.styleClasses.bgClass, builder.bgClass || ""); + if (line.styleClasses.textClass) + builder.textClass = joinClasses(line.styleClasses.textClass, builder.textClass || ""); + } + + // Ensure at least a single node is present, for measuring. + if (builder.map.length == 0) + builder.map.push(0, 0, builder.content.appendChild(zeroWidthElement(cm.display.measure))); + + // Store the map and a cache object for the current logical line + if (i == 0) { + lineView.measure.map = builder.map; + lineView.measure.cache = {}; + } else { + (lineView.measure.maps || (lineView.measure.maps = [])).push(builder.map); + (lineView.measure.caches || (lineView.measure.caches = [])).push({}); + } + } + + // See issue #2901 + if (webkit) { + var last = builder.content.lastChild + if (/\bcm-tab\b/.test(last.className) || (last.querySelector && last.querySelector(".cm-tab"))) + builder.content.className = "cm-tab-wrap-hack"; + } + + signal(cm, "renderLine", cm, lineView.line, builder.pre); + if (builder.pre.className) + builder.textClass = joinClasses(builder.pre.className, builder.textClass || ""); + + return builder; + } + + function defaultSpecialCharPlaceholder(ch) { + var token = elt("span", "\u2022", "cm-invalidchar"); + token.title = "\\u" + ch.charCodeAt(0).toString(16); + token.setAttribute("aria-label", token.title); + return token; + } + + // Build up the DOM representation for a single token, and add it to + // the line map. Takes care to render special characters separately. + function buildToken(builder, text, style, startStyle, endStyle, title, css) { + if (!text) return; + var displayText = builder.splitSpaces ? splitSpaces(text, builder.trailingSpace) : text + var special = builder.cm.state.specialChars, mustWrap = false; + if (!special.test(text)) { + builder.col += text.length; + var content = document.createTextNode(displayText); + builder.map.push(builder.pos, builder.pos + text.length, content); + if (ie && ie_version < 9) mustWrap = true; + builder.pos += text.length; + } else { + var content = document.createDocumentFragment(), pos = 0; + while (true) { + special.lastIndex = pos; + var m = special.exec(text); + var skipped = m ? m.index - pos : text.length - pos; + if (skipped) { + var txt = document.createTextNode(displayText.slice(pos, pos + skipped)); + if (ie && ie_version < 9) content.appendChild(elt("span", [txt])); + else content.appendChild(txt); + builder.map.push(builder.pos, builder.pos + skipped, txt); + builder.col += skipped; + builder.pos += skipped; + } + if (!m) break; + pos += skipped + 1; + if (m[0] == "\t") { + var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize; + var txt = content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab")); + txt.setAttribute("role", "presentation"); + txt.setAttribute("cm-text", "\t"); + builder.col += tabWidth; + } else if (m[0] == "\r" || m[0] == "\n") { + var txt = content.appendChild(elt("span", m[0] == "\r" ? "\u240d" : "\u2424", "cm-invalidchar")); + txt.setAttribute("cm-text", m[0]); + builder.col += 1; + } else { + var txt = builder.cm.options.specialCharPlaceholder(m[0]); + txt.setAttribute("cm-text", m[0]); + if (ie && ie_version < 9) content.appendChild(elt("span", [txt])); + else content.appendChild(txt); + builder.col += 1; + } + builder.map.push(builder.pos, builder.pos + 1, txt); + builder.pos++; + } + } + builder.trailingSpace = displayText.charCodeAt(text.length - 1) == 32 + if (style || startStyle || endStyle || mustWrap || css) { + var fullStyle = style || ""; + if (startStyle) fullStyle += startStyle; + if (endStyle) fullStyle += endStyle; + var token = elt("span", [content], fullStyle, css); + if (title) token.title = title; + return builder.content.appendChild(token); + } + builder.content.appendChild(content); + } + + function splitSpaces(text, trailingBefore) { + if (text.length > 1 && !/ /.test(text)) return text + var spaceBefore = trailingBefore, result = "" + for (var i = 0; i < text.length; i++) { + var ch = text.charAt(i) + if (ch == " " && spaceBefore && (i == text.length - 1 || text.charCodeAt(i + 1) == 32)) + ch = "\u00a0" + result += ch + spaceBefore = ch == " " + } + return result + } + + // Work around nonsense dimensions being reported for stretches of + // right-to-left text. + function buildTokenBadBidi(inner, order) { + return function(builder, text, style, startStyle, endStyle, title, css) { + style = style ? style + " cm-force-border" : "cm-force-border"; + var start = builder.pos, end = start + text.length; + for (;;) { + // Find the part that overlaps with the start of this text + for (var i = 0; i < order.length; i++) { + var part = order[i]; + if (part.to > start && part.from <= start) break; + } + if (part.to >= end) return inner(builder, text, style, startStyle, endStyle, title, css); + inner(builder, text.slice(0, part.to - start), style, startStyle, null, title, css); + startStyle = null; + text = text.slice(part.to - start); + start = part.to; + } + }; + } + + function buildCollapsedSpan(builder, size, marker, ignoreWidget) { + var widget = !ignoreWidget && marker.widgetNode; + if (widget) builder.map.push(builder.pos, builder.pos + size, widget); + if (!ignoreWidget && builder.cm.display.input.needsContentAttribute) { + if (!widget) + widget = builder.content.appendChild(document.createElement("span")); + widget.setAttribute("cm-marker", marker.id); + } + if (widget) { + builder.cm.display.input.setUneditable(widget); + builder.content.appendChild(widget); + } + builder.pos += size; + builder.trailingSpace = false + } + + // Outputs a number of spans to make up a line, taking highlighting + // and marked text into account. + function insertLineContent(line, builder, styles) { + var spans = line.markedSpans, allText = line.text, at = 0; + if (!spans) { + for (var i = 1; i < styles.length; i+=2) + builder.addToken(builder, allText.slice(at, at = styles[i]), interpretTokenStyle(styles[i+1], builder.cm.options)); + return; + } + + var len = allText.length, pos = 0, i = 1, text = "", style, css; + var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, title, collapsed; + for (;;) { + if (nextChange == pos) { // Update current marker set + spanStyle = spanEndStyle = spanStartStyle = title = css = ""; + collapsed = null; nextChange = Infinity; + var foundBookmarks = [], endStyles + for (var j = 0; j < spans.length; ++j) { + var sp = spans[j], m = sp.marker; + if (m.type == "bookmark" && sp.from == pos && m.widgetNode) { + foundBookmarks.push(m); + } else if (sp.from <= pos && (sp.to == null || sp.to > pos || m.collapsed && sp.to == pos && sp.from == pos)) { + if (sp.to != null && sp.to != pos && nextChange > sp.to) { + nextChange = sp.to; + spanEndStyle = ""; + } + if (m.className) spanStyle += " " + m.className; + if (m.css) css = (css ? css + ";" : "") + m.css; + if (m.startStyle && sp.from == pos) spanStartStyle += " " + m.startStyle; + if (m.endStyle && sp.to == nextChange) (endStyles || (endStyles = [])).push(m.endStyle, sp.to) + if (m.title && !title) title = m.title; + if (m.collapsed && (!collapsed || compareCollapsedMarkers(collapsed.marker, m) < 0)) + collapsed = sp; + } else if (sp.from > pos && nextChange > sp.from) { + nextChange = sp.from; + } + } + if (endStyles) for (var j = 0; j < endStyles.length; j += 2) + if (endStyles[j + 1] == nextChange) spanEndStyle += " " + endStyles[j] + + if (!collapsed || collapsed.from == pos) for (var j = 0; j < foundBookmarks.length; ++j) + buildCollapsedSpan(builder, 0, foundBookmarks[j]); + if (collapsed && (collapsed.from || 0) == pos) { + buildCollapsedSpan(builder, (collapsed.to == null ? len + 1 : collapsed.to) - pos, + collapsed.marker, collapsed.from == null); + if (collapsed.to == null) return; + if (collapsed.to == pos) collapsed = false; + } + } + if (pos >= len) break; + + var upto = Math.min(len, nextChange); + while (true) { + if (text) { + var end = pos + text.length; + if (!collapsed) { + var tokenText = end > upto ? text.slice(0, upto - pos) : text; + builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle, + spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", title, css); + } + if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;} + pos = end; + spanStartStyle = ""; + } + text = allText.slice(at, at = styles[i++]); + style = interpretTokenStyle(styles[i++], builder.cm.options); + } + } + } + + // DOCUMENT DATA STRUCTURE + + // By default, updates that start and end at the beginning of a line + // are treated specially, in order to make the association of line + // widgets and marker elements with the text behave more intuitive. + function isWholeLineUpdate(doc, change) { + return change.from.ch == 0 && change.to.ch == 0 && lst(change.text) == "" && + (!doc.cm || doc.cm.options.wholeLineUpdateBefore); + } + + // Perform a change on the document data structure. + function updateDoc(doc, change, markedSpans, estimateHeight) { + function spansFor(n) {return markedSpans ? markedSpans[n] : null;} + function update(line, text, spans) { + updateLine(line, text, spans, estimateHeight); + signalLater(line, "change", line, change); + } + function linesFor(start, end) { + for (var i = start, result = []; i < end; ++i) + result.push(new Line(text[i], spansFor(i), estimateHeight)); + return result; + } + + var from = change.from, to = change.to, text = change.text; + var firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line); + var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line; + + // Adjust the line structure + if (change.full) { + doc.insert(0, linesFor(0, text.length)); + doc.remove(text.length, doc.size - text.length); + } else if (isWholeLineUpdate(doc, change)) { + // This is a whole-line replace. Treated specially to make + // sure line objects move the way they are supposed to. + var added = linesFor(0, text.length - 1); + update(lastLine, lastLine.text, lastSpans); + if (nlines) doc.remove(from.line, nlines); + if (added.length) doc.insert(from.line, added); + } else if (firstLine == lastLine) { + if (text.length == 1) { + update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans); + } else { + var added = linesFor(1, text.length - 1); + added.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight)); + update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0)); + doc.insert(from.line + 1, added); + } + } else if (text.length == 1) { + update(firstLine, firstLine.text.slice(0, from.ch) + text[0] + lastLine.text.slice(to.ch), spansFor(0)); + doc.remove(from.line + 1, nlines); + } else { + update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0)); + update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans); + var added = linesFor(1, text.length - 1); + if (nlines > 1) doc.remove(from.line + 1, nlines - 1); + doc.insert(from.line + 1, added); + } + + signalLater(doc, "change", doc, change); + } + + // The document is represented as a BTree consisting of leaves, with + // chunk of lines in them, and branches, with up to ten leaves or + // other branch nodes below them. The top node is always a branch + // node, and is the document object itself (meaning it has + // additional methods and properties). + // + // All nodes have parent links. The tree is used both to go from + // line numbers to line objects, and to go from objects to numbers. + // It also indexes by height, and is used to convert between height + // and line object, and to find the total height of the document. + // + // See also http://marijnhaverbeke.nl/blog/codemirror-line-tree.html + + function LeafChunk(lines) { + this.lines = lines; + this.parent = null; + for (var i = 0, height = 0; i < lines.length; ++i) { + lines[i].parent = this; + height += lines[i].height; + } + this.height = height; + } + + LeafChunk.prototype = { + chunkSize: function() { return this.lines.length; }, + // Remove the n lines at offset 'at'. + removeInner: function(at, n) { + for (var i = at, e = at + n; i < e; ++i) { + var line = this.lines[i]; + this.height -= line.height; + cleanUpLine(line); + signalLater(line, "delete"); + } + this.lines.splice(at, n); + }, + // Helper used to collapse a small branch into a single leaf. + collapse: function(lines) { + lines.push.apply(lines, this.lines); + }, + // Insert the given array of lines at offset 'at', count them as + // having the given height. + insertInner: function(at, lines, height) { + this.height += height; + this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at)); + for (var i = 0; i < lines.length; ++i) lines[i].parent = this; + }, + // Used to iterate over a part of the tree. + iterN: function(at, n, op) { + for (var e = at + n; at < e; ++at) + if (op(this.lines[at])) return true; + } + }; + + function BranchChunk(children) { + this.children = children; + var size = 0, height = 0; + for (var i = 0; i < children.length; ++i) { + var ch = children[i]; + size += ch.chunkSize(); height += ch.height; + ch.parent = this; + } + this.size = size; + this.height = height; + this.parent = null; + } + + BranchChunk.prototype = { + chunkSize: function() { return this.size; }, + removeInner: function(at, n) { + this.size -= n; + for (var i = 0; i < this.children.length; ++i) { + var child = this.children[i], sz = child.chunkSize(); + if (at < sz) { + var rm = Math.min(n, sz - at), oldHeight = child.height; + child.removeInner(at, rm); + this.height -= oldHeight - child.height; + if (sz == rm) { this.children.splice(i--, 1); child.parent = null; } + if ((n -= rm) == 0) break; + at = 0; + } else at -= sz; + } + // If the result is smaller than 25 lines, ensure that it is a + // single leaf node. + if (this.size - n < 25 && + (this.children.length > 1 || !(this.children[0] instanceof LeafChunk))) { + var lines = []; + this.collapse(lines); + this.children = [new LeafChunk(lines)]; + this.children[0].parent = this; + } + }, + collapse: function(lines) { + for (var i = 0; i < this.children.length; ++i) this.children[i].collapse(lines); + }, + insertInner: function(at, lines, height) { + this.size += lines.length; + this.height += height; + for (var i = 0; i < this.children.length; ++i) { + var child = this.children[i], sz = child.chunkSize(); + if (at <= sz) { + child.insertInner(at, lines, height); + if (child.lines && child.lines.length > 50) { + // To avoid memory thrashing when child.lines is huge (e.g. first view of a large file), it's never spliced. + // Instead, small slices are taken. They're taken in order because sequential memory accesses are fastest. + var remaining = child.lines.length % 25 + 25 + for (var pos = remaining; pos < child.lines.length;) { + var leaf = new LeafChunk(child.lines.slice(pos, pos += 25)); + child.height -= leaf.height; + this.children.splice(++i, 0, leaf); + leaf.parent = this; + } + child.lines = child.lines.slice(0, remaining); + this.maybeSpill(); + } + break; + } + at -= sz; + } + }, + // When a node has grown, check whether it should be split. + maybeSpill: function() { + if (this.children.length <= 10) return; + var me = this; + do { + var spilled = me.children.splice(me.children.length - 5, 5); + var sibling = new BranchChunk(spilled); + if (!me.parent) { // Become the parent node + var copy = new BranchChunk(me.children); + copy.parent = me; + me.children = [copy, sibling]; + me = copy; + } else { + me.size -= sibling.size; + me.height -= sibling.height; + var myIndex = indexOf(me.parent.children, me); + me.parent.children.splice(myIndex + 1, 0, sibling); + } + sibling.parent = me.parent; + } while (me.children.length > 10); + me.parent.maybeSpill(); + }, + iterN: function(at, n, op) { + for (var i = 0; i < this.children.length; ++i) { + var child = this.children[i], sz = child.chunkSize(); + if (at < sz) { + var used = Math.min(n, sz - at); + if (child.iterN(at, used, op)) return true; + if ((n -= used) == 0) break; + at = 0; + } else at -= sz; + } + } + }; + + var nextDocId = 0; + var Doc = CodeMirror.Doc = function(text, mode, firstLine, lineSep) { + if (!(this instanceof Doc)) return new Doc(text, mode, firstLine, lineSep); + if (firstLine == null) firstLine = 0; + + BranchChunk.call(this, [new LeafChunk([new Line("", null)])]); + this.first = firstLine; + this.scrollTop = this.scrollLeft = 0; + this.cantEdit = false; + this.cleanGeneration = 1; + this.frontier = firstLine; + var start = Pos(firstLine, 0); + this.sel = simpleSelection(start); + this.history = new History(null); + this.id = ++nextDocId; + this.modeOption = mode; + this.lineSep = lineSep; + this.extend = false; + + if (typeof text == "string") text = this.splitLines(text); + updateDoc(this, {from: start, to: start, text: text}); + setSelection(this, simpleSelection(start), sel_dontScroll); + }; + + Doc.prototype = createObj(BranchChunk.prototype, { + constructor: Doc, + // Iterate over the document. Supports two forms -- with only one + // argument, it calls that for each line in the document. With + // three, it iterates over the range given by the first two (with + // the second being non-inclusive). + iter: function(from, to, op) { + if (op) this.iterN(from - this.first, to - from, op); + else this.iterN(this.first, this.first + this.size, from); + }, + + // Non-public interface for adding and removing lines. + insert: function(at, lines) { + var height = 0; + for (var i = 0; i < lines.length; ++i) height += lines[i].height; + this.insertInner(at - this.first, lines, height); + }, + remove: function(at, n) { this.removeInner(at - this.first, n); }, + + // From here, the methods are part of the public interface. Most + // are also available from CodeMirror (editor) instances. + + getValue: function(lineSep) { + var lines = getLines(this, this.first, this.first + this.size); + if (lineSep === false) return lines; + return lines.join(lineSep || this.lineSeparator()); + }, + setValue: docMethodOp(function(code) { + var top = Pos(this.first, 0), last = this.first + this.size - 1; + makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length), + text: this.splitLines(code), origin: "setValue", full: true}, true); + setSelection(this, simpleSelection(top)); + }), + replaceRange: function(code, from, to, origin) { + from = clipPos(this, from); + to = to ? clipPos(this, to) : from; + replaceRange(this, code, from, to, origin); + }, + getRange: function(from, to, lineSep) { + var lines = getBetween(this, clipPos(this, from), clipPos(this, to)); + if (lineSep === false) return lines; + return lines.join(lineSep || this.lineSeparator()); + }, + + getLine: function(line) {var l = this.getLineHandle(line); return l && l.text;}, + + getLineHandle: function(line) {if (isLine(this, line)) return getLine(this, line);}, + getLineNumber: function(line) {return lineNo(line);}, + + getLineHandleVisualStart: function(line) { + if (typeof line == "number") line = getLine(this, line); + return visualLine(line); + }, + + lineCount: function() {return this.size;}, + firstLine: function() {return this.first;}, + lastLine: function() {return this.first + this.size - 1;}, + + clipPos: function(pos) {return clipPos(this, pos);}, + + getCursor: function(start) { + var range = this.sel.primary(), pos; + if (start == null || start == "head") pos = range.head; + else if (start == "anchor") pos = range.anchor; + else if (start == "end" || start == "to" || start === false) pos = range.to(); + else pos = range.from(); + return pos; + }, + listSelections: function() { return this.sel.ranges; }, + somethingSelected: function() {return this.sel.somethingSelected();}, + + setCursor: docMethodOp(function(line, ch, options) { + setSimpleSelection(this, clipPos(this, typeof line == "number" ? Pos(line, ch || 0) : line), null, options); + }), + setSelection: docMethodOp(function(anchor, head, options) { + setSimpleSelection(this, clipPos(this, anchor), clipPos(this, head || anchor), options); + }), + extendSelection: docMethodOp(function(head, other, options) { + extendSelection(this, clipPos(this, head), other && clipPos(this, other), options); + }), + extendSelections: docMethodOp(function(heads, options) { + extendSelections(this, clipPosArray(this, heads), options); + }), + extendSelectionsBy: docMethodOp(function(f, options) { + var heads = map(this.sel.ranges, f); + extendSelections(this, clipPosArray(this, heads), options); + }), + setSelections: docMethodOp(function(ranges, primary, options) { + if (!ranges.length) return; + for (var i = 0, out = []; i < ranges.length; i++) + out[i] = new Range(clipPos(this, ranges[i].anchor), + clipPos(this, ranges[i].head)); + if (primary == null) primary = Math.min(ranges.length - 1, this.sel.primIndex); + setSelection(this, normalizeSelection(out, primary), options); + }), + addSelection: docMethodOp(function(anchor, head, options) { + var ranges = this.sel.ranges.slice(0); + ranges.push(new Range(clipPos(this, anchor), clipPos(this, head || anchor))); + setSelection(this, normalizeSelection(ranges, ranges.length - 1), options); + }), + + getSelection: function(lineSep) { + var ranges = this.sel.ranges, lines; + for (var i = 0; i < ranges.length; i++) { + var sel = getBetween(this, ranges[i].from(), ranges[i].to()); + lines = lines ? lines.concat(sel) : sel; + } + if (lineSep === false) return lines; + else return lines.join(lineSep || this.lineSeparator()); + }, + getSelections: function(lineSep) { + var parts = [], ranges = this.sel.ranges; + for (var i = 0; i < ranges.length; i++) { + var sel = getBetween(this, ranges[i].from(), ranges[i].to()); + if (lineSep !== false) sel = sel.join(lineSep || this.lineSeparator()); + parts[i] = sel; + } + return parts; + }, + replaceSelection: function(code, collapse, origin) { + var dup = []; + for (var i = 0; i < this.sel.ranges.length; i++) + dup[i] = code; + this.replaceSelections(dup, collapse, origin || "+input"); + }, + replaceSelections: docMethodOp(function(code, collapse, origin) { + var changes = [], sel = this.sel; + for (var i = 0; i < sel.ranges.length; i++) { + var range = sel.ranges[i]; + changes[i] = {from: range.from(), to: range.to(), text: this.splitLines(code[i]), origin: origin}; + } + var newSel = collapse && collapse != "end" && computeReplacedSel(this, changes, collapse); + for (var i = changes.length - 1; i >= 0; i--) + makeChange(this, changes[i]); + if (newSel) setSelectionReplaceHistory(this, newSel); + else if (this.cm) ensureCursorVisible(this.cm); + }), + undo: docMethodOp(function() {makeChangeFromHistory(this, "undo");}), + redo: docMethodOp(function() {makeChangeFromHistory(this, "redo");}), + undoSelection: docMethodOp(function() {makeChangeFromHistory(this, "undo", true);}), + redoSelection: docMethodOp(function() {makeChangeFromHistory(this, "redo", true);}), + + setExtending: function(val) {this.extend = val;}, + getExtending: function() {return this.extend;}, + + historySize: function() { + var hist = this.history, done = 0, undone = 0; + for (var i = 0; i < hist.done.length; i++) if (!hist.done[i].ranges) ++done; + for (var i = 0; i < hist.undone.length; i++) if (!hist.undone[i].ranges) ++undone; + return {undo: done, redo: undone}; + }, + clearHistory: function() {this.history = new History(this.history.maxGeneration);}, + + markClean: function() { + this.cleanGeneration = this.changeGeneration(true); + }, + changeGeneration: function(forceSplit) { + if (forceSplit) + this.history.lastOp = this.history.lastSelOp = this.history.lastOrigin = null; + return this.history.generation; + }, + isClean: function (gen) { + return this.history.generation == (gen || this.cleanGeneration); + }, + + getHistory: function() { + return {done: copyHistoryArray(this.history.done), + undone: copyHistoryArray(this.history.undone)}; + }, + setHistory: function(histData) { + var hist = this.history = new History(this.history.maxGeneration); + hist.done = copyHistoryArray(histData.done.slice(0), null, true); + hist.undone = copyHistoryArray(histData.undone.slice(0), null, true); + }, + + addLineClass: docMethodOp(function(handle, where, cls) { + return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function(line) { + var prop = where == "text" ? "textClass" + : where == "background" ? "bgClass" + : where == "gutter" ? "gutterClass" : "wrapClass"; + if (!line[prop]) line[prop] = cls; + else if (classTest(cls).test(line[prop])) return false; + else line[prop] += " " + cls; + return true; + }); + }), + removeLineClass: docMethodOp(function(handle, where, cls) { + return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function(line) { + var prop = where == "text" ? "textClass" + : where == "background" ? "bgClass" + : where == "gutter" ? "gutterClass" : "wrapClass"; + var cur = line[prop]; + if (!cur) return false; + else if (cls == null) line[prop] = null; + else { + var found = cur.match(classTest(cls)); + if (!found) return false; + var end = found.index + found[0].length; + line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? "" : " ") + cur.slice(end) || null; + } + return true; + }); + }), + + addLineWidget: docMethodOp(function(handle, node, options) { + return addLineWidget(this, handle, node, options); + }), + removeLineWidget: function(widget) { widget.clear(); }, + + markText: function(from, to, options) { + return markText(this, clipPos(this, from), clipPos(this, to), options, options && options.type || "range"); + }, + setBookmark: function(pos, options) { + var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options), + insertLeft: options && options.insertLeft, + clearWhenEmpty: false, shared: options && options.shared, + handleMouseEvents: options && options.handleMouseEvents}; + pos = clipPos(this, pos); + return markText(this, pos, pos, realOpts, "bookmark"); + }, + findMarksAt: function(pos) { + pos = clipPos(this, pos); + var markers = [], spans = getLine(this, pos.line).markedSpans; + if (spans) for (var i = 0; i < spans.length; ++i) { + var span = spans[i]; + if ((span.from == null || span.from <= pos.ch) && + (span.to == null || span.to >= pos.ch)) + markers.push(span.marker.parent || span.marker); + } + return markers; + }, + findMarks: function(from, to, filter) { + from = clipPos(this, from); to = clipPos(this, to); + var found = [], lineNo = from.line; + this.iter(from.line, to.line + 1, function(line) { + var spans = line.markedSpans; + if (spans) for (var i = 0; i < spans.length; i++) { + var span = spans[i]; + if (!(span.to != null && lineNo == from.line && from.ch >= span.to || + span.from == null && lineNo != from.line || + span.from != null && lineNo == to.line && span.from >= to.ch) && + (!filter || filter(span.marker))) + found.push(span.marker.parent || span.marker); + } + ++lineNo; + }); + return found; + }, + getAllMarks: function() { + var markers = []; + this.iter(function(line) { + var sps = line.markedSpans; + if (sps) for (var i = 0; i < sps.length; ++i) + if (sps[i].from != null) markers.push(sps[i].marker); + }); + return markers; + }, + + posFromIndex: function(off) { + var ch, lineNo = this.first, sepSize = this.lineSeparator().length; + this.iter(function(line) { + var sz = line.text.length + sepSize; + if (sz > off) { ch = off; return true; } + off -= sz; + ++lineNo; + }); + return clipPos(this, Pos(lineNo, ch)); + }, + indexFromPos: function (coords) { + coords = clipPos(this, coords); + var index = coords.ch; + if (coords.line < this.first || coords.ch < 0) return 0; + var sepSize = this.lineSeparator().length; + this.iter(this.first, coords.line, function (line) { + index += line.text.length + sepSize; + }); + return index; + }, + + copy: function(copyHistory) { + var doc = new Doc(getLines(this, this.first, this.first + this.size), + this.modeOption, this.first, this.lineSep); + doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft; + doc.sel = this.sel; + doc.extend = false; + if (copyHistory) { + doc.history.undoDepth = this.history.undoDepth; + doc.setHistory(this.getHistory()); + } + return doc; + }, + + linkedDoc: function(options) { + if (!options) options = {}; + var from = this.first, to = this.first + this.size; + if (options.from != null && options.from > from) from = options.from; + if (options.to != null && options.to < to) to = options.to; + var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from, this.lineSep); + if (options.sharedHist) copy.history = this.history; + (this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist}); + copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}]; + copySharedMarkers(copy, findSharedMarkers(this)); + return copy; + }, + unlinkDoc: function(other) { + if (other instanceof CodeMirror) other = other.doc; + if (this.linked) for (var i = 0; i < this.linked.length; ++i) { + var link = this.linked[i]; + if (link.doc != other) continue; + this.linked.splice(i, 1); + other.unlinkDoc(this); + detachSharedMarkers(findSharedMarkers(this)); + break; + } + // If the histories were shared, split them again + if (other.history == this.history) { + var splitIds = [other.id]; + linkedDocs(other, function(doc) {splitIds.push(doc.id);}, true); + other.history = new History(null); + other.history.done = copyHistoryArray(this.history.done, splitIds); + other.history.undone = copyHistoryArray(this.history.undone, splitIds); + } + }, + iterLinkedDocs: function(f) {linkedDocs(this, f);}, + + getMode: function() {return this.mode;}, + getEditor: function() {return this.cm;}, + + splitLines: function(str) { + if (this.lineSep) return str.split(this.lineSep); + return splitLinesAuto(str); + }, + lineSeparator: function() { return this.lineSep || "\n"; } + }); + + // Public alias. + Doc.prototype.eachLine = Doc.prototype.iter; + + // Set up methods on CodeMirror's prototype to redirect to the editor's document. + var dontDelegate = "iter insert remove copy getEditor constructor".split(" "); + for (var prop in Doc.prototype) if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0) + CodeMirror.prototype[prop] = (function(method) { + return function() {return method.apply(this.doc, arguments);}; + })(Doc.prototype[prop]); + + eventMixin(Doc); + + // Call f for all linked documents. + function linkedDocs(doc, f, sharedHistOnly) { + function propagate(doc, skip, sharedHist) { + if (doc.linked) for (var i = 0; i < doc.linked.length; ++i) { + var rel = doc.linked[i]; + if (rel.doc == skip) continue; + var shared = sharedHist && rel.sharedHist; + if (sharedHistOnly && !shared) continue; + f(rel.doc, shared); + propagate(rel.doc, doc, shared); + } + } + propagate(doc, null, true); + } + + // Attach a document to an editor. + function attachDoc(cm, doc) { + if (doc.cm) throw new Error("This document is already in use."); + cm.doc = doc; + doc.cm = cm; + estimateLineHeights(cm); + loadMode(cm); + if (!cm.options.lineWrapping) findMaxLine(cm); + cm.options.mode = doc.modeOption; + regChange(cm); + } + + // LINE UTILITIES + + // Find the line object corresponding to the given line number. + function getLine(doc, n) { + n -= doc.first; + if (n < 0 || n >= doc.size) throw new Error("There is no line " + (n + doc.first) + " in the document."); + for (var chunk = doc; !chunk.lines;) { + for (var i = 0;; ++i) { + var child = chunk.children[i], sz = child.chunkSize(); + if (n < sz) { chunk = child; break; } + n -= sz; + } + } + return chunk.lines[n]; + } + + // Get the part of a document between two positions, as an array of + // strings. + function getBetween(doc, start, end) { + var out = [], n = start.line; + doc.iter(start.line, end.line + 1, function(line) { + var text = line.text; + if (n == end.line) text = text.slice(0, end.ch); + if (n == start.line) text = text.slice(start.ch); + out.push(text); + ++n; + }); + return out; + } + // Get the lines between from and to, as array of strings. + function getLines(doc, from, to) { + var out = []; + doc.iter(from, to, function(line) { out.push(line.text); }); + return out; + } + + // Update the height of a line, propagating the height change + // upwards to parent nodes. + function updateLineHeight(line, height) { + var diff = height - line.height; + if (diff) for (var n = line; n; n = n.parent) n.height += diff; + } + + // Given a line object, find its line number by walking up through + // its parent links. + function lineNo(line) { + if (line.parent == null) return null; + var cur = line.parent, no = indexOf(cur.lines, line); + for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) { + for (var i = 0;; ++i) { + if (chunk.children[i] == cur) break; + no += chunk.children[i].chunkSize(); + } + } + return no + cur.first; + } + + // Find the line at the given vertical position, using the height + // information in the document tree. + function lineAtHeight(chunk, h) { + var n = chunk.first; + outer: do { + for (var i = 0; i < chunk.children.length; ++i) { + var child = chunk.children[i], ch = child.height; + if (h < ch) { chunk = child; continue outer; } + h -= ch; + n += child.chunkSize(); + } + return n; + } while (!chunk.lines); + for (var i = 0; i < chunk.lines.length; ++i) { + var line = chunk.lines[i], lh = line.height; + if (h < lh) break; + h -= lh; + } + return n + i; + } + + + // Find the height above the given line. + function heightAtLine(lineObj) { + lineObj = visualLine(lineObj); + + var h = 0, chunk = lineObj.parent; + for (var i = 0; i < chunk.lines.length; ++i) { + var line = chunk.lines[i]; + if (line == lineObj) break; + else h += line.height; + } + for (var p = chunk.parent; p; chunk = p, p = chunk.parent) { + for (var i = 0; i < p.children.length; ++i) { + var cur = p.children[i]; + if (cur == chunk) break; + else h += cur.height; + } + } + return h; + } + + // Get the bidi ordering for the given line (and cache it). Returns + // false for lines that are fully left-to-right, and an array of + // BidiSpan objects otherwise. + function getOrder(line) { + var order = line.order; + if (order == null) order = line.order = bidiOrdering(line.text); + return order; + } + + // HISTORY + + function History(startGen) { + // Arrays of change events and selections. Doing something adds an + // event to done and clears undo. Undoing moves events from done + // to undone, redoing moves them in the other direction. + this.done = []; this.undone = []; + this.undoDepth = Infinity; + // Used to track when changes can be merged into a single undo + // event + this.lastModTime = this.lastSelTime = 0; + this.lastOp = this.lastSelOp = null; + this.lastOrigin = this.lastSelOrigin = null; + // Used by the isClean() method + this.generation = this.maxGeneration = startGen || 1; + } + + // Create a history change event from an updateDoc-style change + // object. + function historyChangeFromChange(doc, change) { + var histChange = {from: copyPos(change.from), to: changeEnd(change), text: getBetween(doc, change.from, change.to)}; + attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1); + linkedDocs(doc, function(doc) {attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);}, true); + return histChange; + } + + // Pop all selection events off the end of a history array. Stop at + // a change event. + function clearSelectionEvents(array) { + while (array.length) { + var last = lst(array); + if (last.ranges) array.pop(); + else break; + } + } + + // Find the top change event in the history. Pop off selection + // events that are in the way. + function lastChangeEvent(hist, force) { + if (force) { + clearSelectionEvents(hist.done); + return lst(hist.done); + } else if (hist.done.length && !lst(hist.done).ranges) { + return lst(hist.done); + } else if (hist.done.length > 1 && !hist.done[hist.done.length - 2].ranges) { + hist.done.pop(); + return lst(hist.done); + } + } + + // Register a change in the history. Merges changes that are within + // a single operation, or are close together with an origin that + // allows merging (starting with "+") into a single event. + function addChangeToHistory(doc, change, selAfter, opId) { + var hist = doc.history; + hist.undone.length = 0; + var time = +new Date, cur; + + if ((hist.lastOp == opId || + hist.lastOrigin == change.origin && change.origin && + ((change.origin.charAt(0) == "+" && doc.cm && hist.lastModTime > time - doc.cm.options.historyEventDelay) || + change.origin.charAt(0) == "*")) && + (cur = lastChangeEvent(hist, hist.lastOp == opId))) { + // Merge this change into the last event + var last = lst(cur.changes); + if (cmp(change.from, change.to) == 0 && cmp(change.from, last.to) == 0) { + // Optimized case for simple insertion -- don't want to add + // new changesets for every character typed + last.to = changeEnd(change); + } else { + // Add new sub-event + cur.changes.push(historyChangeFromChange(doc, change)); + } + } else { + // Can not be merged, start a new event. + var before = lst(hist.done); + if (!before || !before.ranges) + pushSelectionToHistory(doc.sel, hist.done); + cur = {changes: [historyChangeFromChange(doc, change)], + generation: hist.generation}; + hist.done.push(cur); + while (hist.done.length > hist.undoDepth) { + hist.done.shift(); + if (!hist.done[0].ranges) hist.done.shift(); + } + } + hist.done.push(selAfter); + hist.generation = ++hist.maxGeneration; + hist.lastModTime = hist.lastSelTime = time; + hist.lastOp = hist.lastSelOp = opId; + hist.lastOrigin = hist.lastSelOrigin = change.origin; + + if (!last) signal(doc, "historyAdded"); + } + + function selectionEventCanBeMerged(doc, origin, prev, sel) { + var ch = origin.charAt(0); + return ch == "*" || + ch == "+" && + prev.ranges.length == sel.ranges.length && + prev.somethingSelected() == sel.somethingSelected() && + new Date - doc.history.lastSelTime <= (doc.cm ? doc.cm.options.historyEventDelay : 500); + } + + // Called whenever the selection changes, sets the new selection as + // the pending selection in the history, and pushes the old pending + // selection into the 'done' array when it was significantly + // different (in number of selected ranges, emptiness, or time). + function addSelectionToHistory(doc, sel, opId, options) { + var hist = doc.history, origin = options && options.origin; + + // A new event is started when the previous origin does not match + // the current, or the origins don't allow matching. Origins + // starting with * are always merged, those starting with + are + // merged when similar and close together in time. + if (opId == hist.lastSelOp || + (origin && hist.lastSelOrigin == origin && + (hist.lastModTime == hist.lastSelTime && hist.lastOrigin == origin || + selectionEventCanBeMerged(doc, origin, lst(hist.done), sel)))) + hist.done[hist.done.length - 1] = sel; + else + pushSelectionToHistory(sel, hist.done); + + hist.lastSelTime = +new Date; + hist.lastSelOrigin = origin; + hist.lastSelOp = opId; + if (options && options.clearRedo !== false) + clearSelectionEvents(hist.undone); + } + + function pushSelectionToHistory(sel, dest) { + var top = lst(dest); + if (!(top && top.ranges && top.equals(sel))) + dest.push(sel); + } + + // Used to store marked span information in the history. + function attachLocalSpans(doc, change, from, to) { + var existing = change["spans_" + doc.id], n = 0; + doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function(line) { + if (line.markedSpans) + (existing || (existing = change["spans_" + doc.id] = {}))[n] = line.markedSpans; + ++n; + }); + } + + // When un/re-doing restores text containing marked spans, those + // that have been explicitly cleared should not be restored. + function removeClearedSpans(spans) { + if (!spans) return null; + for (var i = 0, out; i < spans.length; ++i) { + if (spans[i].marker.explicitlyCleared) { if (!out) out = spans.slice(0, i); } + else if (out) out.push(spans[i]); + } + return !out ? spans : out.length ? out : null; + } + + // Retrieve and filter the old marked spans stored in a change event. + function getOldSpans(doc, change) { + var found = change["spans_" + doc.id]; + if (!found) return null; + for (var i = 0, nw = []; i < change.text.length; ++i) + nw.push(removeClearedSpans(found[i])); + return nw; + } + + // Used both to provide a JSON-safe object in .getHistory, and, when + // detaching a document, to split the history in two + function copyHistoryArray(events, newGroup, instantiateSel) { + for (var i = 0, copy = []; i < events.length; ++i) { + var event = events[i]; + if (event.ranges) { + copy.push(instantiateSel ? Selection.prototype.deepCopy.call(event) : event); + continue; + } + var changes = event.changes, newChanges = []; + copy.push({changes: newChanges}); + for (var j = 0; j < changes.length; ++j) { + var change = changes[j], m; + newChanges.push({from: change.from, to: change.to, text: change.text}); + if (newGroup) for (var prop in change) if (m = prop.match(/^spans_(\d+)$/)) { + if (indexOf(newGroup, Number(m[1])) > -1) { + lst(newChanges)[prop] = change[prop]; + delete change[prop]; + } + } + } + } + return copy; + } + + // Rebasing/resetting history to deal with externally-sourced changes + + function rebaseHistSelSingle(pos, from, to, diff) { + if (to < pos.line) { + pos.line += diff; + } else if (from < pos.line) { + pos.line = from; + pos.ch = 0; + } + } + + // Tries to rebase an array of history events given a change in the + // document. If the change touches the same lines as the event, the + // event, and everything 'behind' it, is discarded. If the change is + // before the event, the event's positions are updated. Uses a + // copy-on-write scheme for the positions, to avoid having to + // reallocate them all on every rebase, but also avoid problems with + // shared position objects being unsafely updated. + function rebaseHistArray(array, from, to, diff) { + for (var i = 0; i < array.length; ++i) { + var sub = array[i], ok = true; + if (sub.ranges) { + if (!sub.copied) { sub = array[i] = sub.deepCopy(); sub.copied = true; } + for (var j = 0; j < sub.ranges.length; j++) { + rebaseHistSelSingle(sub.ranges[j].anchor, from, to, diff); + rebaseHistSelSingle(sub.ranges[j].head, from, to, diff); + } + continue; + } + for (var j = 0; j < sub.changes.length; ++j) { + var cur = sub.changes[j]; + if (to < cur.from.line) { + cur.from = Pos(cur.from.line + diff, cur.from.ch); + cur.to = Pos(cur.to.line + diff, cur.to.ch); + } else if (from <= cur.to.line) { + ok = false; + break; + } + } + if (!ok) { + array.splice(0, i + 1); + i = 0; + } + } + } + + function rebaseHist(hist, change) { + var from = change.from.line, to = change.to.line, diff = change.text.length - (to - from) - 1; + rebaseHistArray(hist.done, from, to, diff); + rebaseHistArray(hist.undone, from, to, diff); + } + + // EVENT UTILITIES + + // Due to the fact that we still support jurassic IE versions, some + // compatibility wrappers are needed. + + var e_preventDefault = CodeMirror.e_preventDefault = function(e) { + if (e.preventDefault) e.preventDefault(); + else e.returnValue = false; + }; + var e_stopPropagation = CodeMirror.e_stopPropagation = function(e) { + if (e.stopPropagation) e.stopPropagation(); + else e.cancelBubble = true; + }; + function e_defaultPrevented(e) { + return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false; + } + var e_stop = CodeMirror.e_stop = function(e) {e_preventDefault(e); e_stopPropagation(e);}; + + function e_target(e) {return e.target || e.srcElement;} + function e_button(e) { + var b = e.which; + if (b == null) { + if (e.button & 1) b = 1; + else if (e.button & 2) b = 3; + else if (e.button & 4) b = 2; + } + if (mac && e.ctrlKey && b == 1) b = 3; + return b; + } + + // EVENT HANDLING + + // Lightweight event framework. on/off also work on DOM nodes, + // registering native DOM handlers. + + var on = CodeMirror.on = function(emitter, type, f) { + if (emitter.addEventListener) + emitter.addEventListener(type, f, false); + else if (emitter.attachEvent) + emitter.attachEvent("on" + type, f); + else { + var map = emitter._handlers || (emitter._handlers = {}); + var arr = map[type] || (map[type] = []); + arr.push(f); + } + }; + + var noHandlers = [] + function getHandlers(emitter, type, copy) { + var arr = emitter._handlers && emitter._handlers[type] + if (copy) return arr && arr.length > 0 ? arr.slice() : noHandlers + else return arr || noHandlers + } + + var off = CodeMirror.off = function(emitter, type, f) { + if (emitter.removeEventListener) + emitter.removeEventListener(type, f, false); + else if (emitter.detachEvent) + emitter.detachEvent("on" + type, f); + else { + var handlers = getHandlers(emitter, type, false) + for (var i = 0; i < handlers.length; ++i) + if (handlers[i] == f) { handlers.splice(i, 1); break; } + } + }; + + var signal = CodeMirror.signal = function(emitter, type /*, values...*/) { + var handlers = getHandlers(emitter, type, true) + if (!handlers.length) return; + var args = Array.prototype.slice.call(arguments, 2); + for (var i = 0; i < handlers.length; ++i) handlers[i].apply(null, args); + }; + + var orphanDelayedCallbacks = null; + + // Often, we want to signal events at a point where we are in the + // middle of some work, but don't want the handler to start calling + // other methods on the editor, which might be in an inconsistent + // state or simply not expect any other events to happen. + // signalLater looks whether there are any handlers, and schedules + // them to be executed when the last operation ends, or, if no + // operation is active, when a timeout fires. + function signalLater(emitter, type /*, values...*/) { + var arr = getHandlers(emitter, type, false) + if (!arr.length) return; + var args = Array.prototype.slice.call(arguments, 2), list; + if (operationGroup) { + list = operationGroup.delayedCallbacks; + } else if (orphanDelayedCallbacks) { + list = orphanDelayedCallbacks; + } else { + list = orphanDelayedCallbacks = []; + setTimeout(fireOrphanDelayed, 0); + } + function bnd(f) {return function(){f.apply(null, args);};}; + for (var i = 0; i < arr.length; ++i) + list.push(bnd(arr[i])); + } + + function fireOrphanDelayed() { + var delayed = orphanDelayedCallbacks; + orphanDelayedCallbacks = null; + for (var i = 0; i < delayed.length; ++i) delayed[i](); + } + + // The DOM events that CodeMirror handles can be overridden by + // registering a (non-DOM) handler on the editor for the event name, + // and preventDefault-ing the event in that handler. + function signalDOMEvent(cm, e, override) { + if (typeof e == "string") + e = {type: e, preventDefault: function() { this.defaultPrevented = true; }}; + signal(cm, override || e.type, cm, e); + return e_defaultPrevented(e) || e.codemirrorIgnore; + } + + function signalCursorActivity(cm) { + var arr = cm._handlers && cm._handlers.cursorActivity; + if (!arr) return; + var set = cm.curOp.cursorActivityHandlers || (cm.curOp.cursorActivityHandlers = []); + for (var i = 0; i < arr.length; ++i) if (indexOf(set, arr[i]) == -1) + set.push(arr[i]); + } + + function hasHandler(emitter, type) { + return getHandlers(emitter, type).length > 0 + } + + // Add on and off methods to a constructor's prototype, to make + // registering events on such objects more convenient. + function eventMixin(ctor) { + ctor.prototype.on = function(type, f) {on(this, type, f);}; + ctor.prototype.off = function(type, f) {off(this, type, f);}; + } + + // MISC UTILITIES + + // Number of pixels added to scroller and sizer to hide scrollbar + var scrollerGap = 30; + + // Returned or thrown by various protocols to signal 'I'm not + // handling this'. + var Pass = CodeMirror.Pass = {toString: function(){return "CodeMirror.Pass";}}; + + // Reused option objects for setSelection & friends + var sel_dontScroll = {scroll: false}, sel_mouse = {origin: "*mouse"}, sel_move = {origin: "+move"}; + + function Delayed() {this.id = null;} + Delayed.prototype.set = function(ms, f) { + clearTimeout(this.id); + this.id = setTimeout(f, ms); + }; + + // Counts the column offset in a string, taking tabs into account. + // Used mostly to find indentation. + var countColumn = CodeMirror.countColumn = function(string, end, tabSize, startIndex, startValue) { + if (end == null) { + end = string.search(/[^\s\u00a0]/); + if (end == -1) end = string.length; + } + for (var i = startIndex || 0, n = startValue || 0;;) { + var nextTab = string.indexOf("\t", i); + if (nextTab < 0 || nextTab >= end) + return n + (end - i); + n += nextTab - i; + n += tabSize - (n % tabSize); + i = nextTab + 1; + } + }; + + // The inverse of countColumn -- find the offset that corresponds to + // a particular column. + var findColumn = CodeMirror.findColumn = function(string, goal, tabSize) { + for (var pos = 0, col = 0;;) { + var nextTab = string.indexOf("\t", pos); + if (nextTab == -1) nextTab = string.length; + var skipped = nextTab - pos; + if (nextTab == string.length || col + skipped >= goal) + return pos + Math.min(skipped, goal - col); + col += nextTab - pos; + col += tabSize - (col % tabSize); + pos = nextTab + 1; + if (col >= goal) return pos; + } + } + + var spaceStrs = [""]; + function spaceStr(n) { + while (spaceStrs.length <= n) + spaceStrs.push(lst(spaceStrs) + " "); + return spaceStrs[n]; + } + + function lst(arr) { return arr[arr.length-1]; } + + var selectInput = function(node) { node.select(); }; + if (ios) // Mobile Safari apparently has a bug where select() is broken. + selectInput = function(node) { node.selectionStart = 0; node.selectionEnd = node.value.length; }; + else if (ie) // Suppress mysterious IE10 errors + selectInput = function(node) { try { node.select(); } catch(_e) {} }; + + function indexOf(array, elt) { + for (var i = 0; i < array.length; ++i) + if (array[i] == elt) return i; + return -1; + } + function map(array, f) { + var out = []; + for (var i = 0; i < array.length; i++) out[i] = f(array[i], i); + return out; + } + + function insertSorted(array, value, score) { + var pos = 0, priority = score(value) + while (pos < array.length && score(array[pos]) <= priority) pos++ + array.splice(pos, 0, value) + } + + function nothing() {} + + function createObj(base, props) { + var inst; + if (Object.create) { + inst = Object.create(base); + } else { + nothing.prototype = base; + inst = new nothing(); + } + if (props) copyObj(props, inst); + return inst; + }; + + function copyObj(obj, target, overwrite) { + if (!target) target = {}; + for (var prop in obj) + if (obj.hasOwnProperty(prop) && (overwrite !== false || !target.hasOwnProperty(prop))) + target[prop] = obj[prop]; + return target; + } + + function bind(f) { + var args = Array.prototype.slice.call(arguments, 1); + return function(){return f.apply(null, args);}; + } + + var nonASCIISingleCaseWordChar = /[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/; + var isWordCharBasic = CodeMirror.isWordChar = function(ch) { + return /\w/.test(ch) || ch > "\x80" && + (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch)); + }; + function isWordChar(ch, helper) { + if (!helper) return isWordCharBasic(ch); + if (helper.source.indexOf("\\w") > -1 && isWordCharBasic(ch)) return true; + return helper.test(ch); + } + + function isEmpty(obj) { + for (var n in obj) if (obj.hasOwnProperty(n) && obj[n]) return false; + return true; + } + + // Extending unicode characters. A series of a non-extending char + + // any number of extending chars is treated as a single unit as far + // as editing and measuring is concerned. This is not fully correct, + // since some scripts/fonts/browsers also treat other configurations + // of code points as a group. + var extendingChars = /[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/; + function isExtendingChar(ch) { return ch.charCodeAt(0) >= 768 && extendingChars.test(ch); } + + // DOM UTILITIES + + function elt(tag, content, className, style) { + var e = document.createElement(tag); + if (className) e.className = className; + if (style) e.style.cssText = style; + if (typeof content == "string") e.appendChild(document.createTextNode(content)); + else if (content) for (var i = 0; i < content.length; ++i) e.appendChild(content[i]); + return e; + } + + var range; + if (document.createRange) range = function(node, start, end, endNode) { + var r = document.createRange(); + r.setEnd(endNode || node, end); + r.setStart(node, start); + return r; + }; + else range = function(node, start, end) { + var r = document.body.createTextRange(); + try { r.moveToElementText(node.parentNode); } + catch(e) { return r; } + r.collapse(true); + r.moveEnd("character", end); + r.moveStart("character", start); + return r; + }; + + function removeChildren(e) { + for (var count = e.childNodes.length; count > 0; --count) + e.removeChild(e.firstChild); + return e; + } + + function removeChildrenAndAdd(parent, e) { + return removeChildren(parent).appendChild(e); + } + + var contains = CodeMirror.contains = function(parent, child) { + if (child.nodeType == 3) // Android browser always returns false when child is a textnode + child = child.parentNode; + if (parent.contains) + return parent.contains(child); + do { + if (child.nodeType == 11) child = child.host; + if (child == parent) return true; + } while (child = child.parentNode); + }; + + function activeElt() { + var activeElement = document.activeElement; + while (activeElement && activeElement.root && activeElement.root.activeElement) + activeElement = activeElement.root.activeElement; + return activeElement; + } + // Older versions of IE throws unspecified error when touching + // document.activeElement in some cases (during loading, in iframe) + if (ie && ie_version < 11) activeElt = function() { + try { return document.activeElement; } + catch(e) { return document.body; } + }; + + function classTest(cls) { return new RegExp("(^|\\s)" + cls + "(?:$|\\s)\\s*"); } + var rmClass = CodeMirror.rmClass = function(node, cls) { + var current = node.className; + var match = classTest(cls).exec(current); + if (match) { + var after = current.slice(match.index + match[0].length); + node.className = current.slice(0, match.index) + (after ? match[1] + after : ""); + } + }; + var addClass = CodeMirror.addClass = function(node, cls) { + var current = node.className; + if (!classTest(cls).test(current)) node.className += (current ? " " : "") + cls; + }; + function joinClasses(a, b) { + var as = a.split(" "); + for (var i = 0; i < as.length; i++) + if (as[i] && !classTest(as[i]).test(b)) b += " " + as[i]; + return b; + } + + // WINDOW-WIDE EVENTS + + // These must be handled carefully, because naively registering a + // handler for each editor will cause the editors to never be + // garbage collected. + + function forEachCodeMirror(f) { + if (!document.body.getElementsByClassName) return; + var byClass = document.body.getElementsByClassName("CodeMirror"); + for (var i = 0; i < byClass.length; i++) { + var cm = byClass[i].CodeMirror; + if (cm) f(cm); + } + } + + var globalsRegistered = false; + function ensureGlobalHandlers() { + if (globalsRegistered) return; + registerGlobalHandlers(); + globalsRegistered = true; + } + function registerGlobalHandlers() { + // When the window resizes, we need to refresh active editors. + var resizeTimer; + on(window, "resize", function() { + if (resizeTimer == null) resizeTimer = setTimeout(function() { + resizeTimer = null; + forEachCodeMirror(onResize); + }, 100); + }); + // When the window loses focus, we want to show the editor as blurred + on(window, "blur", function() { + forEachCodeMirror(onBlur); + }); + } + + // FEATURE DETECTION + + // Detect drag-and-drop + var dragAndDrop = function() { + // There is *some* kind of drag-and-drop support in IE6-8, but I + // couldn't get it to work yet. + if (ie && ie_version < 9) return false; + var div = elt('div'); + return "draggable" in div || "dragDrop" in div; + }(); + + var zwspSupported; + function zeroWidthElement(measure) { + if (zwspSupported == null) { + var test = elt("span", "\u200b"); + removeChildrenAndAdd(measure, elt("span", [test, document.createTextNode("x")])); + if (measure.firstChild.offsetHeight != 0) + zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !(ie && ie_version < 8); + } + var node = zwspSupported ? elt("span", "\u200b") : + elt("span", "\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px"); + node.setAttribute("cm-text", ""); + return node; + } + + // Feature-detect IE's crummy client rect reporting for bidi text + var badBidiRects; + function hasBadBidiRects(measure) { + if (badBidiRects != null) return badBidiRects; + var txt = removeChildrenAndAdd(measure, document.createTextNode("A\u062eA")); + var r0 = range(txt, 0, 1).getBoundingClientRect(); + var r1 = range(txt, 1, 2).getBoundingClientRect(); + removeChildren(measure); + if (!r0 || r0.left == r0.right) return false; // Safari returns null in some cases (#2780) + return badBidiRects = (r1.right - r0.right < 3); + } + + // See if "".split is the broken IE version, if so, provide an + // alternative way to split lines. + var splitLinesAuto = CodeMirror.splitLines = "\n\nb".split(/\n/).length != 3 ? function(string) { + var pos = 0, result = [], l = string.length; + while (pos <= l) { + var nl = string.indexOf("\n", pos); + if (nl == -1) nl = string.length; + var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl); + var rt = line.indexOf("\r"); + if (rt != -1) { + result.push(line.slice(0, rt)); + pos += rt + 1; + } else { + result.push(line); + pos = nl + 1; + } + } + return result; + } : function(string){return string.split(/\r\n?|\n/);}; + + var hasSelection = window.getSelection ? function(te) { + try { return te.selectionStart != te.selectionEnd; } + catch(e) { return false; } + } : function(te) { + try {var range = te.ownerDocument.selection.createRange();} + catch(e) {} + if (!range || range.parentElement() != te) return false; + return range.compareEndPoints("StartToEnd", range) != 0; + }; + + var hasCopyEvent = (function() { + var e = elt("div"); + if ("oncopy" in e) return true; + e.setAttribute("oncopy", "return;"); + return typeof e.oncopy == "function"; + })(); + + var badZoomedRects = null; + function hasBadZoomedRects(measure) { + if (badZoomedRects != null) return badZoomedRects; + var node = removeChildrenAndAdd(measure, elt("span", "x")); + var normal = node.getBoundingClientRect(); + var fromRange = range(node, 0, 1).getBoundingClientRect(); + return badZoomedRects = Math.abs(normal.left - fromRange.left) > 1; + } + + // KEY NAMES + + var keyNames = CodeMirror.keyNames = { + 3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt", + 19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End", + 36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert", + 46: "Delete", 59: ";", 61: "=", 91: "Mod", 92: "Mod", 93: "Mod", + 106: "*", 107: "=", 109: "-", 110: ".", 111: "/", 127: "Delete", + 173: "-", 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\", + 221: "]", 222: "'", 63232: "Up", 63233: "Down", 63234: "Left", 63235: "Right", 63272: "Delete", + 63273: "Home", 63275: "End", 63276: "PageUp", 63277: "PageDown", 63302: "Insert" + }; + (function() { + // Number keys + for (var i = 0; i < 10; i++) keyNames[i + 48] = keyNames[i + 96] = String(i); + // Alphabetic keys + for (var i = 65; i <= 90; i++) keyNames[i] = String.fromCharCode(i); + // Function keys + for (var i = 1; i <= 12; i++) keyNames[i + 111] = keyNames[i + 63235] = "F" + i; + })(); + + // BIDI HELPERS + + function iterateBidiSections(order, from, to, f) { + if (!order) return f(from, to, "ltr"); + var found = false; + for (var i = 0; i < order.length; ++i) { + var part = order[i]; + if (part.from < to && part.to > from || from == to && part.to == from) { + f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr"); + found = true; + } + } + if (!found) f(from, to, "ltr"); + } + + function bidiLeft(part) { return part.level % 2 ? part.to : part.from; } + function bidiRight(part) { return part.level % 2 ? part.from : part.to; } + + function lineLeft(line) { var order = getOrder(line); return order ? bidiLeft(order[0]) : 0; } + function lineRight(line) { + var order = getOrder(line); + if (!order) return line.text.length; + return bidiRight(lst(order)); + } + + function lineStart(cm, lineN) { + var line = getLine(cm.doc, lineN); + var visual = visualLine(line); + if (visual != line) lineN = lineNo(visual); + var order = getOrder(visual); + var ch = !order ? 0 : order[0].level % 2 ? lineRight(visual) : lineLeft(visual); + return Pos(lineN, ch); + } + function lineEnd(cm, lineN) { + var merged, line = getLine(cm.doc, lineN); + while (merged = collapsedSpanAtEnd(line)) { + line = merged.find(1, true).line; + lineN = null; + } + var order = getOrder(line); + var ch = !order ? line.text.length : order[0].level % 2 ? lineLeft(line) : lineRight(line); + return Pos(lineN == null ? lineNo(line) : lineN, ch); + } + function lineStartSmart(cm, pos) { + var start = lineStart(cm, pos.line); + var line = getLine(cm.doc, start.line); + var order = getOrder(line); + if (!order || order[0].level == 0) { + var firstNonWS = Math.max(0, line.text.search(/\S/)); + var inWS = pos.line == start.line && pos.ch <= firstNonWS && pos.ch; + return Pos(start.line, inWS ? 0 : firstNonWS); + } + return start; + } + + function compareBidiLevel(order, a, b) { + var linedir = order[0].level; + if (a == linedir) return true; + if (b == linedir) return false; + return a < b; + } + var bidiOther; + function getBidiPartAt(order, pos) { + bidiOther = null; + for (var i = 0, found; i < order.length; ++i) { + var cur = order[i]; + if (cur.from < pos && cur.to > pos) return i; + if ((cur.from == pos || cur.to == pos)) { + if (found == null) { + found = i; + } else if (compareBidiLevel(order, cur.level, order[found].level)) { + if (cur.from != cur.to) bidiOther = found; + return i; + } else { + if (cur.from != cur.to) bidiOther = i; + return found; + } + } + } + return found; + } + + function moveInLine(line, pos, dir, byUnit) { + if (!byUnit) return pos + dir; + do pos += dir; + while (pos > 0 && isExtendingChar(line.text.charAt(pos))); + return pos; + } + + // This is needed in order to move 'visually' through bi-directional + // text -- i.e., pressing left should make the cursor go left, even + // when in RTL text. The tricky part is the 'jumps', where RTL and + // LTR text touch each other. This often requires the cursor offset + // to move more than one unit, in order to visually move one unit. + function moveVisually(line, start, dir, byUnit) { + var bidi = getOrder(line); + if (!bidi) return moveLogically(line, start, dir, byUnit); + var pos = getBidiPartAt(bidi, start), part = bidi[pos]; + var target = moveInLine(line, start, part.level % 2 ? -dir : dir, byUnit); + + for (;;) { + if (target > part.from && target < part.to) return target; + if (target == part.from || target == part.to) { + if (getBidiPartAt(bidi, target) == pos) return target; + part = bidi[pos += dir]; + return (dir > 0) == part.level % 2 ? part.to : part.from; + } else { + part = bidi[pos += dir]; + if (!part) return null; + if ((dir > 0) == part.level % 2) + target = moveInLine(line, part.to, -1, byUnit); + else + target = moveInLine(line, part.from, 1, byUnit); + } + } + } + + function moveLogically(line, start, dir, byUnit) { + var target = start + dir; + if (byUnit) while (target > 0 && isExtendingChar(line.text.charAt(target))) target += dir; + return target < 0 || target > line.text.length ? null : target; + } + + // Bidirectional ordering algorithm + // See http://unicode.org/reports/tr9/tr9-13.html for the algorithm + // that this (partially) implements. + + // One-char codes used for character types: + // L (L): Left-to-Right + // R (R): Right-to-Left + // r (AL): Right-to-Left Arabic + // 1 (EN): European Number + // + (ES): European Number Separator + // % (ET): European Number Terminator + // n (AN): Arabic Number + // , (CS): Common Number Separator + // m (NSM): Non-Spacing Mark + // b (BN): Boundary Neutral + // s (B): Paragraph Separator + // t (S): Segment Separator + // w (WS): Whitespace + // N (ON): Other Neutrals + + // Returns null if characters are ordered as they appear + // (left-to-right), or an array of sections ({from, to, level} + // objects) in the order in which they occur visually. + var bidiOrdering = (function() { + // Character types for codepoints 0 to 0xff + var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN"; + // Character types for codepoints 0x600 to 0x6ff + var arabicTypes = "rrrrrrrrrrrr,rNNmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmrrrrrrrnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmNmmmm"; + function charType(code) { + if (code <= 0xf7) return lowTypes.charAt(code); + else if (0x590 <= code && code <= 0x5f4) return "R"; + else if (0x600 <= code && code <= 0x6ed) return arabicTypes.charAt(code - 0x600); + else if (0x6ee <= code && code <= 0x8ac) return "r"; + else if (0x2000 <= code && code <= 0x200b) return "w"; + else if (code == 0x200c) return "b"; + else return "L"; + } + + var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/; + var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/; + // Browsers seem to always treat the boundaries of block elements as being L. + var outerType = "L"; + + function BidiSpan(level, from, to) { + this.level = level; + this.from = from; this.to = to; + } + + return function(str) { + if (!bidiRE.test(str)) return false; + var len = str.length, types = []; + for (var i = 0, type; i < len; ++i) + types.push(type = charType(str.charCodeAt(i))); + + // W1. Examine each non-spacing mark (NSM) in the level run, and + // change the type of the NSM to the type of the previous + // character. If the NSM is at the start of the level run, it will + // get the type of sor. + for (var i = 0, prev = outerType; i < len; ++i) { + var type = types[i]; + if (type == "m") types[i] = prev; + else prev = type; + } + + // W2. Search backwards from each instance of a European number + // until the first strong type (R, L, AL, or sor) is found. If an + // AL is found, change the type of the European number to Arabic + // number. + // W3. Change all ALs to R. + for (var i = 0, cur = outerType; i < len; ++i) { + var type = types[i]; + if (type == "1" && cur == "r") types[i] = "n"; + else if (isStrong.test(type)) { cur = type; if (type == "r") types[i] = "R"; } + } + + // W4. A single European separator between two European numbers + // changes to a European number. A single common separator between + // two numbers of the same type changes to that type. + for (var i = 1, prev = types[0]; i < len - 1; ++i) { + var type = types[i]; + if (type == "+" && prev == "1" && types[i+1] == "1") types[i] = "1"; + else if (type == "," && prev == types[i+1] && + (prev == "1" || prev == "n")) types[i] = prev; + prev = type; + } + + // W5. A sequence of European terminators adjacent to European + // numbers changes to all European numbers. + // W6. Otherwise, separators and terminators change to Other + // Neutral. + for (var i = 0; i < len; ++i) { + var type = types[i]; + if (type == ",") types[i] = "N"; + else if (type == "%") { + for (var end = i + 1; end < len && types[end] == "%"; ++end) {} + var replace = (i && types[i-1] == "!") || (end < len && types[end] == "1") ? "1" : "N"; + for (var j = i; j < end; ++j) types[j] = replace; + i = end - 1; + } + } + + // W7. Search backwards from each instance of a European number + // until the first strong type (R, L, or sor) is found. If an L is + // found, then change the type of the European number to L. + for (var i = 0, cur = outerType; i < len; ++i) { + var type = types[i]; + if (cur == "L" && type == "1") types[i] = "L"; + else if (isStrong.test(type)) cur = type; + } + + // N1. A sequence of neutrals takes the direction of the + // surrounding strong text if the text on both sides has the same + // direction. European and Arabic numbers act as if they were R in + // terms of their influence on neutrals. Start-of-level-run (sor) + // and end-of-level-run (eor) are used at level run boundaries. + // N2. Any remaining neutrals take the embedding direction. + for (var i = 0; i < len; ++i) { + if (isNeutral.test(types[i])) { + for (var end = i + 1; end < len && isNeutral.test(types[end]); ++end) {} + var before = (i ? types[i-1] : outerType) == "L"; + var after = (end < len ? types[end] : outerType) == "L"; + var replace = before || after ? "L" : "R"; + for (var j = i; j < end; ++j) types[j] = replace; + i = end - 1; + } + } + + // Here we depart from the documented algorithm, in order to avoid + // building up an actual levels array. Since there are only three + // levels (0, 1, 2) in an implementation that doesn't take + // explicit embedding into account, we can build up the order on + // the fly, without following the level-based algorithm. + var order = [], m; + for (var i = 0; i < len;) { + if (countsAsLeft.test(types[i])) { + var start = i; + for (++i; i < len && countsAsLeft.test(types[i]); ++i) {} + order.push(new BidiSpan(0, start, i)); + } else { + var pos = i, at = order.length; + for (++i; i < len && types[i] != "L"; ++i) {} + for (var j = pos; j < i;) { + if (countsAsNum.test(types[j])) { + if (pos < j) order.splice(at, 0, new BidiSpan(1, pos, j)); + var nstart = j; + for (++j; j < i && countsAsNum.test(types[j]); ++j) {} + order.splice(at, 0, new BidiSpan(2, nstart, j)); + pos = j; + } else ++j; + } + if (pos < i) order.splice(at, 0, new BidiSpan(1, pos, i)); + } + } + if (order[0].level == 1 && (m = str.match(/^\s+/))) { + order[0].from = m[0].length; + order.unshift(new BidiSpan(0, 0, m[0].length)); + } + if (lst(order).level == 1 && (m = str.match(/\s+$/))) { + lst(order).to -= m[0].length; + order.push(new BidiSpan(0, len - m[0].length, len)); + } + if (order[0].level == 2) + order.unshift(new BidiSpan(1, order[0].to, order[0].to)); + if (order[0].level != lst(order).level) + order.push(new BidiSpan(order[0].level, len, len)); + + return order; + }; + })(); + + // THE END + + CodeMirror.version = "5.18.2"; + + return CodeMirror; +}); diff --git a/pagure/static/codemirror/codemirror.css b/pagure/static/codemirror/codemirror.css deleted file mode 100644 index 3543523..0000000 --- a/pagure/static/codemirror/codemirror.css +++ /dev/null @@ -1,334 +0,0 @@ -/* BASICS */ - -.CodeMirror { - /* Set height, width, borders, and global font properties here */ - font-family: monospace; - height: 300px; - color: black; -} - -/* PADDING */ - -.CodeMirror-lines { - padding: 4px 0; /* Vertical padding around content */ -} -.CodeMirror pre { - padding: 0 4px; /* Horizontal padding of content */ -} - -.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { - background-color: white; /* The little square between H and V scrollbars */ -} - -/* GUTTER */ - -.CodeMirror-gutters { - border-right: 1px solid #ddd; - background-color: #f7f7f7; - white-space: nowrap; -} -.CodeMirror-linenumbers {} -.CodeMirror-linenumber { - padding: 0 3px 0 5px; - min-width: 20px; - text-align: right; - color: #999; - white-space: nowrap; -} - -.CodeMirror-guttermarker { color: black; } -.CodeMirror-guttermarker-subtle { color: #999; } - -/* CURSOR */ - -.CodeMirror-cursor { - border-left: 1px solid black; - border-right: none; - width: 0; -} -/* Shown when moving in bi-directional text */ -.CodeMirror div.CodeMirror-secondarycursor { - border-left: 1px solid silver; -} -.cm-fat-cursor .CodeMirror-cursor { - width: auto; - border: 0; - background: #7e7; -} -.cm-fat-cursor div.CodeMirror-cursors { - z-index: 1; -} - -.cm-animate-fat-cursor { - width: auto; - border: 0; - -webkit-animation: blink 1.06s steps(1) infinite; - -moz-animation: blink 1.06s steps(1) infinite; - animation: blink 1.06s steps(1) infinite; - background-color: #7e7; -} -@-moz-keyframes blink { - 0% {} - 50% { background-color: transparent; } - 100% {} -} -@-webkit-keyframes blink { - 0% {} - 50% { background-color: transparent; } - 100% {} -} -@keyframes blink { - 0% {} - 50% { background-color: transparent; } - 100% {} -} - -/* Can style cursor different in overwrite (non-insert) mode */ -.CodeMirror-overwrite .CodeMirror-cursor {} - -.cm-tab { display: inline-block; text-decoration: inherit; } - -.CodeMirror-ruler { - border-left: 1px solid #ccc; - position: absolute; -} - -/* DEFAULT THEME */ - -.cm-s-default .cm-header {color: blue;} -.cm-s-default .cm-quote {color: #090;} -.cm-negative {color: #d44;} -.cm-positive {color: #292;} -.cm-header, .cm-strong {font-weight: bold;} -.cm-em {font-style: italic;} -.cm-link {text-decoration: underline;} -.cm-strikethrough {text-decoration: line-through;} - -.cm-s-default .cm-keyword {color: #708;} -.cm-s-default .cm-atom {color: #219;} -.cm-s-default .cm-number {color: #164;} -.cm-s-default .cm-def {color: #00f;} -.cm-s-default .cm-variable, -.cm-s-default .cm-punctuation, -.cm-s-default .cm-property, -.cm-s-default .cm-operator {} -.cm-s-default .cm-variable-2 {color: #05a;} -.cm-s-default .cm-variable-3 {color: #085;} -.cm-s-default .cm-comment {color: #a50;} -.cm-s-default .cm-string {color: #a11;} -.cm-s-default .cm-string-2 {color: #f50;} -.cm-s-default .cm-meta {color: #555;} -.cm-s-default .cm-qualifier {color: #555;} -.cm-s-default .cm-builtin {color: #30a;} -.cm-s-default .cm-bracket {color: #997;} -.cm-s-default .cm-tag {color: #170;} -.cm-s-default .cm-attribute {color: #00c;} -.cm-s-default .cm-hr {color: #999;} -.cm-s-default .cm-link {color: #00c;} - -.cm-s-default .cm-error {color: #f00;} -.cm-invalidchar {color: #f00;} - -.CodeMirror-composing { border-bottom: 2px solid; } - -/* Default styles for common addons */ - -div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;} -div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;} -.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); } -.CodeMirror-activeline-background {background: #e8f2ff;} - -/* STOP */ - -/* The rest of this file contains styles related to the mechanics of - the editor. You probably shouldn't touch them. */ - -.CodeMirror { - position: relative; - overflow: hidden; - background: white; -} - -.CodeMirror-scroll { - overflow: scroll !important; /* Things will break if this is overridden */ - /* 30px is the magic margin used to hide the element's real scrollbars */ - /* See overflow: hidden in .CodeMirror */ - margin-bottom: -30px; margin-right: -30px; - padding-bottom: 30px; - height: 100%; - outline: none; /* Prevent dragging from highlighting the element */ - position: relative; -} -.CodeMirror-sizer { - position: relative; - border-right: 30px solid transparent; -} - -/* The fake, visible scrollbars. Used to force redraw during scrolling - before actuall scrolling happens, thus preventing shaking and - flickering artifacts. */ -.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { - position: absolute; - z-index: 6; - display: none; -} -.CodeMirror-vscrollbar { - right: 0; top: 0; - overflow-x: hidden; - overflow-y: scroll; -} -.CodeMirror-hscrollbar { - bottom: 0; left: 0; - overflow-y: hidden; - overflow-x: scroll; -} -.CodeMirror-scrollbar-filler { - right: 0; bottom: 0; -} -.CodeMirror-gutter-filler { - left: 0; bottom: 0; -} - -.CodeMirror-gutters { - position: absolute; left: 0; top: 0; - z-index: 3; -} -.CodeMirror-gutter { - white-space: normal; - height: 100%; - display: inline-block; - margin-bottom: -30px; - /* Hack to make IE7 behave */ - *zoom:1; - *display:inline; -} -.CodeMirror-gutter-wrapper { - position: absolute; - z-index: 4; - background: none !important; - border: none !important; -} -.CodeMirror-gutter-background { - position: absolute; - top: 0; bottom: 0; - z-index: 4; -} -.CodeMirror-gutter-elt { - position: absolute; - cursor: default; - z-index: 4; -} -.CodeMirror-gutter-wrapper { - -webkit-user-select: none; - -moz-user-select: none; - user-select: none; -} - -.CodeMirror-lines { - cursor: text; - min-height: 1px; /* prevents collapsing before first draw */ -} -.CodeMirror pre { - /* Reset some styles that the rest of the page might have set */ - -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0; - border-width: 0; - background: transparent; - font-family: inherit; - font-size: inherit; - margin: 0; - white-space: pre; - word-wrap: normal; - line-height: inherit; - color: inherit; - z-index: 2; - position: relative; - overflow: visible; - -webkit-tap-highlight-color: transparent; -} -.CodeMirror-wrap pre { - word-wrap: break-word; - white-space: pre-wrap; - word-break: normal; -} - -.CodeMirror-linebackground { - position: absolute; - left: 0; right: 0; top: 0; bottom: 0; - z-index: 0; -} - -.CodeMirror-linewidget { - position: relative; - z-index: 2; - overflow: auto; -} - -.CodeMirror-widget {} - -.CodeMirror-code { - outline: none; -} - -/* Force content-box sizing for the elements where we expect it */ -.CodeMirror-scroll, -.CodeMirror-sizer, -.CodeMirror-gutter, -.CodeMirror-gutters, -.CodeMirror-linenumber { - -moz-box-sizing: content-box; - box-sizing: content-box; -} - -.CodeMirror-measure { - position: absolute; - width: 100%; - height: 0; - overflow: hidden; - visibility: hidden; -} - -.CodeMirror-cursor { position: absolute; } -.CodeMirror-measure pre { position: static; } - -div.CodeMirror-cursors { - visibility: hidden; - position: relative; - z-index: 3; -} -div.CodeMirror-dragcursors { - visibility: visible; -} - -.CodeMirror-focused div.CodeMirror-cursors { - visibility: visible; -} - -.CodeMirror-selected { background: #d9d9d9; } -.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; } -.CodeMirror-crosshair { cursor: crosshair; } -.CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; } -.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; } - -.cm-searching { - background: #ffa; - background: rgba(255, 255, 0, .4); -} - -/* IE7 hack to prevent it from returning funny offsetTops on the spans */ -.CodeMirror span { *vertical-align: text-bottom; } - -/* Used to force a border model for a node */ -.cm-force-border { padding-right: .1px; } - -@media print { - /* Hide the cursor when printing */ - .CodeMirror div.CodeMirror-cursors { - visibility: hidden; - } -} - -/* See issue #2901 */ -.cm-tab-wrap-hack:after { content: ''; } - -/* Help users use markselection to safely style text background */ -span.CodeMirror-selectedtext { background: none; } diff --git a/pagure/static/codemirror/codemirror.css b/pagure/static/codemirror/codemirror.css new file mode 120000 index 0000000..9132274 --- /dev/null +++ b/pagure/static/codemirror/codemirror.css @@ -0,0 +1 @@ +codemirror-5.18.2.css \ No newline at end of file diff --git a/pagure/static/codemirror/codemirror.js b/pagure/static/codemirror/codemirror.js deleted file mode 100644 index 2c4c3fb..0000000 --- a/pagure/static/codemirror/codemirror.js +++ /dev/null @@ -1,8872 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -// This is CodeMirror (http://codemirror.net), a code editor -// implemented in JavaScript on top of the browser's DOM. -// -// You can find some technical background for some of the code below -// at http://marijnhaverbeke.nl/blog/#cm-internals . - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - module.exports = mod(); - else if (typeof define == "function" && define.amd) // AMD - return define([], mod); - else // Plain browser env - this.CodeMirror = mod(); -})(function() { - "use strict"; - - // BROWSER SNIFFING - - // Kludges for bugs and behavior differences that can't be feature - // detected are enabled based on userAgent etc sniffing. - var userAgent = navigator.userAgent; - var platform = navigator.platform; - - var gecko = /gecko\/\d/i.test(userAgent); - var ie_upto10 = /MSIE \d/.test(userAgent); - var ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(userAgent); - var ie = ie_upto10 || ie_11up; - var ie_version = ie && (ie_upto10 ? document.documentMode || 6 : ie_11up[1]); - var webkit = /WebKit\//.test(userAgent); - var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(userAgent); - var chrome = /Chrome\//.test(userAgent); - var presto = /Opera\//.test(userAgent); - var safari = /Apple Computer/.test(navigator.vendor); - var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(userAgent); - var phantom = /PhantomJS/.test(userAgent); - - var ios = /AppleWebKit/.test(userAgent) && /Mobile\/\w+/.test(userAgent); - // This is woefully incomplete. Suggestions for alternative methods welcome. - var mobile = ios || /Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(userAgent); - var mac = ios || /Mac/.test(platform); - var windows = /win/i.test(platform); - - var presto_version = presto && userAgent.match(/Version\/(\d*\.\d*)/); - if (presto_version) presto_version = Number(presto_version[1]); - if (presto_version && presto_version >= 15) { presto = false; webkit = true; } - // Some browsers use the wrong event properties to signal cmd/ctrl on OS X - var flipCtrlCmd = mac && (qtwebkit || presto && (presto_version == null || presto_version < 12.11)); - var captureRightClick = gecko || (ie && ie_version >= 9); - - // Optimize some code when these features are not used. - var sawReadOnlySpans = false, sawCollapsedSpans = false; - - // EDITOR CONSTRUCTOR - - // A CodeMirror instance represents an editor. This is the object - // that user code is usually dealing with. - - function CodeMirror(place, options) { - if (!(this instanceof CodeMirror)) return new CodeMirror(place, options); - - this.options = options = options ? copyObj(options) : {}; - // Determine effective options based on given values and defaults. - copyObj(defaults, options, false); - setGuttersForLineNumbers(options); - - var doc = options.value; - if (typeof doc == "string") doc = new Doc(doc, options.mode, null, options.lineSeparator); - this.doc = doc; - - var input = new CodeMirror.inputStyles[options.inputStyle](this); - var display = this.display = new Display(place, doc, input); - display.wrapper.CodeMirror = this; - updateGutters(this); - themeChanged(this); - if (options.lineWrapping) - this.display.wrapper.className += " CodeMirror-wrap"; - if (options.autofocus && !mobile) display.input.focus(); - initScrollbars(this); - - this.state = { - keyMaps: [], // stores maps added by addKeyMap - overlays: [], // highlighting overlays, as added by addOverlay - modeGen: 0, // bumped when mode/overlay changes, used to invalidate highlighting info - overwrite: false, - delayingBlurEvent: false, - focused: false, - suppressEdits: false, // used to disable editing during key handlers when in readOnly mode - pasteIncoming: false, cutIncoming: false, // help recognize paste/cut edits in input.poll - selectingText: false, - draggingText: false, - highlight: new Delayed(), // stores highlight worker timeout - keySeq: null, // Unfinished key sequence - specialChars: null - }; - - var cm = this; - - // Override magic textarea content restore that IE sometimes does - // on our hidden textarea on reload - if (ie && ie_version < 11) setTimeout(function() { cm.display.input.reset(true); }, 20); - - registerEventHandlers(this); - ensureGlobalHandlers(); - - startOperation(this); - this.curOp.forceUpdate = true; - attachDoc(this, doc); - - if ((options.autofocus && !mobile) || cm.hasFocus()) - setTimeout(bind(onFocus, this), 20); - else - onBlur(this); - - for (var opt in optionHandlers) if (optionHandlers.hasOwnProperty(opt)) - optionHandlers[opt](this, options[opt], Init); - maybeUpdateLineNumberWidth(this); - if (options.finishInit) options.finishInit(this); - for (var i = 0; i < initHooks.length; ++i) initHooks[i](this); - endOperation(this); - // Suppress optimizelegibility in Webkit, since it breaks text - // measuring on line wrapping boundaries. - if (webkit && options.lineWrapping && - getComputedStyle(display.lineDiv).textRendering == "optimizelegibility") - display.lineDiv.style.textRendering = "auto"; - } - - // DISPLAY CONSTRUCTOR - - // The display handles the DOM integration, both for input reading - // and content drawing. It holds references to DOM nodes and - // display-related state. - - function Display(place, doc, input) { - var d = this; - this.input = input; - - // Covers bottom-right square when both scrollbars are present. - d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler"); - d.scrollbarFiller.setAttribute("cm-not-content", "true"); - // Covers bottom of gutter when coverGutterNextToScrollbar is on - // and h scrollbar is present. - d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler"); - d.gutterFiller.setAttribute("cm-not-content", "true"); - // Will contain the actual code, positioned to cover the viewport. - d.lineDiv = elt("div", null, "CodeMirror-code"); - // Elements are added to these to represent selection and cursors. - d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1"); - d.cursorDiv = elt("div", null, "CodeMirror-cursors"); - // A visibility: hidden element used to find the size of things. - d.measure = elt("div", null, "CodeMirror-measure"); - // When lines outside of the viewport are measured, they are drawn in this. - d.lineMeasure = elt("div", null, "CodeMirror-measure"); - // Wraps everything that needs to exist inside the vertically-padded coordinate system - d.lineSpace = elt("div", [d.measure, d.lineMeasure, d.selectionDiv, d.cursorDiv, d.lineDiv], - null, "position: relative; outline: none"); - // Moved around its parent to cover visible view. - d.mover = elt("div", [elt("div", [d.lineSpace], "CodeMirror-lines")], null, "position: relative"); - // Set to the height of the document, allowing scrolling. - d.sizer = elt("div", [d.mover], "CodeMirror-sizer"); - d.sizerWidth = null; - // Behavior of elts with overflow: auto and padding is - // inconsistent across browsers. This is used to ensure the - // scrollable area is big enough. - d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerGap + "px; width: 1px;"); - // Will contain the gutters, if any. - d.gutters = elt("div", null, "CodeMirror-gutters"); - d.lineGutter = null; - // Actual scrollable element. - d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll"); - d.scroller.setAttribute("tabIndex", "-1"); - // The element in which the editor lives. - d.wrapper = elt("div", [d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror"); - - // Work around IE7 z-index bug (not perfect, hence IE7 not really being supported) - if (ie && ie_version < 8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; } - if (!webkit && !(gecko && mobile)) d.scroller.draggable = true; - - if (place) { - if (place.appendChild) place.appendChild(d.wrapper); - else place(d.wrapper); - } - - // Current rendered range (may be bigger than the view window). - d.viewFrom = d.viewTo = doc.first; - d.reportedViewFrom = d.reportedViewTo = doc.first; - // Information about the rendered lines. - d.view = []; - d.renderedView = null; - // Holds info about a single rendered line when it was rendered - // for measurement, while not in view. - d.externalMeasured = null; - // Empty space (in pixels) above the view - d.viewOffset = 0; - d.lastWrapHeight = d.lastWrapWidth = 0; - d.updateLineNumbers = null; - - d.nativeBarWidth = d.barHeight = d.barWidth = 0; - d.scrollbarsClipped = false; - - // Used to only resize the line number gutter when necessary (when - // the amount of lines crosses a boundary that makes its width change) - d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null; - // Set to true when a non-horizontal-scrolling line widget is - // added. As an optimization, line widget aligning is skipped when - // this is false. - d.alignWidgets = false; - - d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null; - - // Tracks the maximum line length so that the horizontal scrollbar - // can be kept static when scrolling. - d.maxLine = null; - d.maxLineLength = 0; - d.maxLineChanged = false; - - // Used for measuring wheel scrolling granularity - d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null; - - // True when shift is held down. - d.shift = false; - - // Used to track whether anything happened since the context menu - // was opened. - d.selForContextMenu = null; - - d.activeTouch = null; - - input.init(d); - } - - // STATE UPDATES - - // Used to get the editor into a consistent state again when options change. - - function loadMode(cm) { - cm.doc.mode = CodeMirror.getMode(cm.options, cm.doc.modeOption); - resetModeState(cm); - } - - function resetModeState(cm) { - cm.doc.iter(function(line) { - if (line.stateAfter) line.stateAfter = null; - if (line.styles) line.styles = null; - }); - cm.doc.frontier = cm.doc.first; - startWorker(cm, 100); - cm.state.modeGen++; - if (cm.curOp) regChange(cm); - } - - function wrappingChanged(cm) { - if (cm.options.lineWrapping) { - addClass(cm.display.wrapper, "CodeMirror-wrap"); - cm.display.sizer.style.minWidth = ""; - cm.display.sizerWidth = null; - } else { - rmClass(cm.display.wrapper, "CodeMirror-wrap"); - findMaxLine(cm); - } - estimateLineHeights(cm); - regChange(cm); - clearCaches(cm); - setTimeout(function(){updateScrollbars(cm);}, 100); - } - - // Returns a function that estimates the height of a line, to use as - // first approximation until the line becomes visible (and is thus - // properly measurable). - function estimateHeight(cm) { - var th = textHeight(cm.display), wrapping = cm.options.lineWrapping; - var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3); - return function(line) { - if (lineIsHidden(cm.doc, line)) return 0; - - var widgetsHeight = 0; - if (line.widgets) for (var i = 0; i < line.widgets.length; i++) { - if (line.widgets[i].height) widgetsHeight += line.widgets[i].height; - } - - if (wrapping) - return widgetsHeight + (Math.ceil(line.text.length / perLine) || 1) * th; - else - return widgetsHeight + th; - }; - } - - function estimateLineHeights(cm) { - var doc = cm.doc, est = estimateHeight(cm); - doc.iter(function(line) { - var estHeight = est(line); - if (estHeight != line.height) updateLineHeight(line, estHeight); - }); - } - - function themeChanged(cm) { - cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") + - cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-"); - clearCaches(cm); - } - - function guttersChanged(cm) { - updateGutters(cm); - regChange(cm); - setTimeout(function(){alignHorizontally(cm);}, 20); - } - - // Rebuild the gutter elements, ensure the margin to the left of the - // code matches their width. - function updateGutters(cm) { - var gutters = cm.display.gutters, specs = cm.options.gutters; - removeChildren(gutters); - for (var i = 0; i < specs.length; ++i) { - var gutterClass = specs[i]; - var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + gutterClass)); - if (gutterClass == "CodeMirror-linenumbers") { - cm.display.lineGutter = gElt; - gElt.style.width = (cm.display.lineNumWidth || 1) + "px"; - } - } - gutters.style.display = i ? "" : "none"; - updateGutterSpace(cm); - } - - function updateGutterSpace(cm) { - var width = cm.display.gutters.offsetWidth; - cm.display.sizer.style.marginLeft = width + "px"; - } - - // Compute the character length of a line, taking into account - // collapsed ranges (see markText) that might hide parts, and join - // other lines onto it. - function lineLength(line) { - if (line.height == 0) return 0; - var len = line.text.length, merged, cur = line; - while (merged = collapsedSpanAtStart(cur)) { - var found = merged.find(0, true); - cur = found.from.line; - len += found.from.ch - found.to.ch; - } - cur = line; - while (merged = collapsedSpanAtEnd(cur)) { - var found = merged.find(0, true); - len -= cur.text.length - found.from.ch; - cur = found.to.line; - len += cur.text.length - found.to.ch; - } - return len; - } - - // Find the longest line in the document. - function findMaxLine(cm) { - var d = cm.display, doc = cm.doc; - d.maxLine = getLine(doc, doc.first); - d.maxLineLength = lineLength(d.maxLine); - d.maxLineChanged = true; - doc.iter(function(line) { - var len = lineLength(line); - if (len > d.maxLineLength) { - d.maxLineLength = len; - d.maxLine = line; - } - }); - } - - // Make sure the gutters options contains the element - // "CodeMirror-linenumbers" when the lineNumbers option is true. - function setGuttersForLineNumbers(options) { - var found = indexOf(options.gutters, "CodeMirror-linenumbers"); - if (found == -1 && options.lineNumbers) { - options.gutters = options.gutters.concat(["CodeMirror-linenumbers"]); - } else if (found > -1 && !options.lineNumbers) { - options.gutters = options.gutters.slice(0); - options.gutters.splice(found, 1); - } - } - - // SCROLLBARS - - // Prepare DOM reads needed to update the scrollbars. Done in one - // shot to minimize update/measure roundtrips. - function measureForScrollbars(cm) { - var d = cm.display, gutterW = d.gutters.offsetWidth; - var docH = Math.round(cm.doc.height + paddingVert(cm.display)); - return { - clientHeight: d.scroller.clientHeight, - viewHeight: d.wrapper.clientHeight, - scrollWidth: d.scroller.scrollWidth, clientWidth: d.scroller.clientWidth, - viewWidth: d.wrapper.clientWidth, - barLeft: cm.options.fixedGutter ? gutterW : 0, - docHeight: docH, - scrollHeight: docH + scrollGap(cm) + d.barHeight, - nativeBarWidth: d.nativeBarWidth, - gutterWidth: gutterW - }; - } - - function NativeScrollbars(place, scroll, cm) { - this.cm = cm; - var vert = this.vert = elt("div", [elt("div", null, null, "min-width: 1px")], "CodeMirror-vscrollbar"); - var horiz = this.horiz = elt("div", [elt("div", null, null, "height: 100%; min-height: 1px")], "CodeMirror-hscrollbar"); - place(vert); place(horiz); - - on(vert, "scroll", function() { - if (vert.clientHeight) scroll(vert.scrollTop, "vertical"); - }); - on(horiz, "scroll", function() { - if (horiz.clientWidth) scroll(horiz.scrollLeft, "horizontal"); - }); - - this.checkedZeroWidth = false; - // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8). - if (ie && ie_version < 8) this.horiz.style.minHeight = this.vert.style.minWidth = "18px"; - } - - NativeScrollbars.prototype = copyObj({ - update: function(measure) { - var needsH = measure.scrollWidth > measure.clientWidth + 1; - var needsV = measure.scrollHeight > measure.clientHeight + 1; - var sWidth = measure.nativeBarWidth; - - if (needsV) { - this.vert.style.display = "block"; - this.vert.style.bottom = needsH ? sWidth + "px" : "0"; - var totalHeight = measure.viewHeight - (needsH ? sWidth : 0); - // A bug in IE8 can cause this value to be negative, so guard it. - this.vert.firstChild.style.height = - Math.max(0, measure.scrollHeight - measure.clientHeight + totalHeight) + "px"; - } else { - this.vert.style.display = ""; - this.vert.firstChild.style.height = "0"; - } - - if (needsH) { - this.horiz.style.display = "block"; - this.horiz.style.right = needsV ? sWidth + "px" : "0"; - this.horiz.style.left = measure.barLeft + "px"; - var totalWidth = measure.viewWidth - measure.barLeft - (needsV ? sWidth : 0); - this.horiz.firstChild.style.width = - (measure.scrollWidth - measure.clientWidth + totalWidth) + "px"; - } else { - this.horiz.style.display = ""; - this.horiz.firstChild.style.width = "0"; - } - - if (!this.checkedZeroWidth && measure.clientHeight > 0) { - if (sWidth == 0) this.zeroWidthHack(); - this.checkedZeroWidth = true; - } - - return {right: needsV ? sWidth : 0, bottom: needsH ? sWidth : 0}; - }, - setScrollLeft: function(pos) { - if (this.horiz.scrollLeft != pos) this.horiz.scrollLeft = pos; - if (this.disableHoriz) this.enableZeroWidthBar(this.horiz, this.disableHoriz); - }, - setScrollTop: function(pos) { - if (this.vert.scrollTop != pos) this.vert.scrollTop = pos; - if (this.disableVert) this.enableZeroWidthBar(this.vert, this.disableVert); - }, - zeroWidthHack: function() { - var w = mac && !mac_geMountainLion ? "12px" : "18px"; - this.horiz.style.height = this.vert.style.width = w; - this.horiz.style.pointerEvents = this.vert.style.pointerEvents = "none"; - this.disableHoriz = new Delayed; - this.disableVert = new Delayed; - }, - enableZeroWidthBar: function(bar, delay) { - bar.style.pointerEvents = "auto"; - function maybeDisable() { - // To find out whether the scrollbar is still visible, we - // check whether the element under the pixel in the bottom - // left corner of the scrollbar box is the scrollbar box - // itself (when the bar is still visible) or its filler child - // (when the bar is hidden). If it is still visible, we keep - // it enabled, if it's hidden, we disable pointer events. - var box = bar.getBoundingClientRect(); - var elt = document.elementFromPoint(box.left + 1, box.bottom - 1); - if (elt != bar) bar.style.pointerEvents = "none"; - else delay.set(1000, maybeDisable); - } - delay.set(1000, maybeDisable); - }, - clear: function() { - var parent = this.horiz.parentNode; - parent.removeChild(this.horiz); - parent.removeChild(this.vert); - } - }, NativeScrollbars.prototype); - - function NullScrollbars() {} - - NullScrollbars.prototype = copyObj({ - update: function() { return {bottom: 0, right: 0}; }, - setScrollLeft: function() {}, - setScrollTop: function() {}, - clear: function() {} - }, NullScrollbars.prototype); - - CodeMirror.scrollbarModel = {"native": NativeScrollbars, "null": NullScrollbars}; - - function initScrollbars(cm) { - if (cm.display.scrollbars) { - cm.display.scrollbars.clear(); - if (cm.display.scrollbars.addClass) - rmClass(cm.display.wrapper, cm.display.scrollbars.addClass); - } - - cm.display.scrollbars = new CodeMirror.scrollbarModel[cm.options.scrollbarStyle](function(node) { - cm.display.wrapper.insertBefore(node, cm.display.scrollbarFiller); - // Prevent clicks in the scrollbars from killing focus - on(node, "mousedown", function() { - if (cm.state.focused) setTimeout(function() { cm.display.input.focus(); }, 0); - }); - node.setAttribute("cm-not-content", "true"); - }, function(pos, axis) { - if (axis == "horizontal") setScrollLeft(cm, pos); - else setScrollTop(cm, pos); - }, cm); - if (cm.display.scrollbars.addClass) - addClass(cm.display.wrapper, cm.display.scrollbars.addClass); - } - - function updateScrollbars(cm, measure) { - if (!measure) measure = measureForScrollbars(cm); - var startWidth = cm.display.barWidth, startHeight = cm.display.barHeight; - updateScrollbarsInner(cm, measure); - for (var i = 0; i < 4 && startWidth != cm.display.barWidth || startHeight != cm.display.barHeight; i++) { - if (startWidth != cm.display.barWidth && cm.options.lineWrapping) - updateHeightsInViewport(cm); - updateScrollbarsInner(cm, measureForScrollbars(cm)); - startWidth = cm.display.barWidth; startHeight = cm.display.barHeight; - } - } - - // Re-synchronize the fake scrollbars with the actual size of the - // content. - function updateScrollbarsInner(cm, measure) { - var d = cm.display; - var sizes = d.scrollbars.update(measure); - - d.sizer.style.paddingRight = (d.barWidth = sizes.right) + "px"; - d.sizer.style.paddingBottom = (d.barHeight = sizes.bottom) + "px"; - - if (sizes.right && sizes.bottom) { - d.scrollbarFiller.style.display = "block"; - d.scrollbarFiller.style.height = sizes.bottom + "px"; - d.scrollbarFiller.style.width = sizes.right + "px"; - } else d.scrollbarFiller.style.display = ""; - if (sizes.bottom && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) { - d.gutterFiller.style.display = "block"; - d.gutterFiller.style.height = sizes.bottom + "px"; - d.gutterFiller.style.width = measure.gutterWidth + "px"; - } else d.gutterFiller.style.display = ""; - } - - // Compute the lines that are visible in a given viewport (defaults - // the the current scroll position). viewport may contain top, - // height, and ensure (see op.scrollToPos) properties. - function visibleLines(display, doc, viewport) { - var top = viewport && viewport.top != null ? Math.max(0, viewport.top) : display.scroller.scrollTop; - top = Math.floor(top - paddingTop(display)); - var bottom = viewport && viewport.bottom != null ? viewport.bottom : top + display.wrapper.clientHeight; - - var from = lineAtHeight(doc, top), to = lineAtHeight(doc, bottom); - // Ensure is a {from: {line, ch}, to: {line, ch}} object, and - // forces those lines into the viewport (if possible). - if (viewport && viewport.ensure) { - var ensureFrom = viewport.ensure.from.line, ensureTo = viewport.ensure.to.line; - if (ensureFrom < from) { - from = ensureFrom; - to = lineAtHeight(doc, heightAtLine(getLine(doc, ensureFrom)) + display.wrapper.clientHeight); - } else if (Math.min(ensureTo, doc.lastLine()) >= to) { - from = lineAtHeight(doc, heightAtLine(getLine(doc, ensureTo)) - display.wrapper.clientHeight); - to = ensureTo; - } - } - return {from: from, to: Math.max(to, from + 1)}; - } - - // LINE NUMBERS - - // Re-align line numbers and gutter marks to compensate for - // horizontal scrolling. - function alignHorizontally(cm) { - var display = cm.display, view = display.view; - if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) return; - var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft; - var gutterW = display.gutters.offsetWidth, left = comp + "px"; - for (var i = 0; i < view.length; i++) if (!view[i].hidden) { - if (cm.options.fixedGutter && view[i].gutter) - view[i].gutter.style.left = left; - var align = view[i].alignable; - if (align) for (var j = 0; j < align.length; j++) - align[j].style.left = left; - } - if (cm.options.fixedGutter) - display.gutters.style.left = (comp + gutterW) + "px"; - } - - // Used to ensure that the line number gutter is still the right - // size for the current document size. Returns true when an update - // is needed. - function maybeUpdateLineNumberWidth(cm) { - if (!cm.options.lineNumbers) return false; - var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display; - if (last.length != display.lineNumChars) { - var test = display.measure.appendChild(elt("div", [elt("div", last)], - "CodeMirror-linenumber CodeMirror-gutter-elt")); - var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW; - display.lineGutter.style.width = ""; - display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding) + 1; - display.lineNumWidth = display.lineNumInnerWidth + padding; - display.lineNumChars = display.lineNumInnerWidth ? last.length : -1; - display.lineGutter.style.width = display.lineNumWidth + "px"; - updateGutterSpace(cm); - return true; - } - return false; - } - - function lineNumberFor(options, i) { - return String(options.lineNumberFormatter(i + options.firstLineNumber)); - } - - // Computes display.scroller.scrollLeft + display.gutters.offsetWidth, - // but using getBoundingClientRect to get a sub-pixel-accurate - // result. - function compensateForHScroll(display) { - return display.scroller.getBoundingClientRect().left - display.sizer.getBoundingClientRect().left; - } - - // DISPLAY DRAWING - - function DisplayUpdate(cm, viewport, force) { - var display = cm.display; - - this.viewport = viewport; - // Store some values that we'll need later (but don't want to force a relayout for) - this.visible = visibleLines(display, cm.doc, viewport); - this.editorIsHidden = !display.wrapper.offsetWidth; - this.wrapperHeight = display.wrapper.clientHeight; - this.wrapperWidth = display.wrapper.clientWidth; - this.oldDisplayWidth = displayWidth(cm); - this.force = force; - this.dims = getDimensions(cm); - this.events = []; - } - - DisplayUpdate.prototype.signal = function(emitter, type) { - if (hasHandler(emitter, type)) - this.events.push(arguments); - }; - DisplayUpdate.prototype.finish = function() { - for (var i = 0; i < this.events.length; i++) - signal.apply(null, this.events[i]); - }; - - function maybeClipScrollbars(cm) { - var display = cm.display; - if (!display.scrollbarsClipped && display.scroller.offsetWidth) { - display.nativeBarWidth = display.scroller.offsetWidth - display.scroller.clientWidth; - display.heightForcer.style.height = scrollGap(cm) + "px"; - display.sizer.style.marginBottom = -display.nativeBarWidth + "px"; - display.sizer.style.borderRightWidth = scrollGap(cm) + "px"; - display.scrollbarsClipped = true; - } - } - - // Does the actual updating of the line display. Bails out - // (returning false) when there is nothing to be done and forced is - // false. - function updateDisplayIfNeeded(cm, update) { - var display = cm.display, doc = cm.doc; - - if (update.editorIsHidden) { - resetView(cm); - return false; - } - - // Bail out if the visible area is already rendered and nothing changed. - if (!update.force && - update.visible.from >= display.viewFrom && update.visible.to <= display.viewTo && - (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo) && - display.renderedView == display.view && countDirtyView(cm) == 0) - return false; - - if (maybeUpdateLineNumberWidth(cm)) { - resetView(cm); - update.dims = getDimensions(cm); - } - - // Compute a suitable new viewport (from & to) - var end = doc.first + doc.size; - var from = Math.max(update.visible.from - cm.options.viewportMargin, doc.first); - var to = Math.min(end, update.visible.to + cm.options.viewportMargin); - if (display.viewFrom < from && from - display.viewFrom < 20) from = Math.max(doc.first, display.viewFrom); - if (display.viewTo > to && display.viewTo - to < 20) to = Math.min(end, display.viewTo); - if (sawCollapsedSpans) { - from = visualLineNo(cm.doc, from); - to = visualLineEndNo(cm.doc, to); - } - - var different = from != display.viewFrom || to != display.viewTo || - display.lastWrapHeight != update.wrapperHeight || display.lastWrapWidth != update.wrapperWidth; - adjustView(cm, from, to); - - display.viewOffset = heightAtLine(getLine(cm.doc, display.viewFrom)); - // Position the mover div to align with the current scroll position - cm.display.mover.style.top = display.viewOffset + "px"; - - var toUpdate = countDirtyView(cm); - if (!different && toUpdate == 0 && !update.force && display.renderedView == display.view && - (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo)) - return false; - - // For big changes, we hide the enclosing element during the - // update, since that speeds up the operations on most browsers. - var focused = activeElt(); - if (toUpdate > 4) display.lineDiv.style.display = "none"; - patchDisplay(cm, display.updateLineNumbers, update.dims); - if (toUpdate > 4) display.lineDiv.style.display = ""; - display.renderedView = display.view; - // There might have been a widget with a focused element that got - // hidden or updated, if so re-focus it. - if (focused && activeElt() != focused && focused.offsetHeight) focused.focus(); - - // Prevent selection and cursors from interfering with the scroll - // width and height. - removeChildren(display.cursorDiv); - removeChildren(display.selectionDiv); - display.gutters.style.height = display.sizer.style.minHeight = 0; - - if (different) { - display.lastWrapHeight = update.wrapperHeight; - display.lastWrapWidth = update.wrapperWidth; - startWorker(cm, 400); - } - - display.updateLineNumbers = null; - - return true; - } - - function postUpdateDisplay(cm, update) { - var viewport = update.viewport; - for (var first = true;; first = false) { - if (!first || !cm.options.lineWrapping || update.oldDisplayWidth == displayWidth(cm)) { - // Clip forced viewport to actual scrollable area. - if (viewport && viewport.top != null) - viewport = {top: Math.min(cm.doc.height + paddingVert(cm.display) - displayHeight(cm), viewport.top)}; - // Updated line heights might result in the drawn area not - // actually covering the viewport. Keep looping until it does. - update.visible = visibleLines(cm.display, cm.doc, viewport); - if (update.visible.from >= cm.display.viewFrom && update.visible.to <= cm.display.viewTo) - break; - } - if (!updateDisplayIfNeeded(cm, update)) break; - updateHeightsInViewport(cm); - var barMeasure = measureForScrollbars(cm); - updateSelection(cm); - setDocumentHeight(cm, barMeasure); - updateScrollbars(cm, barMeasure); - } - - update.signal(cm, "update", cm); - if (cm.display.viewFrom != cm.display.reportedViewFrom || cm.display.viewTo != cm.display.reportedViewTo) { - update.signal(cm, "viewportChange", cm, cm.display.viewFrom, cm.display.viewTo); - cm.display.reportedViewFrom = cm.display.viewFrom; cm.display.reportedViewTo = cm.display.viewTo; - } - } - - function updateDisplaySimple(cm, viewport) { - var update = new DisplayUpdate(cm, viewport); - if (updateDisplayIfNeeded(cm, update)) { - updateHeightsInViewport(cm); - postUpdateDisplay(cm, update); - var barMeasure = measureForScrollbars(cm); - updateSelection(cm); - setDocumentHeight(cm, barMeasure); - updateScrollbars(cm, barMeasure); - update.finish(); - } - } - - function setDocumentHeight(cm, measure) { - cm.display.sizer.style.minHeight = measure.docHeight + "px"; - var total = measure.docHeight + cm.display.barHeight; - cm.display.heightForcer.style.top = total + "px"; - cm.display.gutters.style.height = Math.max(total + scrollGap(cm), measure.clientHeight) + "px"; - } - - // Read the actual heights of the rendered lines, and update their - // stored heights to match. - function updateHeightsInViewport(cm) { - var display = cm.display; - var prevBottom = display.lineDiv.offsetTop; - for (var i = 0; i < display.view.length; i++) { - var cur = display.view[i], height; - if (cur.hidden) continue; - if (ie && ie_version < 8) { - var bot = cur.node.offsetTop + cur.node.offsetHeight; - height = bot - prevBottom; - prevBottom = bot; - } else { - var box = cur.node.getBoundingClientRect(); - height = box.bottom - box.top; - } - var diff = cur.line.height - height; - if (height < 2) height = textHeight(display); - if (diff > .001 || diff < -.001) { - updateLineHeight(cur.line, height); - updateWidgetHeight(cur.line); - if (cur.rest) for (var j = 0; j < cur.rest.length; j++) - updateWidgetHeight(cur.rest[j]); - } - } - } - - // Read and store the height of line widgets associated with the - // given line. - function updateWidgetHeight(line) { - if (line.widgets) for (var i = 0; i < line.widgets.length; ++i) - line.widgets[i].height = line.widgets[i].node.offsetHeight; - } - - // Do a bulk-read of the DOM positions and sizes needed to draw the - // view, so that we don't interleave reading and writing to the DOM. - function getDimensions(cm) { - var d = cm.display, left = {}, width = {}; - var gutterLeft = d.gutters.clientLeft; - for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) { - left[cm.options.gutters[i]] = n.offsetLeft + n.clientLeft + gutterLeft; - width[cm.options.gutters[i]] = n.clientWidth; - } - return {fixedPos: compensateForHScroll(d), - gutterTotalWidth: d.gutters.offsetWidth, - gutterLeft: left, - gutterWidth: width, - wrapperWidth: d.wrapper.clientWidth}; - } - - // Sync the actual display DOM structure with display.view, removing - // nodes for lines that are no longer in view, and creating the ones - // that are not there yet, and updating the ones that are out of - // date. - function patchDisplay(cm, updateNumbersFrom, dims) { - var display = cm.display, lineNumbers = cm.options.lineNumbers; - var container = display.lineDiv, cur = container.firstChild; - - function rm(node) { - var next = node.nextSibling; - // Works around a throw-scroll bug in OS X Webkit - if (webkit && mac && cm.display.currentWheelTarget == node) - node.style.display = "none"; - else - node.parentNode.removeChild(node); - return next; - } - - var view = display.view, lineN = display.viewFrom; - // Loop over the elements in the view, syncing cur (the DOM nodes - // in display.lineDiv) with the view as we go. - for (var i = 0; i < view.length; i++) { - var lineView = view[i]; - if (lineView.hidden) { - } else if (!lineView.node || lineView.node.parentNode != container) { // Not drawn yet - var node = buildLineElement(cm, lineView, lineN, dims); - container.insertBefore(node, cur); - } else { // Already drawn - while (cur != lineView.node) cur = rm(cur); - var updateNumber = lineNumbers && updateNumbersFrom != null && - updateNumbersFrom <= lineN && lineView.lineNumber; - if (lineView.changes) { - if (indexOf(lineView.changes, "gutter") > -1) updateNumber = false; - updateLineForChanges(cm, lineView, lineN, dims); - } - if (updateNumber) { - removeChildren(lineView.lineNumber); - lineView.lineNumber.appendChild(document.createTextNode(lineNumberFor(cm.options, lineN))); - } - cur = lineView.node.nextSibling; - } - lineN += lineView.size; - } - while (cur) cur = rm(cur); - } - - // When an aspect of a line changes, a string is added to - // lineView.changes. This updates the relevant part of the line's - // DOM structure. - function updateLineForChanges(cm, lineView, lineN, dims) { - for (var j = 0; j < lineView.changes.length; j++) { - var type = lineView.changes[j]; - if (type == "text") updateLineText(cm, lineView); - else if (type == "gutter") updateLineGutter(cm, lineView, lineN, dims); - else if (type == "class") updateLineClasses(lineView); - else if (type == "widget") updateLineWidgets(cm, lineView, dims); - } - lineView.changes = null; - } - - // Lines with gutter elements, widgets or a background class need to - // be wrapped, and have the extra elements added to the wrapper div - function ensureLineWrapped(lineView) { - if (lineView.node == lineView.text) { - lineView.node = elt("div", null, null, "position: relative"); - if (lineView.text.parentNode) - lineView.text.parentNode.replaceChild(lineView.node, lineView.text); - lineView.node.appendChild(lineView.text); - if (ie && ie_version < 8) lineView.node.style.zIndex = 2; - } - return lineView.node; - } - - function updateLineBackground(lineView) { - var cls = lineView.bgClass ? lineView.bgClass + " " + (lineView.line.bgClass || "") : lineView.line.bgClass; - if (cls) cls += " CodeMirror-linebackground"; - if (lineView.background) { - if (cls) lineView.background.className = cls; - else { lineView.background.parentNode.removeChild(lineView.background); lineView.background = null; } - } else if (cls) { - var wrap = ensureLineWrapped(lineView); - lineView.background = wrap.insertBefore(elt("div", null, cls), wrap.firstChild); - } - } - - // Wrapper around buildLineContent which will reuse the structure - // in display.externalMeasured when possible. - function getLineContent(cm, lineView) { - var ext = cm.display.externalMeasured; - if (ext && ext.line == lineView.line) { - cm.display.externalMeasured = null; - lineView.measure = ext.measure; - return ext.built; - } - return buildLineContent(cm, lineView); - } - - // Redraw the line's text. Interacts with the background and text - // classes because the mode may output tokens that influence these - // classes. - function updateLineText(cm, lineView) { - var cls = lineView.text.className; - var built = getLineContent(cm, lineView); - if (lineView.text == lineView.node) lineView.node = built.pre; - lineView.text.parentNode.replaceChild(built.pre, lineView.text); - lineView.text = built.pre; - if (built.bgClass != lineView.bgClass || built.textClass != lineView.textClass) { - lineView.bgClass = built.bgClass; - lineView.textClass = built.textClass; - updateLineClasses(lineView); - } else if (cls) { - lineView.text.className = cls; - } - } - - function updateLineClasses(lineView) { - updateLineBackground(lineView); - if (lineView.line.wrapClass) - ensureLineWrapped(lineView).className = lineView.line.wrapClass; - else if (lineView.node != lineView.text) - lineView.node.className = ""; - var textClass = lineView.textClass ? lineView.textClass + " " + (lineView.line.textClass || "") : lineView.line.textClass; - lineView.text.className = textClass || ""; - } - - function updateLineGutter(cm, lineView, lineN, dims) { - if (lineView.gutter) { - lineView.node.removeChild(lineView.gutter); - lineView.gutter = null; - } - if (lineView.gutterBackground) { - lineView.node.removeChild(lineView.gutterBackground); - lineView.gutterBackground = null; - } - if (lineView.line.gutterClass) { - var wrap = ensureLineWrapped(lineView); - lineView.gutterBackground = elt("div", null, "CodeMirror-gutter-background " + lineView.line.gutterClass, - "left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + - "px; width: " + dims.gutterTotalWidth + "px"); - wrap.insertBefore(lineView.gutterBackground, lineView.text); - } - var markers = lineView.line.gutterMarkers; - if (cm.options.lineNumbers || markers) { - var wrap = ensureLineWrapped(lineView); - var gutterWrap = lineView.gutter = elt("div", null, "CodeMirror-gutter-wrapper", "left: " + - (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px"); - cm.display.input.setUneditable(gutterWrap); - wrap.insertBefore(gutterWrap, lineView.text); - if (lineView.line.gutterClass) - gutterWrap.className += " " + lineView.line.gutterClass; - if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"])) - lineView.lineNumber = gutterWrap.appendChild( - elt("div", lineNumberFor(cm.options, lineN), - "CodeMirror-linenumber CodeMirror-gutter-elt", - "left: " + dims.gutterLeft["CodeMirror-linenumbers"] + "px; width: " - + cm.display.lineNumInnerWidth + "px")); - if (markers) for (var k = 0; k < cm.options.gutters.length; ++k) { - var id = cm.options.gutters[k], found = markers.hasOwnProperty(id) && markers[id]; - if (found) - gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt", "left: " + - dims.gutterLeft[id] + "px; width: " + dims.gutterWidth[id] + "px")); - } - } - } - - function updateLineWidgets(cm, lineView, dims) { - if (lineView.alignable) lineView.alignable = null; - for (var node = lineView.node.firstChild, next; node; node = next) { - var next = node.nextSibling; - if (node.className == "CodeMirror-linewidget") - lineView.node.removeChild(node); - } - insertLineWidgets(cm, lineView, dims); - } - - // Build a line's DOM representation from scratch - function buildLineElement(cm, lineView, lineN, dims) { - var built = getLineContent(cm, lineView); - lineView.text = lineView.node = built.pre; - if (built.bgClass) lineView.bgClass = built.bgClass; - if (built.textClass) lineView.textClass = built.textClass; - - updateLineClasses(lineView); - updateLineGutter(cm, lineView, lineN, dims); - insertLineWidgets(cm, lineView, dims); - return lineView.node; - } - - // A lineView may contain multiple logical lines (when merged by - // collapsed spans). The widgets for all of them need to be drawn. - function insertLineWidgets(cm, lineView, dims) { - insertLineWidgetsFor(cm, lineView.line, lineView, dims, true); - if (lineView.rest) for (var i = 0; i < lineView.rest.length; i++) - insertLineWidgetsFor(cm, lineView.rest[i], lineView, dims, false); - } - - function insertLineWidgetsFor(cm, line, lineView, dims, allowAbove) { - if (!line.widgets) return; - var wrap = ensureLineWrapped(lineView); - for (var i = 0, ws = line.widgets; i < ws.length; ++i) { - var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget"); - if (!widget.handleMouseEvents) node.setAttribute("cm-ignore-events", "true"); - positionLineWidget(widget, node, lineView, dims); - cm.display.input.setUneditable(node); - if (allowAbove && widget.above) - wrap.insertBefore(node, lineView.gutter || lineView.text); - else - wrap.appendChild(node); - signalLater(widget, "redraw"); - } - } - - function positionLineWidget(widget, node, lineView, dims) { - if (widget.noHScroll) { - (lineView.alignable || (lineView.alignable = [])).push(node); - var width = dims.wrapperWidth; - node.style.left = dims.fixedPos + "px"; - if (!widget.coverGutter) { - width -= dims.gutterTotalWidth; - node.style.paddingLeft = dims.gutterTotalWidth + "px"; - } - node.style.width = width + "px"; - } - if (widget.coverGutter) { - node.style.zIndex = 5; - node.style.position = "relative"; - if (!widget.noHScroll) node.style.marginLeft = -dims.gutterTotalWidth + "px"; - } - } - - // POSITION OBJECT - - // A Pos instance represents a position within the text. - var Pos = CodeMirror.Pos = function(line, ch) { - if (!(this instanceof Pos)) return new Pos(line, ch); - this.line = line; this.ch = ch; - }; - - // Compare two positions, return 0 if they are the same, a negative - // number when a is less, and a positive number otherwise. - var cmp = CodeMirror.cmpPos = function(a, b) { return a.line - b.line || a.ch - b.ch; }; - - function copyPos(x) {return Pos(x.line, x.ch);} - function maxPos(a, b) { return cmp(a, b) < 0 ? b : a; } - function minPos(a, b) { return cmp(a, b) < 0 ? a : b; } - - // INPUT HANDLING - - function ensureFocus(cm) { - if (!cm.state.focused) { cm.display.input.focus(); onFocus(cm); } - } - - function isReadOnly(cm) { - return cm.options.readOnly || cm.doc.cantEdit; - } - - // This will be set to an array of strings when copying, so that, - // when pasting, we know what kind of selections the copied text - // was made out of. - var lastCopied = null; - - function applyTextInput(cm, inserted, deleted, sel, origin) { - var doc = cm.doc; - cm.display.shift = false; - if (!sel) sel = doc.sel; - - var paste = cm.state.pasteIncoming || origin == "paste"; - var textLines = doc.splitLines(inserted), multiPaste = null; - // When pasing N lines into N selections, insert one line per selection - if (paste && sel.ranges.length > 1) { - if (lastCopied && lastCopied.join("\n") == inserted) { - if (sel.ranges.length % lastCopied.length == 0) { - multiPaste = []; - for (var i = 0; i < lastCopied.length; i++) - multiPaste.push(doc.splitLines(lastCopied[i])); - } - } else if (textLines.length == sel.ranges.length) { - multiPaste = map(textLines, function(l) { return [l]; }); - } - } - - // Normal behavior is to insert the new text into every selection - for (var i = sel.ranges.length - 1; i >= 0; i--) { - var range = sel.ranges[i]; - var from = range.from(), to = range.to(); - if (range.empty()) { - if (deleted && deleted > 0) // Handle deletion - from = Pos(from.line, from.ch - deleted); - else if (cm.state.overwrite && !paste) // Handle overwrite - to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + lst(textLines).length)); - } - var updateInput = cm.curOp.updateInput; - var changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i % multiPaste.length] : textLines, - origin: origin || (paste ? "paste" : cm.state.cutIncoming ? "cut" : "+input")}; - makeChange(cm.doc, changeEvent); - signalLater(cm, "inputRead", cm, changeEvent); - } - if (inserted && !paste) - triggerElectric(cm, inserted); - - ensureCursorVisible(cm); - cm.curOp.updateInput = updateInput; - cm.curOp.typing = true; - cm.state.pasteIncoming = cm.state.cutIncoming = false; - } - - function handlePaste(e, cm) { - var pasted = e.clipboardData && e.clipboardData.getData("text/plain"); - if (pasted) { - e.preventDefault(); - if (!isReadOnly(cm) && !cm.options.disableInput) - runInOp(cm, function() { applyTextInput(cm, pasted, 0, null, "paste"); }); - return true; - } - } - - function triggerElectric(cm, inserted) { - // When an 'electric' character is inserted, immediately trigger a reindent - if (!cm.options.electricChars || !cm.options.smartIndent) return; - var sel = cm.doc.sel; - - for (var i = sel.ranges.length - 1; i >= 0; i--) { - var range = sel.ranges[i]; - if (range.head.ch > 100 || (i && sel.ranges[i - 1].head.line == range.head.line)) continue; - var mode = cm.getModeAt(range.head); - var indented = false; - if (mode.electricChars) { - for (var j = 0; j < mode.electricChars.length; j++) - if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) { - indented = indentLine(cm, range.head.line, "smart"); - break; - } - } else if (mode.electricInput) { - if (mode.electricInput.test(getLine(cm.doc, range.head.line).text.slice(0, range.head.ch))) - indented = indentLine(cm, range.head.line, "smart"); - } - if (indented) signalLater(cm, "electricInput", cm, range.head.line); - } - } - - function copyableRanges(cm) { - var text = [], ranges = []; - for (var i = 0; i < cm.doc.sel.ranges.length; i++) { - var line = cm.doc.sel.ranges[i].head.line; - var lineRange = {anchor: Pos(line, 0), head: Pos(line + 1, 0)}; - ranges.push(lineRange); - text.push(cm.getRange(lineRange.anchor, lineRange.head)); - } - return {text: text, ranges: ranges}; - } - - function disableBrowserMagic(field) { - field.setAttribute("autocorrect", "off"); - field.setAttribute("autocapitalize", "off"); - field.setAttribute("spellcheck", "false"); - } - - // TEXTAREA INPUT STYLE - - function TextareaInput(cm) { - this.cm = cm; - // See input.poll and input.reset - this.prevInput = ""; - - // Flag that indicates whether we expect input to appear real soon - // now (after some event like 'keypress' or 'input') and are - // polling intensively. - this.pollingFast = false; - // Self-resetting timeout for the poller - this.polling = new Delayed(); - // Tracks when input.reset has punted to just putting a short - // string into the textarea instead of the full selection. - this.inaccurateSelection = false; - // Used to work around IE issue with selection being forgotten when focus moves away from textarea - this.hasSelection = false; - this.composing = null; - }; - - function hiddenTextarea() { - var te = elt("textarea", null, null, "position: absolute; padding: 0; width: 1px; height: 1em; outline: none"); - var div = elt("div", [te], null, "overflow: hidden; position: relative; width: 3px; height: 0px;"); - // The textarea is kept positioned near the cursor to prevent the - // fact that it'll be scrolled into view on input from scrolling - // our fake cursor out of view. On webkit, when wrap=off, paste is - // very slow. So make the area wide instead. - if (webkit) te.style.width = "1000px"; - else te.setAttribute("wrap", "off"); - // If border: 0; -- iOS fails to open keyboard (issue #1287) - if (ios) te.style.border = "1px solid black"; - disableBrowserMagic(te); - return div; - } - - TextareaInput.prototype = copyObj({ - init: function(display) { - var input = this, cm = this.cm; - - // Wraps and hides input textarea - var div = this.wrapper = hiddenTextarea(); - // The semihidden textarea that is focused when the editor is - // focused, and receives input. - var te = this.textarea = div.firstChild; - display.wrapper.insertBefore(div, display.wrapper.firstChild); - - // Needed to hide big blue blinking cursor on Mobile Safari (doesn't seem to work in iOS 8 anymore) - if (ios) te.style.width = "0px"; - - on(te, "input", function() { - if (ie && ie_version >= 9 && input.hasSelection) input.hasSelection = null; - input.poll(); - }); - - on(te, "paste", function(e) { - if (handlePaste(e, cm)) return true; - - cm.state.pasteIncoming = true; - input.fastPoll(); - }); - - function prepareCopyCut(e) { - if (cm.somethingSelected()) { - lastCopied = cm.getSelections(); - if (input.inaccurateSelection) { - input.prevInput = ""; - input.inaccurateSelection = false; - te.value = lastCopied.join("\n"); - selectInput(te); - } - } else if (!cm.options.lineWiseCopyCut) { - return; - } else { - var ranges = copyableRanges(cm); - lastCopied = ranges.text; - if (e.type == "cut") { - cm.setSelections(ranges.ranges, null, sel_dontScroll); - } else { - input.prevInput = ""; - te.value = ranges.text.join("\n"); - selectInput(te); - } - } - if (e.type == "cut") cm.state.cutIncoming = true; - } - on(te, "cut", prepareCopyCut); - on(te, "copy", prepareCopyCut); - - on(display.scroller, "paste", function(e) { - if (eventInWidget(display, e)) return; - cm.state.pasteIncoming = true; - input.focus(); - }); - - // Prevent normal selection in the editor (we handle our own) - on(display.lineSpace, "selectstart", function(e) { - if (!eventInWidget(display, e)) e_preventDefault(e); - }); - - on(te, "compositionstart", function() { - var start = cm.getCursor("from"); - if (input.composing) input.composing.range.clear() - input.composing = { - start: start, - range: cm.markText(start, cm.getCursor("to"), {className: "CodeMirror-composing"}) - }; - }); - on(te, "compositionend", function() { - if (input.composing) { - input.poll(); - input.composing.range.clear(); - input.composing = null; - } - }); - }, - - prepareSelection: function() { - // Redraw the selection and/or cursor - var cm = this.cm, display = cm.display, doc = cm.doc; - var result = prepareSelection(cm); - - // Move the hidden textarea near the cursor to prevent scrolling artifacts - if (cm.options.moveInputWithCursor) { - var headPos = cursorCoords(cm, doc.sel.primary().head, "div"); - var wrapOff = display.wrapper.getBoundingClientRect(), lineOff = display.lineDiv.getBoundingClientRect(); - result.teTop = Math.max(0, Math.min(display.wrapper.clientHeight - 10, - headPos.top + lineOff.top - wrapOff.top)); - result.teLeft = Math.max(0, Math.min(display.wrapper.clientWidth - 10, - headPos.left + lineOff.left - wrapOff.left)); - } - - return result; - }, - - showSelection: function(drawn) { - var cm = this.cm, display = cm.display; - removeChildrenAndAdd(display.cursorDiv, drawn.cursors); - removeChildrenAndAdd(display.selectionDiv, drawn.selection); - if (drawn.teTop != null) { - this.wrapper.style.top = drawn.teTop + "px"; - this.wrapper.style.left = drawn.teLeft + "px"; - } - }, - - // Reset the input to correspond to the selection (or to be empty, - // when not typing and nothing is selected) - reset: function(typing) { - if (this.contextMenuPending) return; - var minimal, selected, cm = this.cm, doc = cm.doc; - if (cm.somethingSelected()) { - this.prevInput = ""; - var range = doc.sel.primary(); - minimal = hasCopyEvent && - (range.to().line - range.from().line > 100 || (selected = cm.getSelection()).length > 1000); - var content = minimal ? "-" : selected || cm.getSelection(); - this.textarea.value = content; - if (cm.state.focused) selectInput(this.textarea); - if (ie && ie_version >= 9) this.hasSelection = content; - } else if (!typing) { - this.prevInput = this.textarea.value = ""; - if (ie && ie_version >= 9) this.hasSelection = null; - } - this.inaccurateSelection = minimal; - }, - - getField: function() { return this.textarea; }, - - supportsTouch: function() { return false; }, - - focus: function() { - if (this.cm.options.readOnly != "nocursor" && (!mobile || activeElt() != this.textarea)) { - try { this.textarea.focus(); } - catch (e) {} // IE8 will throw if the textarea is display: none or not in DOM - } - }, - - blur: function() { this.textarea.blur(); }, - - resetPosition: function() { - this.wrapper.style.top = this.wrapper.style.left = 0; - }, - - receivedFocus: function() { this.slowPoll(); }, - - // Poll for input changes, using the normal rate of polling. This - // runs as long as the editor is focused. - slowPoll: function() { - var input = this; - if (input.pollingFast) return; - input.polling.set(this.cm.options.pollInterval, function() { - input.poll(); - if (input.cm.state.focused) input.slowPoll(); - }); - }, - - // When an event has just come in that is likely to add or change - // something in the input textarea, we poll faster, to ensure that - // the change appears on the screen quickly. - fastPoll: function() { - var missed = false, input = this; - input.pollingFast = true; - function p() { - var changed = input.poll(); - if (!changed && !missed) {missed = true; input.polling.set(60, p);} - else {input.pollingFast = false; input.slowPoll();} - } - input.polling.set(20, p); - }, - - // Read input from the textarea, and update the document to match. - // When something is selected, it is present in the textarea, and - // selected (unless it is huge, in which case a placeholder is - // used). When nothing is selected, the cursor sits after previously - // seen text (can be empty), which is stored in prevInput (we must - // not reset the textarea when typing, because that breaks IME). - poll: function() { - var cm = this.cm, input = this.textarea, prevInput = this.prevInput; - // Since this is called a *lot*, try to bail out as cheaply as - // possible when it is clear that nothing happened. hasSelection - // will be the case when there is a lot of text in the textarea, - // in which case reading its value would be expensive. - if (this.contextMenuPending || !cm.state.focused || - (hasSelection(input) && !prevInput && !this.composing) || - isReadOnly(cm) || cm.options.disableInput || cm.state.keySeq) - return false; - - var text = input.value; - // If nothing changed, bail. - if (text == prevInput && !cm.somethingSelected()) return false; - // Work around nonsensical selection resetting in IE9/10, and - // inexplicable appearance of private area unicode characters on - // some key combos in Mac (#2689). - if (ie && ie_version >= 9 && this.hasSelection === text || - mac && /[\uf700-\uf7ff]/.test(text)) { - cm.display.input.reset(); - return false; - } - - if (cm.doc.sel == cm.display.selForContextMenu) { - var first = text.charCodeAt(0); - if (first == 0x200b && !prevInput) prevInput = "\u200b"; - if (first == 0x21da) { this.reset(); return this.cm.execCommand("undo"); } - } - // Find the part of the input that is actually new - var same = 0, l = Math.min(prevInput.length, text.length); - while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) ++same; - - var self = this; - runInOp(cm, function() { - applyTextInput(cm, text.slice(same), prevInput.length - same, - null, self.composing ? "*compose" : null); - - // Don't leave long text in the textarea, since it makes further polling slow - if (text.length > 1000 || text.indexOf("\n") > -1) input.value = self.prevInput = ""; - else self.prevInput = text; - - if (self.composing) { - self.composing.range.clear(); - self.composing.range = cm.markText(self.composing.start, cm.getCursor("to"), - {className: "CodeMirror-composing"}); - } - }); - return true; - }, - - ensurePolled: function() { - if (this.pollingFast && this.poll()) this.pollingFast = false; - }, - - onKeyPress: function() { - if (ie && ie_version >= 9) this.hasSelection = null; - this.fastPoll(); - }, - - onContextMenu: function(e) { - var input = this, cm = input.cm, display = cm.display, te = input.textarea; - var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop; - if (!pos || presto) return; // Opera is difficult. - - // Reset the current text selection only if the click is done outside of the selection - // and 'resetSelectionOnContextMenu' option is true. - var reset = cm.options.resetSelectionOnContextMenu; - if (reset && cm.doc.sel.contains(pos) == -1) - operation(cm, setSelection)(cm.doc, simpleSelection(pos), sel_dontScroll); - - var oldCSS = te.style.cssText; - input.wrapper.style.position = "absolute"; - te.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e.clientY - 5) + - "px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: " + - (ie ? "rgba(255, 255, 255, .05)" : "transparent") + - "; outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);"; - if (webkit) var oldScrollY = window.scrollY; // Work around Chrome issue (#2712) - display.input.focus(); - if (webkit) window.scrollTo(null, oldScrollY); - display.input.reset(); - // Adds "Select all" to context menu in FF - if (!cm.somethingSelected()) te.value = input.prevInput = " "; - input.contextMenuPending = true; - display.selForContextMenu = cm.doc.sel; - clearTimeout(display.detectingSelectAll); - - // Select-all will be greyed out if there's nothing to select, so - // this adds a zero-width space so that we can later check whether - // it got selected. - function prepareSelectAllHack() { - if (te.selectionStart != null) { - var selected = cm.somethingSelected(); - var extval = "\u200b" + (selected ? te.value : ""); - te.value = "\u21da"; // Used to catch context-menu undo - te.value = extval; - input.prevInput = selected ? "" : "\u200b"; - te.selectionStart = 1; te.selectionEnd = extval.length; - // Re-set this, in case some other handler touched the - // selection in the meantime. - display.selForContextMenu = cm.doc.sel; - } - } - function rehide() { - input.contextMenuPending = false; - input.wrapper.style.position = "relative"; - te.style.cssText = oldCSS; - if (ie && ie_version < 9) display.scrollbars.setScrollTop(display.scroller.scrollTop = scrollPos); - - // Try to detect the user choosing select-all - if (te.selectionStart != null) { - if (!ie || (ie && ie_version < 9)) prepareSelectAllHack(); - var i = 0, poll = function() { - if (display.selForContextMenu == cm.doc.sel && te.selectionStart == 0 && - te.selectionEnd > 0 && input.prevInput == "\u200b") - operation(cm, commands.selectAll)(cm); - else if (i++ < 10) display.detectingSelectAll = setTimeout(poll, 500); - else display.input.reset(); - }; - display.detectingSelectAll = setTimeout(poll, 200); - } - } - - if (ie && ie_version >= 9) prepareSelectAllHack(); - if (captureRightClick) { - e_stop(e); - var mouseup = function() { - off(window, "mouseup", mouseup); - setTimeout(rehide, 20); - }; - on(window, "mouseup", mouseup); - } else { - setTimeout(rehide, 50); - } - }, - - readOnlyChanged: function(val) { - if (!val) this.reset(); - }, - - setUneditable: nothing, - - needsContentAttribute: false - }, TextareaInput.prototype); - - // CONTENTEDITABLE INPUT STYLE - - function ContentEditableInput(cm) { - this.cm = cm; - this.lastAnchorNode = this.lastAnchorOffset = this.lastFocusNode = this.lastFocusOffset = null; - this.polling = new Delayed(); - this.gracePeriod = false; - } - - ContentEditableInput.prototype = copyObj({ - init: function(display) { - var input = this, cm = input.cm; - var div = input.div = display.lineDiv; - disableBrowserMagic(div); - - on(div, "paste", function(e) { handlePaste(e, cm); }) - - on(div, "compositionstart", function(e) { - var data = e.data; - input.composing = {sel: cm.doc.sel, data: data, startData: data}; - if (!data) return; - var prim = cm.doc.sel.primary(); - var line = cm.getLine(prim.head.line); - var found = line.indexOf(data, Math.max(0, prim.head.ch - data.length)); - if (found > -1 && found <= prim.head.ch) - input.composing.sel = simpleSelection(Pos(prim.head.line, found), - Pos(prim.head.line, found + data.length)); - }); - on(div, "compositionupdate", function(e) { - input.composing.data = e.data; - }); - on(div, "compositionend", function(e) { - var ours = input.composing; - if (!ours) return; - if (e.data != ours.startData && !/\u200b/.test(e.data)) - ours.data = e.data; - // Need a small delay to prevent other code (input event, - // selection polling) from doing damage when fired right after - // compositionend. - setTimeout(function() { - if (!ours.handled) - input.applyComposition(ours); - if (input.composing == ours) - input.composing = null; - }, 50); - }); - - on(div, "touchstart", function() { - input.forceCompositionEnd(); - }); - - on(div, "input", function() { - if (input.composing) return; - if (isReadOnly(cm) || !input.pollContent()) - runInOp(input.cm, function() {regChange(cm);}); - }); - - function onCopyCut(e) { - if (cm.somethingSelected()) { - lastCopied = cm.getSelections(); - if (e.type == "cut") cm.replaceSelection("", null, "cut"); - } else if (!cm.options.lineWiseCopyCut) { - return; - } else { - var ranges = copyableRanges(cm); - lastCopied = ranges.text; - if (e.type == "cut") { - cm.operation(function() { - cm.setSelections(ranges.ranges, 0, sel_dontScroll); - cm.replaceSelection("", null, "cut"); - }); - } - } - // iOS exposes the clipboard API, but seems to discard content inserted into it - if (e.clipboardData && !ios) { - e.preventDefault(); - e.clipboardData.clearData(); - e.clipboardData.setData("text/plain", lastCopied.join("\n")); - } else { - // Old-fashioned briefly-focus-a-textarea hack - var kludge = hiddenTextarea(), te = kludge.firstChild; - cm.display.lineSpace.insertBefore(kludge, cm.display.lineSpace.firstChild); - te.value = lastCopied.join("\n"); - var hadFocus = document.activeElement; - selectInput(te); - setTimeout(function() { - cm.display.lineSpace.removeChild(kludge); - hadFocus.focus(); - }, 50); - } - } - on(div, "copy", onCopyCut); - on(div, "cut", onCopyCut); - }, - - prepareSelection: function() { - var result = prepareSelection(this.cm, false); - result.focus = this.cm.state.focused; - return result; - }, - - showSelection: function(info) { - if (!info || !this.cm.display.view.length) return; - if (info.focus) this.showPrimarySelection(); - this.showMultipleSelections(info); - }, - - showPrimarySelection: function() { - var sel = window.getSelection(), prim = this.cm.doc.sel.primary(); - var curAnchor = domToPos(this.cm, sel.anchorNode, sel.anchorOffset); - var curFocus = domToPos(this.cm, sel.focusNode, sel.focusOffset); - if (curAnchor && !curAnchor.bad && curFocus && !curFocus.bad && - cmp(minPos(curAnchor, curFocus), prim.from()) == 0 && - cmp(maxPos(curAnchor, curFocus), prim.to()) == 0) - return; - - var start = posToDOM(this.cm, prim.from()); - var end = posToDOM(this.cm, prim.to()); - if (!start && !end) return; - - var view = this.cm.display.view; - var old = sel.rangeCount && sel.getRangeAt(0); - if (!start) { - start = {node: view[0].measure.map[2], offset: 0}; - } else if (!end) { // FIXME dangerously hacky - var measure = view[view.length - 1].measure; - var map = measure.maps ? measure.maps[measure.maps.length - 1] : measure.map; - end = {node: map[map.length - 1], offset: map[map.length - 2] - map[map.length - 3]}; - } - - try { var rng = range(start.node, start.offset, end.offset, end.node); } - catch(e) {} // Our model of the DOM might be outdated, in which case the range we try to set can be impossible - if (rng) { - sel.removeAllRanges(); - sel.addRange(rng); - if (old && sel.anchorNode == null) sel.addRange(old); - else if (gecko) this.startGracePeriod(); - } - this.rememberSelection(); - }, - - startGracePeriod: function() { - var input = this; - clearTimeout(this.gracePeriod); - this.gracePeriod = setTimeout(function() { - input.gracePeriod = false; - if (input.selectionChanged()) - input.cm.operation(function() { input.cm.curOp.selectionChanged = true; }); - }, 20); - }, - - showMultipleSelections: function(info) { - removeChildrenAndAdd(this.cm.display.cursorDiv, info.cursors); - removeChildrenAndAdd(this.cm.display.selectionDiv, info.selection); - }, - - rememberSelection: function() { - var sel = window.getSelection(); - this.lastAnchorNode = sel.anchorNode; this.lastAnchorOffset = sel.anchorOffset; - this.lastFocusNode = sel.focusNode; this.lastFocusOffset = sel.focusOffset; - }, - - selectionInEditor: function() { - var sel = window.getSelection(); - if (!sel.rangeCount) return false; - var node = sel.getRangeAt(0).commonAncestorContainer; - return contains(this.div, node); - }, - - focus: function() { - if (this.cm.options.readOnly != "nocursor") this.div.focus(); - }, - blur: function() { this.div.blur(); }, - getField: function() { return this.div; }, - - supportsTouch: function() { return true; }, - - receivedFocus: function() { - var input = this; - if (this.selectionInEditor()) - this.pollSelection(); - else - runInOp(this.cm, function() { input.cm.curOp.selectionChanged = true; }); - - function poll() { - if (input.cm.state.focused) { - input.pollSelection(); - input.polling.set(input.cm.options.pollInterval, poll); - } - } - this.polling.set(this.cm.options.pollInterval, poll); - }, - - selectionChanged: function() { - var sel = window.getSelection(); - return sel.anchorNode != this.lastAnchorNode || sel.anchorOffset != this.lastAnchorOffset || - sel.focusNode != this.lastFocusNode || sel.focusOffset != this.lastFocusOffset; - }, - - pollSelection: function() { - if (!this.composing && !this.gracePeriod && this.selectionChanged()) { - var sel = window.getSelection(), cm = this.cm; - this.rememberSelection(); - var anchor = domToPos(cm, sel.anchorNode, sel.anchorOffset); - var head = domToPos(cm, sel.focusNode, sel.focusOffset); - if (anchor && head) runInOp(cm, function() { - setSelection(cm.doc, simpleSelection(anchor, head), sel_dontScroll); - if (anchor.bad || head.bad) cm.curOp.selectionChanged = true; - }); - } - }, - - pollContent: function() { - var cm = this.cm, display = cm.display, sel = cm.doc.sel.primary(); - var from = sel.from(), to = sel.to(); - if (from.line < display.viewFrom || to.line > display.viewTo - 1) return false; - - var fromIndex; - if (from.line == display.viewFrom || (fromIndex = findViewIndex(cm, from.line)) == 0) { - var fromLine = lineNo(display.view[0].line); - var fromNode = display.view[0].node; - } else { - var fromLine = lineNo(display.view[fromIndex].line); - var fromNode = display.view[fromIndex - 1].node.nextSibling; - } - var toIndex = findViewIndex(cm, to.line); - if (toIndex == display.view.length - 1) { - var toLine = display.viewTo - 1; - var toNode = display.lineDiv.lastChild; - } else { - var toLine = lineNo(display.view[toIndex + 1].line) - 1; - var toNode = display.view[toIndex + 1].node.previousSibling; - } - - var newText = cm.doc.splitLines(domTextBetween(cm, fromNode, toNode, fromLine, toLine)); - var oldText = getBetween(cm.doc, Pos(fromLine, 0), Pos(toLine, getLine(cm.doc, toLine).text.length)); - while (newText.length > 1 && oldText.length > 1) { - if (lst(newText) == lst(oldText)) { newText.pop(); oldText.pop(); toLine--; } - else if (newText[0] == oldText[0]) { newText.shift(); oldText.shift(); fromLine++; } - else break; - } - - var cutFront = 0, cutEnd = 0; - var newTop = newText[0], oldTop = oldText[0], maxCutFront = Math.min(newTop.length, oldTop.length); - while (cutFront < maxCutFront && newTop.charCodeAt(cutFront) == oldTop.charCodeAt(cutFront)) - ++cutFront; - var newBot = lst(newText), oldBot = lst(oldText); - var maxCutEnd = Math.min(newBot.length - (newText.length == 1 ? cutFront : 0), - oldBot.length - (oldText.length == 1 ? cutFront : 0)); - while (cutEnd < maxCutEnd && - newBot.charCodeAt(newBot.length - cutEnd - 1) == oldBot.charCodeAt(oldBot.length - cutEnd - 1)) - ++cutEnd; - - newText[newText.length - 1] = newBot.slice(0, newBot.length - cutEnd); - newText[0] = newText[0].slice(cutFront); - - var chFrom = Pos(fromLine, cutFront); - var chTo = Pos(toLine, oldText.length ? lst(oldText).length - cutEnd : 0); - if (newText.length > 1 || newText[0] || cmp(chFrom, chTo)) { - replaceRange(cm.doc, newText, chFrom, chTo, "+input"); - return true; - } - }, - - ensurePolled: function() { - this.forceCompositionEnd(); - }, - reset: function() { - this.forceCompositionEnd(); - }, - forceCompositionEnd: function() { - if (!this.composing || this.composing.handled) return; - this.applyComposition(this.composing); - this.composing.handled = true; - this.div.blur(); - this.div.focus(); - }, - applyComposition: function(composing) { - if (isReadOnly(this.cm)) - operation(this.cm, regChange)(this.cm) - else if (composing.data && composing.data != composing.startData) - operation(this.cm, applyTextInput)(this.cm, composing.data, 0, composing.sel); - }, - - setUneditable: function(node) { - node.contentEditable = "false" - }, - - onKeyPress: function(e) { - e.preventDefault(); - if (!isReadOnly(this.cm)) - operation(this.cm, applyTextInput)(this.cm, String.fromCharCode(e.charCode == null ? e.keyCode : e.charCode), 0); - }, - - readOnlyChanged: function(val) { - this.div.contentEditable = String(val != "nocursor") - }, - - onContextMenu: nothing, - resetPosition: nothing, - - needsContentAttribute: true - }, ContentEditableInput.prototype); - - function posToDOM(cm, pos) { - var view = findViewForLine(cm, pos.line); - if (!view || view.hidden) return null; - var line = getLine(cm.doc, pos.line); - var info = mapFromLineView(view, line, pos.line); - - var order = getOrder(line), side = "left"; - if (order) { - var partPos = getBidiPartAt(order, pos.ch); - side = partPos % 2 ? "right" : "left"; - } - var result = nodeAndOffsetInLineMap(info.map, pos.ch, side); - result.offset = result.collapse == "right" ? result.end : result.start; - return result; - } - - function badPos(pos, bad) { if (bad) pos.bad = true; return pos; } - - function domToPos(cm, node, offset) { - var lineNode; - if (node == cm.display.lineDiv) { - lineNode = cm.display.lineDiv.childNodes[offset]; - if (!lineNode) return badPos(cm.clipPos(Pos(cm.display.viewTo - 1)), true); - node = null; offset = 0; - } else { - for (lineNode = node;; lineNode = lineNode.parentNode) { - if (!lineNode || lineNode == cm.display.lineDiv) return null; - if (lineNode.parentNode && lineNode.parentNode == cm.display.lineDiv) break; - } - } - for (var i = 0; i < cm.display.view.length; i++) { - var lineView = cm.display.view[i]; - if (lineView.node == lineNode) - return locateNodeInLineView(lineView, node, offset); - } - } - - function locateNodeInLineView(lineView, node, offset) { - var wrapper = lineView.text.firstChild, bad = false; - if (!node || !contains(wrapper, node)) return badPos(Pos(lineNo(lineView.line), 0), true); - if (node == wrapper) { - bad = true; - node = wrapper.childNodes[offset]; - offset = 0; - if (!node) { - var line = lineView.rest ? lst(lineView.rest) : lineView.line; - return badPos(Pos(lineNo(line), line.text.length), bad); - } - } - - var textNode = node.nodeType == 3 ? node : null, topNode = node; - if (!textNode && node.childNodes.length == 1 && node.firstChild.nodeType == 3) { - textNode = node.firstChild; - if (offset) offset = textNode.nodeValue.length; - } - while (topNode.parentNode != wrapper) topNode = topNode.parentNode; - var measure = lineView.measure, maps = measure.maps; - - function find(textNode, topNode, offset) { - for (var i = -1; i < (maps ? maps.length : 0); i++) { - var map = i < 0 ? measure.map : maps[i]; - for (var j = 0; j < map.length; j += 3) { - var curNode = map[j + 2]; - if (curNode == textNode || curNode == topNode) { - var line = lineNo(i < 0 ? lineView.line : lineView.rest[i]); - var ch = map[j] + offset; - if (offset < 0 || curNode != textNode) ch = map[j + (offset ? 1 : 0)]; - return Pos(line, ch); - } - } - } - } - var found = find(textNode, topNode, offset); - if (found) return badPos(found, bad); - - // FIXME this is all really shaky. might handle the few cases it needs to handle, but likely to cause problems - for (var after = topNode.nextSibling, dist = textNode ? textNode.nodeValue.length - offset : 0; after; after = after.nextSibling) { - found = find(after, after.firstChild, 0); - if (found) - return badPos(Pos(found.line, found.ch - dist), bad); - else - dist += after.textContent.length; - } - for (var before = topNode.previousSibling, dist = offset; before; before = before.previousSibling) { - found = find(before, before.firstChild, -1); - if (found) - return badPos(Pos(found.line, found.ch + dist), bad); - else - dist += after.textContent.length; - } - } - - function domTextBetween(cm, from, to, fromLine, toLine) { - var text = "", closing = false, lineSep = cm.doc.lineSeparator(); - function recognizeMarker(id) { return function(marker) { return marker.id == id; }; } - function walk(node) { - if (node.nodeType == 1) { - var cmText = node.getAttribute("cm-text"); - if (cmText != null) { - if (cmText == "") cmText = node.textContent.replace(/\u200b/g, ""); - text += cmText; - return; - } - var markerID = node.getAttribute("cm-marker"), range; - if (markerID) { - var found = cm.findMarks(Pos(fromLine, 0), Pos(toLine + 1, 0), recognizeMarker(+markerID)); - if (found.length && (range = found[0].find())) - text += getBetween(cm.doc, range.from, range.to).join(lineSep); - return; - } - if (node.getAttribute("contenteditable") == "false") return; - for (var i = 0; i < node.childNodes.length; i++) - walk(node.childNodes[i]); - if (/^(pre|div|p)$/i.test(node.nodeName)) - closing = true; - } else if (node.nodeType == 3) { - var val = node.nodeValue; - if (!val) return; - if (closing) { - text += lineSep; - closing = false; - } - text += val; - } - } - for (;;) { - walk(from); - if (from == to) break; - from = from.nextSibling; - } - return text; - } - - CodeMirror.inputStyles = {"textarea": TextareaInput, "contenteditable": ContentEditableInput}; - - // SELECTION / CURSOR - - // Selection objects are immutable. A new one is created every time - // the selection changes. A selection is one or more non-overlapping - // (and non-touching) ranges, sorted, and an integer that indicates - // which one is the primary selection (the one that's scrolled into - // view, that getCursor returns, etc). - function Selection(ranges, primIndex) { - this.ranges = ranges; - this.primIndex = primIndex; - } - - Selection.prototype = { - primary: function() { return this.ranges[this.primIndex]; }, - equals: function(other) { - if (other == this) return true; - if (other.primIndex != this.primIndex || other.ranges.length != this.ranges.length) return false; - for (var i = 0; i < this.ranges.length; i++) { - var here = this.ranges[i], there = other.ranges[i]; - if (cmp(here.anchor, there.anchor) != 0 || cmp(here.head, there.head) != 0) return false; - } - return true; - }, - deepCopy: function() { - for (var out = [], i = 0; i < this.ranges.length; i++) - out[i] = new Range(copyPos(this.ranges[i].anchor), copyPos(this.ranges[i].head)); - return new Selection(out, this.primIndex); - }, - somethingSelected: function() { - for (var i = 0; i < this.ranges.length; i++) - if (!this.ranges[i].empty()) return true; - return false; - }, - contains: function(pos, end) { - if (!end) end = pos; - for (var i = 0; i < this.ranges.length; i++) { - var range = this.ranges[i]; - if (cmp(end, range.from()) >= 0 && cmp(pos, range.to()) <= 0) - return i; - } - return -1; - } - }; - - function Range(anchor, head) { - this.anchor = anchor; this.head = head; - } - - Range.prototype = { - from: function() { return minPos(this.anchor, this.head); }, - to: function() { return maxPos(this.anchor, this.head); }, - empty: function() { - return this.head.line == this.anchor.line && this.head.ch == this.anchor.ch; - } - }; - - // Take an unsorted, potentially overlapping set of ranges, and - // build a selection out of it. 'Consumes' ranges array (modifying - // it). - function normalizeSelection(ranges, primIndex) { - var prim = ranges[primIndex]; - ranges.sort(function(a, b) { return cmp(a.from(), b.from()); }); - primIndex = indexOf(ranges, prim); - for (var i = 1; i < ranges.length; i++) { - var cur = ranges[i], prev = ranges[i - 1]; - if (cmp(prev.to(), cur.from()) >= 0) { - var from = minPos(prev.from(), cur.from()), to = maxPos(prev.to(), cur.to()); - var inv = prev.empty() ? cur.from() == cur.head : prev.from() == prev.head; - if (i <= primIndex) --primIndex; - ranges.splice(--i, 2, new Range(inv ? to : from, inv ? from : to)); - } - } - return new Selection(ranges, primIndex); - } - - function simpleSelection(anchor, head) { - return new Selection([new Range(anchor, head || anchor)], 0); - } - - // Most of the external API clips given positions to make sure they - // actually exist within the document. - function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1));} - function clipPos(doc, pos) { - if (pos.line < doc.first) return Pos(doc.first, 0); - var last = doc.first + doc.size - 1; - if (pos.line > last) return Pos(last, getLine(doc, last).text.length); - return clipToLen(pos, getLine(doc, pos.line).text.length); - } - function clipToLen(pos, linelen) { - var ch = pos.ch; - if (ch == null || ch > linelen) return Pos(pos.line, linelen); - else if (ch < 0) return Pos(pos.line, 0); - else return pos; - } - function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size;} - function clipPosArray(doc, array) { - for (var out = [], i = 0; i < array.length; i++) out[i] = clipPos(doc, array[i]); - return out; - } - - // SELECTION UPDATES - - // The 'scroll' parameter given to many of these indicated whether - // the new cursor position should be scrolled into view after - // modifying the selection. - - // If shift is held or the extend flag is set, extends a range to - // include a given position (and optionally a second position). - // Otherwise, simply returns the range between the given positions. - // Used for cursor motion and such. - function extendRange(doc, range, head, other) { - if (doc.cm && doc.cm.display.shift || doc.extend) { - var anchor = range.anchor; - if (other) { - var posBefore = cmp(head, anchor) < 0; - if (posBefore != (cmp(other, anchor) < 0)) { - anchor = head; - head = other; - } else if (posBefore != (cmp(head, other) < 0)) { - head = other; - } - } - return new Range(anchor, head); - } else { - return new Range(other || head, head); - } - } - - // Extend the primary selection range, discard the rest. - function extendSelection(doc, head, other, options) { - setSelection(doc, new Selection([extendRange(doc, doc.sel.primary(), head, other)], 0), options); - } - - // Extend all selections (pos is an array of selections with length - // equal the number of selections) - function extendSelections(doc, heads, options) { - for (var out = [], i = 0; i < doc.sel.ranges.length; i++) - out[i] = extendRange(doc, doc.sel.ranges[i], heads[i], null); - var newSel = normalizeSelection(out, doc.sel.primIndex); - setSelection(doc, newSel, options); - } - - // Updates a single range in the selection. - function replaceOneSelection(doc, i, range, options) { - var ranges = doc.sel.ranges.slice(0); - ranges[i] = range; - setSelection(doc, normalizeSelection(ranges, doc.sel.primIndex), options); - } - - // Reset the selection to a single range. - function setSimpleSelection(doc, anchor, head, options) { - setSelection(doc, simpleSelection(anchor, head), options); - } - - // Give beforeSelectionChange handlers a change to influence a - // selection update. - function filterSelectionChange(doc, sel) { - var obj = { - ranges: sel.ranges, - update: function(ranges) { - this.ranges = []; - for (var i = 0; i < ranges.length; i++) - this.ranges[i] = new Range(clipPos(doc, ranges[i].anchor), - clipPos(doc, ranges[i].head)); - } - }; - signal(doc, "beforeSelectionChange", doc, obj); - if (doc.cm) signal(doc.cm, "beforeSelectionChange", doc.cm, obj); - if (obj.ranges != sel.ranges) return normalizeSelection(obj.ranges, obj.ranges.length - 1); - else return sel; - } - - function setSelectionReplaceHistory(doc, sel, options) { - var done = doc.history.done, last = lst(done); - if (last && last.ranges) { - done[done.length - 1] = sel; - setSelectionNoUndo(doc, sel, options); - } else { - setSelection(doc, sel, options); - } - } - - // Set a new selection. - function setSelection(doc, sel, options) { - setSelectionNoUndo(doc, sel, options); - addSelectionToHistory(doc, doc.sel, doc.cm ? doc.cm.curOp.id : NaN, options); - } - - function setSelectionNoUndo(doc, sel, options) { - if (hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange")) - sel = filterSelectionChange(doc, sel); - - var bias = options && options.bias || - (cmp(sel.primary().head, doc.sel.primary().head) < 0 ? -1 : 1); - setSelectionInner(doc, skipAtomicInSelection(doc, sel, bias, true)); - - if (!(options && options.scroll === false) && doc.cm) - ensureCursorVisible(doc.cm); - } - - function setSelectionInner(doc, sel) { - if (sel.equals(doc.sel)) return; - - doc.sel = sel; - - if (doc.cm) { - doc.cm.curOp.updateInput = doc.cm.curOp.selectionChanged = true; - signalCursorActivity(doc.cm); - } - signalLater(doc, "cursorActivity", doc); - } - - // Verify that the selection does not partially select any atomic - // marked ranges. - function reCheckSelection(doc) { - setSelectionInner(doc, skipAtomicInSelection(doc, doc.sel, null, false), sel_dontScroll); - } - - // Return a selection that does not partially select any atomic - // ranges. - function skipAtomicInSelection(doc, sel, bias, mayClear) { - var out; - for (var i = 0; i < sel.ranges.length; i++) { - var range = sel.ranges[i]; - var newAnchor = skipAtomic(doc, range.anchor, bias, mayClear); - var newHead = skipAtomic(doc, range.head, bias, mayClear); - if (out || newAnchor != range.anchor || newHead != range.head) { - if (!out) out = sel.ranges.slice(0, i); - out[i] = new Range(newAnchor, newHead); - } - } - return out ? normalizeSelection(out, sel.primIndex) : sel; - } - - // Ensure a given position is not inside an atomic range. - function skipAtomic(doc, pos, bias, mayClear) { - var flipped = false, curPos = pos; - var dir = bias || 1; - doc.cantEdit = false; - search: for (;;) { - var line = getLine(doc, curPos.line); - if (line.markedSpans) { - for (var i = 0; i < line.markedSpans.length; ++i) { - var sp = line.markedSpans[i], m = sp.marker; - if ((sp.from == null || (m.inclusiveLeft ? sp.from <= curPos.ch : sp.from < curPos.ch)) && - (sp.to == null || (m.inclusiveRight ? sp.to >= curPos.ch : sp.to > curPos.ch))) { - if (mayClear) { - signal(m, "beforeCursorEnter"); - if (m.explicitlyCleared) { - if (!line.markedSpans) break; - else {--i; continue;} - } - } - if (!m.atomic) continue; - var newPos = m.find(dir < 0 ? -1 : 1); - if (cmp(newPos, curPos) == 0) { - newPos.ch += dir; - if (newPos.ch < 0) { - if (newPos.line > doc.first) newPos = clipPos(doc, Pos(newPos.line - 1)); - else newPos = null; - } else if (newPos.ch > line.text.length) { - if (newPos.line < doc.first + doc.size - 1) newPos = Pos(newPos.line + 1, 0); - else newPos = null; - } - if (!newPos) { - if (flipped) { - // Driven in a corner -- no valid cursor position found at all - // -- try again *with* clearing, if we didn't already - if (!mayClear) return skipAtomic(doc, pos, bias, true); - // Otherwise, turn off editing until further notice, and return the start of the doc - doc.cantEdit = true; - return Pos(doc.first, 0); - } - flipped = true; newPos = pos; dir = -dir; - } - } - curPos = newPos; - continue search; - } - } - } - return curPos; - } - } - - // SELECTION DRAWING - - function updateSelection(cm) { - cm.display.input.showSelection(cm.display.input.prepareSelection()); - } - - function prepareSelection(cm, primary) { - var doc = cm.doc, result = {}; - var curFragment = result.cursors = document.createDocumentFragment(); - var selFragment = result.selection = document.createDocumentFragment(); - - for (var i = 0; i < doc.sel.ranges.length; i++) { - if (primary === false && i == doc.sel.primIndex) continue; - var range = doc.sel.ranges[i]; - var collapsed = range.empty(); - if (collapsed || cm.options.showCursorWhenSelecting) - drawSelectionCursor(cm, range.head, curFragment); - if (!collapsed) - drawSelectionRange(cm, range, selFragment); - } - return result; - } - - // Draws a cursor for the given range - function drawSelectionCursor(cm, head, output) { - var pos = cursorCoords(cm, head, "div", null, null, !cm.options.singleCursorHeightPerLine); - - var cursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor")); - cursor.style.left = pos.left + "px"; - cursor.style.top = pos.top + "px"; - cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px"; - - if (pos.other) { - // Secondary cursor, shown when on a 'jump' in bi-directional text - var otherCursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor")); - otherCursor.style.display = ""; - otherCursor.style.left = pos.other.left + "px"; - otherCursor.style.top = pos.other.top + "px"; - otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px"; - } - } - - // Draws the given range as a highlighted selection - function drawSelectionRange(cm, range, output) { - var display = cm.display, doc = cm.doc; - var fragment = document.createDocumentFragment(); - var padding = paddingH(cm.display), leftSide = padding.left; - var rightSide = Math.max(display.sizerWidth, displayWidth(cm) - display.sizer.offsetLeft) - padding.right; - - function add(left, top, width, bottom) { - if (top < 0) top = 0; - top = Math.round(top); - bottom = Math.round(bottom); - fragment.appendChild(elt("div", null, "CodeMirror-selected", "position: absolute; left: " + left + - "px; top: " + top + "px; width: " + (width == null ? rightSide - left : width) + - "px; height: " + (bottom - top) + "px")); - } - - function drawForLine(line, fromArg, toArg) { - var lineObj = getLine(doc, line); - var lineLen = lineObj.text.length; - var start, end; - function coords(ch, bias) { - return charCoords(cm, Pos(line, ch), "div", lineObj, bias); - } - - iterateBidiSections(getOrder(lineObj), fromArg || 0, toArg == null ? lineLen : toArg, function(from, to, dir) { - var leftPos = coords(from, "left"), rightPos, left, right; - if (from == to) { - rightPos = leftPos; - left = right = leftPos.left; - } else { - rightPos = coords(to - 1, "right"); - if (dir == "rtl") { var tmp = leftPos; leftPos = rightPos; rightPos = tmp; } - left = leftPos.left; - right = rightPos.right; - } - if (fromArg == null && from == 0) left = leftSide; - if (rightPos.top - leftPos.top > 3) { // Different lines, draw top part - add(left, leftPos.top, null, leftPos.bottom); - left = leftSide; - if (leftPos.bottom < rightPos.top) add(left, leftPos.bottom, null, rightPos.top); - } - if (toArg == null && to == lineLen) right = rightSide; - if (!start || leftPos.top < start.top || leftPos.top == start.top && leftPos.left < start.left) - start = leftPos; - if (!end || rightPos.bottom > end.bottom || rightPos.bottom == end.bottom && rightPos.right > end.right) - end = rightPos; - if (left < leftSide + 1) left = leftSide; - add(left, rightPos.top, right - left, rightPos.bottom); - }); - return {start: start, end: end}; - } - - var sFrom = range.from(), sTo = range.to(); - if (sFrom.line == sTo.line) { - drawForLine(sFrom.line, sFrom.ch, sTo.ch); - } else { - var fromLine = getLine(doc, sFrom.line), toLine = getLine(doc, sTo.line); - var singleVLine = visualLine(fromLine) == visualLine(toLine); - var leftEnd = drawForLine(sFrom.line, sFrom.ch, singleVLine ? fromLine.text.length + 1 : null).end; - var rightStart = drawForLine(sTo.line, singleVLine ? 0 : null, sTo.ch).start; - if (singleVLine) { - if (leftEnd.top < rightStart.top - 2) { - add(leftEnd.right, leftEnd.top, null, leftEnd.bottom); - add(leftSide, rightStart.top, rightStart.left, rightStart.bottom); - } else { - add(leftEnd.right, leftEnd.top, rightStart.left - leftEnd.right, leftEnd.bottom); - } - } - if (leftEnd.bottom < rightStart.top) - add(leftSide, leftEnd.bottom, null, rightStart.top); - } - - output.appendChild(fragment); - } - - // Cursor-blinking - function restartBlink(cm) { - if (!cm.state.focused) return; - var display = cm.display; - clearInterval(display.blinker); - var on = true; - display.cursorDiv.style.visibility = ""; - if (cm.options.cursorBlinkRate > 0) - display.blinker = setInterval(function() { - display.cursorDiv.style.visibility = (on = !on) ? "" : "hidden"; - }, cm.options.cursorBlinkRate); - else if (cm.options.cursorBlinkRate < 0) - display.cursorDiv.style.visibility = "hidden"; - } - - // HIGHLIGHT WORKER - - function startWorker(cm, time) { - if (cm.doc.mode.startState && cm.doc.frontier < cm.display.viewTo) - cm.state.highlight.set(time, bind(highlightWorker, cm)); - } - - function highlightWorker(cm) { - var doc = cm.doc; - if (doc.frontier < doc.first) doc.frontier = doc.first; - if (doc.frontier >= cm.display.viewTo) return; - var end = +new Date + cm.options.workTime; - var state = copyState(doc.mode, getStateBefore(cm, doc.frontier)); - var changedLines = []; - - doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.viewTo + 500), function(line) { - if (doc.frontier >= cm.display.viewFrom) { // Visible - var oldStyles = line.styles, tooLong = line.text.length > cm.options.maxHighlightLength; - var highlighted = highlightLine(cm, line, tooLong ? copyState(doc.mode, state) : state, true); - line.styles = highlighted.styles; - var oldCls = line.styleClasses, newCls = highlighted.classes; - if (newCls) line.styleClasses = newCls; - else if (oldCls) line.styleClasses = null; - var ischange = !oldStyles || oldStyles.length != line.styles.length || - oldCls != newCls && (!oldCls || !newCls || oldCls.bgClass != newCls.bgClass || oldCls.textClass != newCls.textClass); - for (var i = 0; !ischange && i < oldStyles.length; ++i) ischange = oldStyles[i] != line.styles[i]; - if (ischange) changedLines.push(doc.frontier); - line.stateAfter = tooLong ? state : copyState(doc.mode, state); - } else { - if (line.text.length <= cm.options.maxHighlightLength) - processLine(cm, line.text, state); - line.stateAfter = doc.frontier % 5 == 0 ? copyState(doc.mode, state) : null; - } - ++doc.frontier; - if (+new Date > end) { - startWorker(cm, cm.options.workDelay); - return true; - } - }); - if (changedLines.length) runInOp(cm, function() { - for (var i = 0; i < changedLines.length; i++) - regLineChange(cm, changedLines[i], "text"); - }); - } - - // Finds the line to start with when starting a parse. Tries to - // find a line with a stateAfter, so that it can start with a - // valid state. If that fails, it returns the line with the - // smallest indentation, which tends to need the least context to - // parse correctly. - function findStartLine(cm, n, precise) { - var minindent, minline, doc = cm.doc; - var lim = precise ? -1 : n - (cm.doc.mode.innerMode ? 1000 : 100); - for (var search = n; search > lim; --search) { - if (search <= doc.first) return doc.first; - var line = getLine(doc, search - 1); - if (line.stateAfter && (!precise || search <= doc.frontier)) return search; - var indented = countColumn(line.text, null, cm.options.tabSize); - if (minline == null || minindent > indented) { - minline = search - 1; - minindent = indented; - } - } - return minline; - } - - function getStateBefore(cm, n, precise) { - var doc = cm.doc, display = cm.display; - if (!doc.mode.startState) return true; - var pos = findStartLine(cm, n, precise), state = pos > doc.first && getLine(doc, pos-1).stateAfter; - if (!state) state = startState(doc.mode); - else state = copyState(doc.mode, state); - doc.iter(pos, n, function(line) { - processLine(cm, line.text, state); - var save = pos == n - 1 || pos % 5 == 0 || pos >= display.viewFrom && pos < display.viewTo; - line.stateAfter = save ? copyState(doc.mode, state) : null; - ++pos; - }); - if (precise) doc.frontier = pos; - return state; - } - - // POSITION MEASUREMENT - - function paddingTop(display) {return display.lineSpace.offsetTop;} - function paddingVert(display) {return display.mover.offsetHeight - display.lineSpace.offsetHeight;} - function paddingH(display) { - if (display.cachedPaddingH) return display.cachedPaddingH; - var e = removeChildrenAndAdd(display.measure, elt("pre", "x")); - var style = window.getComputedStyle ? window.getComputedStyle(e) : e.currentStyle; - var data = {left: parseInt(style.paddingLeft), right: parseInt(style.paddingRight)}; - if (!isNaN(data.left) && !isNaN(data.right)) display.cachedPaddingH = data; - return data; - } - - function scrollGap(cm) { return scrollerGap - cm.display.nativeBarWidth; } - function displayWidth(cm) { - return cm.display.scroller.clientWidth - scrollGap(cm) - cm.display.barWidth; - } - function displayHeight(cm) { - return cm.display.scroller.clientHeight - scrollGap(cm) - cm.display.barHeight; - } - - // Ensure the lineView.wrapping.heights array is populated. This is - // an array of bottom offsets for the lines that make up a drawn - // line. When lineWrapping is on, there might be more than one - // height. - function ensureLineHeights(cm, lineView, rect) { - var wrapping = cm.options.lineWrapping; - var curWidth = wrapping && displayWidth(cm); - if (!lineView.measure.heights || wrapping && lineView.measure.width != curWidth) { - var heights = lineView.measure.heights = []; - if (wrapping) { - lineView.measure.width = curWidth; - var rects = lineView.text.firstChild.getClientRects(); - for (var i = 0; i < rects.length - 1; i++) { - var cur = rects[i], next = rects[i + 1]; - if (Math.abs(cur.bottom - next.bottom) > 2) - heights.push((cur.bottom + next.top) / 2 - rect.top); - } - } - heights.push(rect.bottom - rect.top); - } - } - - // Find a line map (mapping character offsets to text nodes) and a - // measurement cache for the given line number. (A line view might - // contain multiple lines when collapsed ranges are present.) - function mapFromLineView(lineView, line, lineN) { - if (lineView.line == line) - return {map: lineView.measure.map, cache: lineView.measure.cache}; - for (var i = 0; i < lineView.rest.length; i++) - if (lineView.rest[i] == line) - return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i]}; - for (var i = 0; i < lineView.rest.length; i++) - if (lineNo(lineView.rest[i]) > lineN) - return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i], before: true}; - } - - // Render a line into the hidden node display.externalMeasured. Used - // when measurement is needed for a line that's not in the viewport. - function updateExternalMeasurement(cm, line) { - line = visualLine(line); - var lineN = lineNo(line); - var view = cm.display.externalMeasured = new LineView(cm.doc, line, lineN); - view.lineN = lineN; - var built = view.built = buildLineContent(cm, view); - view.text = built.pre; - removeChildrenAndAdd(cm.display.lineMeasure, built.pre); - return view; - } - - // Get a {top, bottom, left, right} box (in line-local coordinates) - // for a given character. - function measureChar(cm, line, ch, bias) { - return measureCharPrepared(cm, prepareMeasureForLine(cm, line), ch, bias); - } - - // Find a line view that corresponds to the given line number. - function findViewForLine(cm, lineN) { - if (lineN >= cm.display.viewFrom && lineN < cm.display.viewTo) - return cm.display.view[findViewIndex(cm, lineN)]; - var ext = cm.display.externalMeasured; - if (ext && lineN >= ext.lineN && lineN < ext.lineN + ext.size) - return ext; - } - - // Measurement can be split in two steps, the set-up work that - // applies to the whole line, and the measurement of the actual - // character. Functions like coordsChar, that need to do a lot of - // measurements in a row, can thus ensure that the set-up work is - // only done once. - function prepareMeasureForLine(cm, line) { - var lineN = lineNo(line); - var view = findViewForLine(cm, lineN); - if (view && !view.text) { - view = null; - } else if (view && view.changes) { - updateLineForChanges(cm, view, lineN, getDimensions(cm)); - cm.curOp.forceUpdate = true; - } - if (!view) - view = updateExternalMeasurement(cm, line); - - var info = mapFromLineView(view, line, lineN); - return { - line: line, view: view, rect: null, - map: info.map, cache: info.cache, before: info.before, - hasHeights: false - }; - } - - // Given a prepared measurement object, measures the position of an - // actual character (or fetches it from the cache). - function measureCharPrepared(cm, prepared, ch, bias, varHeight) { - if (prepared.before) ch = -1; - var key = ch + (bias || ""), found; - if (prepared.cache.hasOwnProperty(key)) { - found = prepared.cache[key]; - } else { - if (!prepared.rect) - prepared.rect = prepared.view.text.getBoundingClientRect(); - if (!prepared.hasHeights) { - ensureLineHeights(cm, prepared.view, prepared.rect); - prepared.hasHeights = true; - } - found = measureCharInner(cm, prepared, ch, bias); - if (!found.bogus) prepared.cache[key] = found; - } - return {left: found.left, right: found.right, - top: varHeight ? found.rtop : found.top, - bottom: varHeight ? found.rbottom : found.bottom}; - } - - var nullRect = {left: 0, right: 0, top: 0, bottom: 0}; - - function nodeAndOffsetInLineMap(map, ch, bias) { - var node, start, end, collapse; - // First, search the line map for the text node corresponding to, - // or closest to, the target character. - for (var i = 0; i < map.length; i += 3) { - var mStart = map[i], mEnd = map[i + 1]; - if (ch < mStart) { - start = 0; end = 1; - collapse = "left"; - } else if (ch < mEnd) { - start = ch - mStart; - end = start + 1; - } else if (i == map.length - 3 || ch == mEnd && map[i + 3] > ch) { - end = mEnd - mStart; - start = end - 1; - if (ch >= mEnd) collapse = "right"; - } - if (start != null) { - node = map[i + 2]; - if (mStart == mEnd && bias == (node.insertLeft ? "left" : "right")) - collapse = bias; - if (bias == "left" && start == 0) - while (i && map[i - 2] == map[i - 3] && map[i - 1].insertLeft) { - node = map[(i -= 3) + 2]; - collapse = "left"; - } - if (bias == "right" && start == mEnd - mStart) - while (i < map.length - 3 && map[i + 3] == map[i + 4] && !map[i + 5].insertLeft) { - node = map[(i += 3) + 2]; - collapse = "right"; - } - break; - } - } - return {node: node, start: start, end: end, collapse: collapse, coverStart: mStart, coverEnd: mEnd}; - } - - function measureCharInner(cm, prepared, ch, bias) { - var place = nodeAndOffsetInLineMap(prepared.map, ch, bias); - var node = place.node, start = place.start, end = place.end, collapse = place.collapse; - - var rect; - if (node.nodeType == 3) { // If it is a text node, use a range to retrieve the coordinates. - for (var i = 0; i < 4; i++) { // Retry a maximum of 4 times when nonsense rectangles are returned - while (start && isExtendingChar(prepared.line.text.charAt(place.coverStart + start))) --start; - while (place.coverStart + end < place.coverEnd && isExtendingChar(prepared.line.text.charAt(place.coverStart + end))) ++end; - if (ie && ie_version < 9 && start == 0 && end == place.coverEnd - place.coverStart) { - rect = node.parentNode.getBoundingClientRect(); - } else if (ie && cm.options.lineWrapping) { - var rects = range(node, start, end).getClientRects(); - if (rects.length) - rect = rects[bias == "right" ? rects.length - 1 : 0]; - else - rect = nullRect; - } else { - rect = range(node, start, end).getBoundingClientRect() || nullRect; - } - if (rect.left || rect.right || start == 0) break; - end = start; - start = start - 1; - collapse = "right"; - } - if (ie && ie_version < 11) rect = maybeUpdateRectForZooming(cm.display.measure, rect); - } else { // If it is a widget, simply get the box for the whole widget. - if (start > 0) collapse = bias = "right"; - var rects; - if (cm.options.lineWrapping && (rects = node.getClientRects()).length > 1) - rect = rects[bias == "right" ? rects.length - 1 : 0]; - else - rect = node.getBoundingClientRect(); - } - if (ie && ie_version < 9 && !start && (!rect || !rect.left && !rect.right)) { - var rSpan = node.parentNode.getClientRects()[0]; - if (rSpan) - rect = {left: rSpan.left, right: rSpan.left + charWidth(cm.display), top: rSpan.top, bottom: rSpan.bottom}; - else - rect = nullRect; - } - - var rtop = rect.top - prepared.rect.top, rbot = rect.bottom - prepared.rect.top; - var mid = (rtop + rbot) / 2; - var heights = prepared.view.measure.heights; - for (var i = 0; i < heights.length - 1; i++) - if (mid < heights[i]) break; - var top = i ? heights[i - 1] : 0, bot = heights[i]; - var result = {left: (collapse == "right" ? rect.right : rect.left) - prepared.rect.left, - right: (collapse == "left" ? rect.left : rect.right) - prepared.rect.left, - top: top, bottom: bot}; - if (!rect.left && !rect.right) result.bogus = true; - if (!cm.options.singleCursorHeightPerLine) { result.rtop = rtop; result.rbottom = rbot; } - - return result; - } - - // Work around problem with bounding client rects on ranges being - // returned incorrectly when zoomed on IE10 and below. - function maybeUpdateRectForZooming(measure, rect) { - if (!window.screen || screen.logicalXDPI == null || - screen.logicalXDPI == screen.deviceXDPI || !hasBadZoomedRects(measure)) - return rect; - var scaleX = screen.logicalXDPI / screen.deviceXDPI; - var scaleY = screen.logicalYDPI / screen.deviceYDPI; - return {left: rect.left * scaleX, right: rect.right * scaleX, - top: rect.top * scaleY, bottom: rect.bottom * scaleY}; - } - - function clearLineMeasurementCacheFor(lineView) { - if (lineView.measure) { - lineView.measure.cache = {}; - lineView.measure.heights = null; - if (lineView.rest) for (var i = 0; i < lineView.rest.length; i++) - lineView.measure.caches[i] = {}; - } - } - - function clearLineMeasurementCache(cm) { - cm.display.externalMeasure = null; - removeChildren(cm.display.lineMeasure); - for (var i = 0; i < cm.display.view.length; i++) - clearLineMeasurementCacheFor(cm.display.view[i]); - } - - function clearCaches(cm) { - clearLineMeasurementCache(cm); - cm.display.cachedCharWidth = cm.display.cachedTextHeight = cm.display.cachedPaddingH = null; - if (!cm.options.lineWrapping) cm.display.maxLineChanged = true; - cm.display.lineNumChars = null; - } - - function pageScrollX() { return window.pageXOffset || (document.documentElement || document.body).scrollLeft; } - function pageScrollY() { return window.pageYOffset || (document.documentElement || document.body).scrollTop; } - - // Converts a {top, bottom, left, right} box from line-local - // coordinates into another coordinate system. Context may be one of - // "line", "div" (display.lineDiv), "local"/null (editor), "window", - // or "page". - function intoCoordSystem(cm, lineObj, rect, context) { - if (lineObj.widgets) for (var i = 0; i < lineObj.widgets.length; ++i) if (lineObj.widgets[i].above) { - var size = widgetHeight(lineObj.widgets[i]); - rect.top += size; rect.bottom += size; - } - if (context == "line") return rect; - if (!context) context = "local"; - var yOff = heightAtLine(lineObj); - if (context == "local") yOff += paddingTop(cm.display); - else yOff -= cm.display.viewOffset; - if (context == "page" || context == "window") { - var lOff = cm.display.lineSpace.getBoundingClientRect(); - yOff += lOff.top + (context == "window" ? 0 : pageScrollY()); - var xOff = lOff.left + (context == "window" ? 0 : pageScrollX()); - rect.left += xOff; rect.right += xOff; - } - rect.top += yOff; rect.bottom += yOff; - return rect; - } - - // Coverts a box from "div" coords to another coordinate system. - // Context may be "window", "page", "div", or "local"/null. - function fromCoordSystem(cm, coords, context) { - if (context == "div") return coords; - var left = coords.left, top = coords.top; - // First move into "page" coordinate system - if (context == "page") { - left -= pageScrollX(); - top -= pageScrollY(); - } else if (context == "local" || !context) { - var localBox = cm.display.sizer.getBoundingClientRect(); - left += localBox.left; - top += localBox.top; - } - - var lineSpaceBox = cm.display.lineSpace.getBoundingClientRect(); - return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top}; - } - - function charCoords(cm, pos, context, lineObj, bias) { - if (!lineObj) lineObj = getLine(cm.doc, pos.line); - return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, bias), context); - } - - // Returns a box for a given cursor position, which may have an - // 'other' property containing the position of the secondary cursor - // on a bidi boundary. - function cursorCoords(cm, pos, context, lineObj, preparedMeasure, varHeight) { - lineObj = lineObj || getLine(cm.doc, pos.line); - if (!preparedMeasure) preparedMeasure = prepareMeasureForLine(cm, lineObj); - function get(ch, right) { - var m = measureCharPrepared(cm, preparedMeasure, ch, right ? "right" : "left", varHeight); - if (right) m.left = m.right; else m.right = m.left; - return intoCoordSystem(cm, lineObj, m, context); - } - function getBidi(ch, partPos) { - var part = order[partPos], right = part.level % 2; - if (ch == bidiLeft(part) && partPos && part.level < order[partPos - 1].level) { - part = order[--partPos]; - ch = bidiRight(part) - (part.level % 2 ? 0 : 1); - right = true; - } else if (ch == bidiRight(part) && partPos < order.length - 1 && part.level < order[partPos + 1].level) { - part = order[++partPos]; - ch = bidiLeft(part) - part.level % 2; - right = false; - } - if (right && ch == part.to && ch > part.from) return get(ch - 1); - return get(ch, right); - } - var order = getOrder(lineObj), ch = pos.ch; - if (!order) return get(ch); - var partPos = getBidiPartAt(order, ch); - var val = getBidi(ch, partPos); - if (bidiOther != null) val.other = getBidi(ch, bidiOther); - return val; - } - - // Used to cheaply estimate the coordinates for a position. Used for - // intermediate scroll updates. - function estimateCoords(cm, pos) { - var left = 0, pos = clipPos(cm.doc, pos); - if (!cm.options.lineWrapping) left = charWidth(cm.display) * pos.ch; - var lineObj = getLine(cm.doc, pos.line); - var top = heightAtLine(lineObj) + paddingTop(cm.display); - return {left: left, right: left, top: top, bottom: top + lineObj.height}; - } - - // Positions returned by coordsChar contain some extra information. - // xRel is the relative x position of the input coordinates compared - // to the found position (so xRel > 0 means the coordinates are to - // the right of the character position, for example). When outside - // is true, that means the coordinates lie outside the line's - // vertical range. - function PosWithInfo(line, ch, outside, xRel) { - var pos = Pos(line, ch); - pos.xRel = xRel; - if (outside) pos.outside = true; - return pos; - } - - // Compute the character position closest to the given coordinates. - // Input must be lineSpace-local ("div" coordinate system). - function coordsChar(cm, x, y) { - var doc = cm.doc; - y += cm.display.viewOffset; - if (y < 0) return PosWithInfo(doc.first, 0, true, -1); - var lineN = lineAtHeight(doc, y), last = doc.first + doc.size - 1; - if (lineN > last) - return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, true, 1); - if (x < 0) x = 0; - - var lineObj = getLine(doc, lineN); - for (;;) { - var found = coordsCharInner(cm, lineObj, lineN, x, y); - var merged = collapsedSpanAtEnd(lineObj); - var mergedPos = merged && merged.find(0, true); - if (merged && (found.ch > mergedPos.from.ch || found.ch == mergedPos.from.ch && found.xRel > 0)) - lineN = lineNo(lineObj = mergedPos.to.line); - else - return found; - } - } - - function coordsCharInner(cm, lineObj, lineNo, x, y) { - var innerOff = y - heightAtLine(lineObj); - var wrongLine = false, adjust = 2 * cm.display.wrapper.clientWidth; - var preparedMeasure = prepareMeasureForLine(cm, lineObj); - - function getX(ch) { - var sp = cursorCoords(cm, Pos(lineNo, ch), "line", lineObj, preparedMeasure); - wrongLine = true; - if (innerOff > sp.bottom) return sp.left - adjust; - else if (innerOff < sp.top) return sp.left + adjust; - else wrongLine = false; - return sp.left; - } - - var bidi = getOrder(lineObj), dist = lineObj.text.length; - var from = lineLeft(lineObj), to = lineRight(lineObj); - var fromX = getX(from), fromOutside = wrongLine, toX = getX(to), toOutside = wrongLine; - - if (x > toX) return PosWithInfo(lineNo, to, toOutside, 1); - // Do a binary search between these bounds. - for (;;) { - if (bidi ? to == from || to == moveVisually(lineObj, from, 1) : to - from <= 1) { - var ch = x < fromX || x - fromX <= toX - x ? from : to; - var xDiff = x - (ch == from ? fromX : toX); - while (isExtendingChar(lineObj.text.charAt(ch))) ++ch; - var pos = PosWithInfo(lineNo, ch, ch == from ? fromOutside : toOutside, - xDiff < -1 ? -1 : xDiff > 1 ? 1 : 0); - return pos; - } - var step = Math.ceil(dist / 2), middle = from + step; - if (bidi) { - middle = from; - for (var i = 0; i < step; ++i) middle = moveVisually(lineObj, middle, 1); - } - var middleX = getX(middle); - if (middleX > x) {to = middle; toX = middleX; if (toOutside = wrongLine) toX += 1000; dist = step;} - else {from = middle; fromX = middleX; fromOutside = wrongLine; dist -= step;} - } - } - - var measureText; - // Compute the default text height. - function textHeight(display) { - if (display.cachedTextHeight != null) return display.cachedTextHeight; - if (measureText == null) { - measureText = elt("pre"); - // Measure a bunch of lines, for browsers that compute - // fractional heights. - for (var i = 0; i < 49; ++i) { - measureText.appendChild(document.createTextNode("x")); - measureText.appendChild(elt("br")); - } - measureText.appendChild(document.createTextNode("x")); - } - removeChildrenAndAdd(display.measure, measureText); - var height = measureText.offsetHeight / 50; - if (height > 3) display.cachedTextHeight = height; - removeChildren(display.measure); - return height || 1; - } - - // Compute the default character width. - function charWidth(display) { - if (display.cachedCharWidth != null) return display.cachedCharWidth; - var anchor = elt("span", "xxxxxxxxxx"); - var pre = elt("pre", [anchor]); - removeChildrenAndAdd(display.measure, pre); - var rect = anchor.getBoundingClientRect(), width = (rect.right - rect.left) / 10; - if (width > 2) display.cachedCharWidth = width; - return width || 10; - } - - // OPERATIONS - - // Operations are used to wrap a series of changes to the editor - // state in such a way that each change won't have to update the - // cursor and display (which would be awkward, slow, and - // error-prone). Instead, display updates are batched and then all - // combined and executed at once. - - var operationGroup = null; - - var nextOpId = 0; - // Start a new operation. - function startOperation(cm) { - cm.curOp = { - cm: cm, - viewChanged: false, // Flag that indicates that lines might need to be redrawn - startHeight: cm.doc.height, // Used to detect need to update scrollbar - forceUpdate: false, // Used to force a redraw - updateInput: null, // Whether to reset the input textarea - typing: false, // Whether this reset should be careful to leave existing text (for compositing) - changeObjs: null, // Accumulated changes, for firing change events - cursorActivityHandlers: null, // Set of handlers to fire cursorActivity on - cursorActivityCalled: 0, // Tracks which cursorActivity handlers have been called already - selectionChanged: false, // Whether the selection needs to be redrawn - updateMaxLine: false, // Set when the widest line needs to be determined anew - scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet - scrollToPos: null, // Used to scroll to a specific position - focus: false, - id: ++nextOpId // Unique ID - }; - if (operationGroup) { - operationGroup.ops.push(cm.curOp); - } else { - cm.curOp.ownsGroup = operationGroup = { - ops: [cm.curOp], - delayedCallbacks: [] - }; - } - } - - function fireCallbacksForOps(group) { - // Calls delayed callbacks and cursorActivity handlers until no - // new ones appear - var callbacks = group.delayedCallbacks, i = 0; - do { - for (; i < callbacks.length; i++) - callbacks[i].call(null); - for (var j = 0; j < group.ops.length; j++) { - var op = group.ops[j]; - if (op.cursorActivityHandlers) - while (op.cursorActivityCalled < op.cursorActivityHandlers.length) - op.cursorActivityHandlers[op.cursorActivityCalled++].call(null, op.cm); - } - } while (i < callbacks.length); - } - - // Finish an operation, updating the display and signalling delayed events - function endOperation(cm) { - var op = cm.curOp, group = op.ownsGroup; - if (!group) return; - - try { fireCallbacksForOps(group); } - finally { - operationGroup = null; - for (var i = 0; i < group.ops.length; i++) - group.ops[i].cm.curOp = null; - endOperations(group); - } - } - - // The DOM updates done when an operation finishes are batched so - // that the minimum number of relayouts are required. - function endOperations(group) { - var ops = group.ops; - for (var i = 0; i < ops.length; i++) // Read DOM - endOperation_R1(ops[i]); - for (var i = 0; i < ops.length; i++) // Write DOM (maybe) - endOperation_W1(ops[i]); - for (var i = 0; i < ops.length; i++) // Read DOM - endOperation_R2(ops[i]); - for (var i = 0; i < ops.length; i++) // Write DOM (maybe) - endOperation_W2(ops[i]); - for (var i = 0; i < ops.length; i++) // Read DOM - endOperation_finish(ops[i]); - } - - function endOperation_R1(op) { - var cm = op.cm, display = cm.display; - maybeClipScrollbars(cm); - if (op.updateMaxLine) findMaxLine(cm); - - op.mustUpdate = op.viewChanged || op.forceUpdate || op.scrollTop != null || - op.scrollToPos && (op.scrollToPos.from.line < display.viewFrom || - op.scrollToPos.to.line >= display.viewTo) || - display.maxLineChanged && cm.options.lineWrapping; - op.update = op.mustUpdate && - new DisplayUpdate(cm, op.mustUpdate && {top: op.scrollTop, ensure: op.scrollToPos}, op.forceUpdate); - } - - function endOperation_W1(op) { - op.updatedDisplay = op.mustUpdate && updateDisplayIfNeeded(op.cm, op.update); - } - - function endOperation_R2(op) { - var cm = op.cm, display = cm.display; - if (op.updatedDisplay) updateHeightsInViewport(cm); - - op.barMeasure = measureForScrollbars(cm); - - // If the max line changed since it was last measured, measure it, - // and ensure the document's width matches it. - // updateDisplay_W2 will use these properties to do the actual resizing - if (display.maxLineChanged && !cm.options.lineWrapping) { - op.adjustWidthTo = measureChar(cm, display.maxLine, display.maxLine.text.length).left + 3; - cm.display.sizerWidth = op.adjustWidthTo; - op.barMeasure.scrollWidth = - Math.max(display.scroller.clientWidth, display.sizer.offsetLeft + op.adjustWidthTo + scrollGap(cm) + cm.display.barWidth); - op.maxScrollLeft = Math.max(0, display.sizer.offsetLeft + op.adjustWidthTo - displayWidth(cm)); - } - - if (op.updatedDisplay || op.selectionChanged) - op.preparedSelection = display.input.prepareSelection(); - } - - function endOperation_W2(op) { - var cm = op.cm; - - if (op.adjustWidthTo != null) { - cm.display.sizer.style.minWidth = op.adjustWidthTo + "px"; - if (op.maxScrollLeft < cm.doc.scrollLeft) - setScrollLeft(cm, Math.min(cm.display.scroller.scrollLeft, op.maxScrollLeft), true); - cm.display.maxLineChanged = false; - } - - if (op.preparedSelection) - cm.display.input.showSelection(op.preparedSelection); - if (op.updatedDisplay) - setDocumentHeight(cm, op.barMeasure); - if (op.updatedDisplay || op.startHeight != cm.doc.height) - updateScrollbars(cm, op.barMeasure); - - if (op.selectionChanged) restartBlink(cm); - - if (cm.state.focused && op.updateInput) - cm.display.input.reset(op.typing); - if (op.focus && op.focus == activeElt() && (!document.hasFocus || document.hasFocus())) - ensureFocus(op.cm); - } - - function endOperation_finish(op) { - var cm = op.cm, display = cm.display, doc = cm.doc; - - if (op.updatedDisplay) postUpdateDisplay(cm, op.update); - - // Abort mouse wheel delta measurement, when scrolling explicitly - if (display.wheelStartX != null && (op.scrollTop != null || op.scrollLeft != null || op.scrollToPos)) - display.wheelStartX = display.wheelStartY = null; - - // Propagate the scroll position to the actual DOM scroller - if (op.scrollTop != null && (display.scroller.scrollTop != op.scrollTop || op.forceScroll)) { - doc.scrollTop = Math.max(0, Math.min(display.scroller.scrollHeight - display.scroller.clientHeight, op.scrollTop)); - display.scrollbars.setScrollTop(doc.scrollTop); - display.scroller.scrollTop = doc.scrollTop; - } - if (op.scrollLeft != null && (display.scroller.scrollLeft != op.scrollLeft || op.forceScroll)) { - doc.scrollLeft = Math.max(0, Math.min(display.scroller.scrollWidth - displayWidth(cm), op.scrollLeft)); - display.scrollbars.setScrollLeft(doc.scrollLeft); - display.scroller.scrollLeft = doc.scrollLeft; - alignHorizontally(cm); - } - // If we need to scroll a specific position into view, do so. - if (op.scrollToPos) { - var coords = scrollPosIntoView(cm, clipPos(doc, op.scrollToPos.from), - clipPos(doc, op.scrollToPos.to), op.scrollToPos.margin); - if (op.scrollToPos.isCursor && cm.state.focused) maybeScrollWindow(cm, coords); - } - - // Fire events for markers that are hidden/unidden by editing or - // undoing - var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers; - if (hidden) for (var i = 0; i < hidden.length; ++i) - if (!hidden[i].lines.length) signal(hidden[i], "hide"); - if (unhidden) for (var i = 0; i < unhidden.length; ++i) - if (unhidden[i].lines.length) signal(unhidden[i], "unhide"); - - if (display.wrapper.offsetHeight) - doc.scrollTop = cm.display.scroller.scrollTop; - - // Fire change events, and delayed event handlers - if (op.changeObjs) - signal(cm, "changes", cm, op.changeObjs); - if (op.update) - op.update.finish(); - } - - // Run the given function in an operation - function runInOp(cm, f) { - if (cm.curOp) return f(); - startOperation(cm); - try { return f(); } - finally { endOperation(cm); } - } - // Wraps a function in an operation. Returns the wrapped function. - function operation(cm, f) { - return function() { - if (cm.curOp) return f.apply(cm, arguments); - startOperation(cm); - try { return f.apply(cm, arguments); } - finally { endOperation(cm); } - }; - } - // Used to add methods to editor and doc instances, wrapping them in - // operations. - function methodOp(f) { - return function() { - if (this.curOp) return f.apply(this, arguments); - startOperation(this); - try { return f.apply(this, arguments); } - finally { endOperation(this); } - }; - } - function docMethodOp(f) { - return function() { - var cm = this.cm; - if (!cm || cm.curOp) return f.apply(this, arguments); - startOperation(cm); - try { return f.apply(this, arguments); } - finally { endOperation(cm); } - }; - } - - // VIEW TRACKING - - // These objects are used to represent the visible (currently drawn) - // part of the document. A LineView may correspond to multiple - // logical lines, if those are connected by collapsed ranges. - function LineView(doc, line, lineN) { - // The starting line - this.line = line; - // Continuing lines, if any - this.rest = visualLineContinued(line); - // Number of logical lines in this visual line - this.size = this.rest ? lineNo(lst(this.rest)) - lineN + 1 : 1; - this.node = this.text = null; - this.hidden = lineIsHidden(doc, line); - } - - // Create a range of LineView objects for the given lines. - function buildViewArray(cm, from, to) { - var array = [], nextPos; - for (var pos = from; pos < to; pos = nextPos) { - var view = new LineView(cm.doc, getLine(cm.doc, pos), pos); - nextPos = pos + view.size; - array.push(view); - } - return array; - } - - // Updates the display.view data structure for a given change to the - // document. From and to are in pre-change coordinates. Lendiff is - // the amount of lines added or subtracted by the change. This is - // used for changes that span multiple lines, or change the way - // lines are divided into visual lines. regLineChange (below) - // registers single-line changes. - function regChange(cm, from, to, lendiff) { - if (from == null) from = cm.doc.first; - if (to == null) to = cm.doc.first + cm.doc.size; - if (!lendiff) lendiff = 0; - - var display = cm.display; - if (lendiff && to < display.viewTo && - (display.updateLineNumbers == null || display.updateLineNumbers > from)) - display.updateLineNumbers = from; - - cm.curOp.viewChanged = true; - - if (from >= display.viewTo) { // Change after - if (sawCollapsedSpans && visualLineNo(cm.doc, from) < display.viewTo) - resetView(cm); - } else if (to <= display.viewFrom) { // Change before - if (sawCollapsedSpans && visualLineEndNo(cm.doc, to + lendiff) > display.viewFrom) { - resetView(cm); - } else { - display.viewFrom += lendiff; - display.viewTo += lendiff; - } - } else if (from <= display.viewFrom && to >= display.viewTo) { // Full overlap - resetView(cm); - } else if (from <= display.viewFrom) { // Top overlap - var cut = viewCuttingPoint(cm, to, to + lendiff, 1); - if (cut) { - display.view = display.view.slice(cut.index); - display.viewFrom = cut.lineN; - display.viewTo += lendiff; - } else { - resetView(cm); - } - } else if (to >= display.viewTo) { // Bottom overlap - var cut = viewCuttingPoint(cm, from, from, -1); - if (cut) { - display.view = display.view.slice(0, cut.index); - display.viewTo = cut.lineN; - } else { - resetView(cm); - } - } else { // Gap in the middle - var cutTop = viewCuttingPoint(cm, from, from, -1); - var cutBot = viewCuttingPoint(cm, to, to + lendiff, 1); - if (cutTop && cutBot) { - display.view = display.view.slice(0, cutTop.index) - .concat(buildViewArray(cm, cutTop.lineN, cutBot.lineN)) - .concat(display.view.slice(cutBot.index)); - display.viewTo += lendiff; - } else { - resetView(cm); - } - } - - var ext = display.externalMeasured; - if (ext) { - if (to < ext.lineN) - ext.lineN += lendiff; - else if (from < ext.lineN + ext.size) - display.externalMeasured = null; - } - } - - // Register a change to a single line. Type must be one of "text", - // "gutter", "class", "widget" - function regLineChange(cm, line, type) { - cm.curOp.viewChanged = true; - var display = cm.display, ext = cm.display.externalMeasured; - if (ext && line >= ext.lineN && line < ext.lineN + ext.size) - display.externalMeasured = null; - - if (line < display.viewFrom || line >= display.viewTo) return; - var lineView = display.view[findViewIndex(cm, line)]; - if (lineView.node == null) return; - var arr = lineView.changes || (lineView.changes = []); - if (indexOf(arr, type) == -1) arr.push(type); - } - - // Clear the view. - function resetView(cm) { - cm.display.viewFrom = cm.display.viewTo = cm.doc.first; - cm.display.view = []; - cm.display.viewOffset = 0; - } - - // Find the view element corresponding to a given line. Return null - // when the line isn't visible. - function findViewIndex(cm, n) { - if (n >= cm.display.viewTo) return null; - n -= cm.display.viewFrom; - if (n < 0) return null; - var view = cm.display.view; - for (var i = 0; i < view.length; i++) { - n -= view[i].size; - if (n < 0) return i; - } - } - - function viewCuttingPoint(cm, oldN, newN, dir) { - var index = findViewIndex(cm, oldN), diff, view = cm.display.view; - if (!sawCollapsedSpans || newN == cm.doc.first + cm.doc.size) - return {index: index, lineN: newN}; - for (var i = 0, n = cm.display.viewFrom; i < index; i++) - n += view[i].size; - if (n != oldN) { - if (dir > 0) { - if (index == view.length - 1) return null; - diff = (n + view[index].size) - oldN; - index++; - } else { - diff = n - oldN; - } - oldN += diff; newN += diff; - } - while (visualLineNo(cm.doc, newN) != newN) { - if (index == (dir < 0 ? 0 : view.length - 1)) return null; - newN += dir * view[index - (dir < 0 ? 1 : 0)].size; - index += dir; - } - return {index: index, lineN: newN}; - } - - // Force the view to cover a given range, adding empty view element - // or clipping off existing ones as needed. - function adjustView(cm, from, to) { - var display = cm.display, view = display.view; - if (view.length == 0 || from >= display.viewTo || to <= display.viewFrom) { - display.view = buildViewArray(cm, from, to); - display.viewFrom = from; - } else { - if (display.viewFrom > from) - display.view = buildViewArray(cm, from, display.viewFrom).concat(display.view); - else if (display.viewFrom < from) - display.view = display.view.slice(findViewIndex(cm, from)); - display.viewFrom = from; - if (display.viewTo < to) - display.view = display.view.concat(buildViewArray(cm, display.viewTo, to)); - else if (display.viewTo > to) - display.view = display.view.slice(0, findViewIndex(cm, to)); - } - display.viewTo = to; - } - - // Count the number of lines in the view whose DOM representation is - // out of date (or nonexistent). - function countDirtyView(cm) { - var view = cm.display.view, dirty = 0; - for (var i = 0; i < view.length; i++) { - var lineView = view[i]; - if (!lineView.hidden && (!lineView.node || lineView.changes)) ++dirty; - } - return dirty; - } - - // EVENT HANDLERS - - // Attach the necessary event handlers when initializing the editor - function registerEventHandlers(cm) { - var d = cm.display; - on(d.scroller, "mousedown", operation(cm, onMouseDown)); - // Older IE's will not fire a second mousedown for a double click - if (ie && ie_version < 11) - on(d.scroller, "dblclick", operation(cm, function(e) { - if (signalDOMEvent(cm, e)) return; - var pos = posFromMouse(cm, e); - if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) return; - e_preventDefault(e); - var word = cm.findWordAt(pos); - extendSelection(cm.doc, word.anchor, word.head); - })); - else - on(d.scroller, "dblclick", function(e) { signalDOMEvent(cm, e) || e_preventDefault(e); }); - // Some browsers fire contextmenu *after* opening the menu, at - // which point we can't mess with it anymore. Context menu is - // handled in onMouseDown for these browsers. - if (!captureRightClick) on(d.scroller, "contextmenu", function(e) {onContextMenu(cm, e);}); - - // Used to suppress mouse event handling when a touch happens - var touchFinished, prevTouch = {end: 0}; - function finishTouch() { - if (d.activeTouch) { - touchFinished = setTimeout(function() {d.activeTouch = null;}, 1000); - prevTouch = d.activeTouch; - prevTouch.end = +new Date; - } - }; - function isMouseLikeTouchEvent(e) { - if (e.touches.length != 1) return false; - var touch = e.touches[0]; - return touch.radiusX <= 1 && touch.radiusY <= 1; - } - function farAway(touch, other) { - if (other.left == null) return true; - var dx = other.left - touch.left, dy = other.top - touch.top; - return dx * dx + dy * dy > 20 * 20; - } - on(d.scroller, "touchstart", function(e) { - if (!isMouseLikeTouchEvent(e)) { - clearTimeout(touchFinished); - var now = +new Date; - d.activeTouch = {start: now, moved: false, - prev: now - prevTouch.end <= 300 ? prevTouch : null}; - if (e.touches.length == 1) { - d.activeTouch.left = e.touches[0].pageX; - d.activeTouch.top = e.touches[0].pageY; - } - } - }); - on(d.scroller, "touchmove", function() { - if (d.activeTouch) d.activeTouch.moved = true; - }); - on(d.scroller, "touchend", function(e) { - var touch = d.activeTouch; - if (touch && !eventInWidget(d, e) && touch.left != null && - !touch.moved && new Date - touch.start < 300) { - var pos = cm.coordsChar(d.activeTouch, "page"), range; - if (!touch.prev || farAway(touch, touch.prev)) // Single tap - range = new Range(pos, pos); - else if (!touch.prev.prev || farAway(touch, touch.prev.prev)) // Double tap - range = cm.findWordAt(pos); - else // Triple tap - range = new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0))); - cm.setSelection(range.anchor, range.head); - cm.focus(); - e_preventDefault(e); - } - finishTouch(); - }); - on(d.scroller, "touchcancel", finishTouch); - - // Sync scrolling between fake scrollbars and real scrollable - // area, ensure viewport is updated when scrolling. - on(d.scroller, "scroll", function() { - if (d.scroller.clientHeight) { - setScrollTop(cm, d.scroller.scrollTop); - setScrollLeft(cm, d.scroller.scrollLeft, true); - signal(cm, "scroll", cm); - } - }); - - // Listen to wheel events in order to try and update the viewport on time. - on(d.scroller, "mousewheel", function(e){onScrollWheel(cm, e);}); - on(d.scroller, "DOMMouseScroll", function(e){onScrollWheel(cm, e);}); - - // Prevent wrapper from ever scrolling - on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; }); - - d.dragFunctions = { - enter: function(e) {if (!signalDOMEvent(cm, e)) e_stop(e);}, - over: function(e) {if (!signalDOMEvent(cm, e)) { onDragOver(cm, e); e_stop(e); }}, - start: function(e){onDragStart(cm, e);}, - drop: operation(cm, onDrop), - leave: function() {clearDragCursor(cm);} - }; - - var inp = d.input.getField(); - on(inp, "keyup", function(e) { onKeyUp.call(cm, e); }); - on(inp, "keydown", operation(cm, onKeyDown)); - on(inp, "keypress", operation(cm, onKeyPress)); - on(inp, "focus", bind(onFocus, cm)); - on(inp, "blur", bind(onBlur, cm)); - } - - function dragDropChanged(cm, value, old) { - var wasOn = old && old != CodeMirror.Init; - if (!value != !wasOn) { - var funcs = cm.display.dragFunctions; - var toggle = value ? on : off; - toggle(cm.display.scroller, "dragstart", funcs.start); - toggle(cm.display.scroller, "dragenter", funcs.enter); - toggle(cm.display.scroller, "dragover", funcs.over); - toggle(cm.display.scroller, "dragleave", funcs.leave); - toggle(cm.display.scroller, "drop", funcs.drop); - } - } - - // Called when the window resizes - function onResize(cm) { - var d = cm.display; - if (d.lastWrapHeight == d.wrapper.clientHeight && d.lastWrapWidth == d.wrapper.clientWidth) - return; - // Might be a text scaling operation, clear size caches. - d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null; - d.scrollbarsClipped = false; - cm.setSize(); - } - - // MOUSE EVENTS - - // Return true when the given mouse event happened in a widget - function eventInWidget(display, e) { - for (var n = e_target(e); n != display.wrapper; n = n.parentNode) { - if (!n || (n.nodeType == 1 && n.getAttribute("cm-ignore-events") == "true") || - (n.parentNode == display.sizer && n != display.mover)) - return true; - } - } - - // Given a mouse event, find the corresponding position. If liberal - // is false, it checks whether a gutter or scrollbar was clicked, - // and returns null if it was. forRect is used by rectangular - // selections, and tries to estimate a character position even for - // coordinates beyond the right of the text. - function posFromMouse(cm, e, liberal, forRect) { - var display = cm.display; - if (!liberal && e_target(e).getAttribute("cm-not-content") == "true") return null; - - var x, y, space = display.lineSpace.getBoundingClientRect(); - // Fails unpredictably on IE[67] when mouse is dragged around quickly. - try { x = e.clientX - space.left; y = e.clientY - space.top; } - catch (e) { return null; } - var coords = coordsChar(cm, x, y), line; - if (forRect && coords.xRel == 1 && (line = getLine(cm.doc, coords.line).text).length == coords.ch) { - var colDiff = countColumn(line, line.length, cm.options.tabSize) - line.length; - coords = Pos(coords.line, Math.max(0, Math.round((x - paddingH(cm.display).left) / charWidth(cm.display)) - colDiff)); - } - return coords; - } - - // A mouse down can be a single click, double click, triple click, - // start of selection drag, start of text drag, new cursor - // (ctrl-click), rectangle drag (alt-drag), or xwin - // middle-click-paste. Or it might be a click on something we should - // not interfere with, such as a scrollbar or widget. - function onMouseDown(e) { - var cm = this, display = cm.display; - if (display.activeTouch && display.input.supportsTouch() || signalDOMEvent(cm, e)) return; - display.shift = e.shiftKey; - - if (eventInWidget(display, e)) { - if (!webkit) { - // Briefly turn off draggability, to allow widgets to do - // normal dragging things. - display.scroller.draggable = false; - setTimeout(function(){display.scroller.draggable = true;}, 100); - } - return; - } - if (clickInGutter(cm, e)) return; - var start = posFromMouse(cm, e); - window.focus(); - - switch (e_button(e)) { - case 1: - // #3261: make sure, that we're not starting a second selection - if (cm.state.selectingText) - cm.state.selectingText(e); - else if (start) - leftButtonDown(cm, e, start); - else if (e_target(e) == display.scroller) - e_preventDefault(e); - break; - case 2: - if (webkit) cm.state.lastMiddleDown = +new Date; - if (start) extendSelection(cm.doc, start); - setTimeout(function() {display.input.focus();}, 20); - e_preventDefault(e); - break; - case 3: - if (captureRightClick) onContextMenu(cm, e); - else delayBlurEvent(cm); - break; - } - } - - var lastClick, lastDoubleClick; - function leftButtonDown(cm, e, start) { - if (ie) setTimeout(bind(ensureFocus, cm), 0); - else cm.curOp.focus = activeElt(); - - var now = +new Date, type; - if (lastDoubleClick && lastDoubleClick.time > now - 400 && cmp(lastDoubleClick.pos, start) == 0) { - type = "triple"; - } else if (lastClick && lastClick.time > now - 400 && cmp(lastClick.pos, start) == 0) { - type = "double"; - lastDoubleClick = {time: now, pos: start}; - } else { - type = "single"; - lastClick = {time: now, pos: start}; - } - - var sel = cm.doc.sel, modifier = mac ? e.metaKey : e.ctrlKey, contained; - if (cm.options.dragDrop && dragAndDrop && !isReadOnly(cm) && - type == "single" && (contained = sel.contains(start)) > -1 && - (cmp((contained = sel.ranges[contained]).from(), start) < 0 || start.xRel > 0) && - (cmp(contained.to(), start) > 0 || start.xRel < 0)) - leftButtonStartDrag(cm, e, start, modifier); - else - leftButtonSelect(cm, e, start, type, modifier); - } - - // Start a text drag. When it ends, see if any dragging actually - // happen, and treat as a click if it didn't. - function leftButtonStartDrag(cm, e, start, modifier) { - var display = cm.display, startTime = +new Date; - var dragEnd = operation(cm, function(e2) { - if (webkit) display.scroller.draggable = false; - cm.state.draggingText = false; - off(document, "mouseup", dragEnd); - off(display.scroller, "drop", dragEnd); - if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) { - e_preventDefault(e2); - if (!modifier && +new Date - 200 < startTime) - extendSelection(cm.doc, start); - // Work around unexplainable focus problem in IE9 (#2127) and Chrome (#3081) - if (webkit || ie && ie_version == 9) - setTimeout(function() {document.body.focus(); display.input.focus();}, 20); - else - display.input.focus(); - } - }); - // Let the drag handler handle this. - if (webkit) display.scroller.draggable = true; - cm.state.draggingText = dragEnd; - // IE's approach to draggable - if (display.scroller.dragDrop) display.scroller.dragDrop(); - on(document, "mouseup", dragEnd); - on(display.scroller, "drop", dragEnd); - } - - // Normal selection, as opposed to text dragging. - function leftButtonSelect(cm, e, start, type, addNew) { - var display = cm.display, doc = cm.doc; - e_preventDefault(e); - - var ourRange, ourIndex, startSel = doc.sel, ranges = startSel.ranges; - if (addNew && !e.shiftKey) { - ourIndex = doc.sel.contains(start); - if (ourIndex > -1) - ourRange = ranges[ourIndex]; - else - ourRange = new Range(start, start); - } else { - ourRange = doc.sel.primary(); - ourIndex = doc.sel.primIndex; - } - - if (e.altKey) { - type = "rect"; - if (!addNew) ourRange = new Range(start, start); - start = posFromMouse(cm, e, true, true); - ourIndex = -1; - } else if (type == "double") { - var word = cm.findWordAt(start); - if (cm.display.shift || doc.extend) - ourRange = extendRange(doc, ourRange, word.anchor, word.head); - else - ourRange = word; - } else if (type == "triple") { - var line = new Range(Pos(start.line, 0), clipPos(doc, Pos(start.line + 1, 0))); - if (cm.display.shift || doc.extend) - ourRange = extendRange(doc, ourRange, line.anchor, line.head); - else - ourRange = line; - } else { - ourRange = extendRange(doc, ourRange, start); - } - - if (!addNew) { - ourIndex = 0; - setSelection(doc, new Selection([ourRange], 0), sel_mouse); - startSel = doc.sel; - } else if (ourIndex == -1) { - ourIndex = ranges.length; - setSelection(doc, normalizeSelection(ranges.concat([ourRange]), ourIndex), - {scroll: false, origin: "*mouse"}); - } else if (ranges.length > 1 && ranges[ourIndex].empty() && type == "single" && !e.shiftKey) { - setSelection(doc, normalizeSelection(ranges.slice(0, ourIndex).concat(ranges.slice(ourIndex + 1)), 0), - {scroll: false, origin: "*mouse"}); - startSel = doc.sel; - } else { - replaceOneSelection(doc, ourIndex, ourRange, sel_mouse); - } - - var lastPos = start; - function extendTo(pos) { - if (cmp(lastPos, pos) == 0) return; - lastPos = pos; - - if (type == "rect") { - var ranges = [], tabSize = cm.options.tabSize; - var startCol = countColumn(getLine(doc, start.line).text, start.ch, tabSize); - var posCol = countColumn(getLine(doc, pos.line).text, pos.ch, tabSize); - var left = Math.min(startCol, posCol), right = Math.max(startCol, posCol); - for (var line = Math.min(start.line, pos.line), end = Math.min(cm.lastLine(), Math.max(start.line, pos.line)); - line <= end; line++) { - var text = getLine(doc, line).text, leftPos = findColumn(text, left, tabSize); - if (left == right) - ranges.push(new Range(Pos(line, leftPos), Pos(line, leftPos))); - else if (text.length > leftPos) - ranges.push(new Range(Pos(line, leftPos), Pos(line, findColumn(text, right, tabSize)))); - } - if (!ranges.length) ranges.push(new Range(start, start)); - setSelection(doc, normalizeSelection(startSel.ranges.slice(0, ourIndex).concat(ranges), ourIndex), - {origin: "*mouse", scroll: false}); - cm.scrollIntoView(pos); - } else { - var oldRange = ourRange; - var anchor = oldRange.anchor, head = pos; - if (type != "single") { - if (type == "double") - var range = cm.findWordAt(pos); - else - var range = new Range(Pos(pos.line, 0), clipPos(doc, Pos(pos.line + 1, 0))); - if (cmp(range.anchor, anchor) > 0) { - head = range.head; - anchor = minPos(oldRange.from(), range.anchor); - } else { - head = range.anchor; - anchor = maxPos(oldRange.to(), range.head); - } - } - var ranges = startSel.ranges.slice(0); - ranges[ourIndex] = new Range(clipPos(doc, anchor), head); - setSelection(doc, normalizeSelection(ranges, ourIndex), sel_mouse); - } - } - - var editorSize = display.wrapper.getBoundingClientRect(); - // Used to ensure timeout re-tries don't fire when another extend - // happened in the meantime (clearTimeout isn't reliable -- at - // least on Chrome, the timeouts still happen even when cleared, - // if the clear happens after their scheduled firing time). - var counter = 0; - - function extend(e) { - var curCount = ++counter; - var cur = posFromMouse(cm, e, true, type == "rect"); - if (!cur) return; - if (cmp(cur, lastPos) != 0) { - cm.curOp.focus = activeElt(); - extendTo(cur); - var visible = visibleLines(display, doc); - if (cur.line >= visible.to || cur.line < visible.from) - setTimeout(operation(cm, function(){if (counter == curCount) extend(e);}), 150); - } else { - var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0; - if (outside) setTimeout(operation(cm, function() { - if (counter != curCount) return; - display.scroller.scrollTop += outside; - extend(e); - }), 50); - } - } - - function done(e) { - cm.state.selectingText = false; - counter = Infinity; - e_preventDefault(e); - display.input.focus(); - off(document, "mousemove", move); - off(document, "mouseup", up); - doc.history.lastSelOrigin = null; - } - - var move = operation(cm, function(e) { - if (!e_button(e)) done(e); - else extend(e); - }); - var up = operation(cm, done); - cm.state.selectingText = up; - on(document, "mousemove", move); - on(document, "mouseup", up); - } - - // Determines whether an event happened in the gutter, and fires the - // handlers for the corresponding event. - function gutterEvent(cm, e, type, prevent) { - try { var mX = e.clientX, mY = e.clientY; } - catch(e) { return false; } - if (mX >= Math.floor(cm.display.gutters.getBoundingClientRect().right)) return false; - if (prevent) e_preventDefault(e); - - var display = cm.display; - var lineBox = display.lineDiv.getBoundingClientRect(); - - if (mY > lineBox.bottom || !hasHandler(cm, type)) return e_defaultPrevented(e); - mY -= lineBox.top - display.viewOffset; - - for (var i = 0; i < cm.options.gutters.length; ++i) { - var g = display.gutters.childNodes[i]; - if (g && g.getBoundingClientRect().right >= mX) { - var line = lineAtHeight(cm.doc, mY); - var gutter = cm.options.gutters[i]; - signal(cm, type, cm, line, gutter, e); - return e_defaultPrevented(e); - } - } - } - - function clickInGutter(cm, e) { - return gutterEvent(cm, e, "gutterClick", true); - } - - // Kludge to work around strange IE behavior where it'll sometimes - // re-fire a series of drag-related events right after the drop (#1551) - var lastDrop = 0; - - function onDrop(e) { - var cm = this; - clearDragCursor(cm); - if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) - return; - e_preventDefault(e); - if (ie) lastDrop = +new Date; - var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files; - if (!pos || isReadOnly(cm)) return; - // Might be a file drop, in which case we simply extract the text - // and insert it. - if (files && files.length && window.FileReader && window.File) { - var n = files.length, text = Array(n), read = 0; - var loadFile = function(file, i) { - if (cm.options.allowDropFileTypes && - indexOf(cm.options.allowDropFileTypes, file.type) == -1) - return; - - var reader = new FileReader; - reader.onload = operation(cm, function() { - var content = reader.result; - if (/[\x00-\x08\x0e-\x1f]{2}/.test(content)) content = ""; - text[i] = content; - if (++read == n) { - pos = clipPos(cm.doc, pos); - var change = {from: pos, to: pos, - text: cm.doc.splitLines(text.join(cm.doc.lineSeparator())), - origin: "paste"}; - makeChange(cm.doc, change); - setSelectionReplaceHistory(cm.doc, simpleSelection(pos, changeEnd(change))); - } - }); - reader.readAsText(file); - }; - for (var i = 0; i < n; ++i) loadFile(files[i], i); - } else { // Normal drop - // Don't do a replace if the drop happened inside of the selected text. - if (cm.state.draggingText && cm.doc.sel.contains(pos) > -1) { - cm.state.draggingText(e); - // Ensure the editor is re-focused - setTimeout(function() {cm.display.input.focus();}, 20); - return; - } - try { - var text = e.dataTransfer.getData("Text"); - if (text) { - if (cm.state.draggingText && !(mac ? e.altKey : e.ctrlKey)) - var selected = cm.listSelections(); - setSelectionNoUndo(cm.doc, simpleSelection(pos, pos)); - if (selected) for (var i = 0; i < selected.length; ++i) - replaceRange(cm.doc, "", selected[i].anchor, selected[i].head, "drag"); - cm.replaceSelection(text, "around", "paste"); - cm.display.input.focus(); - } - } - catch(e){} - } - } - - function onDragStart(cm, e) { - if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return; } - if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) return; - - e.dataTransfer.setData("Text", cm.getSelection()); - - // Use dummy image instead of default browsers image. - // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there. - if (e.dataTransfer.setDragImage && !safari) { - var img = elt("img", null, null, "position: fixed; left: 0; top: 0;"); - img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="; - if (presto) { - img.width = img.height = 1; - cm.display.wrapper.appendChild(img); - // Force a relayout, or Opera won't use our image for some obscure reason - img._top = img.offsetTop; - } - e.dataTransfer.setDragImage(img, 0, 0); - if (presto) img.parentNode.removeChild(img); - } - } - - function onDragOver(cm, e) { - var pos = posFromMouse(cm, e); - if (!pos) return; - var frag = document.createDocumentFragment(); - drawSelectionCursor(cm, pos, frag); - if (!cm.display.dragCursor) { - cm.display.dragCursor = elt("div", null, "CodeMirror-cursors CodeMirror-dragcursors"); - cm.display.lineSpace.insertBefore(cm.display.dragCursor, cm.display.cursorDiv); - } - removeChildrenAndAdd(cm.display.dragCursor, frag); - } - - function clearDragCursor(cm) { - if (cm.display.dragCursor) { - cm.display.lineSpace.removeChild(cm.display.dragCursor); - cm.display.dragCursor = null; - } - } - - // SCROLL EVENTS - - // Sync the scrollable area and scrollbars, ensure the viewport - // covers the visible area. - function setScrollTop(cm, val) { - if (Math.abs(cm.doc.scrollTop - val) < 2) return; - cm.doc.scrollTop = val; - if (!gecko) updateDisplaySimple(cm, {top: val}); - if (cm.display.scroller.scrollTop != val) cm.display.scroller.scrollTop = val; - cm.display.scrollbars.setScrollTop(val); - if (gecko) updateDisplaySimple(cm); - startWorker(cm, 100); - } - // Sync scroller and scrollbar, ensure the gutter elements are - // aligned. - function setScrollLeft(cm, val, isScroller) { - if (isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) return; - val = Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth); - cm.doc.scrollLeft = val; - alignHorizontally(cm); - if (cm.display.scroller.scrollLeft != val) cm.display.scroller.scrollLeft = val; - cm.display.scrollbars.setScrollLeft(val); - } - - // Since the delta values reported on mouse wheel events are - // unstandardized between browsers and even browser versions, and - // generally horribly unpredictable, this code starts by measuring - // the scroll effect that the first few mouse wheel events have, - // and, from that, detects the way it can convert deltas to pixel - // offsets afterwards. - // - // The reason we want to know the amount a wheel event will scroll - // is that it gives us a chance to update the display before the - // actual scrolling happens, reducing flickering. - - var wheelSamples = 0, wheelPixelsPerUnit = null; - // Fill in a browser-detected starting value on browsers where we - // know one. These don't have to be accurate -- the result of them - // being wrong would just be a slight flicker on the first wheel - // scroll (if it is large enough). - if (ie) wheelPixelsPerUnit = -.53; - else if (gecko) wheelPixelsPerUnit = 15; - else if (chrome) wheelPixelsPerUnit = -.7; - else if (safari) wheelPixelsPerUnit = -1/3; - - var wheelEventDelta = function(e) { - var dx = e.wheelDeltaX, dy = e.wheelDeltaY; - if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) dx = e.detail; - if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) dy = e.detail; - else if (dy == null) dy = e.wheelDelta; - return {x: dx, y: dy}; - }; - CodeMirror.wheelEventPixels = function(e) { - var delta = wheelEventDelta(e); - delta.x *= wheelPixelsPerUnit; - delta.y *= wheelPixelsPerUnit; - return delta; - }; - - function onScrollWheel(cm, e) { - var delta = wheelEventDelta(e), dx = delta.x, dy = delta.y; - - var display = cm.display, scroll = display.scroller; - // Quit if there's nothing to scroll here - var canScrollX = scroll.scrollWidth > scroll.clientWidth; - var canScrollY = scroll.scrollHeight > scroll.clientHeight; - if (!(dx && canScrollX || dy && canScrollY)) return; - - // Webkit browsers on OS X abort momentum scrolls when the target - // of the scroll event is removed from the scrollable element. - // This hack (see related code in patchDisplay) makes sure the - // element is kept around. - if (dy && mac && webkit) { - outer: for (var cur = e.target, view = display.view; cur != scroll; cur = cur.parentNode) { - for (var i = 0; i < view.length; i++) { - if (view[i].node == cur) { - cm.display.currentWheelTarget = cur; - break outer; - } - } - } - } - - // On some browsers, horizontal scrolling will cause redraws to - // happen before the gutter has been realigned, causing it to - // wriggle around in a most unseemly way. When we have an - // estimated pixels/delta value, we just handle horizontal - // scrolling entirely here. It'll be slightly off from native, but - // better than glitching out. - if (dx && !gecko && !presto && wheelPixelsPerUnit != null) { - if (dy && canScrollY) - setScrollTop(cm, Math.max(0, Math.min(scroll.scrollTop + dy * wheelPixelsPerUnit, scroll.scrollHeight - scroll.clientHeight))); - setScrollLeft(cm, Math.max(0, Math.min(scroll.scrollLeft + dx * wheelPixelsPerUnit, scroll.scrollWidth - scroll.clientWidth))); - // Only prevent default scrolling if vertical scrolling is - // actually possible. Otherwise, it causes vertical scroll - // jitter on OSX trackpads when deltaX is small and deltaY - // is large (issue #3579) - if (!dy || (dy && canScrollY)) - e_preventDefault(e); - display.wheelStartX = null; // Abort measurement, if in progress - return; - } - - // 'Project' the visible viewport to cover the area that is being - // scrolled into view (if we know enough to estimate it). - if (dy && wheelPixelsPerUnit != null) { - var pixels = dy * wheelPixelsPerUnit; - var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight; - if (pixels < 0) top = Math.max(0, top + pixels - 50); - else bot = Math.min(cm.doc.height, bot + pixels + 50); - updateDisplaySimple(cm, {top: top, bottom: bot}); - } - - if (wheelSamples < 20) { - if (display.wheelStartX == null) { - display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop; - display.wheelDX = dx; display.wheelDY = dy; - setTimeout(function() { - if (display.wheelStartX == null) return; - var movedX = scroll.scrollLeft - display.wheelStartX; - var movedY = scroll.scrollTop - display.wheelStartY; - var sample = (movedY && display.wheelDY && movedY / display.wheelDY) || - (movedX && display.wheelDX && movedX / display.wheelDX); - display.wheelStartX = display.wheelStartY = null; - if (!sample) return; - wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1); - ++wheelSamples; - }, 200); - } else { - display.wheelDX += dx; display.wheelDY += dy; - } - } - } - - // KEY EVENTS - - // Run a handler that was bound to a key. - function doHandleBinding(cm, bound, dropShift) { - if (typeof bound == "string") { - bound = commands[bound]; - if (!bound) return false; - } - // Ensure previous input has been read, so that the handler sees a - // consistent view of the document - cm.display.input.ensurePolled(); - var prevShift = cm.display.shift, done = false; - try { - if (isReadOnly(cm)) cm.state.suppressEdits = true; - if (dropShift) cm.display.shift = false; - done = bound(cm) != Pass; - } finally { - cm.display.shift = prevShift; - cm.state.suppressEdits = false; - } - return done; - } - - function lookupKeyForEditor(cm, name, handle) { - for (var i = 0; i < cm.state.keyMaps.length; i++) { - var result = lookupKey(name, cm.state.keyMaps[i], handle, cm); - if (result) return result; - } - return (cm.options.extraKeys && lookupKey(name, cm.options.extraKeys, handle, cm)) - || lookupKey(name, cm.options.keyMap, handle, cm); - } - - var stopSeq = new Delayed; - function dispatchKey(cm, name, e, handle) { - var seq = cm.state.keySeq; - if (seq) { - if (isModifierKey(name)) return "handled"; - stopSeq.set(50, function() { - if (cm.state.keySeq == seq) { - cm.state.keySeq = null; - cm.display.input.reset(); - } - }); - name = seq + " " + name; - } - var result = lookupKeyForEditor(cm, name, handle); - - if (result == "multi") - cm.state.keySeq = name; - if (result == "handled") - signalLater(cm, "keyHandled", cm, name, e); - - if (result == "handled" || result == "multi") { - e_preventDefault(e); - restartBlink(cm); - } - - if (seq && !result && /\'$/.test(name)) { - e_preventDefault(e); - return true; - } - return !!result; - } - - // Handle a key from the keydown event. - function handleKeyBinding(cm, e) { - var name = keyName(e, true); - if (!name) return false; - - if (e.shiftKey && !cm.state.keySeq) { - // First try to resolve full name (including 'Shift-'). Failing - // that, see if there is a cursor-motion command (starting with - // 'go') bound to the keyname without 'Shift-'. - return dispatchKey(cm, "Shift-" + name, e, function(b) {return doHandleBinding(cm, b, true);}) - || dispatchKey(cm, name, e, function(b) { - if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion) - return doHandleBinding(cm, b); - }); - } else { - return dispatchKey(cm, name, e, function(b) { return doHandleBinding(cm, b); }); - } - } - - // Handle a key from the keypress event - function handleCharBinding(cm, e, ch) { - return dispatchKey(cm, "'" + ch + "'", e, - function(b) { return doHandleBinding(cm, b, true); }); - } - - var lastStoppedKey = null; - function onKeyDown(e) { - var cm = this; - cm.curOp.focus = activeElt(); - if (signalDOMEvent(cm, e)) return; - // IE does strange things with escape. - if (ie && ie_version < 11 && e.keyCode == 27) e.returnValue = false; - var code = e.keyCode; - cm.display.shift = code == 16 || e.shiftKey; - var handled = handleKeyBinding(cm, e); - if (presto) { - lastStoppedKey = handled ? code : null; - // Opera has no cut event... we try to at least catch the key combo - if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey)) - cm.replaceSelection("", null, "cut"); - } - - // Turn mouse into crosshair when Alt is held on Mac. - if (code == 18 && !/\bCodeMirror-crosshair\b/.test(cm.display.lineDiv.className)) - showCrossHair(cm); - } - - function showCrossHair(cm) { - var lineDiv = cm.display.lineDiv; - addClass(lineDiv, "CodeMirror-crosshair"); - - function up(e) { - if (e.keyCode == 18 || !e.altKey) { - rmClass(lineDiv, "CodeMirror-crosshair"); - off(document, "keyup", up); - off(document, "mouseover", up); - } - } - on(document, "keyup", up); - on(document, "mouseover", up); - } - - function onKeyUp(e) { - if (e.keyCode == 16) this.doc.sel.shift = false; - signalDOMEvent(this, e); - } - - function onKeyPress(e) { - var cm = this; - if (eventInWidget(cm.display, e) || signalDOMEvent(cm, e) || e.ctrlKey && !e.altKey || mac && e.metaKey) return; - var keyCode = e.keyCode, charCode = e.charCode; - if (presto && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;} - if ((presto && (!e.which || e.which < 10)) && handleKeyBinding(cm, e)) return; - var ch = String.fromCharCode(charCode == null ? keyCode : charCode); - if (handleCharBinding(cm, e, ch)) return; - cm.display.input.onKeyPress(e); - } - - // FOCUS/BLUR EVENTS - - function delayBlurEvent(cm) { - cm.state.delayingBlurEvent = true; - setTimeout(function() { - if (cm.state.delayingBlurEvent) { - cm.state.delayingBlurEvent = false; - onBlur(cm); - } - }, 100); - } - - function onFocus(cm) { - if (cm.state.delayingBlurEvent) cm.state.delayingBlurEvent = false; - - if (cm.options.readOnly == "nocursor") return; - if (!cm.state.focused) { - signal(cm, "focus", cm); - cm.state.focused = true; - addClass(cm.display.wrapper, "CodeMirror-focused"); - // This test prevents this from firing when a context - // menu is closed (since the input reset would kill the - // select-all detection hack) - if (!cm.curOp && cm.display.selForContextMenu != cm.doc.sel) { - cm.display.input.reset(); - if (webkit) setTimeout(function() { cm.display.input.reset(true); }, 20); // Issue #1730 - } - cm.display.input.receivedFocus(); - } - restartBlink(cm); - } - function onBlur(cm) { - if (cm.state.delayingBlurEvent) return; - - if (cm.state.focused) { - signal(cm, "blur", cm); - cm.state.focused = false; - rmClass(cm.display.wrapper, "CodeMirror-focused"); - } - clearInterval(cm.display.blinker); - setTimeout(function() {if (!cm.state.focused) cm.display.shift = false;}, 150); - } - - // CONTEXT MENU HANDLING - - // To make the context menu work, we need to briefly unhide the - // textarea (making it as unobtrusive as possible) to let the - // right-click take effect on it. - function onContextMenu(cm, e) { - if (eventInWidget(cm.display, e) || contextMenuInGutter(cm, e)) return; - if (signalDOMEvent(cm, e, "contextmenu")) return; - cm.display.input.onContextMenu(e); - } - - function contextMenuInGutter(cm, e) { - if (!hasHandler(cm, "gutterContextMenu")) return false; - return gutterEvent(cm, e, "gutterContextMenu", false); - } - - // UPDATING - - // Compute the position of the end of a change (its 'to' property - // refers to the pre-change end). - var changeEnd = CodeMirror.changeEnd = function(change) { - if (!change.text) return change.to; - return Pos(change.from.line + change.text.length - 1, - lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0)); - }; - - // Adjust a position to refer to the post-change position of the - // same text, or the end of the change if the change covers it. - function adjustForChange(pos, change) { - if (cmp(pos, change.from) < 0) return pos; - if (cmp(pos, change.to) <= 0) return changeEnd(change); - - var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch; - if (pos.line == change.to.line) ch += changeEnd(change).ch - change.to.ch; - return Pos(line, ch); - } - - function computeSelAfterChange(doc, change) { - var out = []; - for (var i = 0; i < doc.sel.ranges.length; i++) { - var range = doc.sel.ranges[i]; - out.push(new Range(adjustForChange(range.anchor, change), - adjustForChange(range.head, change))); - } - return normalizeSelection(out, doc.sel.primIndex); - } - - function offsetPos(pos, old, nw) { - if (pos.line == old.line) - return Pos(nw.line, pos.ch - old.ch + nw.ch); - else - return Pos(nw.line + (pos.line - old.line), pos.ch); - } - - // Used by replaceSelections to allow moving the selection to the - // start or around the replaced test. Hint may be "start" or "around". - function computeReplacedSel(doc, changes, hint) { - var out = []; - var oldPrev = Pos(doc.first, 0), newPrev = oldPrev; - for (var i = 0; i < changes.length; i++) { - var change = changes[i]; - var from = offsetPos(change.from, oldPrev, newPrev); - var to = offsetPos(changeEnd(change), oldPrev, newPrev); - oldPrev = change.to; - newPrev = to; - if (hint == "around") { - var range = doc.sel.ranges[i], inv = cmp(range.head, range.anchor) < 0; - out[i] = new Range(inv ? to : from, inv ? from : to); - } else { - out[i] = new Range(from, from); - } - } - return new Selection(out, doc.sel.primIndex); - } - - // Allow "beforeChange" event handlers to influence a change - function filterChange(doc, change, update) { - var obj = { - canceled: false, - from: change.from, - to: change.to, - text: change.text, - origin: change.origin, - cancel: function() { this.canceled = true; } - }; - if (update) obj.update = function(from, to, text, origin) { - if (from) this.from = clipPos(doc, from); - if (to) this.to = clipPos(doc, to); - if (text) this.text = text; - if (origin !== undefined) this.origin = origin; - }; - signal(doc, "beforeChange", doc, obj); - if (doc.cm) signal(doc.cm, "beforeChange", doc.cm, obj); - - if (obj.canceled) return null; - return {from: obj.from, to: obj.to, text: obj.text, origin: obj.origin}; - } - - // Apply a change to a document, and add it to the document's - // history, and propagating it to all linked documents. - function makeChange(doc, change, ignoreReadOnly) { - if (doc.cm) { - if (!doc.cm.curOp) return operation(doc.cm, makeChange)(doc, change, ignoreReadOnly); - if (doc.cm.state.suppressEdits) return; - } - - if (hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")) { - change = filterChange(doc, change, true); - if (!change) return; - } - - // Possibly split or suppress the update based on the presence - // of read-only spans in its range. - var split = sawReadOnlySpans && !ignoreReadOnly && removeReadOnlyRanges(doc, change.from, change.to); - if (split) { - for (var i = split.length - 1; i >= 0; --i) - makeChangeInner(doc, {from: split[i].from, to: split[i].to, text: i ? [""] : change.text}); - } else { - makeChangeInner(doc, change); - } - } - - function makeChangeInner(doc, change) { - if (change.text.length == 1 && change.text[0] == "" && cmp(change.from, change.to) == 0) return; - var selAfter = computeSelAfterChange(doc, change); - addChangeToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN); - - makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change)); - var rebased = []; - - linkedDocs(doc, function(doc, sharedHist) { - if (!sharedHist && indexOf(rebased, doc.history) == -1) { - rebaseHist(doc.history, change); - rebased.push(doc.history); - } - makeChangeSingleDoc(doc, change, null, stretchSpansOverChange(doc, change)); - }); - } - - // Revert a change stored in a document's history. - function makeChangeFromHistory(doc, type, allowSelectionOnly) { - if (doc.cm && doc.cm.state.suppressEdits) return; - - var hist = doc.history, event, selAfter = doc.sel; - var source = type == "undo" ? hist.done : hist.undone, dest = type == "undo" ? hist.undone : hist.done; - - // Verify that there is a useable event (so that ctrl-z won't - // needlessly clear selection events) - for (var i = 0; i < source.length; i++) { - event = source[i]; - if (allowSelectionOnly ? event.ranges && !event.equals(doc.sel) : !event.ranges) - break; - } - if (i == source.length) return; - hist.lastOrigin = hist.lastSelOrigin = null; - - for (;;) { - event = source.pop(); - if (event.ranges) { - pushSelectionToHistory(event, dest); - if (allowSelectionOnly && !event.equals(doc.sel)) { - setSelection(doc, event, {clearRedo: false}); - return; - } - selAfter = event; - } - else break; - } - - // Build up a reverse change object to add to the opposite history - // stack (redo when undoing, and vice versa). - var antiChanges = []; - pushSelectionToHistory(selAfter, dest); - dest.push({changes: antiChanges, generation: hist.generation}); - hist.generation = event.generation || ++hist.maxGeneration; - - var filter = hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange"); - - for (var i = event.changes.length - 1; i >= 0; --i) { - var change = event.changes[i]; - change.origin = type; - if (filter && !filterChange(doc, change, false)) { - source.length = 0; - return; - } - - antiChanges.push(historyChangeFromChange(doc, change)); - - var after = i ? computeSelAfterChange(doc, change) : lst(source); - makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change)); - if (!i && doc.cm) doc.cm.scrollIntoView({from: change.from, to: changeEnd(change)}); - var rebased = []; - - // Propagate to the linked documents - linkedDocs(doc, function(doc, sharedHist) { - if (!sharedHist && indexOf(rebased, doc.history) == -1) { - rebaseHist(doc.history, change); - rebased.push(doc.history); - } - makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change)); - }); - } - } - - // Sub-views need their line numbers shifted when text is added - // above or below them in the parent document. - function shiftDoc(doc, distance) { - if (distance == 0) return; - doc.first += distance; - doc.sel = new Selection(map(doc.sel.ranges, function(range) { - return new Range(Pos(range.anchor.line + distance, range.anchor.ch), - Pos(range.head.line + distance, range.head.ch)); - }), doc.sel.primIndex); - if (doc.cm) { - regChange(doc.cm, doc.first, doc.first - distance, distance); - for (var d = doc.cm.display, l = d.viewFrom; l < d.viewTo; l++) - regLineChange(doc.cm, l, "gutter"); - } - } - - // More lower-level change function, handling only a single document - // (not linked ones). - function makeChangeSingleDoc(doc, change, selAfter, spans) { - if (doc.cm && !doc.cm.curOp) - return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans); - - if (change.to.line < doc.first) { - shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line)); - return; - } - if (change.from.line > doc.lastLine()) return; - - // Clip the change to the size of this doc - if (change.from.line < doc.first) { - var shift = change.text.length - 1 - (doc.first - change.from.line); - shiftDoc(doc, shift); - change = {from: Pos(doc.first, 0), to: Pos(change.to.line + shift, change.to.ch), - text: [lst(change.text)], origin: change.origin}; - } - var last = doc.lastLine(); - if (change.to.line > last) { - change = {from: change.from, to: Pos(last, getLine(doc, last).text.length), - text: [change.text[0]], origin: change.origin}; - } - - change.removed = getBetween(doc, change.from, change.to); - - if (!selAfter) selAfter = computeSelAfterChange(doc, change); - if (doc.cm) makeChangeSingleDocInEditor(doc.cm, change, spans); - else updateDoc(doc, change, spans); - setSelectionNoUndo(doc, selAfter, sel_dontScroll); - } - - // Handle the interaction of a change to a document with the editor - // that this document is part of. - function makeChangeSingleDocInEditor(cm, change, spans) { - var doc = cm.doc, display = cm.display, from = change.from, to = change.to; - - var recomputeMaxLength = false, checkWidthStart = from.line; - if (!cm.options.lineWrapping) { - checkWidthStart = lineNo(visualLine(getLine(doc, from.line))); - doc.iter(checkWidthStart, to.line + 1, function(line) { - if (line == display.maxLine) { - recomputeMaxLength = true; - return true; - } - }); - } - - if (doc.sel.contains(change.from, change.to) > -1) - signalCursorActivity(cm); - - updateDoc(doc, change, spans, estimateHeight(cm)); - - if (!cm.options.lineWrapping) { - doc.iter(checkWidthStart, from.line + change.text.length, function(line) { - var len = lineLength(line); - if (len > display.maxLineLength) { - display.maxLine = line; - display.maxLineLength = len; - display.maxLineChanged = true; - recomputeMaxLength = false; - } - }); - if (recomputeMaxLength) cm.curOp.updateMaxLine = true; - } - - // Adjust frontier, schedule worker - doc.frontier = Math.min(doc.frontier, from.line); - startWorker(cm, 400); - - var lendiff = change.text.length - (to.line - from.line) - 1; - // Remember that these lines changed, for updating the display - if (change.full) - regChange(cm); - else if (from.line == to.line && change.text.length == 1 && !isWholeLineUpdate(cm.doc, change)) - regLineChange(cm, from.line, "text"); - else - regChange(cm, from.line, to.line + 1, lendiff); - - var changesHandler = hasHandler(cm, "changes"), changeHandler = hasHandler(cm, "change"); - if (changeHandler || changesHandler) { - var obj = { - from: from, to: to, - text: change.text, - removed: change.removed, - origin: change.origin - }; - if (changeHandler) signalLater(cm, "change", cm, obj); - if (changesHandler) (cm.curOp.changeObjs || (cm.curOp.changeObjs = [])).push(obj); - } - cm.display.selForContextMenu = null; - } - - function replaceRange(doc, code, from, to, origin) { - if (!to) to = from; - if (cmp(to, from) < 0) { var tmp = to; to = from; from = tmp; } - if (typeof code == "string") code = doc.splitLines(code); - makeChange(doc, {from: from, to: to, text: code, origin: origin}); - } - - // SCROLLING THINGS INTO VIEW - - // If an editor sits on the top or bottom of the window, partially - // scrolled out of view, this ensures that the cursor is visible. - function maybeScrollWindow(cm, coords) { - if (signalDOMEvent(cm, "scrollCursorIntoView")) return; - - var display = cm.display, box = display.sizer.getBoundingClientRect(), doScroll = null; - if (coords.top + box.top < 0) doScroll = true; - else if (coords.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) doScroll = false; - if (doScroll != null && !phantom) { - var scrollNode = elt("div", "\u200b", null, "position: absolute; top: " + - (coords.top - display.viewOffset - paddingTop(cm.display)) + "px; height: " + - (coords.bottom - coords.top + scrollGap(cm) + display.barHeight) + "px; left: " + - coords.left + "px; width: 2px;"); - cm.display.lineSpace.appendChild(scrollNode); - scrollNode.scrollIntoView(doScroll); - cm.display.lineSpace.removeChild(scrollNode); - } - } - - // Scroll a given position into view (immediately), verifying that - // it actually became visible (as line heights are accurately - // measured, the position of something may 'drift' during drawing). - function scrollPosIntoView(cm, pos, end, margin) { - if (margin == null) margin = 0; - for (var limit = 0; limit < 5; limit++) { - var changed = false, coords = cursorCoords(cm, pos); - var endCoords = !end || end == pos ? coords : cursorCoords(cm, end); - var scrollPos = calculateScrollPos(cm, Math.min(coords.left, endCoords.left), - Math.min(coords.top, endCoords.top) - margin, - Math.max(coords.left, endCoords.left), - Math.max(coords.bottom, endCoords.bottom) + margin); - var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft; - if (scrollPos.scrollTop != null) { - setScrollTop(cm, scrollPos.scrollTop); - if (Math.abs(cm.doc.scrollTop - startTop) > 1) changed = true; - } - if (scrollPos.scrollLeft != null) { - setScrollLeft(cm, scrollPos.scrollLeft); - if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) changed = true; - } - if (!changed) break; - } - return coords; - } - - // Scroll a given set of coordinates into view (immediately). - function scrollIntoView(cm, x1, y1, x2, y2) { - var scrollPos = calculateScrollPos(cm, x1, y1, x2, y2); - if (scrollPos.scrollTop != null) setScrollTop(cm, scrollPos.scrollTop); - if (scrollPos.scrollLeft != null) setScrollLeft(cm, scrollPos.scrollLeft); - } - - // Calculate a new scroll position needed to scroll the given - // rectangle into view. Returns an object with scrollTop and - // scrollLeft properties. When these are undefined, the - // vertical/horizontal position does not need to be adjusted. - function calculateScrollPos(cm, x1, y1, x2, y2) { - var display = cm.display, snapMargin = textHeight(cm.display); - if (y1 < 0) y1 = 0; - var screentop = cm.curOp && cm.curOp.scrollTop != null ? cm.curOp.scrollTop : display.scroller.scrollTop; - var screen = displayHeight(cm), result = {}; - if (y2 - y1 > screen) y2 = y1 + screen; - var docBottom = cm.doc.height + paddingVert(display); - var atTop = y1 < snapMargin, atBottom = y2 > docBottom - snapMargin; - if (y1 < screentop) { - result.scrollTop = atTop ? 0 : y1; - } else if (y2 > screentop + screen) { - var newTop = Math.min(y1, (atBottom ? docBottom : y2) - screen); - if (newTop != screentop) result.scrollTop = newTop; - } - - var screenleft = cm.curOp && cm.curOp.scrollLeft != null ? cm.curOp.scrollLeft : display.scroller.scrollLeft; - var screenw = displayWidth(cm) - (cm.options.fixedGutter ? display.gutters.offsetWidth : 0); - var tooWide = x2 - x1 > screenw; - if (tooWide) x2 = x1 + screenw; - if (x1 < 10) - result.scrollLeft = 0; - else if (x1 < screenleft) - result.scrollLeft = Math.max(0, x1 - (tooWide ? 0 : 10)); - else if (x2 > screenw + screenleft - 3) - result.scrollLeft = x2 + (tooWide ? 0 : 10) - screenw; - return result; - } - - // Store a relative adjustment to the scroll position in the current - // operation (to be applied when the operation finishes). - function addToScrollPos(cm, left, top) { - if (left != null || top != null) resolveScrollToPos(cm); - if (left != null) - cm.curOp.scrollLeft = (cm.curOp.scrollLeft == null ? cm.doc.scrollLeft : cm.curOp.scrollLeft) + left; - if (top != null) - cm.curOp.scrollTop = (cm.curOp.scrollTop == null ? cm.doc.scrollTop : cm.curOp.scrollTop) + top; - } - - // Make sure that at the end of the operation the current cursor is - // shown. - function ensureCursorVisible(cm) { - resolveScrollToPos(cm); - var cur = cm.getCursor(), from = cur, to = cur; - if (!cm.options.lineWrapping) { - from = cur.ch ? Pos(cur.line, cur.ch - 1) : cur; - to = Pos(cur.line, cur.ch + 1); - } - cm.curOp.scrollToPos = {from: from, to: to, margin: cm.options.cursorScrollMargin, isCursor: true}; - } - - // When an operation has its scrollToPos property set, and another - // scroll action is applied before the end of the operation, this - // 'simulates' scrolling that position into view in a cheap way, so - // that the effect of intermediate scroll commands is not ignored. - function resolveScrollToPos(cm) { - var range = cm.curOp.scrollToPos; - if (range) { - cm.curOp.scrollToPos = null; - var from = estimateCoords(cm, range.from), to = estimateCoords(cm, range.to); - var sPos = calculateScrollPos(cm, Math.min(from.left, to.left), - Math.min(from.top, to.top) - range.margin, - Math.max(from.right, to.right), - Math.max(from.bottom, to.bottom) + range.margin); - cm.scrollTo(sPos.scrollLeft, sPos.scrollTop); - } - } - - // API UTILITIES - - // Indent the given line. The how parameter can be "smart", - // "add"/null, "subtract", or "prev". When aggressive is false - // (typically set to true for forced single-line indents), empty - // lines are not indented, and places where the mode returns Pass - // are left alone. - function indentLine(cm, n, how, aggressive) { - var doc = cm.doc, state; - if (how == null) how = "add"; - if (how == "smart") { - // Fall back to "prev" when the mode doesn't have an indentation - // method. - if (!doc.mode.indent) how = "prev"; - else state = getStateBefore(cm, n); - } - - var tabSize = cm.options.tabSize; - var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize); - if (line.stateAfter) line.stateAfter = null; - var curSpaceString = line.text.match(/^\s*/)[0], indentation; - if (!aggressive && !/\S/.test(line.text)) { - indentation = 0; - how = "not"; - } else if (how == "smart") { - indentation = doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text); - if (indentation == Pass || indentation > 150) { - if (!aggressive) return; - how = "prev"; - } - } - if (how == "prev") { - if (n > doc.first) indentation = countColumn(getLine(doc, n-1).text, null, tabSize); - else indentation = 0; - } else if (how == "add") { - indentation = curSpace + cm.options.indentUnit; - } else if (how == "subtract") { - indentation = curSpace - cm.options.indentUnit; - } else if (typeof how == "number") { - indentation = curSpace + how; - } - indentation = Math.max(0, indentation); - - var indentString = "", pos = 0; - if (cm.options.indentWithTabs) - for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t";} - if (pos < indentation) indentString += spaceStr(indentation - pos); - - if (indentString != curSpaceString) { - replaceRange(doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input"); - line.stateAfter = null; - return true; - } else { - // Ensure that, if the cursor was in the whitespace at the start - // of the line, it is moved to the end of that space. - for (var i = 0; i < doc.sel.ranges.length; i++) { - var range = doc.sel.ranges[i]; - if (range.head.line == n && range.head.ch < curSpaceString.length) { - var pos = Pos(n, curSpaceString.length); - replaceOneSelection(doc, i, new Range(pos, pos)); - break; - } - } - } - } - - // Utility for applying a change to a line by handle or number, - // returning the number and optionally registering the line as - // changed. - function changeLine(doc, handle, changeType, op) { - var no = handle, line = handle; - if (typeof handle == "number") line = getLine(doc, clipLine(doc, handle)); - else no = lineNo(handle); - if (no == null) return null; - if (op(line, no) && doc.cm) regLineChange(doc.cm, no, changeType); - return line; - } - - // Helper for deleting text near the selection(s), used to implement - // backspace, delete, and similar functionality. - function deleteNearSelection(cm, compute) { - var ranges = cm.doc.sel.ranges, kill = []; - // Build up a set of ranges to kill first, merging overlapping - // ranges. - for (var i = 0; i < ranges.length; i++) { - var toKill = compute(ranges[i]); - while (kill.length && cmp(toKill.from, lst(kill).to) <= 0) { - var replaced = kill.pop(); - if (cmp(replaced.from, toKill.from) < 0) { - toKill.from = replaced.from; - break; - } - } - kill.push(toKill); - } - // Next, remove those actual ranges. - runInOp(cm, function() { - for (var i = kill.length - 1; i >= 0; i--) - replaceRange(cm.doc, "", kill[i].from, kill[i].to, "+delete"); - ensureCursorVisible(cm); - }); - } - - // Used for horizontal relative motion. Dir is -1 or 1 (left or - // right), unit can be "char", "column" (like char, but doesn't - // cross line boundaries), "word" (across next word), or "group" (to - // the start of next group of word or non-word-non-whitespace - // chars). The visually param controls whether, in right-to-left - // text, direction 1 means to move towards the next index in the - // string, or towards the character to the right of the current - // position. The resulting position will have a hitSide=true - // property if it reached the end of the document. - function findPosH(doc, pos, dir, unit, visually) { - var line = pos.line, ch = pos.ch, origDir = dir; - var lineObj = getLine(doc, line); - var possible = true; - function findNextLine() { - var l = line + dir; - if (l < doc.first || l >= doc.first + doc.size) return (possible = false); - line = l; - return lineObj = getLine(doc, l); - } - function moveOnce(boundToLine) { - var next = (visually ? moveVisually : moveLogically)(lineObj, ch, dir, true); - if (next == null) { - if (!boundToLine && findNextLine()) { - if (visually) ch = (dir < 0 ? lineRight : lineLeft)(lineObj); - else ch = dir < 0 ? lineObj.text.length : 0; - } else return (possible = false); - } else ch = next; - return true; - } - - if (unit == "char") moveOnce(); - else if (unit == "column") moveOnce(true); - else if (unit == "word" || unit == "group") { - var sawType = null, group = unit == "group"; - var helper = doc.cm && doc.cm.getHelper(pos, "wordChars"); - for (var first = true;; first = false) { - if (dir < 0 && !moveOnce(!first)) break; - var cur = lineObj.text.charAt(ch) || "\n"; - var type = isWordChar(cur, helper) ? "w" - : group && cur == "\n" ? "n" - : !group || /\s/.test(cur) ? null - : "p"; - if (group && !first && !type) type = "s"; - if (sawType && sawType != type) { - if (dir < 0) {dir = 1; moveOnce();} - break; - } - - if (type) sawType = type; - if (dir > 0 && !moveOnce(!first)) break; - } - } - var result = skipAtomic(doc, Pos(line, ch), origDir, true); - if (!possible) result.hitSide = true; - return result; - } - - // For relative vertical movement. Dir may be -1 or 1. Unit can be - // "page" or "line". The resulting position will have a hitSide=true - // property if it reached the end of the document. - function findPosV(cm, pos, dir, unit) { - var doc = cm.doc, x = pos.left, y; - if (unit == "page") { - var pageSize = Math.min(cm.display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight); - y = pos.top + dir * (pageSize - (dir < 0 ? 1.5 : .5) * textHeight(cm.display)); - } else if (unit == "line") { - y = dir > 0 ? pos.bottom + 3 : pos.top - 3; - } - for (;;) { - var target = coordsChar(cm, x, y); - if (!target.outside) break; - if (dir < 0 ? y <= 0 : y >= doc.height) { target.hitSide = true; break; } - y += dir * 5; - } - return target; - } - - // EDITOR METHODS - - // The publicly visible API. Note that methodOp(f) means - // 'wrap f in an operation, performed on its `this` parameter'. - - // This is not the complete set of editor methods. Most of the - // methods defined on the Doc type are also injected into - // CodeMirror.prototype, for backwards compatibility and - // convenience. - - CodeMirror.prototype = { - constructor: CodeMirror, - focus: function(){window.focus(); this.display.input.focus();}, - - setOption: function(option, value) { - var options = this.options, old = options[option]; - if (options[option] == value && option != "mode") return; - options[option] = value; - if (optionHandlers.hasOwnProperty(option)) - operation(this, optionHandlers[option])(this, value, old); - }, - - getOption: function(option) {return this.options[option];}, - getDoc: function() {return this.doc;}, - - addKeyMap: function(map, bottom) { - this.state.keyMaps[bottom ? "push" : "unshift"](getKeyMap(map)); - }, - removeKeyMap: function(map) { - var maps = this.state.keyMaps; - for (var i = 0; i < maps.length; ++i) - if (maps[i] == map || maps[i].name == map) { - maps.splice(i, 1); - return true; - } - }, - - addOverlay: methodOp(function(spec, options) { - var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec); - if (mode.startState) throw new Error("Overlays may not be stateful."); - this.state.overlays.push({mode: mode, modeSpec: spec, opaque: options && options.opaque}); - this.state.modeGen++; - regChange(this); - }), - removeOverlay: methodOp(function(spec) { - var overlays = this.state.overlays; - for (var i = 0; i < overlays.length; ++i) { - var cur = overlays[i].modeSpec; - if (cur == spec || typeof spec == "string" && cur.name == spec) { - overlays.splice(i, 1); - this.state.modeGen++; - regChange(this); - return; - } - } - }), - - indentLine: methodOp(function(n, dir, aggressive) { - if (typeof dir != "string" && typeof dir != "number") { - if (dir == null) dir = this.options.smartIndent ? "smart" : "prev"; - else dir = dir ? "add" : "subtract"; - } - if (isLine(this.doc, n)) indentLine(this, n, dir, aggressive); - }), - indentSelection: methodOp(function(how) { - var ranges = this.doc.sel.ranges, end = -1; - for (var i = 0; i < ranges.length; i++) { - var range = ranges[i]; - if (!range.empty()) { - var from = range.from(), to = range.to(); - var start = Math.max(end, from.line); - end = Math.min(this.lastLine(), to.line - (to.ch ? 0 : 1)) + 1; - for (var j = start; j < end; ++j) - indentLine(this, j, how); - var newRanges = this.doc.sel.ranges; - if (from.ch == 0 && ranges.length == newRanges.length && newRanges[i].from().ch > 0) - replaceOneSelection(this.doc, i, new Range(from, newRanges[i].to()), sel_dontScroll); - } else if (range.head.line > end) { - indentLine(this, range.head.line, how, true); - end = range.head.line; - if (i == this.doc.sel.primIndex) ensureCursorVisible(this); - } - } - }), - - // Fetch the parser token for a given character. Useful for hacks - // that want to inspect the mode state (say, for completion). - getTokenAt: function(pos, precise) { - return takeToken(this, pos, precise); - }, - - getLineTokens: function(line, precise) { - return takeToken(this, Pos(line), precise, true); - }, - - getTokenTypeAt: function(pos) { - pos = clipPos(this.doc, pos); - var styles = getLineStyles(this, getLine(this.doc, pos.line)); - var before = 0, after = (styles.length - 1) / 2, ch = pos.ch; - var type; - if (ch == 0) type = styles[2]; - else for (;;) { - var mid = (before + after) >> 1; - if ((mid ? styles[mid * 2 - 1] : 0) >= ch) after = mid; - else if (styles[mid * 2 + 1] < ch) before = mid + 1; - else { type = styles[mid * 2 + 2]; break; } - } - var cut = type ? type.indexOf("cm-overlay ") : -1; - return cut < 0 ? type : cut == 0 ? null : type.slice(0, cut - 1); - }, - - getModeAt: function(pos) { - var mode = this.doc.mode; - if (!mode.innerMode) return mode; - return CodeMirror.innerMode(mode, this.getTokenAt(pos).state).mode; - }, - - getHelper: function(pos, type) { - return this.getHelpers(pos, type)[0]; - }, - - getHelpers: function(pos, type) { - var found = []; - if (!helpers.hasOwnProperty(type)) return found; - var help = helpers[type], mode = this.getModeAt(pos); - if (typeof mode[type] == "string") { - if (help[mode[type]]) found.push(help[mode[type]]); - } else if (mode[type]) { - for (var i = 0; i < mode[type].length; i++) { - var val = help[mode[type][i]]; - if (val) found.push(val); - } - } else if (mode.helperType && help[mode.helperType]) { - found.push(help[mode.helperType]); - } else if (help[mode.name]) { - found.push(help[mode.name]); - } - for (var i = 0; i < help._global.length; i++) { - var cur = help._global[i]; - if (cur.pred(mode, this) && indexOf(found, cur.val) == -1) - found.push(cur.val); - } - return found; - }, - - getStateAfter: function(line, precise) { - var doc = this.doc; - line = clipLine(doc, line == null ? doc.first + doc.size - 1: line); - return getStateBefore(this, line + 1, precise); - }, - - cursorCoords: function(start, mode) { - var pos, range = this.doc.sel.primary(); - if (start == null) pos = range.head; - else if (typeof start == "object") pos = clipPos(this.doc, start); - else pos = start ? range.from() : range.to(); - return cursorCoords(this, pos, mode || "page"); - }, - - charCoords: function(pos, mode) { - return charCoords(this, clipPos(this.doc, pos), mode || "page"); - }, - - coordsChar: function(coords, mode) { - coords = fromCoordSystem(this, coords, mode || "page"); - return coordsChar(this, coords.left, coords.top); - }, - - lineAtHeight: function(height, mode) { - height = fromCoordSystem(this, {top: height, left: 0}, mode || "page").top; - return lineAtHeight(this.doc, height + this.display.viewOffset); - }, - heightAtLine: function(line, mode) { - var end = false, lineObj; - if (typeof line == "number") { - var last = this.doc.first + this.doc.size - 1; - if (line < this.doc.first) line = this.doc.first; - else if (line > last) { line = last; end = true; } - lineObj = getLine(this.doc, line); - } else { - lineObj = line; - } - return intoCoordSystem(this, lineObj, {top: 0, left: 0}, mode || "page").top + - (end ? this.doc.height - heightAtLine(lineObj) : 0); - }, - - defaultTextHeight: function() { return textHeight(this.display); }, - defaultCharWidth: function() { return charWidth(this.display); }, - - setGutterMarker: methodOp(function(line, gutterID, value) { - return changeLine(this.doc, line, "gutter", function(line) { - var markers = line.gutterMarkers || (line.gutterMarkers = {}); - markers[gutterID] = value; - if (!value && isEmpty(markers)) line.gutterMarkers = null; - return true; - }); - }), - - clearGutter: methodOp(function(gutterID) { - var cm = this, doc = cm.doc, i = doc.first; - doc.iter(function(line) { - if (line.gutterMarkers && line.gutterMarkers[gutterID]) { - line.gutterMarkers[gutterID] = null; - regLineChange(cm, i, "gutter"); - if (isEmpty(line.gutterMarkers)) line.gutterMarkers = null; - } - ++i; - }); - }), - - lineInfo: function(line) { - if (typeof line == "number") { - if (!isLine(this.doc, line)) return null; - var n = line; - line = getLine(this.doc, line); - if (!line) return null; - } else { - var n = lineNo(line); - if (n == null) return null; - } - return {line: n, handle: line, text: line.text, gutterMarkers: line.gutterMarkers, - textClass: line.textClass, bgClass: line.bgClass, wrapClass: line.wrapClass, - widgets: line.widgets}; - }, - - getViewport: function() { return {from: this.display.viewFrom, to: this.display.viewTo};}, - - addWidget: function(pos, node, scroll, vert, horiz) { - var display = this.display; - pos = cursorCoords(this, clipPos(this.doc, pos)); - var top = pos.bottom, left = pos.left; - node.style.position = "absolute"; - node.setAttribute("cm-ignore-events", "true"); - this.display.input.setUneditable(node); - display.sizer.appendChild(node); - if (vert == "over") { - top = pos.top; - } else if (vert == "above" || vert == "near") { - var vspace = Math.max(display.wrapper.clientHeight, this.doc.height), - hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth); - // Default to positioning above (if specified and possible); otherwise default to positioning below - if ((vert == 'above' || pos.bottom + node.offsetHeight > vspace) && pos.top > node.offsetHeight) - top = pos.top - node.offsetHeight; - else if (pos.bottom + node.offsetHeight <= vspace) - top = pos.bottom; - if (left + node.offsetWidth > hspace) - left = hspace - node.offsetWidth; - } - node.style.top = top + "px"; - node.style.left = node.style.right = ""; - if (horiz == "right") { - left = display.sizer.clientWidth - node.offsetWidth; - node.style.right = "0px"; - } else { - if (horiz == "left") left = 0; - else if (horiz == "middle") left = (display.sizer.clientWidth - node.offsetWidth) / 2; - node.style.left = left + "px"; - } - if (scroll) - scrollIntoView(this, left, top, left + node.offsetWidth, top + node.offsetHeight); - }, - - triggerOnKeyDown: methodOp(onKeyDown), - triggerOnKeyPress: methodOp(onKeyPress), - triggerOnKeyUp: onKeyUp, - - execCommand: function(cmd) { - if (commands.hasOwnProperty(cmd)) - return commands[cmd].call(null, this); - }, - - triggerElectric: methodOp(function(text) { triggerElectric(this, text); }), - - findPosH: function(from, amount, unit, visually) { - var dir = 1; - if (amount < 0) { dir = -1; amount = -amount; } - for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) { - cur = findPosH(this.doc, cur, dir, unit, visually); - if (cur.hitSide) break; - } - return cur; - }, - - moveH: methodOp(function(dir, unit) { - var cm = this; - cm.extendSelectionsBy(function(range) { - if (cm.display.shift || cm.doc.extend || range.empty()) - return findPosH(cm.doc, range.head, dir, unit, cm.options.rtlMoveVisually); - else - return dir < 0 ? range.from() : range.to(); - }, sel_move); - }), - - deleteH: methodOp(function(dir, unit) { - var sel = this.doc.sel, doc = this.doc; - if (sel.somethingSelected()) - doc.replaceSelection("", null, "+delete"); - else - deleteNearSelection(this, function(range) { - var other = findPosH(doc, range.head, dir, unit, false); - return dir < 0 ? {from: other, to: range.head} : {from: range.head, to: other}; - }); - }), - - findPosV: function(from, amount, unit, goalColumn) { - var dir = 1, x = goalColumn; - if (amount < 0) { dir = -1; amount = -amount; } - for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) { - var coords = cursorCoords(this, cur, "div"); - if (x == null) x = coords.left; - else coords.left = x; - cur = findPosV(this, coords, dir, unit); - if (cur.hitSide) break; - } - return cur; - }, - - moveV: methodOp(function(dir, unit) { - var cm = this, doc = this.doc, goals = []; - var collapse = !cm.display.shift && !doc.extend && doc.sel.somethingSelected(); - doc.extendSelectionsBy(function(range) { - if (collapse) - return dir < 0 ? range.from() : range.to(); - var headPos = cursorCoords(cm, range.head, "div"); - if (range.goalColumn != null) headPos.left = range.goalColumn; - goals.push(headPos.left); - var pos = findPosV(cm, headPos, dir, unit); - if (unit == "page" && range == doc.sel.primary()) - addToScrollPos(cm, null, charCoords(cm, pos, "div").top - headPos.top); - return pos; - }, sel_move); - if (goals.length) for (var i = 0; i < doc.sel.ranges.length; i++) - doc.sel.ranges[i].goalColumn = goals[i]; - }), - - // Find the word at the given position (as returned by coordsChar). - findWordAt: function(pos) { - var doc = this.doc, line = getLine(doc, pos.line).text; - var start = pos.ch, end = pos.ch; - if (line) { - var helper = this.getHelper(pos, "wordChars"); - if ((pos.xRel < 0 || end == line.length) && start) --start; else ++end; - var startChar = line.charAt(start); - var check = isWordChar(startChar, helper) - ? function(ch) { return isWordChar(ch, helper); } - : /\s/.test(startChar) ? function(ch) {return /\s/.test(ch);} - : function(ch) {return !/\s/.test(ch) && !isWordChar(ch);}; - while (start > 0 && check(line.charAt(start - 1))) --start; - while (end < line.length && check(line.charAt(end))) ++end; - } - return new Range(Pos(pos.line, start), Pos(pos.line, end)); - }, - - toggleOverwrite: function(value) { - if (value != null && value == this.state.overwrite) return; - if (this.state.overwrite = !this.state.overwrite) - addClass(this.display.cursorDiv, "CodeMirror-overwrite"); - else - rmClass(this.display.cursorDiv, "CodeMirror-overwrite"); - - signal(this, "overwriteToggle", this, this.state.overwrite); - }, - hasFocus: function() { return this.display.input.getField() == activeElt(); }, - - scrollTo: methodOp(function(x, y) { - if (x != null || y != null) resolveScrollToPos(this); - if (x != null) this.curOp.scrollLeft = x; - if (y != null) this.curOp.scrollTop = y; - }), - getScrollInfo: function() { - var scroller = this.display.scroller; - return {left: scroller.scrollLeft, top: scroller.scrollTop, - height: scroller.scrollHeight - scrollGap(this) - this.display.barHeight, - width: scroller.scrollWidth - scrollGap(this) - this.display.barWidth, - clientHeight: displayHeight(this), clientWidth: displayWidth(this)}; - }, - - scrollIntoView: methodOp(function(range, margin) { - if (range == null) { - range = {from: this.doc.sel.primary().head, to: null}; - if (margin == null) margin = this.options.cursorScrollMargin; - } else if (typeof range == "number") { - range = {from: Pos(range, 0), to: null}; - } else if (range.from == null) { - range = {from: range, to: null}; - } - if (!range.to) range.to = range.from; - range.margin = margin || 0; - - if (range.from.line != null) { - resolveScrollToPos(this); - this.curOp.scrollToPos = range; - } else { - var sPos = calculateScrollPos(this, Math.min(range.from.left, range.to.left), - Math.min(range.from.top, range.to.top) - range.margin, - Math.max(range.from.right, range.to.right), - Math.max(range.from.bottom, range.to.bottom) + range.margin); - this.scrollTo(sPos.scrollLeft, sPos.scrollTop); - } - }), - - setSize: methodOp(function(width, height) { - var cm = this; - function interpret(val) { - return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val; - } - if (width != null) cm.display.wrapper.style.width = interpret(width); - if (height != null) cm.display.wrapper.style.height = interpret(height); - if (cm.options.lineWrapping) clearLineMeasurementCache(this); - var lineNo = cm.display.viewFrom; - cm.doc.iter(lineNo, cm.display.viewTo, function(line) { - if (line.widgets) for (var i = 0; i < line.widgets.length; i++) - if (line.widgets[i].noHScroll) { regLineChange(cm, lineNo, "widget"); break; } - ++lineNo; - }); - cm.curOp.forceUpdate = true; - signal(cm, "refresh", this); - }), - - operation: function(f){return runInOp(this, f);}, - - refresh: methodOp(function() { - var oldHeight = this.display.cachedTextHeight; - regChange(this); - this.curOp.forceUpdate = true; - clearCaches(this); - this.scrollTo(this.doc.scrollLeft, this.doc.scrollTop); - updateGutterSpace(this); - if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5) - estimateLineHeights(this); - signal(this, "refresh", this); - }), - - swapDoc: methodOp(function(doc) { - var old = this.doc; - old.cm = null; - attachDoc(this, doc); - clearCaches(this); - this.display.input.reset(); - this.scrollTo(doc.scrollLeft, doc.scrollTop); - this.curOp.forceScroll = true; - signalLater(this, "swapDoc", this, old); - return old; - }), - - getInputField: function(){return this.display.input.getField();}, - getWrapperElement: function(){return this.display.wrapper;}, - getScrollerElement: function(){return this.display.scroller;}, - getGutterElement: function(){return this.display.gutters;} - }; - eventMixin(CodeMirror); - - // OPTION DEFAULTS - - // The default configuration options. - var defaults = CodeMirror.defaults = {}; - // Functions to run when options are changed. - var optionHandlers = CodeMirror.optionHandlers = {}; - - function option(name, deflt, handle, notOnInit) { - CodeMirror.defaults[name] = deflt; - if (handle) optionHandlers[name] = - notOnInit ? function(cm, val, old) {if (old != Init) handle(cm, val, old);} : handle; - } - - // Passed to option handlers when there is no old value. - var Init = CodeMirror.Init = {toString: function(){return "CodeMirror.Init";}}; - - // These two are, on init, called from the constructor because they - // have to be initialized before the editor can start at all. - option("value", "", function(cm, val) { - cm.setValue(val); - }, true); - option("mode", null, function(cm, val) { - cm.doc.modeOption = val; - loadMode(cm); - }, true); - - option("indentUnit", 2, loadMode, true); - option("indentWithTabs", false); - option("smartIndent", true); - option("tabSize", 4, function(cm) { - resetModeState(cm); - clearCaches(cm); - regChange(cm); - }, true); - option("lineSeparator", null, function(cm, val) { - cm.doc.lineSep = val; - if (!val) return; - var newBreaks = [], lineNo = cm.doc.first; - cm.doc.iter(function(line) { - for (var pos = 0;;) { - var found = line.text.indexOf(val, pos); - if (found == -1) break; - pos = found + val.length; - newBreaks.push(Pos(lineNo, found)); - } - lineNo++; - }); - for (var i = newBreaks.length - 1; i >= 0; i--) - replaceRange(cm.doc, val, newBreaks[i], Pos(newBreaks[i].line, newBreaks[i].ch + val.length)) - }); - option("specialChars", /[\t\u0000-\u0019\u00ad\u200b-\u200f\u2028\u2029\ufeff]/g, function(cm, val, old) { - cm.state.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g"); - if (old != CodeMirror.Init) cm.refresh(); - }); - option("specialCharPlaceholder", defaultSpecialCharPlaceholder, function(cm) {cm.refresh();}, true); - option("electricChars", true); - option("inputStyle", mobile ? "contenteditable" : "textarea", function() { - throw new Error("inputStyle can not (yet) be changed in a running editor"); // FIXME - }, true); - option("rtlMoveVisually", !windows); - option("wholeLineUpdateBefore", true); - - option("theme", "default", function(cm) { - themeChanged(cm); - guttersChanged(cm); - }, true); - option("keyMap", "default", function(cm, val, old) { - var next = getKeyMap(val); - var prev = old != CodeMirror.Init && getKeyMap(old); - if (prev && prev.detach) prev.detach(cm, next); - if (next.attach) next.attach(cm, prev || null); - }); - option("extraKeys", null); - - option("lineWrapping", false, wrappingChanged, true); - option("gutters", [], function(cm) { - setGuttersForLineNumbers(cm.options); - guttersChanged(cm); - }, true); - option("fixedGutter", true, function(cm, val) { - cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0"; - cm.refresh(); - }, true); - option("coverGutterNextToScrollbar", false, function(cm) {updateScrollbars(cm);}, true); - option("scrollbarStyle", "native", function(cm) { - initScrollbars(cm); - updateScrollbars(cm); - cm.display.scrollbars.setScrollTop(cm.doc.scrollTop); - cm.display.scrollbars.setScrollLeft(cm.doc.scrollLeft); - }, true); - option("lineNumbers", false, function(cm) { - setGuttersForLineNumbers(cm.options); - guttersChanged(cm); - }, true); - option("firstLineNumber", 1, guttersChanged, true); - option("lineNumberFormatter", function(integer) {return integer;}, guttersChanged, true); - option("showCursorWhenSelecting", false, updateSelection, true); - - option("resetSelectionOnContextMenu", true); - option("lineWiseCopyCut", true); - - option("readOnly", false, function(cm, val) { - if (val == "nocursor") { - onBlur(cm); - cm.display.input.blur(); - cm.display.disabled = true; - } else { - cm.display.disabled = false; - } - cm.display.input.readOnlyChanged(val) - }); - option("disableInput", false, function(cm, val) {if (!val) cm.display.input.reset();}, true); - option("dragDrop", true, dragDropChanged); - option("allowDropFileTypes", null); - - option("cursorBlinkRate", 530); - option("cursorScrollMargin", 0); - option("cursorHeight", 1, updateSelection, true); - option("singleCursorHeightPerLine", true, updateSelection, true); - option("workTime", 100); - option("workDelay", 100); - option("flattenSpans", true, resetModeState, true); - option("addModeClass", false, resetModeState, true); - option("pollInterval", 100); - option("undoDepth", 200, function(cm, val){cm.doc.history.undoDepth = val;}); - option("historyEventDelay", 1250); - option("viewportMargin", 10, function(cm){cm.refresh();}, true); - option("maxHighlightLength", 10000, resetModeState, true); - option("moveInputWithCursor", true, function(cm, val) { - if (!val) cm.display.input.resetPosition(); - }); - - option("tabindex", null, function(cm, val) { - cm.display.input.getField().tabIndex = val || ""; - }); - option("autofocus", null); - - // MODE DEFINITION AND QUERYING - - // Known modes, by name and by MIME - var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {}; - - // Extra arguments are stored as the mode's dependencies, which is - // used by (legacy) mechanisms like loadmode.js to automatically - // load a mode. (Preferred mechanism is the require/define calls.) - CodeMirror.defineMode = function(name, mode) { - if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name; - if (arguments.length > 2) - mode.dependencies = Array.prototype.slice.call(arguments, 2); - modes[name] = mode; - }; - - CodeMirror.defineMIME = function(mime, spec) { - mimeModes[mime] = spec; - }; - - // Given a MIME type, a {name, ...options} config object, or a name - // string, return a mode config object. - CodeMirror.resolveMode = function(spec) { - if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) { - spec = mimeModes[spec]; - } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) { - var found = mimeModes[spec.name]; - if (typeof found == "string") found = {name: found}; - spec = createObj(found, spec); - spec.name = found.name; - } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) { - return CodeMirror.resolveMode("application/xml"); - } - if (typeof spec == "string") return {name: spec}; - else return spec || {name: "null"}; - }; - - // Given a mode spec (anything that resolveMode accepts), find and - // initialize an actual mode object. - CodeMirror.getMode = function(options, spec) { - var spec = CodeMirror.resolveMode(spec); - var mfactory = modes[spec.name]; - if (!mfactory) return CodeMirror.getMode(options, "text/plain"); - var modeObj = mfactory(options, spec); - if (modeExtensions.hasOwnProperty(spec.name)) { - var exts = modeExtensions[spec.name]; - for (var prop in exts) { - if (!exts.hasOwnProperty(prop)) continue; - if (modeObj.hasOwnProperty(prop)) modeObj["_" + prop] = modeObj[prop]; - modeObj[prop] = exts[prop]; - } - } - modeObj.name = spec.name; - if (spec.helperType) modeObj.helperType = spec.helperType; - if (spec.modeProps) for (var prop in spec.modeProps) - modeObj[prop] = spec.modeProps[prop]; - - return modeObj; - }; - - // Minimal default mode. - CodeMirror.defineMode("null", function() { - return {token: function(stream) {stream.skipToEnd();}}; - }); - CodeMirror.defineMIME("text/plain", "null"); - - // This can be used to attach properties to mode objects from - // outside the actual mode definition. - var modeExtensions = CodeMirror.modeExtensions = {}; - CodeMirror.extendMode = function(mode, properties) { - var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {}); - copyObj(properties, exts); - }; - - // EXTENSIONS - - CodeMirror.defineExtension = function(name, func) { - CodeMirror.prototype[name] = func; - }; - CodeMirror.defineDocExtension = function(name, func) { - Doc.prototype[name] = func; - }; - CodeMirror.defineOption = option; - - var initHooks = []; - CodeMirror.defineInitHook = function(f) {initHooks.push(f);}; - - var helpers = CodeMirror.helpers = {}; - CodeMirror.registerHelper = function(type, name, value) { - if (!helpers.hasOwnProperty(type)) helpers[type] = CodeMirror[type] = {_global: []}; - helpers[type][name] = value; - }; - CodeMirror.registerGlobalHelper = function(type, name, predicate, value) { - CodeMirror.registerHelper(type, name, value); - helpers[type]._global.push({pred: predicate, val: value}); - }; - - // MODE STATE HANDLING - - // Utility functions for working with state. Exported because nested - // modes need to do this for their inner modes. - - var copyState = CodeMirror.copyState = function(mode, state) { - if (state === true) return state; - if (mode.copyState) return mode.copyState(state); - var nstate = {}; - for (var n in state) { - var val = state[n]; - if (val instanceof Array) val = val.concat([]); - nstate[n] = val; - } - return nstate; - }; - - var startState = CodeMirror.startState = function(mode, a1, a2) { - return mode.startState ? mode.startState(a1, a2) : true; - }; - - // Given a mode and a state (for that mode), find the inner mode and - // state at the position that the state refers to. - CodeMirror.innerMode = function(mode, state) { - while (mode.innerMode) { - var info = mode.innerMode(state); - if (!info || info.mode == mode) break; - state = info.state; - mode = info.mode; - } - return info || {mode: mode, state: state}; - }; - - // STANDARD COMMANDS - - // Commands are parameter-less actions that can be performed on an - // editor, mostly used for keybindings. - var commands = CodeMirror.commands = { - selectAll: function(cm) {cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()), sel_dontScroll);}, - singleSelection: function(cm) { - cm.setSelection(cm.getCursor("anchor"), cm.getCursor("head"), sel_dontScroll); - }, - killLine: function(cm) { - deleteNearSelection(cm, function(range) { - if (range.empty()) { - var len = getLine(cm.doc, range.head.line).text.length; - if (range.head.ch == len && range.head.line < cm.lastLine()) - return {from: range.head, to: Pos(range.head.line + 1, 0)}; - else - return {from: range.head, to: Pos(range.head.line, len)}; - } else { - return {from: range.from(), to: range.to()}; - } - }); - }, - deleteLine: function(cm) { - deleteNearSelection(cm, function(range) { - return {from: Pos(range.from().line, 0), - to: clipPos(cm.doc, Pos(range.to().line + 1, 0))}; - }); - }, - delLineLeft: function(cm) { - deleteNearSelection(cm, function(range) { - return {from: Pos(range.from().line, 0), to: range.from()}; - }); - }, - delWrappedLineLeft: function(cm) { - deleteNearSelection(cm, function(range) { - var top = cm.charCoords(range.head, "div").top + 5; - var leftPos = cm.coordsChar({left: 0, top: top}, "div"); - return {from: leftPos, to: range.from()}; - }); - }, - delWrappedLineRight: function(cm) { - deleteNearSelection(cm, function(range) { - var top = cm.charCoords(range.head, "div").top + 5; - var rightPos = cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div"); - return {from: range.from(), to: rightPos }; - }); - }, - undo: function(cm) {cm.undo();}, - redo: function(cm) {cm.redo();}, - undoSelection: function(cm) {cm.undoSelection();}, - redoSelection: function(cm) {cm.redoSelection();}, - goDocStart: function(cm) {cm.extendSelection(Pos(cm.firstLine(), 0));}, - goDocEnd: function(cm) {cm.extendSelection(Pos(cm.lastLine()));}, - goLineStart: function(cm) { - cm.extendSelectionsBy(function(range) { return lineStart(cm, range.head.line); }, - {origin: "+move", bias: 1}); - }, - goLineStartSmart: function(cm) { - cm.extendSelectionsBy(function(range) { - return lineStartSmart(cm, range.head); - }, {origin: "+move", bias: 1}); - }, - goLineEnd: function(cm) { - cm.extendSelectionsBy(function(range) { return lineEnd(cm, range.head.line); }, - {origin: "+move", bias: -1}); - }, - goLineRight: function(cm) { - cm.extendSelectionsBy(function(range) { - var top = cm.charCoords(range.head, "div").top + 5; - return cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div"); - }, sel_move); - }, - goLineLeft: function(cm) { - cm.extendSelectionsBy(function(range) { - var top = cm.charCoords(range.head, "div").top + 5; - return cm.coordsChar({left: 0, top: top}, "div"); - }, sel_move); - }, - goLineLeftSmart: function(cm) { - cm.extendSelectionsBy(function(range) { - var top = cm.charCoords(range.head, "div").top + 5; - var pos = cm.coordsChar({left: 0, top: top}, "div"); - if (pos.ch < cm.getLine(pos.line).search(/\S/)) return lineStartSmart(cm, range.head); - return pos; - }, sel_move); - }, - goLineUp: function(cm) {cm.moveV(-1, "line");}, - goLineDown: function(cm) {cm.moveV(1, "line");}, - goPageUp: function(cm) {cm.moveV(-1, "page");}, - goPageDown: function(cm) {cm.moveV(1, "page");}, - goCharLeft: function(cm) {cm.moveH(-1, "char");}, - goCharRight: function(cm) {cm.moveH(1, "char");}, - goColumnLeft: function(cm) {cm.moveH(-1, "column");}, - goColumnRight: function(cm) {cm.moveH(1, "column");}, - goWordLeft: function(cm) {cm.moveH(-1, "word");}, - goGroupRight: function(cm) {cm.moveH(1, "group");}, - goGroupLeft: function(cm) {cm.moveH(-1, "group");}, - goWordRight: function(cm) {cm.moveH(1, "word");}, - delCharBefore: function(cm) {cm.deleteH(-1, "char");}, - delCharAfter: function(cm) {cm.deleteH(1, "char");}, - delWordBefore: function(cm) {cm.deleteH(-1, "word");}, - delWordAfter: function(cm) {cm.deleteH(1, "word");}, - delGroupBefore: function(cm) {cm.deleteH(-1, "group");}, - delGroupAfter: function(cm) {cm.deleteH(1, "group");}, - indentAuto: function(cm) {cm.indentSelection("smart");}, - indentMore: function(cm) {cm.indentSelection("add");}, - indentLess: function(cm) {cm.indentSelection("subtract");}, - insertTab: function(cm) {cm.replaceSelection("\t");}, - insertSoftTab: function(cm) { - var spaces = [], ranges = cm.listSelections(), tabSize = cm.options.tabSize; - for (var i = 0; i < ranges.length; i++) { - var pos = ranges[i].from(); - var col = countColumn(cm.getLine(pos.line), pos.ch, tabSize); - spaces.push(new Array(tabSize - col % tabSize + 1).join(" ")); - } - cm.replaceSelections(spaces); - }, - defaultTab: function(cm) { - if (cm.somethingSelected()) cm.indentSelection("add"); - else cm.execCommand("insertTab"); - }, - transposeChars: function(cm) { - runInOp(cm, function() { - var ranges = cm.listSelections(), newSel = []; - for (var i = 0; i < ranges.length; i++) { - var cur = ranges[i].head, line = getLine(cm.doc, cur.line).text; - if (line) { - if (cur.ch == line.length) cur = new Pos(cur.line, cur.ch - 1); - if (cur.ch > 0) { - cur = new Pos(cur.line, cur.ch + 1); - cm.replaceRange(line.charAt(cur.ch - 1) + line.charAt(cur.ch - 2), - Pos(cur.line, cur.ch - 2), cur, "+transpose"); - } else if (cur.line > cm.doc.first) { - var prev = getLine(cm.doc, cur.line - 1).text; - if (prev) - cm.replaceRange(line.charAt(0) + cm.doc.lineSeparator() + - prev.charAt(prev.length - 1), - Pos(cur.line - 1, prev.length - 1), Pos(cur.line, 1), "+transpose"); - } - } - newSel.push(new Range(cur, cur)); - } - cm.setSelections(newSel); - }); - }, - newlineAndIndent: function(cm) { - runInOp(cm, function() { - var len = cm.listSelections().length; - for (var i = 0; i < len; i++) { - var range = cm.listSelections()[i]; - cm.replaceRange(cm.doc.lineSeparator(), range.anchor, range.head, "+input"); - cm.indentLine(range.from().line + 1, null, true); - } - ensureCursorVisible(cm); - }); - }, - toggleOverwrite: function(cm) {cm.toggleOverwrite();} - }; - - - // STANDARD KEYMAPS - - var keyMap = CodeMirror.keyMap = {}; - - keyMap.basic = { - "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown", - "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown", - "Delete": "delCharAfter", "Backspace": "delCharBefore", "Shift-Backspace": "delCharBefore", - "Tab": "defaultTab", "Shift-Tab": "indentAuto", - "Enter": "newlineAndIndent", "Insert": "toggleOverwrite", - "Esc": "singleSelection" - }; - // Note that the save and find-related commands aren't defined by - // default. User code or addons can define them. Unknown commands - // are simply ignored. - keyMap.pcDefault = { - "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo", - "Ctrl-Home": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Up": "goLineUp", "Ctrl-Down": "goLineDown", - "Ctrl-Left": "goGroupLeft", "Ctrl-Right": "goGroupRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd", - "Ctrl-Backspace": "delGroupBefore", "Ctrl-Delete": "delGroupAfter", "Ctrl-S": "save", "Ctrl-F": "find", - "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll", - "Ctrl-[": "indentLess", "Ctrl-]": "indentMore", - "Ctrl-U": "undoSelection", "Shift-Ctrl-U": "redoSelection", "Alt-U": "redoSelection", - fallthrough: "basic" - }; - // Very basic readline/emacs-style bindings, which are standard on Mac. - keyMap.emacsy = { - "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown", - "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd", - "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore", - "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars" - }; - keyMap.macDefault = { - "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo", - "Cmd-Home": "goDocStart", "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft", - "Alt-Right": "goGroupRight", "Cmd-Left": "goLineLeft", "Cmd-Right": "goLineRight", "Alt-Backspace": "delGroupBefore", - "Ctrl-Alt-Backspace": "delGroupAfter", "Alt-Delete": "delGroupAfter", "Cmd-S": "save", "Cmd-F": "find", - "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll", - "Cmd-[": "indentLess", "Cmd-]": "indentMore", "Cmd-Backspace": "delWrappedLineLeft", "Cmd-Delete": "delWrappedLineRight", - "Cmd-U": "undoSelection", "Shift-Cmd-U": "redoSelection", "Ctrl-Up": "goDocStart", "Ctrl-Down": "goDocEnd", - fallthrough: ["basic", "emacsy"] - }; - keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault; - - // KEYMAP DISPATCH - - function normalizeKeyName(name) { - var parts = name.split(/-(?!$)/), name = parts[parts.length - 1]; - var alt, ctrl, shift, cmd; - for (var i = 0; i < parts.length - 1; i++) { - var mod = parts[i]; - if (/^(cmd|meta|m)$/i.test(mod)) cmd = true; - else if (/^a(lt)?$/i.test(mod)) alt = true; - else if (/^(c|ctrl|control)$/i.test(mod)) ctrl = true; - else if (/^s(hift)$/i.test(mod)) shift = true; - else throw new Error("Unrecognized modifier name: " + mod); - } - if (alt) name = "Alt-" + name; - if (ctrl) name = "Ctrl-" + name; - if (cmd) name = "Cmd-" + name; - if (shift) name = "Shift-" + name; - return name; - } - - // This is a kludge to keep keymaps mostly working as raw objects - // (backwards compatibility) while at the same time support features - // like normalization and multi-stroke key bindings. It compiles a - // new normalized keymap, and then updates the old object to reflect - // this. - CodeMirror.normalizeKeyMap = function(keymap) { - var copy = {}; - for (var keyname in keymap) if (keymap.hasOwnProperty(keyname)) { - var value = keymap[keyname]; - if (/^(name|fallthrough|(de|at)tach)$/.test(keyname)) continue; - if (value == "...") { delete keymap[keyname]; continue; } - - var keys = map(keyname.split(" "), normalizeKeyName); - for (var i = 0; i < keys.length; i++) { - var val, name; - if (i == keys.length - 1) { - name = keys.join(" "); - val = value; - } else { - name = keys.slice(0, i + 1).join(" "); - val = "..."; - } - var prev = copy[name]; - if (!prev) copy[name] = val; - else if (prev != val) throw new Error("Inconsistent bindings for " + name); - } - delete keymap[keyname]; - } - for (var prop in copy) keymap[prop] = copy[prop]; - return keymap; - }; - - var lookupKey = CodeMirror.lookupKey = function(key, map, handle, context) { - map = getKeyMap(map); - var found = map.call ? map.call(key, context) : map[key]; - if (found === false) return "nothing"; - if (found === "...") return "multi"; - if (found != null && handle(found)) return "handled"; - - if (map.fallthrough) { - if (Object.prototype.toString.call(map.fallthrough) != "[object Array]") - return lookupKey(key, map.fallthrough, handle, context); - for (var i = 0; i < map.fallthrough.length; i++) { - var result = lookupKey(key, map.fallthrough[i], handle, context); - if (result) return result; - } - } - }; - - // Modifier key presses don't count as 'real' key presses for the - // purpose of keymap fallthrough. - var isModifierKey = CodeMirror.isModifierKey = function(value) { - var name = typeof value == "string" ? value : keyNames[value.keyCode]; - return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod"; - }; - - // Look up the name of a key as indicated by an event object. - var keyName = CodeMirror.keyName = function(event, noShift) { - if (presto && event.keyCode == 34 && event["char"]) return false; - var base = keyNames[event.keyCode], name = base; - if (name == null || event.altGraphKey) return false; - if (event.altKey && base != "Alt") name = "Alt-" + name; - if ((flipCtrlCmd ? event.metaKey : event.ctrlKey) && base != "Ctrl") name = "Ctrl-" + name; - if ((flipCtrlCmd ? event.ctrlKey : event.metaKey) && base != "Cmd") name = "Cmd-" + name; - if (!noShift && event.shiftKey && base != "Shift") name = "Shift-" + name; - return name; - }; - - function getKeyMap(val) { - return typeof val == "string" ? keyMap[val] : val; - } - - // FROMTEXTAREA - - CodeMirror.fromTextArea = function(textarea, options) { - options = options ? copyObj(options) : {}; - options.value = textarea.value; - if (!options.tabindex && textarea.tabIndex) - options.tabindex = textarea.tabIndex; - if (!options.placeholder && textarea.placeholder) - options.placeholder = textarea.placeholder; - // Set autofocus to true if this textarea is focused, or if it has - // autofocus and no other element is focused. - if (options.autofocus == null) { - var hasFocus = activeElt(); - options.autofocus = hasFocus == textarea || - textarea.getAttribute("autofocus") != null && hasFocus == document.body; - } - - function save() {textarea.value = cm.getValue();} - if (textarea.form) { - on(textarea.form, "submit", save); - // Deplorable hack to make the submit method do the right thing. - if (!options.leaveSubmitMethodAlone) { - var form = textarea.form, realSubmit = form.submit; - try { - var wrappedSubmit = form.submit = function() { - save(); - form.submit = realSubmit; - form.submit(); - form.submit = wrappedSubmit; - }; - } catch(e) {} - } - } - - options.finishInit = function(cm) { - cm.save = save; - cm.getTextArea = function() { return textarea; }; - cm.toTextArea = function() { - cm.toTextArea = isNaN; // Prevent this from being ran twice - save(); - textarea.parentNode.removeChild(cm.getWrapperElement()); - textarea.style.display = ""; - if (textarea.form) { - off(textarea.form, "submit", save); - if (typeof textarea.form.submit == "function") - textarea.form.submit = realSubmit; - } - }; - }; - - textarea.style.display = "none"; - var cm = CodeMirror(function(node) { - textarea.parentNode.insertBefore(node, textarea.nextSibling); - }, options); - return cm; - }; - - // STRING STREAM - - // Fed to the mode parsers, provides helper functions to make - // parsers more succinct. - - var StringStream = CodeMirror.StringStream = function(string, tabSize) { - this.pos = this.start = 0; - this.string = string; - this.tabSize = tabSize || 8; - this.lastColumnPos = this.lastColumnValue = 0; - this.lineStart = 0; - }; - - StringStream.prototype = { - eol: function() {return this.pos >= this.string.length;}, - sol: function() {return this.pos == this.lineStart;}, - peek: function() {return this.string.charAt(this.pos) || undefined;}, - next: function() { - if (this.pos < this.string.length) - return this.string.charAt(this.pos++); - }, - eat: function(match) { - var ch = this.string.charAt(this.pos); - if (typeof match == "string") var ok = ch == match; - else var ok = ch && (match.test ? match.test(ch) : match(ch)); - if (ok) {++this.pos; return ch;} - }, - eatWhile: function(match) { - var start = this.pos; - while (this.eat(match)){} - return this.pos > start; - }, - eatSpace: function() { - var start = this.pos; - while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos; - return this.pos > start; - }, - skipToEnd: function() {this.pos = this.string.length;}, - skipTo: function(ch) { - var found = this.string.indexOf(ch, this.pos); - if (found > -1) {this.pos = found; return true;} - }, - backUp: function(n) {this.pos -= n;}, - column: function() { - if (this.lastColumnPos < this.start) { - this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue); - this.lastColumnPos = this.start; - } - return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0); - }, - indentation: function() { - return countColumn(this.string, null, this.tabSize) - - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0); - }, - match: function(pattern, consume, caseInsensitive) { - if (typeof pattern == "string") { - var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;}; - var substr = this.string.substr(this.pos, pattern.length); - if (cased(substr) == cased(pattern)) { - if (consume !== false) this.pos += pattern.length; - return true; - } - } else { - var match = this.string.slice(this.pos).match(pattern); - if (match && match.index > 0) return null; - if (match && consume !== false) this.pos += match[0].length; - return match; - } - }, - current: function(){return this.string.slice(this.start, this.pos);}, - hideFirstChars: function(n, inner) { - this.lineStart += n; - try { return inner(); } - finally { this.lineStart -= n; } - } - }; - - // TEXTMARKERS - - // Created with markText and setBookmark methods. A TextMarker is a - // handle that can be used to clear or find a marked position in the - // document. Line objects hold arrays (markedSpans) containing - // {from, to, marker} object pointing to such marker objects, and - // indicating that such a marker is present on that line. Multiple - // lines may point to the same marker when it spans across lines. - // The spans will have null for their from/to properties when the - // marker continues beyond the start/end of the line. Markers have - // links back to the lines they currently touch. - - var nextMarkerId = 0; - - var TextMarker = CodeMirror.TextMarker = function(doc, type) { - this.lines = []; - this.type = type; - this.doc = doc; - this.id = ++nextMarkerId; - }; - eventMixin(TextMarker); - - // Clear the marker. - TextMarker.prototype.clear = function() { - if (this.explicitlyCleared) return; - var cm = this.doc.cm, withOp = cm && !cm.curOp; - if (withOp) startOperation(cm); - if (hasHandler(this, "clear")) { - var found = this.find(); - if (found) signalLater(this, "clear", found.from, found.to); - } - var min = null, max = null; - for (var i = 0; i < this.lines.length; ++i) { - var line = this.lines[i]; - var span = getMarkedSpanFor(line.markedSpans, this); - if (cm && !this.collapsed) regLineChange(cm, lineNo(line), "text"); - else if (cm) { - if (span.to != null) max = lineNo(line); - if (span.from != null) min = lineNo(line); - } - line.markedSpans = removeMarkedSpan(line.markedSpans, span); - if (span.from == null && this.collapsed && !lineIsHidden(this.doc, line) && cm) - updateLineHeight(line, textHeight(cm.display)); - } - if (cm && this.collapsed && !cm.options.lineWrapping) for (var i = 0; i < this.lines.length; ++i) { - var visual = visualLine(this.lines[i]), len = lineLength(visual); - if (len > cm.display.maxLineLength) { - cm.display.maxLine = visual; - cm.display.maxLineLength = len; - cm.display.maxLineChanged = true; - } - } - - if (min != null && cm && this.collapsed) regChange(cm, min, max + 1); - this.lines.length = 0; - this.explicitlyCleared = true; - if (this.atomic && this.doc.cantEdit) { - this.doc.cantEdit = false; - if (cm) reCheckSelection(cm.doc); - } - if (cm) signalLater(cm, "markerCleared", cm, this); - if (withOp) endOperation(cm); - if (this.parent) this.parent.clear(); - }; - - // Find the position of the marker in the document. Returns a {from, - // to} object by default. Side can be passed to get a specific side - // -- 0 (both), -1 (left), or 1 (right). When lineObj is true, the - // Pos objects returned contain a line object, rather than a line - // number (used to prevent looking up the same line twice). - TextMarker.prototype.find = function(side, lineObj) { - if (side == null && this.type == "bookmark") side = 1; - var from, to; - for (var i = 0; i < this.lines.length; ++i) { - var line = this.lines[i]; - var span = getMarkedSpanFor(line.markedSpans, this); - if (span.from != null) { - from = Pos(lineObj ? line : lineNo(line), span.from); - if (side == -1) return from; - } - if (span.to != null) { - to = Pos(lineObj ? line : lineNo(line), span.to); - if (side == 1) return to; - } - } - return from && {from: from, to: to}; - }; - - // Signals that the marker's widget changed, and surrounding layout - // should be recomputed. - TextMarker.prototype.changed = function() { - var pos = this.find(-1, true), widget = this, cm = this.doc.cm; - if (!pos || !cm) return; - runInOp(cm, function() { - var line = pos.line, lineN = lineNo(pos.line); - var view = findViewForLine(cm, lineN); - if (view) { - clearLineMeasurementCacheFor(view); - cm.curOp.selectionChanged = cm.curOp.forceUpdate = true; - } - cm.curOp.updateMaxLine = true; - if (!lineIsHidden(widget.doc, line) && widget.height != null) { - var oldHeight = widget.height; - widget.height = null; - var dHeight = widgetHeight(widget) - oldHeight; - if (dHeight) - updateLineHeight(line, line.height + dHeight); - } - }); - }; - - TextMarker.prototype.attachLine = function(line) { - if (!this.lines.length && this.doc.cm) { - var op = this.doc.cm.curOp; - if (!op.maybeHiddenMarkers || indexOf(op.maybeHiddenMarkers, this) == -1) - (op.maybeUnhiddenMarkers || (op.maybeUnhiddenMarkers = [])).push(this); - } - this.lines.push(line); - }; - TextMarker.prototype.detachLine = function(line) { - this.lines.splice(indexOf(this.lines, line), 1); - if (!this.lines.length && this.doc.cm) { - var op = this.doc.cm.curOp; - (op.maybeHiddenMarkers || (op.maybeHiddenMarkers = [])).push(this); - } - }; - - // Collapsed markers have unique ids, in order to be able to order - // them, which is needed for uniquely determining an outer marker - // when they overlap (they may nest, but not partially overlap). - var nextMarkerId = 0; - - // Create a marker, wire it up to the right lines, and - function markText(doc, from, to, options, type) { - // Shared markers (across linked documents) are handled separately - // (markTextShared will call out to this again, once per - // document). - if (options && options.shared) return markTextShared(doc, from, to, options, type); - // Ensure we are in an operation. - if (doc.cm && !doc.cm.curOp) return operation(doc.cm, markText)(doc, from, to, options, type); - - var marker = new TextMarker(doc, type), diff = cmp(from, to); - if (options) copyObj(options, marker, false); - // Don't connect empty markers unless clearWhenEmpty is false - if (diff > 0 || diff == 0 && marker.clearWhenEmpty !== false) - return marker; - if (marker.replacedWith) { - // Showing up as a widget implies collapsed (widget replaces text) - marker.collapsed = true; - marker.widgetNode = elt("span", [marker.replacedWith], "CodeMirror-widget"); - if (!options.handleMouseEvents) marker.widgetNode.setAttribute("cm-ignore-events", "true"); - if (options.insertLeft) marker.widgetNode.insertLeft = true; - } - if (marker.collapsed) { - if (conflictingCollapsedRange(doc, from.line, from, to, marker) || - from.line != to.line && conflictingCollapsedRange(doc, to.line, from, to, marker)) - throw new Error("Inserting collapsed marker partially overlapping an existing one"); - sawCollapsedSpans = true; - } - - if (marker.addToHistory) - addChangeToHistory(doc, {from: from, to: to, origin: "markText"}, doc.sel, NaN); - - var curLine = from.line, cm = doc.cm, updateMaxLine; - doc.iter(curLine, to.line + 1, function(line) { - if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(line) == cm.display.maxLine) - updateMaxLine = true; - if (marker.collapsed && curLine != from.line) updateLineHeight(line, 0); - addMarkedSpan(line, new MarkedSpan(marker, - curLine == from.line ? from.ch : null, - curLine == to.line ? to.ch : null)); - ++curLine; - }); - // lineIsHidden depends on the presence of the spans, so needs a second pass - if (marker.collapsed) doc.iter(from.line, to.line + 1, function(line) { - if (lineIsHidden(doc, line)) updateLineHeight(line, 0); - }); - - if (marker.clearOnEnter) on(marker, "beforeCursorEnter", function() { marker.clear(); }); - - if (marker.readOnly) { - sawReadOnlySpans = true; - if (doc.history.done.length || doc.history.undone.length) - doc.clearHistory(); - } - if (marker.collapsed) { - marker.id = ++nextMarkerId; - marker.atomic = true; - } - if (cm) { - // Sync editor state - if (updateMaxLine) cm.curOp.updateMaxLine = true; - if (marker.collapsed) - regChange(cm, from.line, to.line + 1); - else if (marker.className || marker.title || marker.startStyle || marker.endStyle || marker.css) - for (var i = from.line; i <= to.line; i++) regLineChange(cm, i, "text"); - if (marker.atomic) reCheckSelection(cm.doc); - signalLater(cm, "markerAdded", cm, marker); - } - return marker; - } - - // SHARED TEXTMARKERS - - // A shared marker spans multiple linked documents. It is - // implemented as a meta-marker-object controlling multiple normal - // markers. - var SharedTextMarker = CodeMirror.SharedTextMarker = function(markers, primary) { - this.markers = markers; - this.primary = primary; - for (var i = 0; i < markers.length; ++i) - markers[i].parent = this; - }; - eventMixin(SharedTextMarker); - - SharedTextMarker.prototype.clear = function() { - if (this.explicitlyCleared) return; - this.explicitlyCleared = true; - for (var i = 0; i < this.markers.length; ++i) - this.markers[i].clear(); - signalLater(this, "clear"); - }; - SharedTextMarker.prototype.find = function(side, lineObj) { - return this.primary.find(side, lineObj); - }; - - function markTextShared(doc, from, to, options, type) { - options = copyObj(options); - options.shared = false; - var markers = [markText(doc, from, to, options, type)], primary = markers[0]; - var widget = options.widgetNode; - linkedDocs(doc, function(doc) { - if (widget) options.widgetNode = widget.cloneNode(true); - markers.push(markText(doc, clipPos(doc, from), clipPos(doc, to), options, type)); - for (var i = 0; i < doc.linked.length; ++i) - if (doc.linked[i].isParent) return; - primary = lst(markers); - }); - return new SharedTextMarker(markers, primary); - } - - function findSharedMarkers(doc) { - return doc.findMarks(Pos(doc.first, 0), doc.clipPos(Pos(doc.lastLine())), - function(m) { return m.parent; }); - } - - function copySharedMarkers(doc, markers) { - for (var i = 0; i < markers.length; i++) { - var marker = markers[i], pos = marker.find(); - var mFrom = doc.clipPos(pos.from), mTo = doc.clipPos(pos.to); - if (cmp(mFrom, mTo)) { - var subMark = markText(doc, mFrom, mTo, marker.primary, marker.primary.type); - marker.markers.push(subMark); - subMark.parent = marker; - } - } - } - - function detachSharedMarkers(markers) { - for (var i = 0; i < markers.length; i++) { - var marker = markers[i], linked = [marker.primary.doc];; - linkedDocs(marker.primary.doc, function(d) { linked.push(d); }); - for (var j = 0; j < marker.markers.length; j++) { - var subMarker = marker.markers[j]; - if (indexOf(linked, subMarker.doc) == -1) { - subMarker.parent = null; - marker.markers.splice(j--, 1); - } - } - } - } - - // TEXTMARKER SPANS - - function MarkedSpan(marker, from, to) { - this.marker = marker; - this.from = from; this.to = to; - } - - // Search an array of spans for a span matching the given marker. - function getMarkedSpanFor(spans, marker) { - if (spans) for (var i = 0; i < spans.length; ++i) { - var span = spans[i]; - if (span.marker == marker) return span; - } - } - // Remove a span from an array, returning undefined if no spans are - // left (we don't store arrays for lines without spans). - function removeMarkedSpan(spans, span) { - for (var r, i = 0; i < spans.length; ++i) - if (spans[i] != span) (r || (r = [])).push(spans[i]); - return r; - } - // Add a span to a line. - function addMarkedSpan(line, span) { - line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span]; - span.marker.attachLine(line); - } - - // Used for the algorithm that adjusts markers for a change in the - // document. These functions cut an array of spans at a given - // character position, returning an array of remaining chunks (or - // undefined if nothing remains). - function markedSpansBefore(old, startCh, isInsert) { - if (old) for (var i = 0, nw; i < old.length; ++i) { - var span = old[i], marker = span.marker; - var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh); - if (startsBefore || span.from == startCh && marker.type == "bookmark" && (!isInsert || !span.marker.insertLeft)) { - var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh); - (nw || (nw = [])).push(new MarkedSpan(marker, span.from, endsAfter ? null : span.to)); - } - } - return nw; - } - function markedSpansAfter(old, endCh, isInsert) { - if (old) for (var i = 0, nw; i < old.length; ++i) { - var span = old[i], marker = span.marker; - var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh); - if (endsAfter || span.from == endCh && marker.type == "bookmark" && (!isInsert || span.marker.insertLeft)) { - var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh); - (nw || (nw = [])).push(new MarkedSpan(marker, startsBefore ? null : span.from - endCh, - span.to == null ? null : span.to - endCh)); - } - } - return nw; - } - - // Given a change object, compute the new set of marker spans that - // cover the line in which the change took place. Removes spans - // entirely within the change, reconnects spans belonging to the - // same marker that appear on both sides of the change, and cuts off - // spans partially within the change. Returns an array of span - // arrays with one element for each line in (after) the change. - function stretchSpansOverChange(doc, change) { - if (change.full) return null; - var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans; - var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans; - if (!oldFirst && !oldLast) return null; - - var startCh = change.from.ch, endCh = change.to.ch, isInsert = cmp(change.from, change.to) == 0; - // Get the spans that 'stick out' on both sides - var first = markedSpansBefore(oldFirst, startCh, isInsert); - var last = markedSpansAfter(oldLast, endCh, isInsert); - - // Next, merge those two ends - var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0); - if (first) { - // Fix up .to properties of first - for (var i = 0; i < first.length; ++i) { - var span = first[i]; - if (span.to == null) { - var found = getMarkedSpanFor(last, span.marker); - if (!found) span.to = startCh; - else if (sameLine) span.to = found.to == null ? null : found.to + offset; - } - } - } - if (last) { - // Fix up .from in last (or move them into first in case of sameLine) - for (var i = 0; i < last.length; ++i) { - var span = last[i]; - if (span.to != null) span.to += offset; - if (span.from == null) { - var found = getMarkedSpanFor(first, span.marker); - if (!found) { - span.from = offset; - if (sameLine) (first || (first = [])).push(span); - } - } else { - span.from += offset; - if (sameLine) (first || (first = [])).push(span); - } - } - } - // Make sure we didn't create any zero-length spans - if (first) first = clearEmptySpans(first); - if (last && last != first) last = clearEmptySpans(last); - - var newMarkers = [first]; - if (!sameLine) { - // Fill gap with whole-line-spans - var gap = change.text.length - 2, gapMarkers; - if (gap > 0 && first) - for (var i = 0; i < first.length; ++i) - if (first[i].to == null) - (gapMarkers || (gapMarkers = [])).push(new MarkedSpan(first[i].marker, null, null)); - for (var i = 0; i < gap; ++i) - newMarkers.push(gapMarkers); - newMarkers.push(last); - } - return newMarkers; - } - - // Remove spans that are empty and don't have a clearWhenEmpty - // option of false. - function clearEmptySpans(spans) { - for (var i = 0; i < spans.length; ++i) { - var span = spans[i]; - if (span.from != null && span.from == span.to && span.marker.clearWhenEmpty !== false) - spans.splice(i--, 1); - } - if (!spans.length) return null; - return spans; - } - - // Used for un/re-doing changes from the history. Combines the - // result of computing the existing spans with the set of spans that - // existed in the history (so that deleting around a span and then - // undoing brings back the span). - function mergeOldSpans(doc, change) { - var old = getOldSpans(doc, change); - var stretched = stretchSpansOverChange(doc, change); - if (!old) return stretched; - if (!stretched) return old; - - for (var i = 0; i < old.length; ++i) { - var oldCur = old[i], stretchCur = stretched[i]; - if (oldCur && stretchCur) { - spans: for (var j = 0; j < stretchCur.length; ++j) { - var span = stretchCur[j]; - for (var k = 0; k < oldCur.length; ++k) - if (oldCur[k].marker == span.marker) continue spans; - oldCur.push(span); - } - } else if (stretchCur) { - old[i] = stretchCur; - } - } - return old; - } - - // Used to 'clip' out readOnly ranges when making a change. - function removeReadOnlyRanges(doc, from, to) { - var markers = null; - doc.iter(from.line, to.line + 1, function(line) { - if (line.markedSpans) for (var i = 0; i < line.markedSpans.length; ++i) { - var mark = line.markedSpans[i].marker; - if (mark.readOnly && (!markers || indexOf(markers, mark) == -1)) - (markers || (markers = [])).push(mark); - } - }); - if (!markers) return null; - var parts = [{from: from, to: to}]; - for (var i = 0; i < markers.length; ++i) { - var mk = markers[i], m = mk.find(0); - for (var j = 0; j < parts.length; ++j) { - var p = parts[j]; - if (cmp(p.to, m.from) < 0 || cmp(p.from, m.to) > 0) continue; - var newParts = [j, 1], dfrom = cmp(p.from, m.from), dto = cmp(p.to, m.to); - if (dfrom < 0 || !mk.inclusiveLeft && !dfrom) - newParts.push({from: p.from, to: m.from}); - if (dto > 0 || !mk.inclusiveRight && !dto) - newParts.push({from: m.to, to: p.to}); - parts.splice.apply(parts, newParts); - j += newParts.length - 1; - } - } - return parts; - } - - // Connect or disconnect spans from a line. - function detachMarkedSpans(line) { - var spans = line.markedSpans; - if (!spans) return; - for (var i = 0; i < spans.length; ++i) - spans[i].marker.detachLine(line); - line.markedSpans = null; - } - function attachMarkedSpans(line, spans) { - if (!spans) return; - for (var i = 0; i < spans.length; ++i) - spans[i].marker.attachLine(line); - line.markedSpans = spans; - } - - // Helpers used when computing which overlapping collapsed span - // counts as the larger one. - function extraLeft(marker) { return marker.inclusiveLeft ? -1 : 0; } - function extraRight(marker) { return marker.inclusiveRight ? 1 : 0; } - - // Returns a number indicating which of two overlapping collapsed - // spans is larger (and thus includes the other). Falls back to - // comparing ids when the spans cover exactly the same range. - function compareCollapsedMarkers(a, b) { - var lenDiff = a.lines.length - b.lines.length; - if (lenDiff != 0) return lenDiff; - var aPos = a.find(), bPos = b.find(); - var fromCmp = cmp(aPos.from, bPos.from) || extraLeft(a) - extraLeft(b); - if (fromCmp) return -fromCmp; - var toCmp = cmp(aPos.to, bPos.to) || extraRight(a) - extraRight(b); - if (toCmp) return toCmp; - return b.id - a.id; - } - - // Find out whether a line ends or starts in a collapsed span. If - // so, return the marker for that span. - function collapsedSpanAtSide(line, start) { - var sps = sawCollapsedSpans && line.markedSpans, found; - if (sps) for (var sp, i = 0; i < sps.length; ++i) { - sp = sps[i]; - if (sp.marker.collapsed && (start ? sp.from : sp.to) == null && - (!found || compareCollapsedMarkers(found, sp.marker) < 0)) - found = sp.marker; - } - return found; - } - function collapsedSpanAtStart(line) { return collapsedSpanAtSide(line, true); } - function collapsedSpanAtEnd(line) { return collapsedSpanAtSide(line, false); } - - // Test whether there exists a collapsed span that partially - // overlaps (covers the start or end, but not both) of a new span. - // Such overlap is not allowed. - function conflictingCollapsedRange(doc, lineNo, from, to, marker) { - var line = getLine(doc, lineNo); - var sps = sawCollapsedSpans && line.markedSpans; - if (sps) for (var i = 0; i < sps.length; ++i) { - var sp = sps[i]; - if (!sp.marker.collapsed) continue; - var found = sp.marker.find(0); - var fromCmp = cmp(found.from, from) || extraLeft(sp.marker) - extraLeft(marker); - var toCmp = cmp(found.to, to) || extraRight(sp.marker) - extraRight(marker); - if (fromCmp >= 0 && toCmp <= 0 || fromCmp <= 0 && toCmp >= 0) continue; - if (fromCmp <= 0 && (cmp(found.to, from) > 0 || (sp.marker.inclusiveRight && marker.inclusiveLeft)) || - fromCmp >= 0 && (cmp(found.from, to) < 0 || (sp.marker.inclusiveLeft && marker.inclusiveRight))) - return true; - } - } - - // A visual line is a line as drawn on the screen. Folding, for - // example, can cause multiple logical lines to appear on the same - // visual line. This finds the start of the visual line that the - // given line is part of (usually that is the line itself). - function visualLine(line) { - var merged; - while (merged = collapsedSpanAtStart(line)) - line = merged.find(-1, true).line; - return line; - } - - // Returns an array of logical lines that continue the visual line - // started by the argument, or undefined if there are no such lines. - function visualLineContinued(line) { - var merged, lines; - while (merged = collapsedSpanAtEnd(line)) { - line = merged.find(1, true).line; - (lines || (lines = [])).push(line); - } - return lines; - } - - // Get the line number of the start of the visual line that the - // given line number is part of. - function visualLineNo(doc, lineN) { - var line = getLine(doc, lineN), vis = visualLine(line); - if (line == vis) return lineN; - return lineNo(vis); - } - // Get the line number of the start of the next visual line after - // the given line. - function visualLineEndNo(doc, lineN) { - if (lineN > doc.lastLine()) return lineN; - var line = getLine(doc, lineN), merged; - if (!lineIsHidden(doc, line)) return lineN; - while (merged = collapsedSpanAtEnd(line)) - line = merged.find(1, true).line; - return lineNo(line) + 1; - } - - // Compute whether a line is hidden. Lines count as hidden when they - // are part of a visual line that starts with another line, or when - // they are entirely covered by collapsed, non-widget span. - function lineIsHidden(doc, line) { - var sps = sawCollapsedSpans && line.markedSpans; - if (sps) for (var sp, i = 0; i < sps.length; ++i) { - sp = sps[i]; - if (!sp.marker.collapsed) continue; - if (sp.from == null) return true; - if (sp.marker.widgetNode) continue; - if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp)) - return true; - } - } - function lineIsHiddenInner(doc, line, span) { - if (span.to == null) { - var end = span.marker.find(1, true); - return lineIsHiddenInner(doc, end.line, getMarkedSpanFor(end.line.markedSpans, span.marker)); - } - if (span.marker.inclusiveRight && span.to == line.text.length) - return true; - for (var sp, i = 0; i < line.markedSpans.length; ++i) { - sp = line.markedSpans[i]; - if (sp.marker.collapsed && !sp.marker.widgetNode && sp.from == span.to && - (sp.to == null || sp.to != span.from) && - (sp.marker.inclusiveLeft || span.marker.inclusiveRight) && - lineIsHiddenInner(doc, line, sp)) return true; - } - } - - // LINE WIDGETS - - // Line widgets are block elements displayed above or below a line. - - var LineWidget = CodeMirror.LineWidget = function(doc, node, options) { - if (options) for (var opt in options) if (options.hasOwnProperty(opt)) - this[opt] = options[opt]; - this.doc = doc; - this.node = node; - }; - eventMixin(LineWidget); - - function adjustScrollWhenAboveVisible(cm, line, diff) { - if (heightAtLine(line) < ((cm.curOp && cm.curOp.scrollTop) || cm.doc.scrollTop)) - addToScrollPos(cm, null, diff); - } - - LineWidget.prototype.clear = function() { - var cm = this.doc.cm, ws = this.line.widgets, line = this.line, no = lineNo(line); - if (no == null || !ws) return; - for (var i = 0; i < ws.length; ++i) if (ws[i] == this) ws.splice(i--, 1); - if (!ws.length) line.widgets = null; - var height = widgetHeight(this); - updateLineHeight(line, Math.max(0, line.height - height)); - if (cm) runInOp(cm, function() { - adjustScrollWhenAboveVisible(cm, line, -height); - regLineChange(cm, no, "widget"); - }); - }; - LineWidget.prototype.changed = function() { - var oldH = this.height, cm = this.doc.cm, line = this.line; - this.height = null; - var diff = widgetHeight(this) - oldH; - if (!diff) return; - updateLineHeight(line, line.height + diff); - if (cm) runInOp(cm, function() { - cm.curOp.forceUpdate = true; - adjustScrollWhenAboveVisible(cm, line, diff); - }); - }; - - function widgetHeight(widget) { - if (widget.height != null) return widget.height; - var cm = widget.doc.cm; - if (!cm) return 0; - if (!contains(document.body, widget.node)) { - var parentStyle = "position: relative;"; - if (widget.coverGutter) - parentStyle += "margin-left: -" + cm.display.gutters.offsetWidth + "px;"; - if (widget.noHScroll) - parentStyle += "width: " + cm.display.wrapper.clientWidth + "px;"; - removeChildrenAndAdd(cm.display.measure, elt("div", [widget.node], null, parentStyle)); - } - return widget.height = widget.node.offsetHeight; - } - - function addLineWidget(doc, handle, node, options) { - var widget = new LineWidget(doc, node, options); - var cm = doc.cm; - if (cm && widget.noHScroll) cm.display.alignWidgets = true; - changeLine(doc, handle, "widget", function(line) { - var widgets = line.widgets || (line.widgets = []); - if (widget.insertAt == null) widgets.push(widget); - else widgets.splice(Math.min(widgets.length - 1, Math.max(0, widget.insertAt)), 0, widget); - widget.line = line; - if (cm && !lineIsHidden(doc, line)) { - var aboveVisible = heightAtLine(line) < doc.scrollTop; - updateLineHeight(line, line.height + widgetHeight(widget)); - if (aboveVisible) addToScrollPos(cm, null, widget.height); - cm.curOp.forceUpdate = true; - } - return true; - }); - return widget; - } - - // LINE DATA STRUCTURE - - // Line objects. These hold state related to a line, including - // highlighting info (the styles array). - var Line = CodeMirror.Line = function(text, markedSpans, estimateHeight) { - this.text = text; - attachMarkedSpans(this, markedSpans); - this.height = estimateHeight ? estimateHeight(this) : 1; - }; - eventMixin(Line); - Line.prototype.lineNo = function() { return lineNo(this); }; - - // Change the content (text, markers) of a line. Automatically - // invalidates cached information and tries to re-estimate the - // line's height. - function updateLine(line, text, markedSpans, estimateHeight) { - line.text = text; - if (line.stateAfter) line.stateAfter = null; - if (line.styles) line.styles = null; - if (line.order != null) line.order = null; - detachMarkedSpans(line); - attachMarkedSpans(line, markedSpans); - var estHeight = estimateHeight ? estimateHeight(line) : 1; - if (estHeight != line.height) updateLineHeight(line, estHeight); - } - - // Detach a line from the document tree and its markers. - function cleanUpLine(line) { - line.parent = null; - detachMarkedSpans(line); - } - - function extractLineClasses(type, output) { - if (type) for (;;) { - var lineClass = type.match(/(?:^|\s+)line-(background-)?(\S+)/); - if (!lineClass) break; - type = type.slice(0, lineClass.index) + type.slice(lineClass.index + lineClass[0].length); - var prop = lineClass[1] ? "bgClass" : "textClass"; - if (output[prop] == null) - output[prop] = lineClass[2]; - else if (!(new RegExp("(?:^|\s)" + lineClass[2] + "(?:$|\s)")).test(output[prop])) - output[prop] += " " + lineClass[2]; - } - return type; - } - - function callBlankLine(mode, state) { - if (mode.blankLine) return mode.blankLine(state); - if (!mode.innerMode) return; - var inner = CodeMirror.innerMode(mode, state); - if (inner.mode.blankLine) return inner.mode.blankLine(inner.state); - } - - function readToken(mode, stream, state, inner) { - for (var i = 0; i < 10; i++) { - if (inner) inner[0] = CodeMirror.innerMode(mode, state).mode; - var style = mode.token(stream, state); - if (stream.pos > stream.start) return style; - } - throw new Error("Mode " + mode.name + " failed to advance stream."); - } - - // Utility for getTokenAt and getLineTokens - function takeToken(cm, pos, precise, asArray) { - function getObj(copy) { - return {start: stream.start, end: stream.pos, - string: stream.current(), - type: style || null, - state: copy ? copyState(doc.mode, state) : state}; - } - - var doc = cm.doc, mode = doc.mode, style; - pos = clipPos(doc, pos); - var line = getLine(doc, pos.line), state = getStateBefore(cm, pos.line, precise); - var stream = new StringStream(line.text, cm.options.tabSize), tokens; - if (asArray) tokens = []; - while ((asArray || stream.pos < pos.ch) && !stream.eol()) { - stream.start = stream.pos; - style = readToken(mode, stream, state); - if (asArray) tokens.push(getObj(true)); - } - return asArray ? tokens : getObj(); - } - - // Run the given mode's parser over a line, calling f for each token. - function runMode(cm, text, mode, state, f, lineClasses, forceToEnd) { - var flattenSpans = mode.flattenSpans; - if (flattenSpans == null) flattenSpans = cm.options.flattenSpans; - var curStart = 0, curStyle = null; - var stream = new StringStream(text, cm.options.tabSize), style; - var inner = cm.options.addModeClass && [null]; - if (text == "") extractLineClasses(callBlankLine(mode, state), lineClasses); - while (!stream.eol()) { - if (stream.pos > cm.options.maxHighlightLength) { - flattenSpans = false; - if (forceToEnd) processLine(cm, text, state, stream.pos); - stream.pos = text.length; - style = null; - } else { - style = extractLineClasses(readToken(mode, stream, state, inner), lineClasses); - } - if (inner) { - var mName = inner[0].name; - if (mName) style = "m-" + (style ? mName + " " + style : mName); - } - if (!flattenSpans || curStyle != style) { - while (curStart < stream.start) { - curStart = Math.min(stream.start, curStart + 50000); - f(curStart, curStyle); - } - curStyle = style; - } - stream.start = stream.pos; - } - while (curStart < stream.pos) { - // Webkit seems to refuse to render text nodes longer than 57444 characters - var pos = Math.min(stream.pos, curStart + 50000); - f(pos, curStyle); - curStart = pos; - } - } - - // Compute a style array (an array starting with a mode generation - // -- for invalidation -- followed by pairs of end positions and - // style strings), which is used to highlight the tokens on the - // line. - function highlightLine(cm, line, state, forceToEnd) { - // A styles array always starts with a number identifying the - // mode/overlays that it is based on (for easy invalidation). - var st = [cm.state.modeGen], lineClasses = {}; - // Compute the base array of styles - runMode(cm, line.text, cm.doc.mode, state, function(end, style) { - st.push(end, style); - }, lineClasses, forceToEnd); - - // Run overlays, adjust style array. - for (var o = 0; o < cm.state.overlays.length; ++o) { - var overlay = cm.state.overlays[o], i = 1, at = 0; - runMode(cm, line.text, overlay.mode, true, function(end, style) { - var start = i; - // Ensure there's a token end at the current position, and that i points at it - while (at < end) { - var i_end = st[i]; - if (i_end > end) - st.splice(i, 1, end, st[i+1], i_end); - i += 2; - at = Math.min(end, i_end); - } - if (!style) return; - if (overlay.opaque) { - st.splice(start, i - start, end, "cm-overlay " + style); - i = start + 2; - } else { - for (; start < i; start += 2) { - var cur = st[start+1]; - st[start+1] = (cur ? cur + " " : "") + "cm-overlay " + style; - } - } - }, lineClasses); - } - - return {styles: st, classes: lineClasses.bgClass || lineClasses.textClass ? lineClasses : null}; - } - - function getLineStyles(cm, line, updateFrontier) { - if (!line.styles || line.styles[0] != cm.state.modeGen) { - var state = getStateBefore(cm, lineNo(line)); - var result = highlightLine(cm, line, line.text.length > cm.options.maxHighlightLength ? copyState(cm.doc.mode, state) : state); - line.stateAfter = state; - line.styles = result.styles; - if (result.classes) line.styleClasses = result.classes; - else if (line.styleClasses) line.styleClasses = null; - if (updateFrontier === cm.doc.frontier) cm.doc.frontier++; - } - return line.styles; - } - - // Lightweight form of highlight -- proceed over this line and - // update state, but don't save a style array. Used for lines that - // aren't currently visible. - function processLine(cm, text, state, startAt) { - var mode = cm.doc.mode; - var stream = new StringStream(text, cm.options.tabSize); - stream.start = stream.pos = startAt || 0; - if (text == "") callBlankLine(mode, state); - while (!stream.eol()) { - readToken(mode, stream, state); - stream.start = stream.pos; - } - } - - // Convert a style as returned by a mode (either null, or a string - // containing one or more styles) to a CSS style. This is cached, - // and also looks for line-wide styles. - var styleToClassCache = {}, styleToClassCacheWithMode = {}; - function interpretTokenStyle(style, options) { - if (!style || /^\s*$/.test(style)) return null; - var cache = options.addModeClass ? styleToClassCacheWithMode : styleToClassCache; - return cache[style] || - (cache[style] = style.replace(/\S+/g, "cm-$&")); - } - - // Render the DOM representation of the text of a line. Also builds - // up a 'line map', which points at the DOM nodes that represent - // specific stretches of text, and is used by the measuring code. - // The returned object contains the DOM node, this map, and - // information about line-wide styles that were set by the mode. - function buildLineContent(cm, lineView) { - // The padding-right forces the element to have a 'border', which - // is needed on Webkit to be able to get line-level bounding - // rectangles for it (in measureChar). - var content = elt("span", null, null, webkit ? "padding-right: .1px" : null); - var builder = {pre: elt("pre", [content], "CodeMirror-line"), content: content, - col: 0, pos: 0, cm: cm, - splitSpaces: (ie || webkit) && cm.getOption("lineWrapping")}; - lineView.measure = {}; - - // Iterate over the logical lines that make up this visual line. - for (var i = 0; i <= (lineView.rest ? lineView.rest.length : 0); i++) { - var line = i ? lineView.rest[i - 1] : lineView.line, order; - builder.pos = 0; - builder.addToken = buildToken; - // Optionally wire in some hacks into the token-rendering - // algorithm, to deal with browser quirks. - if (hasBadBidiRects(cm.display.measure) && (order = getOrder(line))) - builder.addToken = buildTokenBadBidi(builder.addToken, order); - builder.map = []; - var allowFrontierUpdate = lineView != cm.display.externalMeasured && lineNo(line); - insertLineContent(line, builder, getLineStyles(cm, line, allowFrontierUpdate)); - if (line.styleClasses) { - if (line.styleClasses.bgClass) - builder.bgClass = joinClasses(line.styleClasses.bgClass, builder.bgClass || ""); - if (line.styleClasses.textClass) - builder.textClass = joinClasses(line.styleClasses.textClass, builder.textClass || ""); - } - - // Ensure at least a single node is present, for measuring. - if (builder.map.length == 0) - builder.map.push(0, 0, builder.content.appendChild(zeroWidthElement(cm.display.measure))); - - // Store the map and a cache object for the current logical line - if (i == 0) { - lineView.measure.map = builder.map; - lineView.measure.cache = {}; - } else { - (lineView.measure.maps || (lineView.measure.maps = [])).push(builder.map); - (lineView.measure.caches || (lineView.measure.caches = [])).push({}); - } - } - - // See issue #2901 - if (webkit && /\bcm-tab\b/.test(builder.content.lastChild.className)) - builder.content.className = "cm-tab-wrap-hack"; - - signal(cm, "renderLine", cm, lineView.line, builder.pre); - if (builder.pre.className) - builder.textClass = joinClasses(builder.pre.className, builder.textClass || ""); - - return builder; - } - - function defaultSpecialCharPlaceholder(ch) { - var token = elt("span", "\u2022", "cm-invalidchar"); - token.title = "\\u" + ch.charCodeAt(0).toString(16); - token.setAttribute("aria-label", token.title); - return token; - } - - // Build up the DOM representation for a single token, and add it to - // the line map. Takes care to render special characters separately. - function buildToken(builder, text, style, startStyle, endStyle, title, css) { - if (!text) return; - var displayText = builder.splitSpaces ? text.replace(/ {3,}/g, splitSpaces) : text; - var special = builder.cm.state.specialChars, mustWrap = false; - if (!special.test(text)) { - builder.col += text.length; - var content = document.createTextNode(displayText); - builder.map.push(builder.pos, builder.pos + text.length, content); - if (ie && ie_version < 9) mustWrap = true; - builder.pos += text.length; - } else { - var content = document.createDocumentFragment(), pos = 0; - while (true) { - special.lastIndex = pos; - var m = special.exec(text); - var skipped = m ? m.index - pos : text.length - pos; - if (skipped) { - var txt = document.createTextNode(displayText.slice(pos, pos + skipped)); - if (ie && ie_version < 9) content.appendChild(elt("span", [txt])); - else content.appendChild(txt); - builder.map.push(builder.pos, builder.pos + skipped, txt); - builder.col += skipped; - builder.pos += skipped; - } - if (!m) break; - pos += skipped + 1; - if (m[0] == "\t") { - var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize; - var txt = content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab")); - txt.setAttribute("role", "presentation"); - txt.setAttribute("cm-text", "\t"); - builder.col += tabWidth; - } else if (m[0] == "\r" || m[0] == "\n") { - var txt = content.appendChild(elt("span", m[0] == "\r" ? "\u240d" : "\u2424", "cm-invalidchar")); - txt.setAttribute("cm-text", m[0]); - builder.col += 1; - } else { - var txt = builder.cm.options.specialCharPlaceholder(m[0]); - txt.setAttribute("cm-text", m[0]); - if (ie && ie_version < 9) content.appendChild(elt("span", [txt])); - else content.appendChild(txt); - builder.col += 1; - } - builder.map.push(builder.pos, builder.pos + 1, txt); - builder.pos++; - } - } - if (style || startStyle || endStyle || mustWrap || css) { - var fullStyle = style || ""; - if (startStyle) fullStyle += startStyle; - if (endStyle) fullStyle += endStyle; - var token = elt("span", [content], fullStyle, css); - if (title) token.title = title; - return builder.content.appendChild(token); - } - builder.content.appendChild(content); - } - - function splitSpaces(old) { - var out = " "; - for (var i = 0; i < old.length - 2; ++i) out += i % 2 ? " " : "\u00a0"; - out += " "; - return out; - } - - // Work around nonsense dimensions being reported for stretches of - // right-to-left text. - function buildTokenBadBidi(inner, order) { - return function(builder, text, style, startStyle, endStyle, title, css) { - style = style ? style + " cm-force-border" : "cm-force-border"; - var start = builder.pos, end = start + text.length; - for (;;) { - // Find the part that overlaps with the start of this text - for (var i = 0; i < order.length; i++) { - var part = order[i]; - if (part.to > start && part.from <= start) break; - } - if (part.to >= end) return inner(builder, text, style, startStyle, endStyle, title, css); - inner(builder, text.slice(0, part.to - start), style, startStyle, null, title, css); - startStyle = null; - text = text.slice(part.to - start); - start = part.to; - } - }; - } - - function buildCollapsedSpan(builder, size, marker, ignoreWidget) { - var widget = !ignoreWidget && marker.widgetNode; - if (widget) builder.map.push(builder.pos, builder.pos + size, widget); - if (!ignoreWidget && builder.cm.display.input.needsContentAttribute) { - if (!widget) - widget = builder.content.appendChild(document.createElement("span")); - widget.setAttribute("cm-marker", marker.id); - } - if (widget) { - builder.cm.display.input.setUneditable(widget); - builder.content.appendChild(widget); - } - builder.pos += size; - } - - // Outputs a number of spans to make up a line, taking highlighting - // and marked text into account. - function insertLineContent(line, builder, styles) { - var spans = line.markedSpans, allText = line.text, at = 0; - if (!spans) { - for (var i = 1; i < styles.length; i+=2) - builder.addToken(builder, allText.slice(at, at = styles[i]), interpretTokenStyle(styles[i+1], builder.cm.options)); - return; - } - - var len = allText.length, pos = 0, i = 1, text = "", style, css; - var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, title, collapsed; - for (;;) { - if (nextChange == pos) { // Update current marker set - spanStyle = spanEndStyle = spanStartStyle = title = css = ""; - collapsed = null; nextChange = Infinity; - var foundBookmarks = []; - for (var j = 0; j < spans.length; ++j) { - var sp = spans[j], m = sp.marker; - if (m.type == "bookmark" && sp.from == pos && m.widgetNode) { - foundBookmarks.push(m); - } else if (sp.from <= pos && (sp.to == null || sp.to > pos || m.collapsed && sp.to == pos && sp.from == pos)) { - if (sp.to != null && sp.to != pos && nextChange > sp.to) { - nextChange = sp.to; - spanEndStyle = ""; - } - if (m.className) spanStyle += " " + m.className; - if (m.css) css = (css ? css + ";" : "") + m.css; - if (m.startStyle && sp.from == pos) spanStartStyle += " " + m.startStyle; - if (m.endStyle && sp.to == nextChange) spanEndStyle += " " + m.endStyle; - if (m.title && !title) title = m.title; - if (m.collapsed && (!collapsed || compareCollapsedMarkers(collapsed.marker, m) < 0)) - collapsed = sp; - } else if (sp.from > pos && nextChange > sp.from) { - nextChange = sp.from; - } - } - if (collapsed && (collapsed.from || 0) == pos) { - buildCollapsedSpan(builder, (collapsed.to == null ? len + 1 : collapsed.to) - pos, - collapsed.marker, collapsed.from == null); - if (collapsed.to == null) return; - if (collapsed.to == pos) collapsed = false; - } - if (!collapsed && foundBookmarks.length) for (var j = 0; j < foundBookmarks.length; ++j) - buildCollapsedSpan(builder, 0, foundBookmarks[j]); - } - if (pos >= len) break; - - var upto = Math.min(len, nextChange); - while (true) { - if (text) { - var end = pos + text.length; - if (!collapsed) { - var tokenText = end > upto ? text.slice(0, upto - pos) : text; - builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle, - spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", title, css); - } - if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;} - pos = end; - spanStartStyle = ""; - } - text = allText.slice(at, at = styles[i++]); - style = interpretTokenStyle(styles[i++], builder.cm.options); - } - } - } - - // DOCUMENT DATA STRUCTURE - - // By default, updates that start and end at the beginning of a line - // are treated specially, in order to make the association of line - // widgets and marker elements with the text behave more intuitive. - function isWholeLineUpdate(doc, change) { - return change.from.ch == 0 && change.to.ch == 0 && lst(change.text) == "" && - (!doc.cm || doc.cm.options.wholeLineUpdateBefore); - } - - // Perform a change on the document data structure. - function updateDoc(doc, change, markedSpans, estimateHeight) { - function spansFor(n) {return markedSpans ? markedSpans[n] : null;} - function update(line, text, spans) { - updateLine(line, text, spans, estimateHeight); - signalLater(line, "change", line, change); - } - function linesFor(start, end) { - for (var i = start, result = []; i < end; ++i) - result.push(new Line(text[i], spansFor(i), estimateHeight)); - return result; - } - - var from = change.from, to = change.to, text = change.text; - var firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line); - var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line; - - // Adjust the line structure - if (change.full) { - doc.insert(0, linesFor(0, text.length)); - doc.remove(text.length, doc.size - text.length); - } else if (isWholeLineUpdate(doc, change)) { - // This is a whole-line replace. Treated specially to make - // sure line objects move the way they are supposed to. - var added = linesFor(0, text.length - 1); - update(lastLine, lastLine.text, lastSpans); - if (nlines) doc.remove(from.line, nlines); - if (added.length) doc.insert(from.line, added); - } else if (firstLine == lastLine) { - if (text.length == 1) { - update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans); - } else { - var added = linesFor(1, text.length - 1); - added.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight)); - update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0)); - doc.insert(from.line + 1, added); - } - } else if (text.length == 1) { - update(firstLine, firstLine.text.slice(0, from.ch) + text[0] + lastLine.text.slice(to.ch), spansFor(0)); - doc.remove(from.line + 1, nlines); - } else { - update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0)); - update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans); - var added = linesFor(1, text.length - 1); - if (nlines > 1) doc.remove(from.line + 1, nlines - 1); - doc.insert(from.line + 1, added); - } - - signalLater(doc, "change", doc, change); - } - - // The document is represented as a BTree consisting of leaves, with - // chunk of lines in them, and branches, with up to ten leaves or - // other branch nodes below them. The top node is always a branch - // node, and is the document object itself (meaning it has - // additional methods and properties). - // - // All nodes have parent links. The tree is used both to go from - // line numbers to line objects, and to go from objects to numbers. - // It also indexes by height, and is used to convert between height - // and line object, and to find the total height of the document. - // - // See also http://marijnhaverbeke.nl/blog/codemirror-line-tree.html - - function LeafChunk(lines) { - this.lines = lines; - this.parent = null; - for (var i = 0, height = 0; i < lines.length; ++i) { - lines[i].parent = this; - height += lines[i].height; - } - this.height = height; - } - - LeafChunk.prototype = { - chunkSize: function() { return this.lines.length; }, - // Remove the n lines at offset 'at'. - removeInner: function(at, n) { - for (var i = at, e = at + n; i < e; ++i) { - var line = this.lines[i]; - this.height -= line.height; - cleanUpLine(line); - signalLater(line, "delete"); - } - this.lines.splice(at, n); - }, - // Helper used to collapse a small branch into a single leaf. - collapse: function(lines) { - lines.push.apply(lines, this.lines); - }, - // Insert the given array of lines at offset 'at', count them as - // having the given height. - insertInner: function(at, lines, height) { - this.height += height; - this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at)); - for (var i = 0; i < lines.length; ++i) lines[i].parent = this; - }, - // Used to iterate over a part of the tree. - iterN: function(at, n, op) { - for (var e = at + n; at < e; ++at) - if (op(this.lines[at])) return true; - } - }; - - function BranchChunk(children) { - this.children = children; - var size = 0, height = 0; - for (var i = 0; i < children.length; ++i) { - var ch = children[i]; - size += ch.chunkSize(); height += ch.height; - ch.parent = this; - } - this.size = size; - this.height = height; - this.parent = null; - } - - BranchChunk.prototype = { - chunkSize: function() { return this.size; }, - removeInner: function(at, n) { - this.size -= n; - for (var i = 0; i < this.children.length; ++i) { - var child = this.children[i], sz = child.chunkSize(); - if (at < sz) { - var rm = Math.min(n, sz - at), oldHeight = child.height; - child.removeInner(at, rm); - this.height -= oldHeight - child.height; - if (sz == rm) { this.children.splice(i--, 1); child.parent = null; } - if ((n -= rm) == 0) break; - at = 0; - } else at -= sz; - } - // If the result is smaller than 25 lines, ensure that it is a - // single leaf node. - if (this.size - n < 25 && - (this.children.length > 1 || !(this.children[0] instanceof LeafChunk))) { - var lines = []; - this.collapse(lines); - this.children = [new LeafChunk(lines)]; - this.children[0].parent = this; - } - }, - collapse: function(lines) { - for (var i = 0; i < this.children.length; ++i) this.children[i].collapse(lines); - }, - insertInner: function(at, lines, height) { - this.size += lines.length; - this.height += height; - for (var i = 0; i < this.children.length; ++i) { - var child = this.children[i], sz = child.chunkSize(); - if (at <= sz) { - child.insertInner(at, lines, height); - if (child.lines && child.lines.length > 50) { - while (child.lines.length > 50) { - var spilled = child.lines.splice(child.lines.length - 25, 25); - var newleaf = new LeafChunk(spilled); - child.height -= newleaf.height; - this.children.splice(i + 1, 0, newleaf); - newleaf.parent = this; - } - this.maybeSpill(); - } - break; - } - at -= sz; - } - }, - // When a node has grown, check whether it should be split. - maybeSpill: function() { - if (this.children.length <= 10) return; - var me = this; - do { - var spilled = me.children.splice(me.children.length - 5, 5); - var sibling = new BranchChunk(spilled); - if (!me.parent) { // Become the parent node - var copy = new BranchChunk(me.children); - copy.parent = me; - me.children = [copy, sibling]; - me = copy; - } else { - me.size -= sibling.size; - me.height -= sibling.height; - var myIndex = indexOf(me.parent.children, me); - me.parent.children.splice(myIndex + 1, 0, sibling); - } - sibling.parent = me.parent; - } while (me.children.length > 10); - me.parent.maybeSpill(); - }, - iterN: function(at, n, op) { - for (var i = 0; i < this.children.length; ++i) { - var child = this.children[i], sz = child.chunkSize(); - if (at < sz) { - var used = Math.min(n, sz - at); - if (child.iterN(at, used, op)) return true; - if ((n -= used) == 0) break; - at = 0; - } else at -= sz; - } - } - }; - - var nextDocId = 0; - var Doc = CodeMirror.Doc = function(text, mode, firstLine, lineSep) { - if (!(this instanceof Doc)) return new Doc(text, mode, firstLine, lineSep); - if (firstLine == null) firstLine = 0; - - BranchChunk.call(this, [new LeafChunk([new Line("", null)])]); - this.first = firstLine; - this.scrollTop = this.scrollLeft = 0; - this.cantEdit = false; - this.cleanGeneration = 1; - this.frontier = firstLine; - var start = Pos(firstLine, 0); - this.sel = simpleSelection(start); - this.history = new History(null); - this.id = ++nextDocId; - this.modeOption = mode; - this.lineSep = lineSep; - this.extend = false; - - if (typeof text == "string") text = this.splitLines(text); - updateDoc(this, {from: start, to: start, text: text}); - setSelection(this, simpleSelection(start), sel_dontScroll); - }; - - Doc.prototype = createObj(BranchChunk.prototype, { - constructor: Doc, - // Iterate over the document. Supports two forms -- with only one - // argument, it calls that for each line in the document. With - // three, it iterates over the range given by the first two (with - // the second being non-inclusive). - iter: function(from, to, op) { - if (op) this.iterN(from - this.first, to - from, op); - else this.iterN(this.first, this.first + this.size, from); - }, - - // Non-public interface for adding and removing lines. - insert: function(at, lines) { - var height = 0; - for (var i = 0; i < lines.length; ++i) height += lines[i].height; - this.insertInner(at - this.first, lines, height); - }, - remove: function(at, n) { this.removeInner(at - this.first, n); }, - - // From here, the methods are part of the public interface. Most - // are also available from CodeMirror (editor) instances. - - getValue: function(lineSep) { - var lines = getLines(this, this.first, this.first + this.size); - if (lineSep === false) return lines; - return lines.join(lineSep || this.lineSeparator()); - }, - setValue: docMethodOp(function(code) { - var top = Pos(this.first, 0), last = this.first + this.size - 1; - makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length), - text: this.splitLines(code), origin: "setValue", full: true}, true); - setSelection(this, simpleSelection(top)); - }), - replaceRange: function(code, from, to, origin) { - from = clipPos(this, from); - to = to ? clipPos(this, to) : from; - replaceRange(this, code, from, to, origin); - }, - getRange: function(from, to, lineSep) { - var lines = getBetween(this, clipPos(this, from), clipPos(this, to)); - if (lineSep === false) return lines; - return lines.join(lineSep || this.lineSeparator()); - }, - - getLine: function(line) {var l = this.getLineHandle(line); return l && l.text;}, - - getLineHandle: function(line) {if (isLine(this, line)) return getLine(this, line);}, - getLineNumber: function(line) {return lineNo(line);}, - - getLineHandleVisualStart: function(line) { - if (typeof line == "number") line = getLine(this, line); - return visualLine(line); - }, - - lineCount: function() {return this.size;}, - firstLine: function() {return this.first;}, - lastLine: function() {return this.first + this.size - 1;}, - - clipPos: function(pos) {return clipPos(this, pos);}, - - getCursor: function(start) { - var range = this.sel.primary(), pos; - if (start == null || start == "head") pos = range.head; - else if (start == "anchor") pos = range.anchor; - else if (start == "end" || start == "to" || start === false) pos = range.to(); - else pos = range.from(); - return pos; - }, - listSelections: function() { return this.sel.ranges; }, - somethingSelected: function() {return this.sel.somethingSelected();}, - - setCursor: docMethodOp(function(line, ch, options) { - setSimpleSelection(this, clipPos(this, typeof line == "number" ? Pos(line, ch || 0) : line), null, options); - }), - setSelection: docMethodOp(function(anchor, head, options) { - setSimpleSelection(this, clipPos(this, anchor), clipPos(this, head || anchor), options); - }), - extendSelection: docMethodOp(function(head, other, options) { - extendSelection(this, clipPos(this, head), other && clipPos(this, other), options); - }), - extendSelections: docMethodOp(function(heads, options) { - extendSelections(this, clipPosArray(this, heads, options)); - }), - extendSelectionsBy: docMethodOp(function(f, options) { - extendSelections(this, map(this.sel.ranges, f), options); - }), - setSelections: docMethodOp(function(ranges, primary, options) { - if (!ranges.length) return; - for (var i = 0, out = []; i < ranges.length; i++) - out[i] = new Range(clipPos(this, ranges[i].anchor), - clipPos(this, ranges[i].head)); - if (primary == null) primary = Math.min(ranges.length - 1, this.sel.primIndex); - setSelection(this, normalizeSelection(out, primary), options); - }), - addSelection: docMethodOp(function(anchor, head, options) { - var ranges = this.sel.ranges.slice(0); - ranges.push(new Range(clipPos(this, anchor), clipPos(this, head || anchor))); - setSelection(this, normalizeSelection(ranges, ranges.length - 1), options); - }), - - getSelection: function(lineSep) { - var ranges = this.sel.ranges, lines; - for (var i = 0; i < ranges.length; i++) { - var sel = getBetween(this, ranges[i].from(), ranges[i].to()); - lines = lines ? lines.concat(sel) : sel; - } - if (lineSep === false) return lines; - else return lines.join(lineSep || this.lineSeparator()); - }, - getSelections: function(lineSep) { - var parts = [], ranges = this.sel.ranges; - for (var i = 0; i < ranges.length; i++) { - var sel = getBetween(this, ranges[i].from(), ranges[i].to()); - if (lineSep !== false) sel = sel.join(lineSep || this.lineSeparator()); - parts[i] = sel; - } - return parts; - }, - replaceSelection: function(code, collapse, origin) { - var dup = []; - for (var i = 0; i < this.sel.ranges.length; i++) - dup[i] = code; - this.replaceSelections(dup, collapse, origin || "+input"); - }, - replaceSelections: docMethodOp(function(code, collapse, origin) { - var changes = [], sel = this.sel; - for (var i = 0; i < sel.ranges.length; i++) { - var range = sel.ranges[i]; - changes[i] = {from: range.from(), to: range.to(), text: this.splitLines(code[i]), origin: origin}; - } - var newSel = collapse && collapse != "end" && computeReplacedSel(this, changes, collapse); - for (var i = changes.length - 1; i >= 0; i--) - makeChange(this, changes[i]); - if (newSel) setSelectionReplaceHistory(this, newSel); - else if (this.cm) ensureCursorVisible(this.cm); - }), - undo: docMethodOp(function() {makeChangeFromHistory(this, "undo");}), - redo: docMethodOp(function() {makeChangeFromHistory(this, "redo");}), - undoSelection: docMethodOp(function() {makeChangeFromHistory(this, "undo", true);}), - redoSelection: docMethodOp(function() {makeChangeFromHistory(this, "redo", true);}), - - setExtending: function(val) {this.extend = val;}, - getExtending: function() {return this.extend;}, - - historySize: function() { - var hist = this.history, done = 0, undone = 0; - for (var i = 0; i < hist.done.length; i++) if (!hist.done[i].ranges) ++done; - for (var i = 0; i < hist.undone.length; i++) if (!hist.undone[i].ranges) ++undone; - return {undo: done, redo: undone}; - }, - clearHistory: function() {this.history = new History(this.history.maxGeneration);}, - - markClean: function() { - this.cleanGeneration = this.changeGeneration(true); - }, - changeGeneration: function(forceSplit) { - if (forceSplit) - this.history.lastOp = this.history.lastSelOp = this.history.lastOrigin = null; - return this.history.generation; - }, - isClean: function (gen) { - return this.history.generation == (gen || this.cleanGeneration); - }, - - getHistory: function() { - return {done: copyHistoryArray(this.history.done), - undone: copyHistoryArray(this.history.undone)}; - }, - setHistory: function(histData) { - var hist = this.history = new History(this.history.maxGeneration); - hist.done = copyHistoryArray(histData.done.slice(0), null, true); - hist.undone = copyHistoryArray(histData.undone.slice(0), null, true); - }, - - addLineClass: docMethodOp(function(handle, where, cls) { - return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function(line) { - var prop = where == "text" ? "textClass" - : where == "background" ? "bgClass" - : where == "gutter" ? "gutterClass" : "wrapClass"; - if (!line[prop]) line[prop] = cls; - else if (classTest(cls).test(line[prop])) return false; - else line[prop] += " " + cls; - return true; - }); - }), - removeLineClass: docMethodOp(function(handle, where, cls) { - return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function(line) { - var prop = where == "text" ? "textClass" - : where == "background" ? "bgClass" - : where == "gutter" ? "gutterClass" : "wrapClass"; - var cur = line[prop]; - if (!cur) return false; - else if (cls == null) line[prop] = null; - else { - var found = cur.match(classTest(cls)); - if (!found) return false; - var end = found.index + found[0].length; - line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? "" : " ") + cur.slice(end) || null; - } - return true; - }); - }), - - addLineWidget: docMethodOp(function(handle, node, options) { - return addLineWidget(this, handle, node, options); - }), - removeLineWidget: function(widget) { widget.clear(); }, - - markText: function(from, to, options) { - return markText(this, clipPos(this, from), clipPos(this, to), options, options && options.type || "range"); - }, - setBookmark: function(pos, options) { - var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options), - insertLeft: options && options.insertLeft, - clearWhenEmpty: false, shared: options && options.shared, - handleMouseEvents: options && options.handleMouseEvents}; - pos = clipPos(this, pos); - return markText(this, pos, pos, realOpts, "bookmark"); - }, - findMarksAt: function(pos) { - pos = clipPos(this, pos); - var markers = [], spans = getLine(this, pos.line).markedSpans; - if (spans) for (var i = 0; i < spans.length; ++i) { - var span = spans[i]; - if ((span.from == null || span.from <= pos.ch) && - (span.to == null || span.to >= pos.ch)) - markers.push(span.marker.parent || span.marker); - } - return markers; - }, - findMarks: function(from, to, filter) { - from = clipPos(this, from); to = clipPos(this, to); - var found = [], lineNo = from.line; - this.iter(from.line, to.line + 1, function(line) { - var spans = line.markedSpans; - if (spans) for (var i = 0; i < spans.length; i++) { - var span = spans[i]; - if (!(lineNo == from.line && from.ch > span.to || - span.from == null && lineNo != from.line|| - lineNo == to.line && span.from > to.ch) && - (!filter || filter(span.marker))) - found.push(span.marker.parent || span.marker); - } - ++lineNo; - }); - return found; - }, - getAllMarks: function() { - var markers = []; - this.iter(function(line) { - var sps = line.markedSpans; - if (sps) for (var i = 0; i < sps.length; ++i) - if (sps[i].from != null) markers.push(sps[i].marker); - }); - return markers; - }, - - posFromIndex: function(off) { - var ch, lineNo = this.first; - this.iter(function(line) { - var sz = line.text.length + 1; - if (sz > off) { ch = off; return true; } - off -= sz; - ++lineNo; - }); - return clipPos(this, Pos(lineNo, ch)); - }, - indexFromPos: function (coords) { - coords = clipPos(this, coords); - var index = coords.ch; - if (coords.line < this.first || coords.ch < 0) return 0; - this.iter(this.first, coords.line, function (line) { - index += line.text.length + 1; - }); - return index; - }, - - copy: function(copyHistory) { - var doc = new Doc(getLines(this, this.first, this.first + this.size), - this.modeOption, this.first, this.lineSep); - doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft; - doc.sel = this.sel; - doc.extend = false; - if (copyHistory) { - doc.history.undoDepth = this.history.undoDepth; - doc.setHistory(this.getHistory()); - } - return doc; - }, - - linkedDoc: function(options) { - if (!options) options = {}; - var from = this.first, to = this.first + this.size; - if (options.from != null && options.from > from) from = options.from; - if (options.to != null && options.to < to) to = options.to; - var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from, this.lineSep); - if (options.sharedHist) copy.history = this.history; - (this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist}); - copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}]; - copySharedMarkers(copy, findSharedMarkers(this)); - return copy; - }, - unlinkDoc: function(other) { - if (other instanceof CodeMirror) other = other.doc; - if (this.linked) for (var i = 0; i < this.linked.length; ++i) { - var link = this.linked[i]; - if (link.doc != other) continue; - this.linked.splice(i, 1); - other.unlinkDoc(this); - detachSharedMarkers(findSharedMarkers(this)); - break; - } - // If the histories were shared, split them again - if (other.history == this.history) { - var splitIds = [other.id]; - linkedDocs(other, function(doc) {splitIds.push(doc.id);}, true); - other.history = new History(null); - other.history.done = copyHistoryArray(this.history.done, splitIds); - other.history.undone = copyHistoryArray(this.history.undone, splitIds); - } - }, - iterLinkedDocs: function(f) {linkedDocs(this, f);}, - - getMode: function() {return this.mode;}, - getEditor: function() {return this.cm;}, - - splitLines: function(str) { - if (this.lineSep) return str.split(this.lineSep); - return splitLinesAuto(str); - }, - lineSeparator: function() { return this.lineSep || "\n"; } - }); - - // Public alias. - Doc.prototype.eachLine = Doc.prototype.iter; - - // Set up methods on CodeMirror's prototype to redirect to the editor's document. - var dontDelegate = "iter insert remove copy getEditor constructor".split(" "); - for (var prop in Doc.prototype) if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0) - CodeMirror.prototype[prop] = (function(method) { - return function() {return method.apply(this.doc, arguments);}; - })(Doc.prototype[prop]); - - eventMixin(Doc); - - // Call f for all linked documents. - function linkedDocs(doc, f, sharedHistOnly) { - function propagate(doc, skip, sharedHist) { - if (doc.linked) for (var i = 0; i < doc.linked.length; ++i) { - var rel = doc.linked[i]; - if (rel.doc == skip) continue; - var shared = sharedHist && rel.sharedHist; - if (sharedHistOnly && !shared) continue; - f(rel.doc, shared); - propagate(rel.doc, doc, shared); - } - } - propagate(doc, null, true); - } - - // Attach a document to an editor. - function attachDoc(cm, doc) { - if (doc.cm) throw new Error("This document is already in use."); - cm.doc = doc; - doc.cm = cm; - estimateLineHeights(cm); - loadMode(cm); - if (!cm.options.lineWrapping) findMaxLine(cm); - cm.options.mode = doc.modeOption; - regChange(cm); - } - - // LINE UTILITIES - - // Find the line object corresponding to the given line number. - function getLine(doc, n) { - n -= doc.first; - if (n < 0 || n >= doc.size) throw new Error("There is no line " + (n + doc.first) + " in the document."); - for (var chunk = doc; !chunk.lines;) { - for (var i = 0;; ++i) { - var child = chunk.children[i], sz = child.chunkSize(); - if (n < sz) { chunk = child; break; } - n -= sz; - } - } - return chunk.lines[n]; - } - - // Get the part of a document between two positions, as an array of - // strings. - function getBetween(doc, start, end) { - var out = [], n = start.line; - doc.iter(start.line, end.line + 1, function(line) { - var text = line.text; - if (n == end.line) text = text.slice(0, end.ch); - if (n == start.line) text = text.slice(start.ch); - out.push(text); - ++n; - }); - return out; - } - // Get the lines between from and to, as array of strings. - function getLines(doc, from, to) { - var out = []; - doc.iter(from, to, function(line) { out.push(line.text); }); - return out; - } - - // Update the height of a line, propagating the height change - // upwards to parent nodes. - function updateLineHeight(line, height) { - var diff = height - line.height; - if (diff) for (var n = line; n; n = n.parent) n.height += diff; - } - - // Given a line object, find its line number by walking up through - // its parent links. - function lineNo(line) { - if (line.parent == null) return null; - var cur = line.parent, no = indexOf(cur.lines, line); - for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) { - for (var i = 0;; ++i) { - if (chunk.children[i] == cur) break; - no += chunk.children[i].chunkSize(); - } - } - return no + cur.first; - } - - // Find the line at the given vertical position, using the height - // information in the document tree. - function lineAtHeight(chunk, h) { - var n = chunk.first; - outer: do { - for (var i = 0; i < chunk.children.length; ++i) { - var child = chunk.children[i], ch = child.height; - if (h < ch) { chunk = child; continue outer; } - h -= ch; - n += child.chunkSize(); - } - return n; - } while (!chunk.lines); - for (var i = 0; i < chunk.lines.length; ++i) { - var line = chunk.lines[i], lh = line.height; - if (h < lh) break; - h -= lh; - } - return n + i; - } - - - // Find the height above the given line. - function heightAtLine(lineObj) { - lineObj = visualLine(lineObj); - - var h = 0, chunk = lineObj.parent; - for (var i = 0; i < chunk.lines.length; ++i) { - var line = chunk.lines[i]; - if (line == lineObj) break; - else h += line.height; - } - for (var p = chunk.parent; p; chunk = p, p = chunk.parent) { - for (var i = 0; i < p.children.length; ++i) { - var cur = p.children[i]; - if (cur == chunk) break; - else h += cur.height; - } - } - return h; - } - - // Get the bidi ordering for the given line (and cache it). Returns - // false for lines that are fully left-to-right, and an array of - // BidiSpan objects otherwise. - function getOrder(line) { - var order = line.order; - if (order == null) order = line.order = bidiOrdering(line.text); - return order; - } - - // HISTORY - - function History(startGen) { - // Arrays of change events and selections. Doing something adds an - // event to done and clears undo. Undoing moves events from done - // to undone, redoing moves them in the other direction. - this.done = []; this.undone = []; - this.undoDepth = Infinity; - // Used to track when changes can be merged into a single undo - // event - this.lastModTime = this.lastSelTime = 0; - this.lastOp = this.lastSelOp = null; - this.lastOrigin = this.lastSelOrigin = null; - // Used by the isClean() method - this.generation = this.maxGeneration = startGen || 1; - } - - // Create a history change event from an updateDoc-style change - // object. - function historyChangeFromChange(doc, change) { - var histChange = {from: copyPos(change.from), to: changeEnd(change), text: getBetween(doc, change.from, change.to)}; - attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1); - linkedDocs(doc, function(doc) {attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);}, true); - return histChange; - } - - // Pop all selection events off the end of a history array. Stop at - // a change event. - function clearSelectionEvents(array) { - while (array.length) { - var last = lst(array); - if (last.ranges) array.pop(); - else break; - } - } - - // Find the top change event in the history. Pop off selection - // events that are in the way. - function lastChangeEvent(hist, force) { - if (force) { - clearSelectionEvents(hist.done); - return lst(hist.done); - } else if (hist.done.length && !lst(hist.done).ranges) { - return lst(hist.done); - } else if (hist.done.length > 1 && !hist.done[hist.done.length - 2].ranges) { - hist.done.pop(); - return lst(hist.done); - } - } - - // Register a change in the history. Merges changes that are within - // a single operation, ore are close together with an origin that - // allows merging (starting with "+") into a single event. - function addChangeToHistory(doc, change, selAfter, opId) { - var hist = doc.history; - hist.undone.length = 0; - var time = +new Date, cur; - - if ((hist.lastOp == opId || - hist.lastOrigin == change.origin && change.origin && - ((change.origin.charAt(0) == "+" && doc.cm && hist.lastModTime > time - doc.cm.options.historyEventDelay) || - change.origin.charAt(0) == "*")) && - (cur = lastChangeEvent(hist, hist.lastOp == opId))) { - // Merge this change into the last event - var last = lst(cur.changes); - if (cmp(change.from, change.to) == 0 && cmp(change.from, last.to) == 0) { - // Optimized case for simple insertion -- don't want to add - // new changesets for every character typed - last.to = changeEnd(change); - } else { - // Add new sub-event - cur.changes.push(historyChangeFromChange(doc, change)); - } - } else { - // Can not be merged, start a new event. - var before = lst(hist.done); - if (!before || !before.ranges) - pushSelectionToHistory(doc.sel, hist.done); - cur = {changes: [historyChangeFromChange(doc, change)], - generation: hist.generation}; - hist.done.push(cur); - while (hist.done.length > hist.undoDepth) { - hist.done.shift(); - if (!hist.done[0].ranges) hist.done.shift(); - } - } - hist.done.push(selAfter); - hist.generation = ++hist.maxGeneration; - hist.lastModTime = hist.lastSelTime = time; - hist.lastOp = hist.lastSelOp = opId; - hist.lastOrigin = hist.lastSelOrigin = change.origin; - - if (!last) signal(doc, "historyAdded"); - } - - function selectionEventCanBeMerged(doc, origin, prev, sel) { - var ch = origin.charAt(0); - return ch == "*" || - ch == "+" && - prev.ranges.length == sel.ranges.length && - prev.somethingSelected() == sel.somethingSelected() && - new Date - doc.history.lastSelTime <= (doc.cm ? doc.cm.options.historyEventDelay : 500); - } - - // Called whenever the selection changes, sets the new selection as - // the pending selection in the history, and pushes the old pending - // selection into the 'done' array when it was significantly - // different (in number of selected ranges, emptiness, or time). - function addSelectionToHistory(doc, sel, opId, options) { - var hist = doc.history, origin = options && options.origin; - - // A new event is started when the previous origin does not match - // the current, or the origins don't allow matching. Origins - // starting with * are always merged, those starting with + are - // merged when similar and close together in time. - if (opId == hist.lastSelOp || - (origin && hist.lastSelOrigin == origin && - (hist.lastModTime == hist.lastSelTime && hist.lastOrigin == origin || - selectionEventCanBeMerged(doc, origin, lst(hist.done), sel)))) - hist.done[hist.done.length - 1] = sel; - else - pushSelectionToHistory(sel, hist.done); - - hist.lastSelTime = +new Date; - hist.lastSelOrigin = origin; - hist.lastSelOp = opId; - if (options && options.clearRedo !== false) - clearSelectionEvents(hist.undone); - } - - function pushSelectionToHistory(sel, dest) { - var top = lst(dest); - if (!(top && top.ranges && top.equals(sel))) - dest.push(sel); - } - - // Used to store marked span information in the history. - function attachLocalSpans(doc, change, from, to) { - var existing = change["spans_" + doc.id], n = 0; - doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function(line) { - if (line.markedSpans) - (existing || (existing = change["spans_" + doc.id] = {}))[n] = line.markedSpans; - ++n; - }); - } - - // When un/re-doing restores text containing marked spans, those - // that have been explicitly cleared should not be restored. - function removeClearedSpans(spans) { - if (!spans) return null; - for (var i = 0, out; i < spans.length; ++i) { - if (spans[i].marker.explicitlyCleared) { if (!out) out = spans.slice(0, i); } - else if (out) out.push(spans[i]); - } - return !out ? spans : out.length ? out : null; - } - - // Retrieve and filter the old marked spans stored in a change event. - function getOldSpans(doc, change) { - var found = change["spans_" + doc.id]; - if (!found) return null; - for (var i = 0, nw = []; i < change.text.length; ++i) - nw.push(removeClearedSpans(found[i])); - return nw; - } - - // Used both to provide a JSON-safe object in .getHistory, and, when - // detaching a document, to split the history in two - function copyHistoryArray(events, newGroup, instantiateSel) { - for (var i = 0, copy = []; i < events.length; ++i) { - var event = events[i]; - if (event.ranges) { - copy.push(instantiateSel ? Selection.prototype.deepCopy.call(event) : event); - continue; - } - var changes = event.changes, newChanges = []; - copy.push({changes: newChanges}); - for (var j = 0; j < changes.length; ++j) { - var change = changes[j], m; - newChanges.push({from: change.from, to: change.to, text: change.text}); - if (newGroup) for (var prop in change) if (m = prop.match(/^spans_(\d+)$/)) { - if (indexOf(newGroup, Number(m[1])) > -1) { - lst(newChanges)[prop] = change[prop]; - delete change[prop]; - } - } - } - } - return copy; - } - - // Rebasing/resetting history to deal with externally-sourced changes - - function rebaseHistSelSingle(pos, from, to, diff) { - if (to < pos.line) { - pos.line += diff; - } else if (from < pos.line) { - pos.line = from; - pos.ch = 0; - } - } - - // Tries to rebase an array of history events given a change in the - // document. If the change touches the same lines as the event, the - // event, and everything 'behind' it, is discarded. If the change is - // before the event, the event's positions are updated. Uses a - // copy-on-write scheme for the positions, to avoid having to - // reallocate them all on every rebase, but also avoid problems with - // shared position objects being unsafely updated. - function rebaseHistArray(array, from, to, diff) { - for (var i = 0; i < array.length; ++i) { - var sub = array[i], ok = true; - if (sub.ranges) { - if (!sub.copied) { sub = array[i] = sub.deepCopy(); sub.copied = true; } - for (var j = 0; j < sub.ranges.length; j++) { - rebaseHistSelSingle(sub.ranges[j].anchor, from, to, diff); - rebaseHistSelSingle(sub.ranges[j].head, from, to, diff); - } - continue; - } - for (var j = 0; j < sub.changes.length; ++j) { - var cur = sub.changes[j]; - if (to < cur.from.line) { - cur.from = Pos(cur.from.line + diff, cur.from.ch); - cur.to = Pos(cur.to.line + diff, cur.to.ch); - } else if (from <= cur.to.line) { - ok = false; - break; - } - } - if (!ok) { - array.splice(0, i + 1); - i = 0; - } - } - } - - function rebaseHist(hist, change) { - var from = change.from.line, to = change.to.line, diff = change.text.length - (to - from) - 1; - rebaseHistArray(hist.done, from, to, diff); - rebaseHistArray(hist.undone, from, to, diff); - } - - // EVENT UTILITIES - - // Due to the fact that we still support jurassic IE versions, some - // compatibility wrappers are needed. - - var e_preventDefault = CodeMirror.e_preventDefault = function(e) { - if (e.preventDefault) e.preventDefault(); - else e.returnValue = false; - }; - var e_stopPropagation = CodeMirror.e_stopPropagation = function(e) { - if (e.stopPropagation) e.stopPropagation(); - else e.cancelBubble = true; - }; - function e_defaultPrevented(e) { - return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false; - } - var e_stop = CodeMirror.e_stop = function(e) {e_preventDefault(e); e_stopPropagation(e);}; - - function e_target(e) {return e.target || e.srcElement;} - function e_button(e) { - var b = e.which; - if (b == null) { - if (e.button & 1) b = 1; - else if (e.button & 2) b = 3; - else if (e.button & 4) b = 2; - } - if (mac && e.ctrlKey && b == 1) b = 3; - return b; - } - - // EVENT HANDLING - - // Lightweight event framework. on/off also work on DOM nodes, - // registering native DOM handlers. - - var on = CodeMirror.on = function(emitter, type, f) { - if (emitter.addEventListener) - emitter.addEventListener(type, f, false); - else if (emitter.attachEvent) - emitter.attachEvent("on" + type, f); - else { - var map = emitter._handlers || (emitter._handlers = {}); - var arr = map[type] || (map[type] = []); - arr.push(f); - } - }; - - var noHandlers = [] - function getHandlers(emitter, type, copy) { - var arr = emitter._handlers && emitter._handlers[type] - if (copy) return arr && arr.length > 0 ? arr.slice() : noHandlers - else return arr || noHandlers - } - - var off = CodeMirror.off = function(emitter, type, f) { - if (emitter.removeEventListener) - emitter.removeEventListener(type, f, false); - else if (emitter.detachEvent) - emitter.detachEvent("on" + type, f); - else { - var handlers = getHandlers(emitter, type, false) - for (var i = 0; i < handlers.length; ++i) - if (handlers[i] == f) { handlers.splice(i, 1); break; } - } - }; - - var signal = CodeMirror.signal = function(emitter, type /*, values...*/) { - var handlers = getHandlers(emitter, type, true) - if (!handlers.length) return; - var args = Array.prototype.slice.call(arguments, 2); - for (var i = 0; i < handlers.length; ++i) handlers[i].apply(null, args); - }; - - var orphanDelayedCallbacks = null; - - // Often, we want to signal events at a point where we are in the - // middle of some work, but don't want the handler to start calling - // other methods on the editor, which might be in an inconsistent - // state or simply not expect any other events to happen. - // signalLater looks whether there are any handlers, and schedules - // them to be executed when the last operation ends, or, if no - // operation is active, when a timeout fires. - function signalLater(emitter, type /*, values...*/) { - var arr = getHandlers(emitter, type, false) - if (!arr.length) return; - var args = Array.prototype.slice.call(arguments, 2), list; - if (operationGroup) { - list = operationGroup.delayedCallbacks; - } else if (orphanDelayedCallbacks) { - list = orphanDelayedCallbacks; - } else { - list = orphanDelayedCallbacks = []; - setTimeout(fireOrphanDelayed, 0); - } - function bnd(f) {return function(){f.apply(null, args);};}; - for (var i = 0; i < arr.length; ++i) - list.push(bnd(arr[i])); - } - - function fireOrphanDelayed() { - var delayed = orphanDelayedCallbacks; - orphanDelayedCallbacks = null; - for (var i = 0; i < delayed.length; ++i) delayed[i](); - } - - // The DOM events that CodeMirror handles can be overridden by - // registering a (non-DOM) handler on the editor for the event name, - // and preventDefault-ing the event in that handler. - function signalDOMEvent(cm, e, override) { - if (typeof e == "string") - e = {type: e, preventDefault: function() { this.defaultPrevented = true; }}; - signal(cm, override || e.type, cm, e); - return e_defaultPrevented(e) || e.codemirrorIgnore; - } - - function signalCursorActivity(cm) { - var arr = cm._handlers && cm._handlers.cursorActivity; - if (!arr) return; - var set = cm.curOp.cursorActivityHandlers || (cm.curOp.cursorActivityHandlers = []); - for (var i = 0; i < arr.length; ++i) if (indexOf(set, arr[i]) == -1) - set.push(arr[i]); - } - - function hasHandler(emitter, type) { - return getHandlers(emitter, type).length > 0 - } - - // Add on and off methods to a constructor's prototype, to make - // registering events on such objects more convenient. - function eventMixin(ctor) { - ctor.prototype.on = function(type, f) {on(this, type, f);}; - ctor.prototype.off = function(type, f) {off(this, type, f);}; - } - - // MISC UTILITIES - - // Number of pixels added to scroller and sizer to hide scrollbar - var scrollerGap = 30; - - // Returned or thrown by various protocols to signal 'I'm not - // handling this'. - var Pass = CodeMirror.Pass = {toString: function(){return "CodeMirror.Pass";}}; - - // Reused option objects for setSelection & friends - var sel_dontScroll = {scroll: false}, sel_mouse = {origin: "*mouse"}, sel_move = {origin: "+move"}; - - function Delayed() {this.id = null;} - Delayed.prototype.set = function(ms, f) { - clearTimeout(this.id); - this.id = setTimeout(f, ms); - }; - - // Counts the column offset in a string, taking tabs into account. - // Used mostly to find indentation. - var countColumn = CodeMirror.countColumn = function(string, end, tabSize, startIndex, startValue) { - if (end == null) { - end = string.search(/[^\s\u00a0]/); - if (end == -1) end = string.length; - } - for (var i = startIndex || 0, n = startValue || 0;;) { - var nextTab = string.indexOf("\t", i); - if (nextTab < 0 || nextTab >= end) - return n + (end - i); - n += nextTab - i; - n += tabSize - (n % tabSize); - i = nextTab + 1; - } - }; - - // The inverse of countColumn -- find the offset that corresponds to - // a particular column. - var findColumn = CodeMirror.findColumn = function(string, goal, tabSize) { - for (var pos = 0, col = 0;;) { - var nextTab = string.indexOf("\t", pos); - if (nextTab == -1) nextTab = string.length; - var skipped = nextTab - pos; - if (nextTab == string.length || col + skipped >= goal) - return pos + Math.min(skipped, goal - col); - col += nextTab - pos; - col += tabSize - (col % tabSize); - pos = nextTab + 1; - if (col >= goal) return pos; - } - } - - var spaceStrs = [""]; - function spaceStr(n) { - while (spaceStrs.length <= n) - spaceStrs.push(lst(spaceStrs) + " "); - return spaceStrs[n]; - } - - function lst(arr) { return arr[arr.length-1]; } - - var selectInput = function(node) { node.select(); }; - if (ios) // Mobile Safari apparently has a bug where select() is broken. - selectInput = function(node) { node.selectionStart = 0; node.selectionEnd = node.value.length; }; - else if (ie) // Suppress mysterious IE10 errors - selectInput = function(node) { try { node.select(); } catch(_e) {} }; - - function indexOf(array, elt) { - for (var i = 0; i < array.length; ++i) - if (array[i] == elt) return i; - return -1; - } - function map(array, f) { - var out = []; - for (var i = 0; i < array.length; i++) out[i] = f(array[i], i); - return out; - } - - function nothing() {} - - function createObj(base, props) { - var inst; - if (Object.create) { - inst = Object.create(base); - } else { - nothing.prototype = base; - inst = new nothing(); - } - if (props) copyObj(props, inst); - return inst; - }; - - function copyObj(obj, target, overwrite) { - if (!target) target = {}; - for (var prop in obj) - if (obj.hasOwnProperty(prop) && (overwrite !== false || !target.hasOwnProperty(prop))) - target[prop] = obj[prop]; - return target; - } - - function bind(f) { - var args = Array.prototype.slice.call(arguments, 1); - return function(){return f.apply(null, args);}; - } - - var nonASCIISingleCaseWordChar = /[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/; - var isWordCharBasic = CodeMirror.isWordChar = function(ch) { - return /\w/.test(ch) || ch > "\x80" && - (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch)); - }; - function isWordChar(ch, helper) { - if (!helper) return isWordCharBasic(ch); - if (helper.source.indexOf("\\w") > -1 && isWordCharBasic(ch)) return true; - return helper.test(ch); - } - - function isEmpty(obj) { - for (var n in obj) if (obj.hasOwnProperty(n) && obj[n]) return false; - return true; - } - - // Extending unicode characters. A series of a non-extending char + - // any number of extending chars is treated as a single unit as far - // as editing and measuring is concerned. This is not fully correct, - // since some scripts/fonts/browsers also treat other configurations - // of code points as a group. - var extendingChars = /[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/; - function isExtendingChar(ch) { return ch.charCodeAt(0) >= 768 && extendingChars.test(ch); } - - // DOM UTILITIES - - function elt(tag, content, className, style) { - var e = document.createElement(tag); - if (className) e.className = className; - if (style) e.style.cssText = style; - if (typeof content == "string") e.appendChild(document.createTextNode(content)); - else if (content) for (var i = 0; i < content.length; ++i) e.appendChild(content[i]); - return e; - } - - var range; - if (document.createRange) range = function(node, start, end, endNode) { - var r = document.createRange(); - r.setEnd(endNode || node, end); - r.setStart(node, start); - return r; - }; - else range = function(node, start, end) { - var r = document.body.createTextRange(); - try { r.moveToElementText(node.parentNode); } - catch(e) { return r; } - r.collapse(true); - r.moveEnd("character", end); - r.moveStart("character", start); - return r; - }; - - function removeChildren(e) { - for (var count = e.childNodes.length; count > 0; --count) - e.removeChild(e.firstChild); - return e; - } - - function removeChildrenAndAdd(parent, e) { - return removeChildren(parent).appendChild(e); - } - - var contains = CodeMirror.contains = function(parent, child) { - if (child.nodeType == 3) // Android browser always returns false when child is a textnode - child = child.parentNode; - if (parent.contains) - return parent.contains(child); - do { - if (child.nodeType == 11) child = child.host; - if (child == parent) return true; - } while (child = child.parentNode); - }; - - function activeElt() { - var activeElement = document.activeElement; - while (activeElement && activeElement.root && activeElement.root.activeElement) - activeElement = activeElement.root.activeElement; - return activeElement; - } - // Older versions of IE throws unspecified error when touching - // document.activeElement in some cases (during loading, in iframe) - if (ie && ie_version < 11) activeElt = function() { - try { return document.activeElement; } - catch(e) { return document.body; } - }; - - function classTest(cls) { return new RegExp("(^|\\s)" + cls + "(?:$|\\s)\\s*"); } - var rmClass = CodeMirror.rmClass = function(node, cls) { - var current = node.className; - var match = classTest(cls).exec(current); - if (match) { - var after = current.slice(match.index + match[0].length); - node.className = current.slice(0, match.index) + (after ? match[1] + after : ""); - } - }; - var addClass = CodeMirror.addClass = function(node, cls) { - var current = node.className; - if (!classTest(cls).test(current)) node.className += (current ? " " : "") + cls; - }; - function joinClasses(a, b) { - var as = a.split(" "); - for (var i = 0; i < as.length; i++) - if (as[i] && !classTest(as[i]).test(b)) b += " " + as[i]; - return b; - } - - // WINDOW-WIDE EVENTS - - // These must be handled carefully, because naively registering a - // handler for each editor will cause the editors to never be - // garbage collected. - - function forEachCodeMirror(f) { - if (!document.body.getElementsByClassName) return; - var byClass = document.body.getElementsByClassName("CodeMirror"); - for (var i = 0; i < byClass.length; i++) { - var cm = byClass[i].CodeMirror; - if (cm) f(cm); - } - } - - var globalsRegistered = false; - function ensureGlobalHandlers() { - if (globalsRegistered) return; - registerGlobalHandlers(); - globalsRegistered = true; - } - function registerGlobalHandlers() { - // When the window resizes, we need to refresh active editors. - var resizeTimer; - on(window, "resize", function() { - if (resizeTimer == null) resizeTimer = setTimeout(function() { - resizeTimer = null; - forEachCodeMirror(onResize); - }, 100); - }); - // When the window loses focus, we want to show the editor as blurred - on(window, "blur", function() { - forEachCodeMirror(onBlur); - }); - } - - // FEATURE DETECTION - - // Detect drag-and-drop - var dragAndDrop = function() { - // There is *some* kind of drag-and-drop support in IE6-8, but I - // couldn't get it to work yet. - if (ie && ie_version < 9) return false; - var div = elt('div'); - return "draggable" in div || "dragDrop" in div; - }(); - - var zwspSupported; - function zeroWidthElement(measure) { - if (zwspSupported == null) { - var test = elt("span", "\u200b"); - removeChildrenAndAdd(measure, elt("span", [test, document.createTextNode("x")])); - if (measure.firstChild.offsetHeight != 0) - zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !(ie && ie_version < 8); - } - var node = zwspSupported ? elt("span", "\u200b") : - elt("span", "\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px"); - node.setAttribute("cm-text", ""); - return node; - } - - // Feature-detect IE's crummy client rect reporting for bidi text - var badBidiRects; - function hasBadBidiRects(measure) { - if (badBidiRects != null) return badBidiRects; - var txt = removeChildrenAndAdd(measure, document.createTextNode("A\u062eA")); - var r0 = range(txt, 0, 1).getBoundingClientRect(); - if (!r0 || r0.left == r0.right) return false; // Safari returns null in some cases (#2780) - var r1 = range(txt, 1, 2).getBoundingClientRect(); - return badBidiRects = (r1.right - r0.right < 3); - } - - // See if "".split is the broken IE version, if so, provide an - // alternative way to split lines. - var splitLinesAuto = CodeMirror.splitLines = "\n\nb".split(/\n/).length != 3 ? function(string) { - var pos = 0, result = [], l = string.length; - while (pos <= l) { - var nl = string.indexOf("\n", pos); - if (nl == -1) nl = string.length; - var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl); - var rt = line.indexOf("\r"); - if (rt != -1) { - result.push(line.slice(0, rt)); - pos += rt + 1; - } else { - result.push(line); - pos = nl + 1; - } - } - return result; - } : function(string){return string.split(/\r\n?|\n/);}; - - var hasSelection = window.getSelection ? function(te) { - try { return te.selectionStart != te.selectionEnd; } - catch(e) { return false; } - } : function(te) { - try {var range = te.ownerDocument.selection.createRange();} - catch(e) {} - if (!range || range.parentElement() != te) return false; - return range.compareEndPoints("StartToEnd", range) != 0; - }; - - var hasCopyEvent = (function() { - var e = elt("div"); - if ("oncopy" in e) return true; - e.setAttribute("oncopy", "return;"); - return typeof e.oncopy == "function"; - })(); - - var badZoomedRects = null; - function hasBadZoomedRects(measure) { - if (badZoomedRects != null) return badZoomedRects; - var node = removeChildrenAndAdd(measure, elt("span", "x")); - var normal = node.getBoundingClientRect(); - var fromRange = range(node, 0, 1).getBoundingClientRect(); - return badZoomedRects = Math.abs(normal.left - fromRange.left) > 1; - } - - // KEY NAMES - - var keyNames = CodeMirror.keyNames = { - 3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt", - 19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End", - 36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert", - 46: "Delete", 59: ";", 61: "=", 91: "Mod", 92: "Mod", 93: "Mod", - 106: "*", 107: "=", 109: "-", 110: ".", 111: "/", 127: "Delete", - 173: "-", 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\", - 221: "]", 222: "'", 63232: "Up", 63233: "Down", 63234: "Left", 63235: "Right", 63272: "Delete", - 63273: "Home", 63275: "End", 63276: "PageUp", 63277: "PageDown", 63302: "Insert" - }; - (function() { - // Number keys - for (var i = 0; i < 10; i++) keyNames[i + 48] = keyNames[i + 96] = String(i); - // Alphabetic keys - for (var i = 65; i <= 90; i++) keyNames[i] = String.fromCharCode(i); - // Function keys - for (var i = 1; i <= 12; i++) keyNames[i + 111] = keyNames[i + 63235] = "F" + i; - })(); - - // BIDI HELPERS - - function iterateBidiSections(order, from, to, f) { - if (!order) return f(from, to, "ltr"); - var found = false; - for (var i = 0; i < order.length; ++i) { - var part = order[i]; - if (part.from < to && part.to > from || from == to && part.to == from) { - f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr"); - found = true; - } - } - if (!found) f(from, to, "ltr"); - } - - function bidiLeft(part) { return part.level % 2 ? part.to : part.from; } - function bidiRight(part) { return part.level % 2 ? part.from : part.to; } - - function lineLeft(line) { var order = getOrder(line); return order ? bidiLeft(order[0]) : 0; } - function lineRight(line) { - var order = getOrder(line); - if (!order) return line.text.length; - return bidiRight(lst(order)); - } - - function lineStart(cm, lineN) { - var line = getLine(cm.doc, lineN); - var visual = visualLine(line); - if (visual != line) lineN = lineNo(visual); - var order = getOrder(visual); - var ch = !order ? 0 : order[0].level % 2 ? lineRight(visual) : lineLeft(visual); - return Pos(lineN, ch); - } - function lineEnd(cm, lineN) { - var merged, line = getLine(cm.doc, lineN); - while (merged = collapsedSpanAtEnd(line)) { - line = merged.find(1, true).line; - lineN = null; - } - var order = getOrder(line); - var ch = !order ? line.text.length : order[0].level % 2 ? lineLeft(line) : lineRight(line); - return Pos(lineN == null ? lineNo(line) : lineN, ch); - } - function lineStartSmart(cm, pos) { - var start = lineStart(cm, pos.line); - var line = getLine(cm.doc, start.line); - var order = getOrder(line); - if (!order || order[0].level == 0) { - var firstNonWS = Math.max(0, line.text.search(/\S/)); - var inWS = pos.line == start.line && pos.ch <= firstNonWS && pos.ch; - return Pos(start.line, inWS ? 0 : firstNonWS); - } - return start; - } - - function compareBidiLevel(order, a, b) { - var linedir = order[0].level; - if (a == linedir) return true; - if (b == linedir) return false; - return a < b; - } - var bidiOther; - function getBidiPartAt(order, pos) { - bidiOther = null; - for (var i = 0, found; i < order.length; ++i) { - var cur = order[i]; - if (cur.from < pos && cur.to > pos) return i; - if ((cur.from == pos || cur.to == pos)) { - if (found == null) { - found = i; - } else if (compareBidiLevel(order, cur.level, order[found].level)) { - if (cur.from != cur.to) bidiOther = found; - return i; - } else { - if (cur.from != cur.to) bidiOther = i; - return found; - } - } - } - return found; - } - - function moveInLine(line, pos, dir, byUnit) { - if (!byUnit) return pos + dir; - do pos += dir; - while (pos > 0 && isExtendingChar(line.text.charAt(pos))); - return pos; - } - - // This is needed in order to move 'visually' through bi-directional - // text -- i.e., pressing left should make the cursor go left, even - // when in RTL text. The tricky part is the 'jumps', where RTL and - // LTR text touch each other. This often requires the cursor offset - // to move more than one unit, in order to visually move one unit. - function moveVisually(line, start, dir, byUnit) { - var bidi = getOrder(line); - if (!bidi) return moveLogically(line, start, dir, byUnit); - var pos = getBidiPartAt(bidi, start), part = bidi[pos]; - var target = moveInLine(line, start, part.level % 2 ? -dir : dir, byUnit); - - for (;;) { - if (target > part.from && target < part.to) return target; - if (target == part.from || target == part.to) { - if (getBidiPartAt(bidi, target) == pos) return target; - part = bidi[pos += dir]; - return (dir > 0) == part.level % 2 ? part.to : part.from; - } else { - part = bidi[pos += dir]; - if (!part) return null; - if ((dir > 0) == part.level % 2) - target = moveInLine(line, part.to, -1, byUnit); - else - target = moveInLine(line, part.from, 1, byUnit); - } - } - } - - function moveLogically(line, start, dir, byUnit) { - var target = start + dir; - if (byUnit) while (target > 0 && isExtendingChar(line.text.charAt(target))) target += dir; - return target < 0 || target > line.text.length ? null : target; - } - - // Bidirectional ordering algorithm - // See http://unicode.org/reports/tr9/tr9-13.html for the algorithm - // that this (partially) implements. - - // One-char codes used for character types: - // L (L): Left-to-Right - // R (R): Right-to-Left - // r (AL): Right-to-Left Arabic - // 1 (EN): European Number - // + (ES): European Number Separator - // % (ET): European Number Terminator - // n (AN): Arabic Number - // , (CS): Common Number Separator - // m (NSM): Non-Spacing Mark - // b (BN): Boundary Neutral - // s (B): Paragraph Separator - // t (S): Segment Separator - // w (WS): Whitespace - // N (ON): Other Neutrals - - // Returns null if characters are ordered as they appear - // (left-to-right), or an array of sections ({from, to, level} - // objects) in the order in which they occur visually. - var bidiOrdering = (function() { - // Character types for codepoints 0 to 0xff - var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN"; - // Character types for codepoints 0x600 to 0x6ff - var arabicTypes = "rrrrrrrrrrrr,rNNmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmrrrrrrrnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmNmmmm"; - function charType(code) { - if (code <= 0xf7) return lowTypes.charAt(code); - else if (0x590 <= code && code <= 0x5f4) return "R"; - else if (0x600 <= code && code <= 0x6ed) return arabicTypes.charAt(code - 0x600); - else if (0x6ee <= code && code <= 0x8ac) return "r"; - else if (0x2000 <= code && code <= 0x200b) return "w"; - else if (code == 0x200c) return "b"; - else return "L"; - } - - var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/; - var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/; - // Browsers seem to always treat the boundaries of block elements as being L. - var outerType = "L"; - - function BidiSpan(level, from, to) { - this.level = level; - this.from = from; this.to = to; - } - - return function(str) { - if (!bidiRE.test(str)) return false; - var len = str.length, types = []; - for (var i = 0, type; i < len; ++i) - types.push(type = charType(str.charCodeAt(i))); - - // W1. Examine each non-spacing mark (NSM) in the level run, and - // change the type of the NSM to the type of the previous - // character. If the NSM is at the start of the level run, it will - // get the type of sor. - for (var i = 0, prev = outerType; i < len; ++i) { - var type = types[i]; - if (type == "m") types[i] = prev; - else prev = type; - } - - // W2. Search backwards from each instance of a European number - // until the first strong type (R, L, AL, or sor) is found. If an - // AL is found, change the type of the European number to Arabic - // number. - // W3. Change all ALs to R. - for (var i = 0, cur = outerType; i < len; ++i) { - var type = types[i]; - if (type == "1" && cur == "r") types[i] = "n"; - else if (isStrong.test(type)) { cur = type; if (type == "r") types[i] = "R"; } - } - - // W4. A single European separator between two European numbers - // changes to a European number. A single common separator between - // two numbers of the same type changes to that type. - for (var i = 1, prev = types[0]; i < len - 1; ++i) { - var type = types[i]; - if (type == "+" && prev == "1" && types[i+1] == "1") types[i] = "1"; - else if (type == "," && prev == types[i+1] && - (prev == "1" || prev == "n")) types[i] = prev; - prev = type; - } - - // W5. A sequence of European terminators adjacent to European - // numbers changes to all European numbers. - // W6. Otherwise, separators and terminators change to Other - // Neutral. - for (var i = 0; i < len; ++i) { - var type = types[i]; - if (type == ",") types[i] = "N"; - else if (type == "%") { - for (var end = i + 1; end < len && types[end] == "%"; ++end) {} - var replace = (i && types[i-1] == "!") || (end < len && types[end] == "1") ? "1" : "N"; - for (var j = i; j < end; ++j) types[j] = replace; - i = end - 1; - } - } - - // W7. Search backwards from each instance of a European number - // until the first strong type (R, L, or sor) is found. If an L is - // found, then change the type of the European number to L. - for (var i = 0, cur = outerType; i < len; ++i) { - var type = types[i]; - if (cur == "L" && type == "1") types[i] = "L"; - else if (isStrong.test(type)) cur = type; - } - - // N1. A sequence of neutrals takes the direction of the - // surrounding strong text if the text on both sides has the same - // direction. European and Arabic numbers act as if they were R in - // terms of their influence on neutrals. Start-of-level-run (sor) - // and end-of-level-run (eor) are used at level run boundaries. - // N2. Any remaining neutrals take the embedding direction. - for (var i = 0; i < len; ++i) { - if (isNeutral.test(types[i])) { - for (var end = i + 1; end < len && isNeutral.test(types[end]); ++end) {} - var before = (i ? types[i-1] : outerType) == "L"; - var after = (end < len ? types[end] : outerType) == "L"; - var replace = before || after ? "L" : "R"; - for (var j = i; j < end; ++j) types[j] = replace; - i = end - 1; - } - } - - // Here we depart from the documented algorithm, in order to avoid - // building up an actual levels array. Since there are only three - // levels (0, 1, 2) in an implementation that doesn't take - // explicit embedding into account, we can build up the order on - // the fly, without following the level-based algorithm. - var order = [], m; - for (var i = 0; i < len;) { - if (countsAsLeft.test(types[i])) { - var start = i; - for (++i; i < len && countsAsLeft.test(types[i]); ++i) {} - order.push(new BidiSpan(0, start, i)); - } else { - var pos = i, at = order.length; - for (++i; i < len && types[i] != "L"; ++i) {} - for (var j = pos; j < i;) { - if (countsAsNum.test(types[j])) { - if (pos < j) order.splice(at, 0, new BidiSpan(1, pos, j)); - var nstart = j; - for (++j; j < i && countsAsNum.test(types[j]); ++j) {} - order.splice(at, 0, new BidiSpan(2, nstart, j)); - pos = j; - } else ++j; - } - if (pos < i) order.splice(at, 0, new BidiSpan(1, pos, i)); - } - } - if (order[0].level == 1 && (m = str.match(/^\s+/))) { - order[0].from = m[0].length; - order.unshift(new BidiSpan(0, 0, m[0].length)); - } - if (lst(order).level == 1 && (m = str.match(/\s+$/))) { - lst(order).to -= m[0].length; - order.push(new BidiSpan(0, len - m[0].length, len)); - } - if (order[0].level == 2) - order.unshift(new BidiSpan(1, order[0].to, order[0].to)); - if (order[0].level != lst(order).level) - order.push(new BidiSpan(order[0].level, len, len)); - - return order; - }; - })(); - - // THE END - - CodeMirror.version = "5.9.0"; - - return CodeMirror; -}); diff --git a/pagure/static/codemirror/codemirror.js b/pagure/static/codemirror/codemirror.js new file mode 120000 index 0000000..0b38438 --- /dev/null +++ b/pagure/static/codemirror/codemirror.js @@ -0,0 +1 @@ +codemirror-5.18.2.js \ No newline at end of file diff --git a/pagure/static/codemirror/solarized-5.18.2.css b/pagure/static/codemirror/solarized-5.18.2.css new file mode 100644 index 0000000..1f39c7e --- /dev/null +++ b/pagure/static/codemirror/solarized-5.18.2.css @@ -0,0 +1,169 @@ +/* +Solarized theme for code-mirror +http://ethanschoonover.com/solarized +*/ + +/* +Solarized color palette +http://ethanschoonover.com/solarized/img/solarized-palette.png +*/ + +.solarized.base03 { color: #002b36; } +.solarized.base02 { color: #073642; } +.solarized.base01 { color: #586e75; } +.solarized.base00 { color: #657b83; } +.solarized.base0 { color: #839496; } +.solarized.base1 { color: #93a1a1; } +.solarized.base2 { color: #eee8d5; } +.solarized.base3 { color: #fdf6e3; } +.solarized.solar-yellow { color: #b58900; } +.solarized.solar-orange { color: #cb4b16; } +.solarized.solar-red { color: #dc322f; } +.solarized.solar-magenta { color: #d33682; } +.solarized.solar-violet { color: #6c71c4; } +.solarized.solar-blue { color: #268bd2; } +.solarized.solar-cyan { color: #2aa198; } +.solarized.solar-green { color: #859900; } + +/* Color scheme for code-mirror */ + +.cm-s-solarized { + line-height: 1.45em; + color-profile: sRGB; + rendering-intent: auto; +} +.cm-s-solarized.cm-s-dark { + color: #839496; + background-color: #002b36; + text-shadow: #002b36 0 1px; +} +.cm-s-solarized.cm-s-light { + background-color: #fdf6e3; + color: #657b83; + text-shadow: #eee8d5 0 1px; +} + +.cm-s-solarized .CodeMirror-widget { + text-shadow: none; +} + +.cm-s-solarized .cm-header { color: #586e75; } +.cm-s-solarized .cm-quote { color: #93a1a1; } + +.cm-s-solarized .cm-keyword { color: #cb4b16; } +.cm-s-solarized .cm-atom { color: #d33682; } +.cm-s-solarized .cm-number { color: #d33682; } +.cm-s-solarized .cm-def { color: #2aa198; } + +.cm-s-solarized .cm-variable { color: #839496; } +.cm-s-solarized .cm-variable-2 { color: #b58900; } +.cm-s-solarized .cm-variable-3 { color: #6c71c4; } + +.cm-s-solarized .cm-property { color: #2aa198; } +.cm-s-solarized .cm-operator { color: #6c71c4; } + +.cm-s-solarized .cm-comment { color: #586e75; font-style:italic; } + +.cm-s-solarized .cm-string { color: #859900; } +.cm-s-solarized .cm-string-2 { color: #b58900; } + +.cm-s-solarized .cm-meta { color: #859900; } +.cm-s-solarized .cm-qualifier { color: #b58900; } +.cm-s-solarized .cm-builtin { color: #d33682; } +.cm-s-solarized .cm-bracket { color: #cb4b16; } +.cm-s-solarized .CodeMirror-matchingbracket { color: #859900; } +.cm-s-solarized .CodeMirror-nonmatchingbracket { color: #dc322f; } +.cm-s-solarized .cm-tag { color: #93a1a1; } +.cm-s-solarized .cm-attribute { color: #2aa198; } +.cm-s-solarized .cm-hr { + color: transparent; + border-top: 1px solid #586e75; + display: block; +} +.cm-s-solarized .cm-link { color: #93a1a1; cursor: pointer; } +.cm-s-solarized .cm-special { color: #6c71c4; } +.cm-s-solarized .cm-em { + color: #999; + text-decoration: underline; + text-decoration-style: dotted; +} +.cm-s-solarized .cm-strong { color: #eee; } +.cm-s-solarized .cm-error, +.cm-s-solarized .cm-invalidchar { + color: #586e75; + border-bottom: 1px dotted #dc322f; +} + +.cm-s-solarized.cm-s-dark div.CodeMirror-selected { background: #073642; } +.cm-s-solarized.cm-s-dark.CodeMirror ::selection { background: rgba(7, 54, 66, 0.99); } +.cm-s-solarized.cm-s-dark .CodeMirror-line::-moz-selection, .cm-s-dark .CodeMirror-line > span::-moz-selection, .cm-s-dark .CodeMirror-line > span > span::-moz-selection { background: rgba(7, 54, 66, 0.99); } + +.cm-s-solarized.cm-s-light div.CodeMirror-selected { background: #eee8d5; } +.cm-s-solarized.cm-s-light .CodeMirror-line::selection, .cm-s-light .CodeMirror-line > span::selection, .cm-s-light .CodeMirror-line > span > span::selection { background: #eee8d5; } +.cm-s-solarized.cm-s-light .CodeMirror-line::-moz-selection, .cm-s-ligh .CodeMirror-line > span::-moz-selection, .cm-s-ligh .CodeMirror-line > span > span::-moz-selection { background: #eee8d5; } + +/* Editor styling */ + + + +/* Little shadow on the view-port of the buffer view */ +.cm-s-solarized.CodeMirror { + -moz-box-shadow: inset 7px 0 12px -6px #000; + -webkit-box-shadow: inset 7px 0 12px -6px #000; + box-shadow: inset 7px 0 12px -6px #000; +} + +/* Remove gutter border */ +.cm-s-solarized .CodeMirror-gutters { + border-right: 0; +} + +/* Gutter colors and line number styling based of color scheme (dark / light) */ + +/* Dark */ +.cm-s-solarized.cm-s-dark .CodeMirror-gutters { + background-color: #073642; +} + +.cm-s-solarized.cm-s-dark .CodeMirror-linenumber { + color: #586e75; + text-shadow: #021014 0 -1px; +} + +/* Light */ +.cm-s-solarized.cm-s-light .CodeMirror-gutters { + background-color: #eee8d5; +} + +.cm-s-solarized.cm-s-light .CodeMirror-linenumber { + color: #839496; +} + +/* Common */ +.cm-s-solarized .CodeMirror-linenumber { + padding: 0 5px; +} +.cm-s-solarized .CodeMirror-guttermarker-subtle { color: #586e75; } +.cm-s-solarized.cm-s-dark .CodeMirror-guttermarker { color: #ddd; } +.cm-s-solarized.cm-s-light .CodeMirror-guttermarker { color: #cb4b16; } + +.cm-s-solarized .CodeMirror-gutter .CodeMirror-gutter-text { + color: #586e75; +} + +/* Cursor */ +.cm-s-solarized .CodeMirror-cursor { border-left: 1px solid #819090; } + +/* Fat cursor */ +.cm-s-solarized.cm-s-light.cm-fat-cursor .CodeMirror-cursor { background: #77ee77; } +.cm-s-solarized.cm-s-light .cm-animate-fat-cursor { background-color: #77ee77; } +.cm-s-solarized.cm-s-dark.cm-fat-cursor .CodeMirror-cursor { background: #586e75; } +.cm-s-solarized.cm-s-dark .cm-animate-fat-cursor { background-color: #586e75; } + +/* Active line */ +.cm-s-solarized.cm-s-dark .CodeMirror-activeline-background { + background: rgba(255, 255, 255, 0.06); +} +.cm-s-solarized.cm-s-light .CodeMirror-activeline-background { + background: rgba(0, 0, 0, 0.06); +} diff --git a/pagure/static/codemirror/solarized.css b/pagure/static/codemirror/solarized.css deleted file mode 100644 index 7882c93..0000000 --- a/pagure/static/codemirror/solarized.css +++ /dev/null @@ -1,163 +0,0 @@ -/* -Solarized theme for code-mirror -http://ethanschoonover.com/solarized -*/ - -/* -Solarized color pallet -http://ethanschoonover.com/solarized/img/solarized-palette.png -*/ - -.solarized.base03 { color: #002b36; } -.solarized.base02 { color: #073642; } -.solarized.base01 { color: #586e75; } -.solarized.base00 { color: #657b83; } -.solarized.base0 { color: #839496; } -.solarized.base1 { color: #93a1a1; } -.solarized.base2 { color: #eee8d5; } -.solarized.base3 { color: #fdf6e3; } -.solarized.solar-yellow { color: #b58900; } -.solarized.solar-orange { color: #cb4b16; } -.solarized.solar-red { color: #dc322f; } -.solarized.solar-magenta { color: #d33682; } -.solarized.solar-violet { color: #6c71c4; } -.solarized.solar-blue { color: #268bd2; } -.solarized.solar-cyan { color: #2aa198; } -.solarized.solar-green { color: #859900; } - -/* Color scheme for code-mirror */ - -.cm-s-solarized { - line-height: 1.45em; - color-profile: sRGB; - rendering-intent: auto; -} -.cm-s-solarized.cm-s-dark { - color: #839496; - background-color: #002b36; - text-shadow: #002b36 0 1px; -} -.cm-s-solarized.cm-s-light { - background-color: #fdf6e3; - color: #657b83; - text-shadow: #eee8d5 0 1px; -} - -.cm-s-solarized .CodeMirror-widget { - text-shadow: none; -} - -.cm-s-solarized .cm-header { color: #586e75; } -.cm-s-solarized .cm-quote { color: #93a1a1; } - -.cm-s-solarized .cm-keyword { color: #cb4b16; } -.cm-s-solarized .cm-atom { color: #d33682; } -.cm-s-solarized .cm-number { color: #d33682; } -.cm-s-solarized .cm-def { color: #2aa198; } - -.cm-s-solarized .cm-variable { color: #839496; } -.cm-s-solarized .cm-variable-2 { color: #b58900; } -.cm-s-solarized .cm-variable-3 { color: #6c71c4; } - -.cm-s-solarized .cm-property { color: #2aa198; } -.cm-s-solarized .cm-operator { color: #6c71c4; } - -.cm-s-solarized .cm-comment { color: #586e75; font-style:italic; } - -.cm-s-solarized .cm-string { color: #859900; } -.cm-s-solarized .cm-string-2 { color: #b58900; } - -.cm-s-solarized .cm-meta { color: #859900; } -.cm-s-solarized .cm-qualifier { color: #b58900; } -.cm-s-solarized .cm-builtin { color: #d33682; } -.cm-s-solarized .cm-bracket { color: #cb4b16; } -.cm-s-solarized .CodeMirror-matchingbracket { color: #859900; } -.cm-s-solarized .CodeMirror-nonmatchingbracket { color: #dc322f; } -.cm-s-solarized .cm-tag { color: #93a1a1; } -.cm-s-solarized .cm-attribute { color: #2aa198; } -.cm-s-solarized .cm-hr { - color: transparent; - border-top: 1px solid #586e75; - display: block; -} -.cm-s-solarized .cm-link { color: #93a1a1; cursor: pointer; } -.cm-s-solarized .cm-special { color: #6c71c4; } -.cm-s-solarized .cm-em { - color: #999; - text-decoration: underline; - text-decoration-style: dotted; -} -.cm-s-solarized .cm-strong { color: #eee; } -.cm-s-solarized .cm-error, -.cm-s-solarized .cm-invalidchar { - color: #586e75; - border-bottom: 1px dotted #dc322f; -} - -.cm-s-solarized.cm-s-dark div.CodeMirror-selected { background: #073642; } -.cm-s-solarized.cm-s-dark.CodeMirror ::selection { background: rgba(7, 54, 66, 0.99); } -.cm-s-solarized.cm-s-dark .CodeMirror-line::-moz-selection, .cm-s-dark .CodeMirror-line > span::-moz-selection, .cm-s-dark .CodeMirror-line > span > span::-moz-selection { background: rgba(7, 54, 66, 0.99); } - -.cm-s-solarized.cm-s-light div.CodeMirror-selected { background: #eee8d5; } -.cm-s-solarized.cm-s-light .CodeMirror-line::selection, .cm-s-light .CodeMirror-line > span::selection, .cm-s-light .CodeMirror-line > span > span::selection { background: #eee8d5; } -.cm-s-solarized.cm-s-light .CodeMirror-line::-moz-selection, .cm-s-ligh .CodeMirror-line > span::-moz-selection, .cm-s-ligh .CodeMirror-line > span > span::-moz-selection { background: #eee8d5; } - -/* Editor styling */ - - - -/* Little shadow on the view-port of the buffer view */ -.cm-s-solarized.CodeMirror { - -moz-box-shadow: inset 7px 0 12px -6px #000; - -webkit-box-shadow: inset 7px 0 12px -6px #000; - box-shadow: inset 7px 0 12px -6px #000; -} - -/* Gutter border and some shadow from it */ -.cm-s-solarized .CodeMirror-gutters { - border-right: 1px solid; -} - -/* Gutter colors and line number styling based of color scheme (dark / light) */ - -/* Dark */ -.cm-s-solarized.cm-s-dark .CodeMirror-gutters { - background-color: #002b36; - border-color: #00232c; -} - -.cm-s-solarized.cm-s-dark .CodeMirror-linenumber { - text-shadow: #021014 0 -1px; -} - -/* Light */ -.cm-s-solarized.cm-s-light .CodeMirror-gutters { - background-color: #fdf6e3; - border-color: #eee8d5; -} - -/* Common */ -.cm-s-solarized .CodeMirror-linenumber { - color: #586e75; - padding: 0 5px; -} -.cm-s-solarized .CodeMirror-guttermarker-subtle { color: #586e75; } -.cm-s-solarized.cm-s-dark .CodeMirror-guttermarker { color: #ddd; } -.cm-s-solarized.cm-s-light .CodeMirror-guttermarker { color: #cb4b16; } - -.cm-s-solarized .CodeMirror-gutter .CodeMirror-gutter-text { - color: #586e75; -} - -.cm-s-solarized .CodeMirror-cursor { border-left: 1px solid #819090; } - -/* -Active line. Negative margin compensates left padding of the text in the -view-port -*/ -.cm-s-solarized.cm-s-dark .CodeMirror-activeline-background { - background: rgba(255, 255, 255, 0.10); -} -.cm-s-solarized.cm-s-light .CodeMirror-activeline-background { - background: rgba(0, 0, 0, 0.10); -} diff --git a/pagure/static/codemirror/solarized.css b/pagure/static/codemirror/solarized.css new file mode 120000 index 0000000..372d39a --- /dev/null +++ b/pagure/static/codemirror/solarized.css @@ -0,0 +1 @@ +solarized-5.18.2.css \ No newline at end of file diff --git a/pagure/static/emoji/emoji_strategy-2.2.6.json b/pagure/static/emoji/emoji_strategy-2.2.6.json new file mode 100644 index 0000000..bc8d9ec --- /dev/null +++ b/pagure/static/emoji/emoji_strategy-2.2.6.json @@ -0,0 +1 @@ +{"grinning":{"unicode":"1f600","shortname":":grinning:","aliases":"","keywords":"grinning face happy smiley emotion emotion"},"grimacing":{"unicode":"1f62c","shortname":":grimacing:","aliases":"","keywords":"grimacing face silly smiley emotion emotion selfie selfie"},"grin":{"unicode":"1f601","shortname":":grin:","aliases":"","keywords":"grinning face with smiling eyes happy silly smiley emotion emotion good good selfie selfie"},"joy":{"unicode":"1f602","shortname":":joy:","aliases":"","keywords":"face with tears of joy happy silly smiley cry laugh laugh emotion emotion sarcastic sarcastic"},"smiley":{"unicode":"1f603","shortname":":smiley:","aliases":"","keywords":"smiling face with open mouth happy smiley emotion emotion good good"},"smile":{"unicode":"1f604","shortname":":smile:","aliases":"","keywords":"smiling face with open mouth and smiling eyes happy smiley emotion emotion"},"sweat_smile":{"unicode":"1f605","shortname":":sweat_smile:","aliases":"","keywords":"smiling face with open mouth and cold sweat smiley workout sweat emotion emotion"},"laughing":{"unicode":"1f606","shortname":":laughing:","aliases":":satisfied:","keywords":"smiling face with open mouth and tightly-closed eyes happy smiley laugh laugh emotion emotion"},"innocent":{"unicode":"1f607","shortname":":innocent:","aliases":"","keywords":"smiling face with halo smiley emotion emotion"},"wink":{"unicode":"1f609","shortname":":wink:","aliases":"","keywords":"winking face silly smiley emotion emotion"},"blush":{"unicode":"1f60a","shortname":":blush:","aliases":"","keywords":"smiling face with smiling eyes happy smiley emotion emotion good good beautiful beautiful"},"slight_smile":{"unicode":"1f642","shortname":":slight_smile:","aliases":":slightly_smiling_face:","keywords":"slightly smiling face happy smiley"},"upside_down":{"unicode":"1f643","shortname":":upside_down:","aliases":":upside_down_face:","keywords":"upside-down face silly smiley sarcastic sarcastic"},"relaxed":{"unicode":"263a","shortname":":relaxed:","aliases":"","keywords":"white smiling face happy smiley"},"yum":{"unicode":"1f60b","shortname":":yum:","aliases":"","keywords":"face savouring delicious food happy silly smiley emotion emotion sarcastic sarcastic good good"},"relieved":{"unicode":"1f60c","shortname":":relieved:","aliases":"","keywords":"relieved face smiley emotion emotion"},"heart_eyes":{"unicode":"1f60d","shortname":":heart_eyes:","aliases":"","keywords":"smiling face with heart-shaped eyes happy smiley love sex heart eyes emotion emotion beautiful beautiful"},"kissing_heart":{"unicode":"1f618","shortname":":kissing_heart:","aliases":"","keywords":"face throwing a kiss smiley love sexy"},"kissing":{"unicode":"1f617","shortname":":kissing:","aliases":"","keywords":"kissing face smiley sexy"},"kissing_smiling_eyes":{"unicode":"1f619","shortname":":kissing_smiling_eyes:","aliases":"","keywords":"kissing face with smiling eyes smiley sexy"},"kissing_closed_eyes":{"unicode":"1f61a","shortname":":kissing_closed_eyes:","aliases":"","keywords":"kissing face with closed eyes smiley sexy"},"stuck_out_tongue_winking_eye":{"unicode":"1f61c","shortname":":stuck_out_tongue_winking_eye:","aliases":"","keywords":"face with stuck-out tongue and winking eye happy smiley emotion emotion parties parties"},"stuck_out_tongue_closed_eyes":{"unicode":"1f61d","shortname":":stuck_out_tongue_closed_eyes:","aliases":"","keywords":"face with stuck-out tongue and tightly-closed eyes happy smiley emotion emotion"},"stuck_out_tongue":{"unicode":"1f61b","shortname":":stuck_out_tongue:","aliases":"","keywords":"face with stuck-out tongue smiley sex emotion emotion"},"money_mouth":{"unicode":"1f911","shortname":":money_mouth:","aliases":":money_mouth_face:","keywords":"money-mouth face smiley win win money money emotion emotion boys night boys night"},"nerd":{"unicode":"1f913","shortname":":nerd:","aliases":":nerd_face:","keywords":"nerd face smiley glasses"},"sunglasses":{"unicode":"1f60e","shortname":":sunglasses:","aliases":"","keywords":"smiling face with sunglasses silly smiley emojione glasses boys night boys night"},"hugging":{"unicode":"1f917","shortname":":hugging:","aliases":":hugging_face:","keywords":"hugging face smiley hug thank you"},"smirk":{"unicode":"1f60f","shortname":":smirk:","aliases":"","keywords":"smirking face silly smiley sexy sarcastic sarcastic"},"no_mouth":{"unicode":"1f636","shortname":":no_mouth:","aliases":"","keywords":"face without mouth mad smiley neutral emotion emotion"},"neutral_face":{"unicode":"1f610","shortname":":neutral_face:","aliases":"","keywords":"neutral face mad smiley shrug neutral emotion emotion"},"expressionless":{"unicode":"1f611","shortname":":expressionless:","aliases":"","keywords":"expressionless face mad smiley neutral emotion emotion"},"unamused":{"unicode":"1f612","shortname":":unamused:","aliases":"","keywords":"unamused face sad mad smiley tired emotion emotion"},"rolling_eyes":{"unicode":"1f644","shortname":":rolling_eyes:","aliases":":face_with_rolling_eyes:","keywords":"face with rolling eyes mad smiley rolling eyes emotion emotion sarcastic sarcastic"},"thinking":{"unicode":"1f914","shortname":":thinking:","aliases":":thinking_face:","keywords":"thinking face smiley thinking boys night boys night"},"flushed":{"unicode":"1f633","shortname":":flushed:","aliases":"","keywords":"flushed face smiley emotion emotion omg omg"},"disappointed":{"unicode":"1f61e","shortname":":disappointed:","aliases":"","keywords":"disappointed face sad smiley tired emotion emotion"},"worried":{"unicode":"1f61f","shortname":":worried:","aliases":"","keywords":"worried face sad smiley emotion emotion"},"angry":{"unicode":"1f620","shortname":":angry:","aliases":"","keywords":"angry face mad smiley emotion emotion"},"rage":{"unicode":"1f621","shortname":":rage:","aliases":"","keywords":"pouting face mad smiley angry emotion emotion"},"pensive":{"unicode":"1f614","shortname":":pensive:","aliases":"","keywords":"pensive face sad smiley emotion emotion rip rip"},"confused":{"unicode":"1f615","shortname":":confused:","aliases":"","keywords":"confused face smiley surprised emotion emotion"},"slight_frown":{"unicode":"1f641","shortname":":slight_frown:","aliases":":slightly_frowning_face:","keywords":"slightly frowning face sad smiley emotion emotion"},"frowning2":{"unicode":"2639","shortname":":frowning2:","aliases":":white_frowning_face:","keywords":"white frowning face sad smiley emotion emotion"},"persevere":{"unicode":"1f623","shortname":":persevere:","aliases":"","keywords":"persevering face sad smiley angry emotion emotion"},"confounded":{"unicode":"1f616","shortname":":confounded:","aliases":"","keywords":"confounded face sad smiley angry emotion emotion"},"tired_face":{"unicode":"1f62b","shortname":":tired_face:","aliases":"","keywords":"tired face sad smiley tired emotion emotion"},"weary":{"unicode":"1f629","shortname":":weary:","aliases":"","keywords":"weary face sad smiley tired stressed emotion emotion"},"triumph":{"unicode":"1f624","shortname":":triumph:","aliases":"","keywords":"face with look of triumph mad smiley angry emotion emotion steam steam"},"open_mouth":{"unicode":"1f62e","shortname":":open_mouth:","aliases":"","keywords":"face with open mouth smiley surprised wow wow emotion emotion"},"scream":{"unicode":"1f631","shortname":":scream:","aliases":"","keywords":"face screaming in fear smiley surprised wow wow emotion emotion omg omg"},"fearful":{"unicode":"1f628","shortname":":fearful:","aliases":"","keywords":"fearful face smiley surprised emotion emotion"},"cold_sweat":{"unicode":"1f630","shortname":":cold_sweat:","aliases":"","keywords":"face with open mouth and cold sweat smiley sweat emotion emotion"},"hushed":{"unicode":"1f62f","shortname":":hushed:","aliases":"","keywords":"hushed face smiley surprised wow wow"},"frowning":{"unicode":"1f626","shortname":":frowning:","aliases":"","keywords":"frowning face with open mouth sad smiley surprised emotion emotion"},"anguished":{"unicode":"1f627","shortname":":anguished:","aliases":"","keywords":"anguished face sad smiley surprised emotion emotion"},"cry":{"unicode":"1f622","shortname":":cry:","aliases":"","keywords":"crying face sad smiley cry emotion emotion rip rip heartbreak heartbreak"},"disappointed_relieved":{"unicode":"1f625","shortname":":disappointed_relieved:","aliases":"","keywords":"disappointed but relieved face sad smiley stressed sweat cry emotion emotion"},"sleepy":{"unicode":"1f62a","shortname":":sleepy:","aliases":"","keywords":"sleepy face smiley sick emotion emotion"},"sweat":{"unicode":"1f613","shortname":":sweat:","aliases":"","keywords":"face with cold sweat sad smiley stressed sweat emotion emotion"},"sob":{"unicode":"1f62d","shortname":":sob:","aliases":"","keywords":"loudly crying face sad smiley cry emotion emotion heartbreak heartbreak"},"dizzy_face":{"unicode":"1f635","shortname":":dizzy_face:","aliases":"","keywords":"dizzy face smiley surprised dead wow wow emotion emotion omg omg"},"astonished":{"unicode":"1f632","shortname":":astonished:","aliases":"","keywords":"astonished face smiley surprised wow wow emotion emotion omg omg"},"zipper_mouth":{"unicode":"1f910","shortname":":zipper_mouth:","aliases":":zipper_mouth_face:","keywords":"zipper-mouth face mad smiley"},"mask":{"unicode":"1f637","shortname":":mask:","aliases":"","keywords":"face with medical mask smiley dead health sick"},"thermometer_face":{"unicode":"1f912","shortname":":thermometer_face:","aliases":":face_with_thermometer:","keywords":"face with thermometer smiley health sick emotion emotion"},"head_bandage":{"unicode":"1f915","shortname":":head_bandage:","aliases":":face_with_head_bandage:","keywords":"face with head-bandage smiley health sick emotion emotion"},"sleeping":{"unicode":"1f634","shortname":":sleeping:","aliases":"","keywords":"sleeping face smiley tired emotion emotion goodnight goodnight"},"zzz":{"unicode":"1f4a4","shortname":":zzz:","aliases":"","keywords":"sleeping symbol tired goodnight goodnight"},"poop":{"unicode":"1f4a9","shortname":":poop:","aliases":":shit: :hankey: :poo:","keywords":"pile of poo bathroom shit sol sol diarrhea diarrhea"},"smiling_imp":{"unicode":"1f608","shortname":":smiling_imp:","aliases":"","keywords":"smiling face with horns silly smiley angry monster devil devil boys night boys night"},"imp":{"unicode":"1f47f","shortname":":imp:","aliases":"","keywords":"imp smiley monster devil devil wth wth"},"japanese_ogre":{"unicode":"1f479","shortname":":japanese_ogre:","aliases":"","keywords":"japanese ogre monster"},"japanese_goblin":{"unicode":"1f47a","shortname":":japanese_goblin:","aliases":"","keywords":"japanese goblin angry monster"},"skull":{"unicode":"1f480","shortname":":skull:","aliases":":skeleton:","keywords":"skull dead halloween skull"},"ghost":{"unicode":"1f47b","shortname":":ghost:","aliases":"","keywords":"ghost holidays halloween monster"},"alien":{"unicode":"1f47d","shortname":":alien:","aliases":"","keywords":"extraterrestrial alien space monster alien scientology scientology"},"robot":{"unicode":"1f916","shortname":":robot:","aliases":":robot_face:","keywords":"robot face monster robot"},"smiley_cat":{"unicode":"1f63a","shortname":":smiley_cat:","aliases":"","keywords":"smiling cat face with open mouth happy cat cat animal animal"},"smile_cat":{"unicode":"1f638","shortname":":smile_cat:","aliases":"","keywords":"grinning cat face with smiling eyes happy cat cat animal animal"},"joy_cat":{"unicode":"1f639","shortname":":joy_cat:","aliases":"","keywords":"cat face with tears of joy happy silly cry laugh laugh cat cat animal animal sarcastic sarcastic"},"heart_eyes_cat":{"unicode":"1f63b","shortname":":heart_eyes_cat:","aliases":"","keywords":"smiling cat face with heart-shaped eyes heart eyes cat cat animal animal beautiful beautiful"},"smirk_cat":{"unicode":"1f63c","shortname":":smirk_cat:","aliases":"","keywords":"cat face with wry smile cat cat animal animal"},"kissing_cat":{"unicode":"1f63d","shortname":":kissing_cat:","aliases":"","keywords":"kissing cat face with closed eyes cat cat animal animal"},"scream_cat":{"unicode":"1f640","shortname":":scream_cat:","aliases":"","keywords":"weary cat face cat cat animal animal"},"crying_cat_face":{"unicode":"1f63f","shortname":":crying_cat_face:","aliases":"","keywords":"crying cat face cry cat cat animal animal"},"pouting_cat":{"unicode":"1f63e","shortname":":pouting_cat:","aliases":"","keywords":"pouting cat face cat cat animal animal"},"raised_hands":{"unicode":"1f64c","shortname":":raised_hands:","aliases":"","keywords":"person raising both hands in celebration body hands diversity diversity perfect perfect good good parties parties"},"clap":{"unicode":"1f44f","shortname":":clap:","aliases":"","keywords":"clapping hands sign body hands win win diversity diversity good good beautiful beautiful"},"wave":{"unicode":"1f44b","shortname":":wave:","aliases":"","keywords":"waving hand sign body hands hi diversity diversity"},"thumbsup":{"unicode":"1f44d","shortname":":thumbsup:","aliases":":+1: :thumbup:","keywords":"thumbs up sign body hands hi luck thank you diversity diversity perfect perfect good good beautiful beautiful"},"thumbsdown":{"unicode":"1f44e","shortname":":thumbsdown:","aliases":":-1: :thumbdown:","keywords":"thumbs down sign body hands diversity diversity"},"punch":{"unicode":"1f44a","shortname":":punch:","aliases":"","keywords":"fisted hand sign body hands hi fist bump diversity diversity boys night boys night"},"fist":{"unicode":"270a","shortname":":fist:","aliases":"","keywords":"raised fist body hands hi fist bump diversity diversity condolence condolence"},"v":{"unicode":"270c","shortname":":v:","aliases":"","keywords":"victory hand body hands hi thank you peace peace diversity diversity girls night girls night"},"ok_hand":{"unicode":"1f44c","shortname":":ok_hand:","aliases":"","keywords":"ok hand sign body hands hi diversity diversity perfect perfect good good beautiful beautiful"},"raised_hand":{"unicode":"270b","shortname":":raised_hand:","aliases":"","keywords":"raised hand body hands hi diversity diversity girls night girls night"},"open_hands":{"unicode":"1f450","shortname":":open_hands:","aliases":"","keywords":"open hands sign body hands diversity diversity condolence condolence"},"muscle":{"unicode":"1f4aa","shortname":":muscle:","aliases":"","keywords":"flexed biceps body hands workout flex win win diversity diversity feminist feminist boys night boys night"},"pray":{"unicode":"1f64f","shortname":":pray:","aliases":"","keywords":"person with folded hands body hands hi luck thank you pray pray diversity diversity scientology scientology"},"point_up":{"unicode":"261d","shortname":":point_up:","aliases":"","keywords":"white up pointing index body hands emojione diversity diversity"},"point_up_2":{"unicode":"1f446","shortname":":point_up_2:","aliases":"","keywords":"white up pointing backhand index body hands diversity diversity"},"point_down":{"unicode":"1f447","shortname":":point_down:","aliases":"","keywords":"white down pointing backhand index body hands diversity diversity"},"point_left":{"unicode":"1f448","shortname":":point_left:","aliases":"","keywords":"white left pointing backhand index body hands hi diversity diversity"},"point_right":{"unicode":"1f449","shortname":":point_right:","aliases":"","keywords":"white right pointing backhand index body hands hi diversity diversity"},"middle_finger":{"unicode":"1f595","shortname":":middle_finger:","aliases":":reversed_hand_with_middle_finger_extended:","keywords":"reversed hand with middle finger extended body hands middle finger diversity diversity"},"hand_splayed":{"unicode":"1f590","shortname":":hand_splayed:","aliases":":raised_hand_with_fingers_splayed:","keywords":"raised hand with fingers splayed body hands hi diversity diversity"},"metal":{"unicode":"1f918","shortname":":metal:","aliases":":sign_of_the_horns:","keywords":"sign of the horns body hands hi diversity diversity boys night boys night parties parties"},"vulcan":{"unicode":"1f596","shortname":":vulcan:","aliases":":raised_hand_with_part_between_middle_and_ring_fingers:","keywords":"raised hand with part between middle and ring fingers body hands hi diversity diversity"},"writing_hand":{"unicode":"270d","shortname":":writing_hand:","aliases":"","keywords":"writing hand body hands write diversity diversity"},"nail_care":{"unicode":"1f485","shortname":":nail_care:","aliases":"","keywords":"nail polish women body hands nailpolish diversity diversity girls night girls night"},"lips":{"unicode":"1f444","shortname":":lips:","aliases":"","keywords":"mouth women body sexy lip"},"tongue":{"unicode":"1f445","shortname":":tongue:","aliases":"","keywords":"tongue body sexy lip"},"ear":{"unicode":"1f442","shortname":":ear:","aliases":"","keywords":"ear body diversity diversity"},"nose":{"unicode":"1f443","shortname":":nose:","aliases":"","keywords":"nose body diversity diversity"},"eye":{"unicode":"1f441","shortname":":eye:","aliases":"","keywords":"eye body eyes"},"eyes":{"unicode":"1f440","shortname":":eyes:","aliases":"","keywords":"eyes body eyes"},"bust_in_silhouette":{"unicode":"1f464","shortname":":bust_in_silhouette:","aliases":"","keywords":"bust in silhouette people"},"busts_in_silhouette":{"unicode":"1f465","shortname":":busts_in_silhouette:","aliases":"","keywords":"busts in silhouette people"},"speaking_head":{"unicode":"1f5e3","shortname":":speaking_head:","aliases":":speaking_head_in_silhouette:","keywords":"speaking head in silhouette people talk"},"baby":{"unicode":"1f476","shortname":":baby:","aliases":"","keywords":"baby people baby diversity diversity"},"boy":{"unicode":"1f466","shortname":":boy:","aliases":"","keywords":"boy people baby diversity diversity"},"girl":{"unicode":"1f467","shortname":":girl:","aliases":"","keywords":"girl people women baby diversity diversity"},"man":{"unicode":"1f468","shortname":":man:","aliases":"","keywords":"man people men sex diversity diversity selfie selfie boys night boys night"},"woman":{"unicode":"1f469","shortname":":woman:","aliases":"","keywords":"woman people women sex diversity diversity feminist feminist selfie selfie girls night girls night"},"person_with_blond_hair":{"unicode":"1f471","shortname":":person_with_blond_hair:","aliases":"","keywords":"person with blond hair people men diversity diversity"},"older_man":{"unicode":"1f474","shortname":":older_man:","aliases":"","keywords":"older man people men old people diversity diversity"},"older_woman":{"unicode":"1f475","shortname":":older_woman:","aliases":":grandma:","keywords":"older woman people old people diversity diversity"},"man_with_gua_pi_mao":{"unicode":"1f472","shortname":":man_with_gua_pi_mao:","aliases":"","keywords":"man with gua pi mao people hat men diversity diversity"},"man_with_turban":{"unicode":"1f473","shortname":":man_with_turban:","aliases":"","keywords":"man with turban people hat diversity diversity"},"cop":{"unicode":"1f46e","shortname":":cop:","aliases":"","keywords":"police officer people hat men diversity diversity job job police police 911 911"},"construction_worker":{"unicode":"1f477","shortname":":construction_worker:","aliases":"","keywords":"construction worker people hat men diversity diversity job job"},"guardsman":{"unicode":"1f482","shortname":":guardsman:","aliases":"","keywords":"guardsman people hat men diversity diversity job job"},"spy":{"unicode":"1f575","shortname":":spy:","aliases":":sleuth_or_spy:","keywords":"sleuth or spy people hat men glasses diversity diversity job job"},"santa":{"unicode":"1f385","shortname":":santa:","aliases":"","keywords":"father christmas people hat winter holidays christmas diversity diversity santa santa"},"angel":{"unicode":"1f47c","shortname":":angel:","aliases":"","keywords":"baby angel people diversity diversity omg omg"},"princess":{"unicode":"1f478","shortname":":princess:","aliases":"","keywords":"princess people women diversity diversity beautiful beautiful girls night girls night"},"bride_with_veil":{"unicode":"1f470","shortname":":bride_with_veil:","aliases":"","keywords":"bride with veil people wedding women diversity diversity"},"walking":{"unicode":"1f6b6","shortname":":walking:","aliases":"","keywords":"pedestrian people men diversity diversity"},"runner":{"unicode":"1f3c3","shortname":":runner:","aliases":"","keywords":"runner people men diversity diversity boys night boys night run run"},"dancer":{"unicode":"1f483","shortname":":dancer:","aliases":"","keywords":"dancer people women sexy diversity diversity girls night girls night dance dance"},"dancers":{"unicode":"1f46f","shortname":":dancers:","aliases":"","keywords":"woman with bunny ears people women sexy girls night girls night boys night boys night parties parties dance dance"},"couple":{"unicode":"1f46b","shortname":":couple:","aliases":"","keywords":"man and woman holding hands people sex creationism creationism"},"two_men_holding_hands":{"unicode":"1f46c","shortname":":two_men_holding_hands:","aliases":"","keywords":"two men holding hands people gay men sex lgbt lgbt"},"two_women_holding_hands":{"unicode":"1f46d","shortname":":two_women_holding_hands:","aliases":"","keywords":"two women holding hands people women sex lgbt lgbt lesbian lesbian girls night girls night"},"bow":{"unicode":"1f647","shortname":":bow:","aliases":"","keywords":"person bowing deeply people pray pray diversity diversity"},"information_desk_person":{"unicode":"1f481","shortname":":information_desk_person:","aliases":"","keywords":"information desk person people women diversity diversity"},"no_good":{"unicode":"1f645","shortname":":no_good:","aliases":"","keywords":"face with no good gesture people women diversity diversity girls night girls night"},"ok_woman":{"unicode":"1f646","shortname":":ok_woman:","aliases":"","keywords":"face with ok gesture people women diversity diversity"},"raising_hand":{"unicode":"1f64b","shortname":":raising_hand:","aliases":"","keywords":"happy person raising one hand people women diversity diversity"},"person_with_pouting_face":{"unicode":"1f64e","shortname":":person_with_pouting_face:","aliases":"","keywords":"person with pouting face people women diversity diversity"},"person_frowning":{"unicode":"1f64d","shortname":":person_frowning:","aliases":"","keywords":"person frowning people women diversity diversity"},"haircut":{"unicode":"1f487","shortname":":haircut:","aliases":"","keywords":"haircut people women diversity diversity"},"massage":{"unicode":"1f486","shortname":":massage:","aliases":"","keywords":"face massage people women diversity diversity"},"couple_with_heart":{"unicode":"1f491","shortname":":couple_with_heart:","aliases":"","keywords":"couple with heart people love sex"},"couple_ww":{"unicode":"1f469-2764-1f469","shortname":":couple_ww:","aliases":":couple_with_heart_ww:","keywords":"couple (woman,woman) people women love sex lgbt lgbt"},"couple_mm":{"unicode":"1f468-2764-1f468","shortname":":couple_mm:","aliases":":couple_with_heart_mm:","keywords":"couple (man,man) people gay men love sex lgbt lgbt"},"couplekiss":{"unicode":"1f48f","shortname":":couplekiss:","aliases":"","keywords":"kiss people love sex"},"kiss_ww":{"unicode":"1f469-2764-1f48b-1f469","shortname":":kiss_ww:","aliases":":couplekiss_ww:","keywords":"kiss (woman,woman) people women love sex lgbt lgbt lesbian lesbian"},"kiss_mm":{"unicode":"1f468-2764-1f48b-1f468","shortname":":kiss_mm:","aliases":":couplekiss_mm:","keywords":"kiss (man,man) people gay men love sex lgbt lgbt"},"family":{"unicode":"1f46a","shortname":":family:","aliases":"","keywords":"family people family baby"},"family_mwg":{"unicode":"1f468-1f469-1f467","shortname":":family_mwg:","aliases":"","keywords":"family (man,woman,girl) people family baby"},"family_mwgb":{"unicode":"1f468-1f469-1f467-1f466","shortname":":family_mwgb:","aliases":"","keywords":"family (man,woman,girl,boy) people family baby"},"family_mwbb":{"unicode":"1f468-1f469-1f466-1f466","shortname":":family_mwbb:","aliases":"","keywords":"family (man,woman,boy,boy) people family baby"},"family_mwgg":{"unicode":"1f468-1f469-1f467-1f467","shortname":":family_mwgg:","aliases":"","keywords":"family (man,woman,girl,girl) people family baby"},"family_wwb":{"unicode":"1f469-1f469-1f466","shortname":":family_wwb:","aliases":"","keywords":"family (woman,woman,boy) people family women baby lgbt lgbt lesbian lesbian"},"family_wwg":{"unicode":"1f469-1f469-1f467","shortname":":family_wwg:","aliases":"","keywords":"family (woman,woman,girl) people family women baby lgbt lgbt lesbian lesbian"},"family_wwgb":{"unicode":"1f469-1f469-1f467-1f466","shortname":":family_wwgb:","aliases":"","keywords":"family (woman,woman,girl,boy) people family women baby lgbt lgbt lesbian lesbian"},"family_wwbb":{"unicode":"1f469-1f469-1f466-1f466","shortname":":family_wwbb:","aliases":"","keywords":"family (woman,woman,boy,boy) people family women baby lgbt lgbt lesbian lesbian"},"family_wwgg":{"unicode":"1f469-1f469-1f467-1f467","shortname":":family_wwgg:","aliases":"","keywords":"family (woman,woman,girl,girl) people family women baby lgbt lgbt lesbian lesbian"},"family_mmb":{"unicode":"1f468-1f468-1f466","shortname":":family_mmb:","aliases":"","keywords":"family (man,man,boy) people gay family men baby lgbt lgbt"},"family_mmg":{"unicode":"1f468-1f468-1f467","shortname":":family_mmg:","aliases":"","keywords":"family (man,man,girl) people gay family men baby lgbt lgbt"},"family_mmgb":{"unicode":"1f468-1f468-1f467-1f466","shortname":":family_mmgb:","aliases":"","keywords":"family (man,man,girl,boy) people gay family men baby lgbt lgbt"},"family_mmbb":{"unicode":"1f468-1f468-1f466-1f466","shortname":":family_mmbb:","aliases":"","keywords":"family (man,man,boy,boy) people gay family men baby lgbt lgbt"},"family_mmgg":{"unicode":"1f468-1f468-1f467-1f467","shortname":":family_mmgg:","aliases":"","keywords":"family (man,man,girl,girl) people gay family men baby lgbt lgbt"},"womans_clothes":{"unicode":"1f45a","shortname":":womans_clothes:","aliases":"","keywords":"womans clothes women fashion"},"shirt":{"unicode":"1f455","shortname":":shirt:","aliases":"","keywords":"t-shirt fashion"},"jeans":{"unicode":"1f456","shortname":":jeans:","aliases":"","keywords":"jeans fashion"},"necktie":{"unicode":"1f454","shortname":":necktie:","aliases":"","keywords":"necktie fashion"},"dress":{"unicode":"1f457","shortname":":dress:","aliases":"","keywords":"dress women fashion sexy girls night girls night"},"bikini":{"unicode":"1f459","shortname":":bikini:","aliases":"","keywords":"bikini women fashion sexy vacation tropical swim"},"kimono":{"unicode":"1f458","shortname":":kimono:","aliases":"","keywords":"kimono fashion"},"lipstick":{"unicode":"1f484","shortname":":lipstick:","aliases":"","keywords":"lipstick object women fashion sexy lip"},"kiss":{"unicode":"1f48b","shortname":":kiss:","aliases":"","keywords":"kiss mark women love sexy lip beautiful beautiful girls night girls night"},"footprints":{"unicode":"1f463","shortname":":footprints:","aliases":"","keywords":"footprints"},"high_heel":{"unicode":"1f460","shortname":":high_heel:","aliases":"","keywords":"high-heeled shoe women fashion shoe sexy accessories girls night girls night"},"sandal":{"unicode":"1f461","shortname":":sandal:","aliases":"","keywords":"womans sandal fashion shoe accessories"},"boot":{"unicode":"1f462","shortname":":boot:","aliases":"","keywords":"womans boots women fashion shoe sexy accessories"},"mans_shoe":{"unicode":"1f45e","shortname":":mans_shoe:","aliases":"","keywords":"mans shoe fashion shoe accessories"},"athletic_shoe":{"unicode":"1f45f","shortname":":athletic_shoe:","aliases":"","keywords":"athletic shoe fashion shoe accessories boys night boys night"},"womans_hat":{"unicode":"1f452","shortname":":womans_hat:","aliases":"","keywords":"womans hat women fashion accessories"},"tophat":{"unicode":"1f3a9","shortname":":tophat:","aliases":"","keywords":"top hat hat fashion accessories"},"helmet_with_cross":{"unicode":"26d1","shortname":":helmet_with_cross:","aliases":":helmet_with_white_cross:","keywords":"helmet with white cross object hat accessories job job"},"mortar_board":{"unicode":"1f393","shortname":":mortar_board:","aliases":"","keywords":"graduation cap hat office accessories"},"crown":{"unicode":"1f451","shortname":":crown:","aliases":"","keywords":"crown object gem accessories"},"school_satchel":{"unicode":"1f392","shortname":":school_satchel:","aliases":"","keywords":"school satchel bag fashion office vacation accessories"},"pouch":{"unicode":"1f45d","shortname":":pouch:","aliases":"","keywords":"pouch bag women fashion accessories"},"purse":{"unicode":"1f45b","shortname":":purse:","aliases":"","keywords":"purse bag women fashion accessories money money"},"handbag":{"unicode":"1f45c","shortname":":handbag:","aliases":"","keywords":"handbag bag women fashion vacation accessories"},"briefcase":{"unicode":"1f4bc","shortname":":briefcase:","aliases":"","keywords":"briefcase bag work accessories nutcase nutcase job job"},"eyeglasses":{"unicode":"1f453","shortname":":eyeglasses:","aliases":"","keywords":"eyeglasses fashion glasses accessories"},"dark_sunglasses":{"unicode":"1f576","shortname":":dark_sunglasses:","aliases":"","keywords":"dark sunglasses fashion glasses accessories"},"ring":{"unicode":"1f48d","shortname":":ring:","aliases":"","keywords":"ring wedding object fashion gem accessories"},"closed_umbrella":{"unicode":"1f302","shortname":":closed_umbrella:","aliases":"","keywords":"closed umbrella object sky rain accessories"},"dog":{"unicode":"1f436","shortname":":dog:","aliases":"","keywords":"dog face dog dog pug pug animal animal"},"cat":{"unicode":"1f431","shortname":":cat:","aliases":"","keywords":"cat face halloween vagina cat cat animal animal"},"mouse":{"unicode":"1f42d","shortname":":mouse:","aliases":"","keywords":"mouse face animal animal"},"hamster":{"unicode":"1f439","shortname":":hamster:","aliases":"","keywords":"hamster face animal animal"},"rabbit":{"unicode":"1f430","shortname":":rabbit:","aliases":"","keywords":"rabbit face wildlife animal animal"},"bear":{"unicode":"1f43b","shortname":":bear:","aliases":"","keywords":"bear face wildlife roar animal animal"},"panda_face":{"unicode":"1f43c","shortname":":panda_face:","aliases":"","keywords":"panda face wildlife roar animal animal"},"koala":{"unicode":"1f428","shortname":":koala:","aliases":"","keywords":"koala wildlife animal animal"},"tiger":{"unicode":"1f42f","shortname":":tiger:","aliases":"","keywords":"tiger face wildlife roar cat cat animal animal"},"lion_face":{"unicode":"1f981","shortname":":lion_face:","aliases":":lion:","keywords":"lion face wildlife roar cat cat animal animal"},"cow":{"unicode":"1f42e","shortname":":cow:","aliases":"","keywords":"cow face animal animal"},"pig":{"unicode":"1f437","shortname":":pig:","aliases":"","keywords":"pig face animal animal"},"pig_nose":{"unicode":"1f43d","shortname":":pig_nose:","aliases":"","keywords":"pig nose animal animal"},"frog":{"unicode":"1f438","shortname":":frog:","aliases":"","keywords":"frog face wildlife animal animal"},"octopus":{"unicode":"1f419","shortname":":octopus:","aliases":"","keywords":"octopus wildlife animal animal"},"monkey_face":{"unicode":"1f435","shortname":":monkey_face:","aliases":"","keywords":"monkey face animal animal"},"see_no_evil":{"unicode":"1f648","shortname":":see_no_evil:","aliases":"","keywords":"see-no-evil monkey animal animal"},"hear_no_evil":{"unicode":"1f649","shortname":":hear_no_evil:","aliases":"","keywords":"hear-no-evil monkey animal animal"},"speak_no_evil":{"unicode":"1f64a","shortname":":speak_no_evil:","aliases":"","keywords":"speak-no-evil monkey animal animal"},"monkey":{"unicode":"1f412","shortname":":monkey:","aliases":"","keywords":"monkey wildlife animal animal"},"chicken":{"unicode":"1f414","shortname":":chicken:","aliases":"","keywords":"chicken animal animal chicken chicken"},"penguin":{"unicode":"1f427","shortname":":penguin:","aliases":"","keywords":"penguin wildlife animal animal"},"bird":{"unicode":"1f426","shortname":":bird:","aliases":"","keywords":"bird wildlife animal animal"},"baby_chick":{"unicode":"1f424","shortname":":baby_chick:","aliases":"","keywords":"baby chick animal animal chicken chicken"},"hatching_chick":{"unicode":"1f423","shortname":":hatching_chick:","aliases":"","keywords":"hatching chick animal animal chicken chicken"},"hatched_chick":{"unicode":"1f425","shortname":":hatched_chick:","aliases":"","keywords":"front-facing baby chick animal animal chicken chicken"},"wolf":{"unicode":"1f43a","shortname":":wolf:","aliases":"","keywords":"wolf face wildlife roar animal animal"},"boar":{"unicode":"1f417","shortname":":boar:","aliases":"","keywords":"boar wildlife animal animal"},"horse":{"unicode":"1f434","shortname":":horse:","aliases":"","keywords":"horse face wildlife animal animal"},"unicorn":{"unicode":"1f984","shortname":":unicorn:","aliases":":unicorn_face:","keywords":"unicorn face animal animal"},"bee":{"unicode":"1f41d","shortname":":bee:","aliases":"","keywords":"honeybee insects animal animal"},"bug":{"unicode":"1f41b","shortname":":bug:","aliases":"","keywords":"bug insects animal animal"},"snail":{"unicode":"1f40c","shortname":":snail:","aliases":"","keywords":"snail insects animal animal"},"beetle":{"unicode":"1f41e","shortname":":beetle:","aliases":"","keywords":"lady beetle insects animal animal"},"ant":{"unicode":"1f41c","shortname":":ant:","aliases":"","keywords":"ant insects animal animal"},"spider":{"unicode":"1f577","shortname":":spider:","aliases":"","keywords":"spider insects halloween animal animal"},"scorpion":{"unicode":"1f982","shortname":":scorpion:","aliases":"","keywords":"scorpion insects reptile reptile animal animal"},"crab":{"unicode":"1f980","shortname":":crab:","aliases":"","keywords":"crab tropical animal animal"},"snake":{"unicode":"1f40d","shortname":":snake:","aliases":"","keywords":"snake wildlife reptile reptile animal animal creationism creationism"},"turtle":{"unicode":"1f422","shortname":":turtle:","aliases":"","keywords":"turtle wildlife reptile reptile animal animal"},"tropical_fish":{"unicode":"1f420","shortname":":tropical_fish:","aliases":"","keywords":"tropical fish wildlife animal animal"},"fish":{"unicode":"1f41f","shortname":":fish:","aliases":"","keywords":"fish wildlife animal animal"},"blowfish":{"unicode":"1f421","shortname":":blowfish:","aliases":"","keywords":"blowfish wildlife animal animal"},"dolphin":{"unicode":"1f42c","shortname":":dolphin:","aliases":"","keywords":"dolphin wildlife tropical animal animal"},"whale":{"unicode":"1f433","shortname":":whale:","aliases":"","keywords":"spouting whale wildlife tropical whales whales animal animal"},"whale2":{"unicode":"1f40b","shortname":":whale2:","aliases":"","keywords":"whale wildlife tropical whales whales animal animal"},"crocodile":{"unicode":"1f40a","shortname":":crocodile:","aliases":"","keywords":"crocodile wildlife reptile reptile animal animal"},"leopard":{"unicode":"1f406","shortname":":leopard:","aliases":"","keywords":"leopard wildlife roar animal animal"},"tiger2":{"unicode":"1f405","shortname":":tiger2:","aliases":"","keywords":"tiger wildlife roar animal animal"},"water_buffalo":{"unicode":"1f403","shortname":":water_buffalo:","aliases":"","keywords":"water buffalo wildlife animal animal"},"ox":{"unicode":"1f402","shortname":":ox:","aliases":"","keywords":"ox animal animal"},"cow2":{"unicode":"1f404","shortname":":cow2:","aliases":"","keywords":"cow animal animal"},"dromedary_camel":{"unicode":"1f42a","shortname":":dromedary_camel:","aliases":"","keywords":"dromedary camel wildlife animal animal"},"camel":{"unicode":"1f42b","shortname":":camel:","aliases":"","keywords":"bactrian camel wildlife animal animal hump day hump day"},"elephant":{"unicode":"1f418","shortname":":elephant:","aliases":"","keywords":"elephant wildlife animal animal"},"goat":{"unicode":"1f410","shortname":":goat:","aliases":"","keywords":"goat animal animal"},"ram":{"unicode":"1f40f","shortname":":ram:","aliases":"","keywords":"ram wildlife animal animal"},"sheep":{"unicode":"1f411","shortname":":sheep:","aliases":"","keywords":"sheep animal animal"},"racehorse":{"unicode":"1f40e","shortname":":racehorse:","aliases":"","keywords":"horse wildlife animal animal"},"pig2":{"unicode":"1f416","shortname":":pig2:","aliases":"","keywords":"pig animal animal"},"rat":{"unicode":"1f400","shortname":":rat:","aliases":"","keywords":"rat animal animal"},"mouse2":{"unicode":"1f401","shortname":":mouse2:","aliases":"","keywords":"mouse animal animal"},"rooster":{"unicode":"1f413","shortname":":rooster:","aliases":"","keywords":"rooster animal animal"},"turkey":{"unicode":"1f983","shortname":":turkey:","aliases":"","keywords":"turkey wildlife animal animal"},"dove":{"unicode":"1f54a","shortname":":dove:","aliases":":dove_of_peace:","keywords":"dove of peace animal animal"},"dog2":{"unicode":"1f415","shortname":":dog2:","aliases":"","keywords":"dog dog dog pug pug animal animal"},"poodle":{"unicode":"1f429","shortname":":poodle:","aliases":"","keywords":"poodle dog dog animal animal"},"cat2":{"unicode":"1f408","shortname":":cat2:","aliases":"","keywords":"cat halloween cat cat animal animal"},"rabbit2":{"unicode":"1f407","shortname":":rabbit2:","aliases":"","keywords":"rabbit wildlife animal animal"},"chipmunk":{"unicode":"1f43f","shortname":":chipmunk:","aliases":"","keywords":"chipmunk wildlife animal animal"},"feet":{"unicode":"1f43e","shortname":":feet:","aliases":":paw_prints:","keywords":"paw prints animal animal"},"dragon":{"unicode":"1f409","shortname":":dragon:","aliases":"","keywords":"dragon roar reptile reptile animal animal"},"dragon_face":{"unicode":"1f432","shortname":":dragon_face:","aliases":"","keywords":"dragon face roar monster reptile reptile animal animal"},"cactus":{"unicode":"1f335","shortname":":cactus:","aliases":"","keywords":"cactus nature plant trees trees"},"christmas_tree":{"unicode":"1f384","shortname":":christmas_tree:","aliases":"","keywords":"christmas tree plant holidays christmas trees trees"},"evergreen_tree":{"unicode":"1f332","shortname":":evergreen_tree:","aliases":"","keywords":"evergreen tree nature plant holidays christmas camp trees trees"},"deciduous_tree":{"unicode":"1f333","shortname":":deciduous_tree:","aliases":"","keywords":"deciduous tree nature plant camp trees trees"},"palm_tree":{"unicode":"1f334","shortname":":palm_tree:","aliases":"","keywords":"palm tree nature plant tropical trees trees"},"seedling":{"unicode":"1f331","shortname":":seedling:","aliases":"","keywords":"seedling nature plant leaf leaf"},"herb":{"unicode":"1f33f","shortname":":herb:","aliases":"","keywords":"herb nature plant leaf leaf"},"shamrock":{"unicode":"2618","shortname":":shamrock:","aliases":"","keywords":"shamrock nature plant luck leaf leaf"},"four_leaf_clover":{"unicode":"1f340","shortname":":four_leaf_clover:","aliases":"","keywords":"four leaf clover nature plant luck leaf leaf sol sol"},"bamboo":{"unicode":"1f38d","shortname":":bamboo:","aliases":"","keywords":"pine decoration nature plant"},"tanabata_tree":{"unicode":"1f38b","shortname":":tanabata_tree:","aliases":"","keywords":"tanabata tree nature plant trees trees"},"leaves":{"unicode":"1f343","shortname":":leaves:","aliases":"","keywords":"leaf fluttering in wind nature plant leaf leaf"},"fallen_leaf":{"unicode":"1f342","shortname":":fallen_leaf:","aliases":"","keywords":"fallen leaf nature plant leaf leaf"},"maple_leaf":{"unicode":"1f341","shortname":":maple_leaf:","aliases":"","keywords":"maple leaf nature plant leaf leaf"},"ear_of_rice":{"unicode":"1f33e","shortname":":ear_of_rice:","aliases":"","keywords":"ear of rice nature plant leaf leaf"},"hibiscus":{"unicode":"1f33a","shortname":":hibiscus:","aliases":"","keywords":"hibiscus nature flower plant tropical"},"sunflower":{"unicode":"1f33b","shortname":":sunflower:","aliases":"","keywords":"sunflower nature flower plant"},"rose":{"unicode":"1f339","shortname":":rose:","aliases":"","keywords":"rose nature flower plant rip rip condolence condolence beautiful beautiful"},"tulip":{"unicode":"1f337","shortname":":tulip:","aliases":"","keywords":"tulip nature flower plant vagina girls night girls night"},"blossom":{"unicode":"1f33c","shortname":":blossom:","aliases":"","keywords":"blossom nature flower plant"},"cherry_blossom":{"unicode":"1f338","shortname":":cherry_blossom:","aliases":"","keywords":"cherry blossom nature flower plant tropical"},"bouquet":{"unicode":"1f490","shortname":":bouquet:","aliases":"","keywords":"bouquet nature flower plant rip rip condolence condolence"},"mushroom":{"unicode":"1f344","shortname":":mushroom:","aliases":"","keywords":"mushroom nature plant drugs drugs"},"chestnut":{"unicode":"1f330","shortname":":chestnut:","aliases":"","keywords":"chestnut nature plant"},"jack_o_lantern":{"unicode":"1f383","shortname":":jack_o_lantern:","aliases":"","keywords":"jack-o-lantern holidays halloween"},"shell":{"unicode":"1f41a","shortname":":shell:","aliases":"","keywords":"spiral shell"},"spider_web":{"unicode":"1f578","shortname":":spider_web:","aliases":"","keywords":"spider web halloween"},"earth_americas":{"unicode":"1f30e","shortname":":earth_americas:","aliases":"","keywords":"earth globe americas map vacation globe globe"},"earth_africa":{"unicode":"1f30d","shortname":":earth_africa:","aliases":"","keywords":"earth globe europe-africa map vacation globe globe"},"earth_asia":{"unicode":"1f30f","shortname":":earth_asia:","aliases":"","keywords":"earth globe asia-australia map vacation globe globe"},"full_moon":{"unicode":"1f315","shortname":":full_moon:","aliases":"","keywords":"full moon symbol space sky moon moon"},"waning_gibbous_moon":{"unicode":"1f316","shortname":":waning_gibbous_moon:","aliases":"","keywords":"waning gibbous moon symbol space sky moon moon"},"last_quarter_moon":{"unicode":"1f317","shortname":":last_quarter_moon:","aliases":"","keywords":"last quarter moon symbol space sky moon moon"},"waning_crescent_moon":{"unicode":"1f318","shortname":":waning_crescent_moon:","aliases":"","keywords":"waning crescent moon symbol space sky moon moon"},"new_moon":{"unicode":"1f311","shortname":":new_moon:","aliases":"","keywords":"new moon symbol space sky moon moon"},"waxing_crescent_moon":{"unicode":"1f312","shortname":":waxing_crescent_moon:","aliases":"","keywords":"waxing crescent moon symbol space sky moon moon"},"first_quarter_moon":{"unicode":"1f313","shortname":":first_quarter_moon:","aliases":"","keywords":"first quarter moon symbol space sky moon moon"},"waxing_gibbous_moon":{"unicode":"1f314","shortname":":waxing_gibbous_moon:","aliases":"","keywords":"waxing gibbous moon symbol space sky moon moon"},"new_moon_with_face":{"unicode":"1f31a","shortname":":new_moon_with_face:","aliases":"","keywords":"new moon with face space sky goodnight goodnight moon moon"},"full_moon_with_face":{"unicode":"1f31d","shortname":":full_moon_with_face:","aliases":"","keywords":"full moon with face space sky goodnight goodnight moon moon"},"first_quarter_moon_with_face":{"unicode":"1f31b","shortname":":first_quarter_moon_with_face:","aliases":"","keywords":"first quarter moon with face space sky moon moon"},"last_quarter_moon_with_face":{"unicode":"1f31c","shortname":":last_quarter_moon_with_face:","aliases":"","keywords":"last quarter moon with face space sky moon moon"},"sun_with_face":{"unicode":"1f31e","shortname":":sun_with_face:","aliases":"","keywords":"sun with face sky day sun hump day hump day morning morning"},"crescent_moon":{"unicode":"1f319","shortname":":crescent_moon:","aliases":"","keywords":"crescent moon space sky goodnight goodnight moon moon"},"star":{"unicode":"2b50","shortname":":star:","aliases":"","keywords":"white medium star space sky star"},"star2":{"unicode":"1f31f","shortname":":star2:","aliases":"","keywords":"glowing star space sky star"},"dizzy":{"unicode":"1f4ab","shortname":":dizzy:","aliases":"","keywords":"dizzy symbol star symbol"},"sparkles":{"unicode":"2728","shortname":":sparkles:","aliases":"","keywords":"sparkles star girls night girls night"},"comet":{"unicode":"2604","shortname":":comet:","aliases":"","keywords":"comet space sky"},"sunny":{"unicode":"2600","shortname":":sunny:","aliases":"","keywords":"black sun with rays weather sky day sun hot hot morning morning"},"white_sun_small_cloud":{"unicode":"1f324","shortname":":white_sun_small_cloud:","aliases":":white_sun_with_small_cloud:","keywords":"white sun with small cloud weather sky cloud sun"},"partly_sunny":{"unicode":"26c5","shortname":":partly_sunny:","aliases":"","keywords":"sun behind cloud weather sky cloud sun"},"white_sun_cloud":{"unicode":"1f325","shortname":":white_sun_cloud:","aliases":":white_sun_behind_cloud:","keywords":"white sun behind cloud weather sky cloud cold sun"},"white_sun_rain_cloud":{"unicode":"1f326","shortname":":white_sun_rain_cloud:","aliases":":white_sun_behind_cloud_with_rain:","keywords":"white sun behind cloud with rain weather sky cloud cold rain sun"},"cloud":{"unicode":"2601","shortname":":cloud:","aliases":"","keywords":"cloud weather sky cloud cold rain"},"cloud_rain":{"unicode":"1f327","shortname":":cloud_rain:","aliases":":cloud_with_rain:","keywords":"cloud with rain weather winter sky cloud cold rain"},"thunder_cloud_rain":{"unicode":"26c8","shortname":":thunder_cloud_rain:","aliases":":thunder_cloud_and_rain:","keywords":"thunder cloud and rain weather sky cloud cold rain"},"cloud_lightning":{"unicode":"1f329","shortname":":cloud_lightning:","aliases":":cloud_with_lightning:","keywords":"cloud with lightning weather sky cloud cold rain"},"zap":{"unicode":"26a1","shortname":":zap:","aliases":"","keywords":"high voltage sign weather sky diarrhea diarrhea"},"fire":{"unicode":"1f525","shortname":":fire:","aliases":":flame:","keywords":"fire wth wth hot hot"},"boom":{"unicode":"1f4a5","shortname":":boom:","aliases":"","keywords":"collision symbol symbol blast blast"},"snowflake":{"unicode":"2744","shortname":":snowflake:","aliases":"","keywords":"snowflake weather winter sky holidays cold snow snow"},"cloud_snow":{"unicode":"1f328","shortname":":cloud_snow:","aliases":":cloud_with_snow:","keywords":"cloud with snow weather winter sky cloud cold snow snow"},"snowman2":{"unicode":"2603","shortname":":snowman2:","aliases":"","keywords":"snowman weather winter holidays christmas cold snow snow"},"snowman":{"unicode":"26c4","shortname":":snowman:","aliases":"","keywords":"snowman without snow weather winter holidays cold snow snow"},"wind_blowing_face":{"unicode":"1f32c","shortname":":wind_blowing_face:","aliases":"","keywords":"wind blowing face weather cold"},"dash":{"unicode":"1f4a8","shortname":":dash:","aliases":"","keywords":"dash symbol cloud cold smoking smoking"},"cloud_tornado":{"unicode":"1f32a","shortname":":cloud_tornado:","aliases":":cloud_with_tornado:","keywords":"cloud with tornado weather sky cold"},"fog":{"unicode":"1f32b","shortname":":fog:","aliases":"","keywords":"fog weather sky cold"},"umbrella2":{"unicode":"2602","shortname":":umbrella2:","aliases":"","keywords":"umbrella weather object sky cold"},"umbrella":{"unicode":"2614","shortname":":umbrella:","aliases":"","keywords":"umbrella with rain drops weather sky cold rain"},"droplet":{"unicode":"1f4a7","shortname":":droplet:","aliases":"","keywords":"droplet weather sky rain"},"sweat_drops":{"unicode":"1f4a6","shortname":":sweat_drops:","aliases":"","keywords":"splashing sweat symbol rain stressed sweat"},"ocean":{"unicode":"1f30a","shortname":":ocean:","aliases":"","keywords":"water wave weather boat tropical swim"},"green_apple":{"unicode":"1f34f","shortname":":green_apple:","aliases":"","keywords":"green apple fruit food"},"apple":{"unicode":"1f34e","shortname":":apple:","aliases":"","keywords":"red apple fruit food creationism creationism"},"pear":{"unicode":"1f350","shortname":":pear:","aliases":"","keywords":"pear fruit food"},"tangerine":{"unicode":"1f34a","shortname":":tangerine:","aliases":"","keywords":"tangerine fruit food"},"lemon":{"unicode":"1f34b","shortname":":lemon:","aliases":"","keywords":"lemon fruit food"},"banana":{"unicode":"1f34c","shortname":":banana:","aliases":"","keywords":"banana fruit penis food"},"watermelon":{"unicode":"1f349","shortname":":watermelon:","aliases":"","keywords":"watermelon fruit food"},"grapes":{"unicode":"1f347","shortname":":grapes:","aliases":"","keywords":"grapes fruit food"},"strawberry":{"unicode":"1f353","shortname":":strawberry:","aliases":"","keywords":"strawberry fruit food"},"melon":{"unicode":"1f348","shortname":":melon:","aliases":"","keywords":"melon fruit boobs food"},"cherries":{"unicode":"1f352","shortname":":cherries:","aliases":"","keywords":"cherries fruit food"},"peach":{"unicode":"1f351","shortname":":peach:","aliases":"","keywords":"peach fruit butt food"},"pineapple":{"unicode":"1f34d","shortname":":pineapple:","aliases":"","keywords":"pineapple fruit food tropical"},"tomato":{"unicode":"1f345","shortname":":tomato:","aliases":"","keywords":"tomato fruit vegetables food"},"eggplant":{"unicode":"1f346","shortname":":eggplant:","aliases":"","keywords":"aubergine vegetables penis food"},"hot_pepper":{"unicode":"1f336","shortname":":hot_pepper:","aliases":"","keywords":"hot pepper vegetables food"},"corn":{"unicode":"1f33d","shortname":":corn:","aliases":"","keywords":"ear of maize vegetables food"},"sweet_potato":{"unicode":"1f360","shortname":":sweet_potato:","aliases":"","keywords":"roasted sweet potato vegetables food"},"honey_pot":{"unicode":"1f36f","shortname":":honey_pot:","aliases":"","keywords":"honey pot food vagina"},"bread":{"unicode":"1f35e","shortname":":bread:","aliases":"","keywords":"bread food"},"cheese":{"unicode":"1f9c0","shortname":":cheese:","aliases":":cheese_wedge:","keywords":"cheese wedge food"},"poultry_leg":{"unicode":"1f357","shortname":":poultry_leg:","aliases":"","keywords":"poultry leg food holidays"},"meat_on_bone":{"unicode":"1f356","shortname":":meat_on_bone:","aliases":"","keywords":"meat on bone food"},"fried_shrimp":{"unicode":"1f364","shortname":":fried_shrimp:","aliases":"","keywords":"fried shrimp food"},"cooking":{"unicode":"1f373","shortname":":cooking:","aliases":"","keywords":"cooking food"},"hamburger":{"unicode":"1f354","shortname":":hamburger:","aliases":"","keywords":"hamburger america food"},"fries":{"unicode":"1f35f","shortname":":fries:","aliases":"","keywords":"french fries america food"},"hotdog":{"unicode":"1f32d","shortname":":hotdog:","aliases":":hot_dog:","keywords":"hot dog america food"},"pizza":{"unicode":"1f355","shortname":":pizza:","aliases":"","keywords":"slice of pizza italian food boys night boys night"},"spaghetti":{"unicode":"1f35d","shortname":":spaghetti:","aliases":"","keywords":"spaghetti noodles pasta italian food"},"taco":{"unicode":"1f32e","shortname":":taco:","aliases":"","keywords":"taco food mexican vagina"},"burrito":{"unicode":"1f32f","shortname":":burrito:","aliases":"","keywords":"burrito food mexican"},"ramen":{"unicode":"1f35c","shortname":":ramen:","aliases":"","keywords":"steaming bowl noodles ramen japan food"},"stew":{"unicode":"1f372","shortname":":stew:","aliases":"","keywords":"pot of food food steam steam"},"fish_cake":{"unicode":"1f365","shortname":":fish_cake:","aliases":"","keywords":"fish cake with swirl design sushi food"},"sushi":{"unicode":"1f363","shortname":":sushi:","aliases":"","keywords":"sushi sushi japan food"},"bento":{"unicode":"1f371","shortname":":bento:","aliases":"","keywords":"bento box object sushi japan food"},"curry":{"unicode":"1f35b","shortname":":curry:","aliases":"","keywords":"curry and rice food"},"rice_ball":{"unicode":"1f359","shortname":":rice_ball:","aliases":"","keywords":"rice ball sushi japan food"},"rice":{"unicode":"1f35a","shortname":":rice:","aliases":"","keywords":"cooked rice sushi japan food"},"rice_cracker":{"unicode":"1f358","shortname":":rice_cracker:","aliases":"","keywords":"rice cracker sushi food"},"oden":{"unicode":"1f362","shortname":":oden:","aliases":"","keywords":"oden food"},"dango":{"unicode":"1f361","shortname":":dango:","aliases":"","keywords":"dango food"},"shaved_ice":{"unicode":"1f367","shortname":":shaved_ice:","aliases":"","keywords":"shaved ice food"},"ice_cream":{"unicode":"1f368","shortname":":ice_cream:","aliases":"","keywords":"ice cream food"},"icecream":{"unicode":"1f366","shortname":":icecream:","aliases":"","keywords":"soft ice cream food"},"cake":{"unicode":"1f370","shortname":":cake:","aliases":"","keywords":"shortcake food"},"birthday":{"unicode":"1f382","shortname":":birthday:","aliases":"","keywords":"birthday cake birthday food parties parties"},"custard":{"unicode":"1f36e","shortname":":custard:","aliases":":pudding: :flan:","keywords":"custard food"},"candy":{"unicode":"1f36c","shortname":":candy:","aliases":"","keywords":"candy food halloween"},"lollipop":{"unicode":"1f36d","shortname":":lollipop:","aliases":"","keywords":"lollipop food halloween"},"chocolate_bar":{"unicode":"1f36b","shortname":":chocolate_bar:","aliases":"","keywords":"chocolate bar food halloween"},"popcorn":{"unicode":"1f37f","shortname":":popcorn:","aliases":"","keywords":"popcorn food parties parties"},"doughnut":{"unicode":"1f369","shortname":":doughnut:","aliases":"","keywords":"doughnut food"},"cookie":{"unicode":"1f36a","shortname":":cookie:","aliases":"","keywords":"cookie food vagina"},"beer":{"unicode":"1f37a","shortname":":beer:","aliases":"","keywords":"beer mug drink beer alcohol parties parties"},"beers":{"unicode":"1f37b","shortname":":beers:","aliases":"","keywords":"clinking beer mugs drink cheers beer alcohol thank you boys night boys night parties parties"},"wine_glass":{"unicode":"1f377","shortname":":wine_glass:","aliases":"","keywords":"wine glass drink italian alcohol girls night girls night parties parties"},"cocktail":{"unicode":"1f378","shortname":":cocktail:","aliases":"","keywords":"cocktail glass drink cocktail alcohol girls night girls night parties parties"},"tropical_drink":{"unicode":"1f379","shortname":":tropical_drink:","aliases":"","keywords":"tropical drink drink cocktail tropical alcohol"},"champagne":{"unicode":"1f37e","shortname":":champagne:","aliases":":bottle_with_popping_cork:","keywords":"bottle with popping cork drink cheers alcohol parties parties"},"sake":{"unicode":"1f376","shortname":":sake:","aliases":"","keywords":"sake bottle and cup drink japan sake alcohol girls night girls night"},"tea":{"unicode":"1f375","shortname":":tea:","aliases":"","keywords":"teacup without handle drink japan caffeine steam steam morning morning"},"coffee":{"unicode":"2615","shortname":":coffee:","aliases":"","keywords":"hot beverage drink caffeine steam steam morning morning"},"baby_bottle":{"unicode":"1f37c","shortname":":baby_bottle:","aliases":"","keywords":"baby bottle drink object food baby"},"fork_and_knife":{"unicode":"1f374","shortname":":fork_and_knife:","aliases":"","keywords":"fork and knife object weapon food"},"fork_knife_plate":{"unicode":"1f37d","shortname":":fork_knife_plate:","aliases":":fork_and_knife_with_plate:","keywords":"fork and knife with plate object food"},"soccer":{"unicode":"26bd","shortname":":soccer:","aliases":"","keywords":"soccer ball game ball sport soccer football"},"basketball":{"unicode":"1f3c0","shortname":":basketball:","aliases":"","keywords":"basketball and hoop game ball sport basketball"},"football":{"unicode":"1f3c8","shortname":":football:","aliases":"","keywords":"american football america game ball sport football"},"baseball":{"unicode":"26be","shortname":":baseball:","aliases":"","keywords":"baseball game ball sport baseball"},"tennis":{"unicode":"1f3be","shortname":":tennis:","aliases":"","keywords":"tennis racquet and ball game ball sport tennis"},"volleyball":{"unicode":"1f3d0","shortname":":volleyball:","aliases":"","keywords":"volleyball game ball sport volleyball"},"rugby_football":{"unicode":"1f3c9","shortname":":rugby_football:","aliases":"","keywords":"rugby football game sport football"},"8ball":{"unicode":"1f3b1","shortname":":8ball:","aliases":"","keywords":"billiards game ball sport billiards luck boys night boys night"},"golf":{"unicode":"26f3","shortname":":golf:","aliases":"","keywords":"flag in hole game ball vacation sport golf golf"},"golfer":{"unicode":"1f3cc","shortname":":golfer:","aliases":"","keywords":"golfer men game ball vacation sport golf golf"},"ping_pong":{"unicode":"1f3d3","shortname":":ping_pong:","aliases":":table_tennis:","keywords":"table tennis paddle and ball game ball sport ping pong"},"badminton":{"unicode":"1f3f8","shortname":":badminton:","aliases":"","keywords":"badminton racquet game sport badminton"},"hockey":{"unicode":"1f3d2","shortname":":hockey:","aliases":"","keywords":"ice hockey stick and puck game sport hockey"},"field_hockey":{"unicode":"1f3d1","shortname":":field_hockey:","aliases":"","keywords":"field hockey stick and ball ball sport hockey"},"cricket":{"unicode":"1f3cf","shortname":":cricket:","aliases":":cricket_bat_ball:","keywords":"cricket bat and ball ball sport cricket"},"ski":{"unicode":"1f3bf","shortname":":ski:","aliases":"","keywords":"ski and ski boot cold sport skiing"},"skier":{"unicode":"26f7","shortname":":skier:","aliases":"","keywords":"skier hat vacation cold sport skiing"},"snowboarder":{"unicode":"1f3c2","shortname":":snowboarder:","aliases":"","keywords":"snowboarder hat vacation cold sport snowboarding"},"ice_skate":{"unicode":"26f8","shortname":":ice_skate:","aliases":"","keywords":"ice skate cold sport ice skating"},"bow_and_arrow":{"unicode":"1f3f9","shortname":":bow_and_arrow:","aliases":":archery:","keywords":"bow and arrow weapon sport"},"fishing_pole_and_fish":{"unicode":"1f3a3","shortname":":fishing_pole_and_fish:","aliases":"","keywords":"fishing pole and fish vacation sport fishing"},"rowboat":{"unicode":"1f6a3","shortname":":rowboat:","aliases":"","keywords":"rowboat men workout sport rowing diversity diversity"},"swimmer":{"unicode":"1f3ca","shortname":":swimmer:","aliases":"","keywords":"swimmer workout sport swim diversity diversity"},"surfer":{"unicode":"1f3c4","shortname":":surfer:","aliases":"","keywords":"surfer men vacation tropical sport diversity diversity"},"bath":{"unicode":"1f6c0","shortname":":bath:","aliases":"","keywords":"bath bathroom tired diversity diversity steam steam"},"basketball_player":{"unicode":"26f9","shortname":":basketball_player:","aliases":":person_with_ball:","keywords":"person with ball men game ball sport basketball diversity diversity"},"lifter":{"unicode":"1f3cb","shortname":":lifter:","aliases":":weight_lifter:","keywords":"weight lifter men workout flex sport weight lifting win win diversity diversity"},"bicyclist":{"unicode":"1f6b4","shortname":":bicyclist:","aliases":"","keywords":"bicyclist men workout sport bike diversity diversity"},"mountain_bicyclist":{"unicode":"1f6b5","shortname":":mountain_bicyclist:","aliases":"","keywords":"mountain bicyclist men sport bike diversity diversity"},"horse_racing":{"unicode":"1f3c7","shortname":":horse_racing:","aliases":"","keywords":"horse racing men sport horse racing"},"levitate":{"unicode":"1f574","shortname":":levitate:","aliases":":man_in_business_suit_levitating:","keywords":"man in business suit levitating men job job"},"trophy":{"unicode":"1f3c6","shortname":":trophy:","aliases":"","keywords":"trophy object game award win win perfect perfect parties parties"},"running_shirt_with_sash":{"unicode":"1f3bd","shortname":":running_shirt_with_sash:","aliases":"","keywords":"running shirt with sash award"},"medal":{"unicode":"1f3c5","shortname":":medal:","aliases":":sports_medal:","keywords":"sports medal object award sport win win perfect perfect"},"military_medal":{"unicode":"1f396","shortname":":military_medal:","aliases":"","keywords":"military medal object award win win"},"reminder_ribbon":{"unicode":"1f397","shortname":":reminder_ribbon:","aliases":"","keywords":"reminder ribbon award"},"rosette":{"unicode":"1f3f5","shortname":":rosette:","aliases":"","keywords":"rosette tropical"},"ticket":{"unicode":"1f3ab","shortname":":ticket:","aliases":"","keywords":"ticket theatre movie parties parties"},"tickets":{"unicode":"1f39f","shortname":":tickets:","aliases":":admission_tickets:","keywords":"admission tickets theatre movie parties parties"},"performing_arts":{"unicode":"1f3ad","shortname":":performing_arts:","aliases":"","keywords":"performing arts theatre movie"},"art":{"unicode":"1f3a8","shortname":":art:","aliases":"","keywords":"artist palette"},"circus_tent":{"unicode":"1f3aa","shortname":":circus_tent:","aliases":"","keywords":"circus tent circus tent"},"microphone":{"unicode":"1f3a4","shortname":":microphone:","aliases":"","keywords":"microphone instruments"},"headphones":{"unicode":"1f3a7","shortname":":headphones:","aliases":"","keywords":"headphone instruments"},"musical_score":{"unicode":"1f3bc","shortname":":musical_score:","aliases":"","keywords":"musical score instruments"},"musical_keyboard":{"unicode":"1f3b9","shortname":":musical_keyboard:","aliases":"","keywords":"musical keyboard instruments"},"saxophone":{"unicode":"1f3b7","shortname":":saxophone:","aliases":"","keywords":"saxophone instruments"},"trumpet":{"unicode":"1f3ba","shortname":":trumpet:","aliases":"","keywords":"trumpet instruments"},"guitar":{"unicode":"1f3b8","shortname":":guitar:","aliases":"","keywords":"guitar instruments"},"violin":{"unicode":"1f3bb","shortname":":violin:","aliases":"","keywords":"violin instruments sarcastic sarcastic"},"clapper":{"unicode":"1f3ac","shortname":":clapper:","aliases":"","keywords":"clapper board movie"},"video_game":{"unicode":"1f3ae","shortname":":video_game:","aliases":"","keywords":"video game electronics game boys night boys night"},"space_invader":{"unicode":"1f47e","shortname":":space_invader:","aliases":"","keywords":"alien monster monster alien"},"dart":{"unicode":"1f3af","shortname":":dart:","aliases":"","keywords":"direct hit game sport boys night boys night"},"game_die":{"unicode":"1f3b2","shortname":":game_die:","aliases":"","keywords":"game die object game boys night boys night"},"slot_machine":{"unicode":"1f3b0","shortname":":slot_machine:","aliases":"","keywords":"slot machine game boys night boys night"},"bowling":{"unicode":"1f3b3","shortname":":bowling:","aliases":"","keywords":"bowling game ball sport boys night boys night"},"red_car":{"unicode":"1f697","shortname":":red_car:","aliases":"","keywords":"automobile transportation car travel"},"taxi":{"unicode":"1f695","shortname":":taxi:","aliases":"","keywords":"taxi transportation car travel"},"blue_car":{"unicode":"1f699","shortname":":blue_car:","aliases":"","keywords":"recreational vehicle transportation car travel"},"bus":{"unicode":"1f68c","shortname":":bus:","aliases":"","keywords":"bus transportation bus office"},"trolleybus":{"unicode":"1f68e","shortname":":trolleybus:","aliases":"","keywords":"trolleybus transportation bus travel"},"race_car":{"unicode":"1f3ce","shortname":":race_car:","aliases":":racing_car:","keywords":"racing car transportation car"},"police_car":{"unicode":"1f693","shortname":":police_car:","aliases":"","keywords":"police car transportation car police police 911 911"},"ambulance":{"unicode":"1f691","shortname":":ambulance:","aliases":"","keywords":"ambulance transportation 911 911"},"fire_engine":{"unicode":"1f692","shortname":":fire_engine:","aliases":"","keywords":"fire engine transportation truck 911 911"},"minibus":{"unicode":"1f690","shortname":":minibus:","aliases":"","keywords":"minibus transportation bus"},"truck":{"unicode":"1f69a","shortname":":truck:","aliases":"","keywords":"delivery truck transportation truck"},"articulated_lorry":{"unicode":"1f69b","shortname":":articulated_lorry:","aliases":"","keywords":"articulated lorry transportation truck"},"tractor":{"unicode":"1f69c","shortname":":tractor:","aliases":"","keywords":"tractor transportation"},"motorcycle":{"unicode":"1f3cd","shortname":":motorcycle:","aliases":":racing_motorcycle:","keywords":"racing motorcycle transportation travel bike"},"bike":{"unicode":"1f6b2","shortname":":bike:","aliases":"","keywords":"bicycle transportation travel bike"},"rotating_light":{"unicode":"1f6a8","shortname":":rotating_light:","aliases":"","keywords":"police cars revolving light transportation object police police 911 911"},"oncoming_police_car":{"unicode":"1f694","shortname":":oncoming_police_car:","aliases":"","keywords":"oncoming police car transportation car police police 911 911"},"oncoming_bus":{"unicode":"1f68d","shortname":":oncoming_bus:","aliases":"","keywords":"oncoming bus transportation bus travel"},"oncoming_automobile":{"unicode":"1f698","shortname":":oncoming_automobile:","aliases":"","keywords":"oncoming automobile transportation car travel"},"oncoming_taxi":{"unicode":"1f696","shortname":":oncoming_taxi:","aliases":"","keywords":"oncoming taxi transportation car travel"},"aerial_tramway":{"unicode":"1f6a1","shortname":":aerial_tramway:","aliases":"","keywords":"aerial tramway transportation travel train"},"mountain_cableway":{"unicode":"1f6a0","shortname":":mountain_cableway:","aliases":"","keywords":"mountain cableway transportation travel train"},"suspension_railway":{"unicode":"1f69f","shortname":":suspension_railway:","aliases":"","keywords":"suspension railway transportation travel train"},"railway_car":{"unicode":"1f683","shortname":":railway_car:","aliases":"","keywords":"railway car transportation travel train"},"train":{"unicode":"1f68b","shortname":":train:","aliases":"","keywords":"tram car transportation travel train"},"monorail":{"unicode":"1f69d","shortname":":monorail:","aliases":"","keywords":"monorail transportation travel train vacation"},"bullettrain_side":{"unicode":"1f684","shortname":":bullettrain_side:","aliases":"","keywords":"high-speed train transportation travel train"},"bullettrain_front":{"unicode":"1f685","shortname":":bullettrain_front:","aliases":"","keywords":"high-speed train with bullet nose transportation travel train"},"light_rail":{"unicode":"1f688","shortname":":light_rail:","aliases":"","keywords":"light rail transportation travel train"},"mountain_railway":{"unicode":"1f69e","shortname":":mountain_railway:","aliases":"","keywords":"mountain railway transportation travel train"},"steam_locomotive":{"unicode":"1f682","shortname":":steam_locomotive:","aliases":"","keywords":"steam locomotive transportation travel train steam steam"},"train2":{"unicode":"1f686","shortname":":train2:","aliases":"","keywords":"train transportation travel train"},"metro":{"unicode":"1f687","shortname":":metro:","aliases":"","keywords":"metro transportation travel train"},"tram":{"unicode":"1f68a","shortname":":tram:","aliases":"","keywords":"tram transportation travel train"},"station":{"unicode":"1f689","shortname":":station:","aliases":"","keywords":"station transportation travel train"},"helicopter":{"unicode":"1f681","shortname":":helicopter:","aliases":"","keywords":"helicopter transportation plane travel fly fly"},"airplane_small":{"unicode":"1f6e9","shortname":":airplane_small:","aliases":":small_airplane:","keywords":"small airplane transportation plane travel vacation fly fly"},"airplane":{"unicode":"2708","shortname":":airplane:","aliases":"","keywords":"airplane transportation plane travel vacation fly fly"},"airplane_departure":{"unicode":"1f6eb","shortname":":airplane_departure:","aliases":"","keywords":"airplane departure transportation plane travel vacation fly fly"},"airplane_arriving":{"unicode":"1f6ec","shortname":":airplane_arriving:","aliases":"","keywords":"airplane arriving transportation plane travel vacation fly fly"},"sailboat":{"unicode":"26f5","shortname":":sailboat:","aliases":"","keywords":"sailboat transportation travel boat vacation"},"motorboat":{"unicode":"1f6e5","shortname":":motorboat:","aliases":"","keywords":"motorboat transportation travel boat"},"speedboat":{"unicode":"1f6a4","shortname":":speedboat:","aliases":"","keywords":"speedboat transportation travel boat vacation tropical"},"ferry":{"unicode":"26f4","shortname":":ferry:","aliases":"","keywords":"ferry transportation travel boat vacation"},"cruise_ship":{"unicode":"1f6f3","shortname":":cruise_ship:","aliases":":passenger_ship:","keywords":"passenger ship transportation travel boat vacation"},"rocket":{"unicode":"1f680","shortname":":rocket:","aliases":"","keywords":"rocket transportation object space fly fly blast blast"},"satellite_orbital":{"unicode":"1f6f0","shortname":":satellite_orbital:","aliases":"","keywords":"satellite object"},"seat":{"unicode":"1f4ba","shortname":":seat:","aliases":"","keywords":"seat transportation object travel vacation"},"anchor":{"unicode":"2693","shortname":":anchor:","aliases":"","keywords":"anchor object travel boat vacation"},"construction":{"unicode":"1f6a7","shortname":":construction:","aliases":"","keywords":"construction sign object"},"fuelpump":{"unicode":"26fd","shortname":":fuelpump:","aliases":"","keywords":"fuel pump object gas pump"},"busstop":{"unicode":"1f68f","shortname":":busstop:","aliases":"","keywords":"bus stop object"},"vertical_traffic_light":{"unicode":"1f6a6","shortname":":vertical_traffic_light:","aliases":"","keywords":"vertical traffic light object stop light"},"traffic_light":{"unicode":"1f6a5","shortname":":traffic_light:","aliases":"","keywords":"horizontal traffic light object stop light"},"checkered_flag":{"unicode":"1f3c1","shortname":":checkered_flag:","aliases":"","keywords":"chequered flag object"},"ship":{"unicode":"1f6a2","shortname":":ship:","aliases":"","keywords":"ship transportation travel boat vacation"},"ferris_wheel":{"unicode":"1f3a1","shortname":":ferris_wheel:","aliases":"","keywords":"ferris wheel places vacation ferris wheel"},"roller_coaster":{"unicode":"1f3a2","shortname":":roller_coaster:","aliases":"","keywords":"roller coaster places vacation roller coaster"},"carousel_horse":{"unicode":"1f3a0","shortname":":carousel_horse:","aliases":"","keywords":"carousel horse places object vacation roller coaster carousel"},"construction_site":{"unicode":"1f3d7","shortname":":construction_site:","aliases":":building_construction:","keywords":"building construction building crane"},"foggy":{"unicode":"1f301","shortname":":foggy:","aliases":"","keywords":"foggy places building sky travel vacation"},"tokyo_tower":{"unicode":"1f5fc","shortname":":tokyo_tower:","aliases":"","keywords":"tokyo tower places travel vacation eiffel tower"},"factory":{"unicode":"1f3ed","shortname":":factory:","aliases":"","keywords":"factory places building travel steam steam"},"fountain":{"unicode":"26f2","shortname":":fountain:","aliases":"","keywords":"fountain travel vacation"},"rice_scene":{"unicode":"1f391","shortname":":rice_scene:","aliases":"","keywords":"moon viewing ceremony places space sky travel"},"mountain":{"unicode":"26f0","shortname":":mountain:","aliases":"","keywords":"mountain places travel vacation camp"},"mountain_snow":{"unicode":"1f3d4","shortname":":mountain_snow:","aliases":":snow_capped_mountain:","keywords":"snow capped mountain places travel vacation cold camp"},"mount_fuji":{"unicode":"1f5fb","shortname":":mount_fuji:","aliases":"","keywords":"mount fuji places travel vacation cold camp"},"volcano":{"unicode":"1f30b","shortname":":volcano:","aliases":"","keywords":"volcano places tropical"},"japan":{"unicode":"1f5fe","shortname":":japan:","aliases":"","keywords":"silhouette of japan places travel map vacation tropical"},"camping":{"unicode":"1f3d5","shortname":":camping:","aliases":"","keywords":"camping places travel vacation camp"},"tent":{"unicode":"26fa","shortname":":tent:","aliases":"","keywords":"tent places travel vacation camp"},"park":{"unicode":"1f3de","shortname":":park:","aliases":":national_park:","keywords":"national park travel vacation park camp"},"motorway":{"unicode":"1f6e3","shortname":":motorway:","aliases":"","keywords":"motorway travel vacation camp"},"railway_track":{"unicode":"1f6e4","shortname":":railway_track:","aliases":":railroad_track:","keywords":"railway track travel train vacation"},"sunrise":{"unicode":"1f305","shortname":":sunrise:","aliases":"","keywords":"sunrise places sky travel vacation tropical day sun hump day hump day morning morning"},"sunrise_over_mountains":{"unicode":"1f304","shortname":":sunrise_over_mountains:","aliases":"","keywords":"sunrise over mountains places sky travel vacation day sun camp morning morning"},"desert":{"unicode":"1f3dc","shortname":":desert:","aliases":"","keywords":"desert places travel vacation hot hot"},"beach":{"unicode":"1f3d6","shortname":":beach:","aliases":":beach_with_umbrella:","keywords":"beach with umbrella places travel vacation tropical beach swim"},"island":{"unicode":"1f3dd","shortname":":island:","aliases":":desert_island:","keywords":"desert island places travel vacation tropical beach swim"},"city_sunset":{"unicode":"1f307","shortname":":city_sunset:","aliases":":city_sunrise:","keywords":"sunset over buildings places building sky vacation"},"city_dusk":{"unicode":"1f306","shortname":":city_dusk:","aliases":"","keywords":"cityscape at dusk places building"},"cityscape":{"unicode":"1f3d9","shortname":":cityscape:","aliases":"","keywords":"cityscape places building vacation"},"night_with_stars":{"unicode":"1f303","shortname":":night_with_stars:","aliases":"","keywords":"night with stars places building sky vacation goodnight goodnight"},"bridge_at_night":{"unicode":"1f309","shortname":":bridge_at_night:","aliases":"","keywords":"bridge at night places travel vacation goodnight goodnight"},"milky_way":{"unicode":"1f30c","shortname":":milky_way:","aliases":"","keywords":"milky way places space sky travel vacation"},"stars":{"unicode":"1f320","shortname":":stars:","aliases":"","keywords":"shooting star space"},"sparkler":{"unicode":"1f387","shortname":":sparkler:","aliases":"","keywords":"firework sparkler parties parties"},"fireworks":{"unicode":"1f386","shortname":":fireworks:","aliases":"","keywords":"fireworks parties parties"},"rainbow":{"unicode":"1f308","shortname":":rainbow:","aliases":"","keywords":"rainbow weather gay sky rain"},"homes":{"unicode":"1f3d8","shortname":":homes:","aliases":":house_buildings:","keywords":"house buildings places building house"},"european_castle":{"unicode":"1f3f0","shortname":":european_castle:","aliases":"","keywords":"european castle places building travel vacation"},"japanese_castle":{"unicode":"1f3ef","shortname":":japanese_castle:","aliases":"","keywords":"japanese castle places building travel vacation"},"stadium":{"unicode":"1f3df","shortname":":stadium:","aliases":"","keywords":"stadium places building travel vacation boys night boys night"},"statue_of_liberty":{"unicode":"1f5fd","shortname":":statue_of_liberty:","aliases":"","keywords":"statue of liberty places america travel vacation statue of liberty free speech free speech"},"house":{"unicode":"1f3e0","shortname":":house:","aliases":"","keywords":"house building places building house"},"house_with_garden":{"unicode":"1f3e1","shortname":":house_with_garden:","aliases":"","keywords":"house with garden places building house"},"house_abandoned":{"unicode":"1f3da","shortname":":house_abandoned:","aliases":":derelict_house_building:","keywords":"derelict house building places building house"},"office":{"unicode":"1f3e2","shortname":":office:","aliases":"","keywords":"office building places building work"},"department_store":{"unicode":"1f3ec","shortname":":department_store:","aliases":"","keywords":"department store places building"},"post_office":{"unicode":"1f3e3","shortname":":post_office:","aliases":"","keywords":"japanese post office places building post office"},"european_post_office":{"unicode":"1f3e4","shortname":":european_post_office:","aliases":"","keywords":"european post office places building post office"},"hospital":{"unicode":"1f3e5","shortname":":hospital:","aliases":"","keywords":"hospital places building health 911 911"},"bank":{"unicode":"1f3e6","shortname":":bank:","aliases":"","keywords":"bank places building"},"hotel":{"unicode":"1f3e8","shortname":":hotel:","aliases":"","keywords":"hotel places building vacation"},"convenience_store":{"unicode":"1f3ea","shortname":":convenience_store:","aliases":"","keywords":"convenience store places building"},"school":{"unicode":"1f3eb","shortname":":school:","aliases":"","keywords":"school places building"},"love_hotel":{"unicode":"1f3e9","shortname":":love_hotel:","aliases":"","keywords":"love hotel places building love"},"wedding":{"unicode":"1f492","shortname":":wedding:","aliases":"","keywords":"wedding places wedding building love parties parties"},"classical_building":{"unicode":"1f3db","shortname":":classical_building:","aliases":"","keywords":"classical building places building travel vacation"},"church":{"unicode":"26ea","shortname":":church:","aliases":"","keywords":"church places wedding religion building condolence condolence"},"mosque":{"unicode":"1f54c","shortname":":mosque:","aliases":"","keywords":"mosque places religion building vacation condolence condolence"},"synagogue":{"unicode":"1f54d","shortname":":synagogue:","aliases":"","keywords":"synagogue places religion building travel vacation condolence condolence"},"kaaba":{"unicode":"1f54b","shortname":":kaaba:","aliases":"","keywords":"kaaba places religion building condolence condolence"},"shinto_shrine":{"unicode":"26e9","shortname":":shinto_shrine:","aliases":"","keywords":"shinto shrine places building travel vacation"},"watch":{"unicode":"231a","shortname":":watch:","aliases":"","keywords":"watch electronics time"},"iphone":{"unicode":"1f4f1","shortname":":iphone:","aliases":"","keywords":"mobile phone electronics phone selfie selfie"},"calling":{"unicode":"1f4f2","shortname":":calling:","aliases":"","keywords":"mobile phone with rightwards arrow at left electronics phone selfie selfie"},"computer":{"unicode":"1f4bb","shortname":":computer:","aliases":"","keywords":"personal computer electronics work office"},"keyboard":{"unicode":"2328","shortname":":keyboard:","aliases":"","keywords":"keyboard electronics work office"},"desktop":{"unicode":"1f5a5","shortname":":desktop:","aliases":":desktop_computer:","keywords":"desktop computer electronics work"},"printer":{"unicode":"1f5a8","shortname":":printer:","aliases":"","keywords":"printer electronics work office"},"mouse_three_button":{"unicode":"1f5b1","shortname":":mouse_three_button:","aliases":":three_button_mouse:","keywords":"three button mouse electronics work game office"},"trackball":{"unicode":"1f5b2","shortname":":trackball:","aliases":"","keywords":"trackball electronics work game office"},"joystick":{"unicode":"1f579","shortname":":joystick:","aliases":"","keywords":"joystick electronics game boys night boys night"},"compression":{"unicode":"1f5dc","shortname":":compression:","aliases":"","keywords":"compression"},"minidisc":{"unicode":"1f4bd","shortname":":minidisc:","aliases":"","keywords":"minidisc electronics"},"floppy_disk":{"unicode":"1f4be","shortname":":floppy_disk:","aliases":"","keywords":"floppy disk electronics office"},"cd":{"unicode":"1f4bf","shortname":":cd:","aliases":"","keywords":"optical disc electronics"},"dvd":{"unicode":"1f4c0","shortname":":dvd:","aliases":"","keywords":"dvd electronics"},"vhs":{"unicode":"1f4fc","shortname":":vhs:","aliases":"","keywords":"videocassette electronics"},"camera":{"unicode":"1f4f7","shortname":":camera:","aliases":"","keywords":"camera electronics camera selfie selfie"},"camera_with_flash":{"unicode":"1f4f8","shortname":":camera_with_flash:","aliases":"","keywords":"camera with flash electronics camera"},"video_camera":{"unicode":"1f4f9","shortname":":video_camera:","aliases":"","keywords":"video camera electronics camera movie"},"movie_camera":{"unicode":"1f3a5","shortname":":movie_camera:","aliases":"","keywords":"movie camera object camera movie"},"projector":{"unicode":"1f4fd","shortname":":projector:","aliases":":film_projector:","keywords":"film projector object camera movie"},"film_frames":{"unicode":"1f39e","shortname":":film_frames:","aliases":"","keywords":"film frames object camera movie"},"telephone_receiver":{"unicode":"1f4de","shortname":":telephone_receiver:","aliases":"","keywords":"telephone receiver electronics phone"},"telephone":{"unicode":"260e","shortname":":telephone:","aliases":"","keywords":"black telephone electronics phone"},"pager":{"unicode":"1f4df","shortname":":pager:","aliases":"","keywords":"pager electronics work"},"fax":{"unicode":"1f4e0","shortname":":fax:","aliases":"","keywords":"fax machine electronics work office"},"tv":{"unicode":"1f4fa","shortname":":tv:","aliases":"","keywords":"television electronics"},"radio":{"unicode":"1f4fb","shortname":":radio:","aliases":"","keywords":"radio electronics"},"microphone2":{"unicode":"1f399","shortname":":microphone2:","aliases":":studio_microphone:","keywords":"studio microphone electronics object"},"level_slider":{"unicode":"1f39a","shortname":":level_slider:","aliases":"","keywords":"level slider"},"control_knobs":{"unicode":"1f39b","shortname":":control_knobs:","aliases":"","keywords":"control knobs time"},"stopwatch":{"unicode":"23f1","shortname":":stopwatch:","aliases":"","keywords":"stopwatch electronics time"},"timer":{"unicode":"23f2","shortname":":timer:","aliases":":timer_clock:","keywords":"timer clock object time"},"alarm_clock":{"unicode":"23f0","shortname":":alarm_clock:","aliases":"","keywords":"alarm clock object time"},"clock":{"unicode":"1f570","shortname":":clock:","aliases":":mantlepiece_clock:","keywords":"mantlepiece clock object time"},"hourglass_flowing_sand":{"unicode":"23f3","shortname":":hourglass_flowing_sand:","aliases":"","keywords":"hourglass with flowing sand object time"},"hourglass":{"unicode":"231b","shortname":":hourglass:","aliases":"","keywords":"hourglass object time"},"satellite":{"unicode":"1f4e1","shortname":":satellite:","aliases":"","keywords":"satellite antenna object"},"battery":{"unicode":"1f50b","shortname":":battery:","aliases":"","keywords":"battery object"},"electric_plug":{"unicode":"1f50c","shortname":":electric_plug:","aliases":"","keywords":"electric plug electronics"},"bulb":{"unicode":"1f4a1","shortname":":bulb:","aliases":"","keywords":"electric light bulb object science"},"flashlight":{"unicode":"1f526","shortname":":flashlight:","aliases":"","keywords":"electric torch electronics object"},"candle":{"unicode":"1f56f","shortname":":candle:","aliases":"","keywords":"candle object"},"wastebasket":{"unicode":"1f5d1","shortname":":wastebasket:","aliases":"","keywords":"wastebasket object work"},"oil":{"unicode":"1f6e2","shortname":":oil:","aliases":":oil_drum:","keywords":"oil drum object"},"money_with_wings":{"unicode":"1f4b8","shortname":":money_with_wings:","aliases":"","keywords":"money with wings money money boys night boys night"},"dollar":{"unicode":"1f4b5","shortname":":dollar:","aliases":"","keywords":"banknote with dollar sign money money"},"yen":{"unicode":"1f4b4","shortname":":yen:","aliases":"","keywords":"banknote with yen sign money money"},"euro":{"unicode":"1f4b6","shortname":":euro:","aliases":"","keywords":"banknote with euro sign money money"},"pound":{"unicode":"1f4b7","shortname":":pound:","aliases":"","keywords":"banknote with pound sign money money"},"moneybag":{"unicode":"1f4b0","shortname":":moneybag:","aliases":"","keywords":"money bag bag award money money"},"credit_card":{"unicode":"1f4b3","shortname":":credit_card:","aliases":"","keywords":"credit card object money money boys night boys night"},"gem":{"unicode":"1f48e","shortname":":gem:","aliases":"","keywords":"gem stone object gem"},"scales":{"unicode":"2696","shortname":":scales:","aliases":"","keywords":"scales object"},"wrench":{"unicode":"1f527","shortname":":wrench:","aliases":"","keywords":"wrench object tool"},"hammer":{"unicode":"1f528","shortname":":hammer:","aliases":"","keywords":"hammer object tool weapon"},"hammer_pick":{"unicode":"2692","shortname":":hammer_pick:","aliases":":hammer_and_pick:","keywords":"hammer and pick object tool weapon"},"tools":{"unicode":"1f6e0","shortname":":tools:","aliases":":hammer_and_wrench:","keywords":"hammer and wrench object tool"},"pick":{"unicode":"26cf","shortname":":pick:","aliases":"","keywords":"pick object tool weapon"},"nut_and_bolt":{"unicode":"1f529","shortname":":nut_and_bolt:","aliases":"","keywords":"nut and bolt object tool nutcase nutcase"},"gear":{"unicode":"2699","shortname":":gear:","aliases":"","keywords":"gear object tool"},"chains":{"unicode":"26d3","shortname":":chains:","aliases":"","keywords":"chains object tool"},"gun":{"unicode":"1f52b","shortname":":gun:","aliases":"","keywords":"pistol object weapon dead gun sarcastic sarcastic"},"bomb":{"unicode":"1f4a3","shortname":":bomb:","aliases":"","keywords":"bomb object weapon dead blast blast"},"knife":{"unicode":"1f52a","shortname":":knife:","aliases":"","keywords":"hocho object weapon"},"dagger":{"unicode":"1f5e1","shortname":":dagger:","aliases":":dagger_knife:","keywords":"dagger knife object weapon"},"crossed_swords":{"unicode":"2694","shortname":":crossed_swords:","aliases":"","keywords":"crossed swords object weapon"},"shield":{"unicode":"1f6e1","shortname":":shield:","aliases":"","keywords":"shield object"},"smoking":{"unicode":"1f6ac","shortname":":smoking:","aliases":"","keywords":"smoking symbol symbol drugs drugs smoking smoking"},"skull_crossbones":{"unicode":"2620","shortname":":skull_crossbones:","aliases":":skull_and_crossbones:","keywords":"skull and crossbones symbol dead skull"},"coffin":{"unicode":"26b0","shortname":":coffin:","aliases":"","keywords":"coffin object dead rip rip"},"urn":{"unicode":"26b1","shortname":":urn:","aliases":":funeral_urn:","keywords":"funeral urn object dead rip rip"},"amphora":{"unicode":"1f3fa","shortname":":amphora:","aliases":"","keywords":"amphora object"},"crystal_ball":{"unicode":"1f52e","shortname":":crystal_ball:","aliases":"","keywords":"crystal ball object ball"},"prayer_beads":{"unicode":"1f4ff","shortname":":prayer_beads:","aliases":"","keywords":"prayer beads object rosary"},"barber":{"unicode":"1f488","shortname":":barber:","aliases":"","keywords":"barber pole object"},"alembic":{"unicode":"2697","shortname":":alembic:","aliases":"","keywords":"alembic object science"},"telescope":{"unicode":"1f52d","shortname":":telescope:","aliases":"","keywords":"telescope object space science"},"microscope":{"unicode":"1f52c","shortname":":microscope:","aliases":"","keywords":"microscope object science"},"hole":{"unicode":"1f573","shortname":":hole:","aliases":"","keywords":"hole object"},"pill":{"unicode":"1f48a","shortname":":pill:","aliases":"","keywords":"pill object health drugs drugs"},"syringe":{"unicode":"1f489","shortname":":syringe:","aliases":"","keywords":"syringe object weapon health drugs drugs"},"thermometer":{"unicode":"1f321","shortname":":thermometer:","aliases":"","keywords":"thermometer object science health hot hot"},"label":{"unicode":"1f3f7","shortname":":label:","aliases":"","keywords":"label object"},"bookmark":{"unicode":"1f516","shortname":":bookmark:","aliases":"","keywords":"bookmark object book"},"toilet":{"unicode":"1f6bd","shortname":":toilet:","aliases":"","keywords":"toilet object bathroom"},"shower":{"unicode":"1f6bf","shortname":":shower:","aliases":"","keywords":"shower object bathroom"},"bathtub":{"unicode":"1f6c1","shortname":":bathtub:","aliases":"","keywords":"bathtub object bathroom tired steam steam"},"key":{"unicode":"1f511","shortname":":key:","aliases":"","keywords":"key object lock"},"key2":{"unicode":"1f5dd","shortname":":key2:","aliases":":old_key:","keywords":"old key object lock"},"couch":{"unicode":"1f6cb","shortname":":couch:","aliases":":couch_and_lamp:","keywords":"couch and lamp object"},"sleeping_accommodation":{"unicode":"1f6cc","shortname":":sleeping_accommodation:","aliases":"","keywords":"sleeping accommodation tired"},"bed":{"unicode":"1f6cf","shortname":":bed:","aliases":"","keywords":"bed object tired"},"door":{"unicode":"1f6aa","shortname":":door:","aliases":"","keywords":"door object"},"bellhop":{"unicode":"1f6ce","shortname":":bellhop:","aliases":":bellhop_bell:","keywords":"bellhop bell object"},"frame_photo":{"unicode":"1f5bc","shortname":":frame_photo:","aliases":":frame_with_picture:","keywords":"frame with picture travel vacation"},"map":{"unicode":"1f5fa","shortname":":map:","aliases":":world_map:","keywords":"world map travel map vacation"},"beach_umbrella":{"unicode":"26f1","shortname":":beach_umbrella:","aliases":":umbrella_on_ground:","keywords":"umbrella on ground travel vacation tropical"},"moyai":{"unicode":"1f5ff","shortname":":moyai:","aliases":"","keywords":"moyai travel vacation"},"shopping_bags":{"unicode":"1f6cd","shortname":":shopping_bags:","aliases":"","keywords":"shopping bags object birthday parties parties"},"balloon":{"unicode":"1f388","shortname":":balloon:","aliases":"","keywords":"balloon object birthday good good parties parties"},"flags":{"unicode":"1f38f","shortname":":flags:","aliases":"","keywords":"carp streamer object japan"},"ribbon":{"unicode":"1f380","shortname":":ribbon:","aliases":"","keywords":"ribbon object gift birthday"},"gift":{"unicode":"1f381","shortname":":gift:","aliases":"","keywords":"wrapped present object gift birthday holidays christmas parties parties"},"confetti_ball":{"unicode":"1f38a","shortname":":confetti_ball:","aliases":"","keywords":"confetti ball object birthday holidays cheers girls night girls night boys night boys night parties parties"},"tada":{"unicode":"1f389","shortname":":tada:","aliases":"","keywords":"party popper object birthday holidays cheers good good girls night girls night boys night boys night parties parties"},"dolls":{"unicode":"1f38e","shortname":":dolls:","aliases":"","keywords":"japanese dolls people japan"},"wind_chime":{"unicode":"1f390","shortname":":wind_chime:","aliases":"","keywords":"wind chime object japan"},"crossed_flags":{"unicode":"1f38c","shortname":":crossed_flags:","aliases":"","keywords":"crossed flags object japan"},"izakaya_lantern":{"unicode":"1f3ee","shortname":":izakaya_lantern:","aliases":"","keywords":"izakaya lantern object japan"},"envelope":{"unicode":"2709","shortname":":envelope:","aliases":"","keywords":"envelope object office write"},"envelope_with_arrow":{"unicode":"1f4e9","shortname":":envelope_with_arrow:","aliases":"","keywords":"envelope with downwards arrow above object office"},"incoming_envelope":{"unicode":"1f4e8","shortname":":incoming_envelope:","aliases":"","keywords":"incoming envelope object"},"e-mail":{"unicode":"1f4e7","shortname":":e-mail:","aliases":":email:","keywords":"e-mail symbol office"},"love_letter":{"unicode":"1f48c","shortname":":love_letter:","aliases":"","keywords":"love letter object"},"postbox":{"unicode":"1f4ee","shortname":":postbox:","aliases":"","keywords":"postbox object"},"mailbox_closed":{"unicode":"1f4ea","shortname":":mailbox_closed:","aliases":"","keywords":"closed mailbox with lowered flag object office"},"mailbox":{"unicode":"1f4eb","shortname":":mailbox:","aliases":"","keywords":"closed mailbox with raised flag object"},"mailbox_with_mail":{"unicode":"1f4ec","shortname":":mailbox_with_mail:","aliases":"","keywords":"open mailbox with raised flag object"},"mailbox_with_no_mail":{"unicode":"1f4ed","shortname":":mailbox_with_no_mail:","aliases":"","keywords":"open mailbox with lowered flag object"},"package":{"unicode":"1f4e6","shortname":":package:","aliases":"","keywords":"package object gift office"},"postal_horn":{"unicode":"1f4ef","shortname":":postal_horn:","aliases":"","keywords":"postal horn object"},"inbox_tray":{"unicode":"1f4e5","shortname":":inbox_tray:","aliases":"","keywords":"inbox tray work office"},"outbox_tray":{"unicode":"1f4e4","shortname":":outbox_tray:","aliases":"","keywords":"outbox tray work office"},"scroll":{"unicode":"1f4dc","shortname":":scroll:","aliases":"","keywords":"scroll object office"},"page_with_curl":{"unicode":"1f4c3","shortname":":page_with_curl:","aliases":"","keywords":"page with curl office write"},"bookmark_tabs":{"unicode":"1f4d1","shortname":":bookmark_tabs:","aliases":"","keywords":"bookmark tabs office write"},"bar_chart":{"unicode":"1f4ca","shortname":":bar_chart:","aliases":"","keywords":"bar chart work office"},"chart_with_upwards_trend":{"unicode":"1f4c8","shortname":":chart_with_upwards_trend:","aliases":"","keywords":"chart with upwards trend work office"},"chart_with_downwards_trend":{"unicode":"1f4c9","shortname":":chart_with_downwards_trend:","aliases":"","keywords":"chart with downwards trend work office"},"page_facing_up":{"unicode":"1f4c4","shortname":":page_facing_up:","aliases":"","keywords":"page facing up work office write"},"date":{"unicode":"1f4c5","shortname":":date:","aliases":"","keywords":"calendar object office"},"calendar":{"unicode":"1f4c6","shortname":":calendar:","aliases":"","keywords":"tear-off calendar object office"},"calendar_spiral":{"unicode":"1f5d3","shortname":":calendar_spiral:","aliases":":spiral_calendar_pad:","keywords":"spiral calendar pad object office"},"card_index":{"unicode":"1f4c7","shortname":":card_index:","aliases":"","keywords":"card index object work office"},"card_box":{"unicode":"1f5c3","shortname":":card_box:","aliases":":card_file_box:","keywords":"card file box object work office"},"ballot_box":{"unicode":"1f5f3","shortname":":ballot_box:","aliases":":ballot_box_with_ballot:","keywords":"ballot box with ballot object office"},"file_cabinet":{"unicode":"1f5c4","shortname":":file_cabinet:","aliases":"","keywords":"file cabinet object work office"},"clipboard":{"unicode":"1f4cb","shortname":":clipboard:","aliases":"","keywords":"clipboard object work office write"},"notepad_spiral":{"unicode":"1f5d2","shortname":":notepad_spiral:","aliases":":spiral_note_pad:","keywords":"spiral note pad work office write"},"file_folder":{"unicode":"1f4c1","shortname":":file_folder:","aliases":"","keywords":"file folder work office"},"open_file_folder":{"unicode":"1f4c2","shortname":":open_file_folder:","aliases":"","keywords":"open file folder work office"},"dividers":{"unicode":"1f5c2","shortname":":dividers:","aliases":":card_index_dividers:","keywords":"card index dividers work office"},"newspaper2":{"unicode":"1f5de","shortname":":newspaper2:","aliases":":rolled_up_newspaper:","keywords":"rolled-up newspaper office write"},"newspaper":{"unicode":"1f4f0","shortname":":newspaper:","aliases":"","keywords":"newspaper office write"},"notebook":{"unicode":"1f4d3","shortname":":notebook:","aliases":"","keywords":"notebook object office write"},"closed_book":{"unicode":"1f4d5","shortname":":closed_book:","aliases":"","keywords":"closed book object office write book"},"green_book":{"unicode":"1f4d7","shortname":":green_book:","aliases":"","keywords":"green book object office book"},"blue_book":{"unicode":"1f4d8","shortname":":blue_book:","aliases":"","keywords":"blue book object office write book"},"orange_book":{"unicode":"1f4d9","shortname":":orange_book:","aliases":"","keywords":"orange book object office write book"},"notebook_with_decorative_cover":{"unicode":"1f4d4","shortname":":notebook_with_decorative_cover:","aliases":"","keywords":"notebook with decorative cover object office write"},"ledger":{"unicode":"1f4d2","shortname":":ledger:","aliases":"","keywords":"ledger object office write"},"books":{"unicode":"1f4da","shortname":":books:","aliases":"","keywords":"books object office write book"},"book":{"unicode":"1f4d6","shortname":":book:","aliases":"","keywords":"open book object office write book"},"link":{"unicode":"1f517","shortname":":link:","aliases":"","keywords":"link symbol symbol office"},"paperclip":{"unicode":"1f4ce","shortname":":paperclip:","aliases":"","keywords":"paperclip object work office"},"paperclips":{"unicode":"1f587","shortname":":paperclips:","aliases":":linked_paperclips:","keywords":"linked paperclips object work office"},"scissors":{"unicode":"2702","shortname":":scissors:","aliases":"","keywords":"black scissors object tool weapon office"},"triangular_ruler":{"unicode":"1f4d0","shortname":":triangular_ruler:","aliases":"","keywords":"triangular ruler object tool office"},"straight_ruler":{"unicode":"1f4cf","shortname":":straight_ruler:","aliases":"","keywords":"straight ruler object tool office"},"pushpin":{"unicode":"1f4cc","shortname":":pushpin:","aliases":"","keywords":"pushpin object office"},"round_pushpin":{"unicode":"1f4cd","shortname":":round_pushpin:","aliases":"","keywords":"round pushpin object office"},"triangular_flag_on_post":{"unicode":"1f6a9","shortname":":triangular_flag_on_post:","aliases":"","keywords":"triangular flag on post object"},"flag_white":{"unicode":"1f3f3","shortname":":flag_white:","aliases":":waving_white_flag:","keywords":"waving white flag object"},"flag_black":{"unicode":"1f3f4","shortname":":flag_black:","aliases":":waving_black_flag:","keywords":"waving black flag object"},"closed_lock_with_key":{"unicode":"1f510","shortname":":closed_lock_with_key:","aliases":"","keywords":"closed lock with key object lock"},"lock":{"unicode":"1f512","shortname":":lock:","aliases":"","keywords":"lock object lock"},"unlock":{"unicode":"1f513","shortname":":unlock:","aliases":"","keywords":"open lock object lock"},"lock_with_ink_pen":{"unicode":"1f50f","shortname":":lock_with_ink_pen:","aliases":"","keywords":"lock with ink pen object lock"},"pen_ballpoint":{"unicode":"1f58a","shortname":":pen_ballpoint:","aliases":":lower_left_ballpoint_pen:","keywords":"lower left ballpoint pen object office write"},"pen_fountain":{"unicode":"1f58b","shortname":":pen_fountain:","aliases":":lower_left_fountain_pen:","keywords":"lower left fountain pen object office write"},"black_nib":{"unicode":"2712","shortname":":black_nib:","aliases":"","keywords":"black nib object office write"},"pencil":{"unicode":"1f4dd","shortname":":pencil:","aliases":"","keywords":"memo work office write"},"pencil2":{"unicode":"270f","shortname":":pencil2:","aliases":"","keywords":"pencil object office write"},"crayon":{"unicode":"1f58d","shortname":":crayon:","aliases":":lower_left_crayon:","keywords":"lower left crayon object office write"},"paintbrush":{"unicode":"1f58c","shortname":":paintbrush:","aliases":":lower_left_paintbrush:","keywords":"lower left paintbrush object office write"},"mag":{"unicode":"1f50d","shortname":":mag:","aliases":"","keywords":"left-pointing magnifying glass object"},"mag_right":{"unicode":"1f50e","shortname":":mag_right:","aliases":"","keywords":"right-pointing magnifying glass object"},"heart":{"unicode":"2764","shortname":":heart:","aliases":"","keywords":"heavy black heart love symbol parties parties"},"yellow_heart":{"unicode":"1f49b","shortname":":yellow_heart:","aliases":"","keywords":"yellow heart love symbol"},"green_heart":{"unicode":"1f49a","shortname":":green_heart:","aliases":"","keywords":"green heart love symbol"},"blue_heart":{"unicode":"1f499","shortname":":blue_heart:","aliases":"","keywords":"blue heart love symbol"},"purple_heart":{"unicode":"1f49c","shortname":":purple_heart:","aliases":"","keywords":"purple heart love symbol"},"broken_heart":{"unicode":"1f494","shortname":":broken_heart:","aliases":"","keywords":"broken heart love symbol heartbreak heartbreak"},"heart_exclamation":{"unicode":"2763","shortname":":heart_exclamation:","aliases":":heavy_heart_exclamation_mark_ornament:","keywords":"heavy heart exclamation mark ornament love symbol"},"two_hearts":{"unicode":"1f495","shortname":":two_hearts:","aliases":"","keywords":"two hearts love symbol"},"revolving_hearts":{"unicode":"1f49e","shortname":":revolving_hearts:","aliases":"","keywords":"revolving hearts love symbol"},"heartbeat":{"unicode":"1f493","shortname":":heartbeat:","aliases":"","keywords":"beating heart love symbol"},"heartpulse":{"unicode":"1f497","shortname":":heartpulse:","aliases":"","keywords":"growing heart love symbol"},"sparkling_heart":{"unicode":"1f496","shortname":":sparkling_heart:","aliases":"","keywords":"sparkling heart love symbol girls night girls night"},"cupid":{"unicode":"1f498","shortname":":cupid:","aliases":"","keywords":"heart with arrow love symbol"},"gift_heart":{"unicode":"1f49d","shortname":":gift_heart:","aliases":"","keywords":"heart with ribbon love symbol condolence condolence"},"heart_decoration":{"unicode":"1f49f","shortname":":heart_decoration:","aliases":"","keywords":"heart decoration love symbol"},"peace":{"unicode":"262e","shortname":":peace:","aliases":":peace_symbol:","keywords":"peace symbol symbol peace peace drugs drugs"},"cross":{"unicode":"271d","shortname":":cross:","aliases":":latin_cross:","keywords":"latin cross religion symbol"},"star_and_crescent":{"unicode":"262a","shortname":":star_and_crescent:","aliases":"","keywords":"star and crescent religion symbol"},"om_symbol":{"unicode":"1f549","shortname":":om_symbol:","aliases":"","keywords":"om symbol religion symbol"},"wheel_of_dharma":{"unicode":"2638","shortname":":wheel_of_dharma:","aliases":"","keywords":"wheel of dharma religion symbol"},"star_of_david":{"unicode":"2721","shortname":":star_of_david:","aliases":"","keywords":"star of david religion jew star symbol"},"six_pointed_star":{"unicode":"1f52f","shortname":":six_pointed_star:","aliases":"","keywords":"six pointed star with middle dot religion jew star symbol"},"menorah":{"unicode":"1f54e","shortname":":menorah:","aliases":"","keywords":"menorah with nine branches religion object jew symbol holidays"},"yin_yang":{"unicode":"262f","shortname":":yin_yang:","aliases":"","keywords":"yin yang symbol"},"orthodox_cross":{"unicode":"2626","shortname":":orthodox_cross:","aliases":"","keywords":"orthodox cross religion symbol"},"place_of_worship":{"unicode":"1f6d0","shortname":":place_of_worship:","aliases":":worship_symbol:","keywords":"place of worship religion symbol pray pray"},"ophiuchus":{"unicode":"26ce","shortname":":ophiuchus:","aliases":"","keywords":"ophiuchus symbol"},"aries":{"unicode":"2648","shortname":":aries:","aliases":"","keywords":"aries zodiac symbol"},"taurus":{"unicode":"2649","shortname":":taurus:","aliases":"","keywords":"taurus zodiac symbol"},"gemini":{"unicode":"264a","shortname":":gemini:","aliases":"","keywords":"gemini zodiac symbol"},"cancer":{"unicode":"264b","shortname":":cancer:","aliases":"","keywords":"cancer zodiac symbol"},"leo":{"unicode":"264c","shortname":":leo:","aliases":"","keywords":"leo zodiac symbol"},"virgo":{"unicode":"264d","shortname":":virgo:","aliases":"","keywords":"virgo zodiac symbol"},"libra":{"unicode":"264e","shortname":":libra:","aliases":"","keywords":"libra zodiac symbol"},"scorpius":{"unicode":"264f","shortname":":scorpius:","aliases":"","keywords":"scorpius zodiac symbol"},"sagittarius":{"unicode":"2650","shortname":":sagittarius:","aliases":"","keywords":"sagittarius zodiac symbol"},"capricorn":{"unicode":"2651","shortname":":capricorn:","aliases":"","keywords":"capricorn zodiac symbol"},"aquarius":{"unicode":"2652","shortname":":aquarius:","aliases":"","keywords":"aquarius zodiac symbol"},"pisces":{"unicode":"2653","shortname":":pisces:","aliases":"","keywords":"pisces zodiac symbol"},"id":{"unicode":"1f194","shortname":":id:","aliases":"","keywords":"squared id symbol"},"atom":{"unicode":"269b","shortname":":atom:","aliases":":atom_symbol:","keywords":"atom symbol symbol science"},"u7a7a":{"unicode":"1f233","shortname":":u7a7a:","aliases":"","keywords":"squared cjk unified ideograph-7a7a symbol"},"u5272":{"unicode":"1f239","shortname":":u5272:","aliases":"","keywords":"squared cjk unified ideograph-5272 symbol"},"radioactive":{"unicode":"2622","shortname":":radioactive:","aliases":":radioactive_sign:","keywords":"radioactive sign symbol science"},"biohazard":{"unicode":"2623","shortname":":biohazard:","aliases":":biohazard_sign:","keywords":"biohazard sign symbol science"},"mobile_phone_off":{"unicode":"1f4f4","shortname":":mobile_phone_off:","aliases":"","keywords":"mobile phone off symbol"},"vibration_mode":{"unicode":"1f4f3","shortname":":vibration_mode:","aliases":"","keywords":"vibration mode symbol"},"u6709":{"unicode":"1f236","shortname":":u6709:","aliases":"","keywords":"squared cjk unified ideograph-6709 symbol"},"u7121":{"unicode":"1f21a","shortname":":u7121:","aliases":"","keywords":"squared cjk unified ideograph-7121 symbol"},"u7533":{"unicode":"1f238","shortname":":u7533:","aliases":"","keywords":"squared cjk unified ideograph-7533 symbol"},"u55b6":{"unicode":"1f23a","shortname":":u55b6:","aliases":"","keywords":"squared cjk unified ideograph-55b6 symbol"},"u6708":{"unicode":"1f237","shortname":":u6708:","aliases":"","keywords":"squared cjk unified ideograph-6708 symbol"},"eight_pointed_black_star":{"unicode":"2734","shortname":":eight_pointed_black_star:","aliases":"","keywords":"eight pointed black star symbol"},"vs":{"unicode":"1f19a","shortname":":vs:","aliases":"","keywords":"squared vs symbol"},"accept":{"unicode":"1f251","shortname":":accept:","aliases":"","keywords":"circled ideograph accept symbol"},"white_flower":{"unicode":"1f4ae","shortname":":white_flower:","aliases":"","keywords":"white flower flower symbol"},"ideograph_advantage":{"unicode":"1f250","shortname":":ideograph_advantage:","aliases":"","keywords":"circled ideograph advantage japan symbol"},"secret":{"unicode":"3299","shortname":":secret:","aliases":"","keywords":"circled ideograph secret japan symbol"},"congratulations":{"unicode":"3297","shortname":":congratulations:","aliases":"","keywords":"circled ideograph congratulation japan symbol"},"u5408":{"unicode":"1f234","shortname":":u5408:","aliases":"","keywords":"squared cjk unified ideograph-5408 japan symbol"},"u6e80":{"unicode":"1f235","shortname":":u6e80:","aliases":"","keywords":"squared cjk unified ideograph-6e80 japan symbol"},"u7981":{"unicode":"1f232","shortname":":u7981:","aliases":"","keywords":"squared cjk unified ideograph-7981 japan symbol"},"a":{"unicode":"1f170","shortname":":a:","aliases":"","keywords":"negative squared latin capital letter a symbol"},"b":{"unicode":"1f171","shortname":":b:","aliases":"","keywords":"negative squared latin capital letter b symbol"},"ab":{"unicode":"1f18e","shortname":":ab:","aliases":"","keywords":"negative squared ab symbol"},"cl":{"unicode":"1f191","shortname":":cl:","aliases":"","keywords":"squared cl symbol"},"o2":{"unicode":"1f17e","shortname":":o2:","aliases":"","keywords":"negative squared latin capital letter o symbol"},"sos":{"unicode":"1f198","shortname":":sos:","aliases":"","keywords":"squared sos symbol"},"no_entry":{"unicode":"26d4","shortname":":no_entry:","aliases":"","keywords":"no entry symbol circle circle"},"name_badge":{"unicode":"1f4db","shortname":":name_badge:","aliases":"","keywords":"name badge work"},"no_entry_sign":{"unicode":"1f6ab","shortname":":no_entry_sign:","aliases":"","keywords":"no entry sign symbol circle circle"},"x":{"unicode":"274c","shortname":":x:","aliases":"","keywords":"cross mark symbol sol sol"},"o":{"unicode":"2b55","shortname":":o:","aliases":"","keywords":"heavy large circle symbol circle circle"},"anger":{"unicode":"1f4a2","shortname":":anger:","aliases":"","keywords":"anger symbol symbol"},"hotsprings":{"unicode":"2668","shortname":":hotsprings:","aliases":"","keywords":"hot springs symbol"},"no_pedestrians":{"unicode":"1f6b7","shortname":":no_pedestrians:","aliases":"","keywords":"no pedestrians symbol"},"do_not_litter":{"unicode":"1f6af","shortname":":do_not_litter:","aliases":"","keywords":"do not litter symbol symbol"},"no_bicycles":{"unicode":"1f6b3","shortname":":no_bicycles:","aliases":"","keywords":"no bicycles symbol"},"non-potable_water":{"unicode":"1f6b1","shortname":":non-potable_water:","aliases":"","keywords":"non-potable water symbol symbol"},"underage":{"unicode":"1f51e","shortname":":underage:","aliases":"","keywords":"no one under eighteen symbol symbol"},"no_mobile_phones":{"unicode":"1f4f5","shortname":":no_mobile_phones:","aliases":"","keywords":"no mobile phones symbol phone"},"exclamation":{"unicode":"2757","shortname":":exclamation:","aliases":"","keywords":"heavy exclamation mark symbol symbol punctuation"},"grey_exclamation":{"unicode":"2755","shortname":":grey_exclamation:","aliases":"","keywords":"white exclamation mark ornament symbol punctuation"},"question":{"unicode":"2753","shortname":":question:","aliases":"","keywords":"black question mark ornament symbol punctuation wth wth"},"grey_question":{"unicode":"2754","shortname":":grey_question:","aliases":"","keywords":"white question mark ornament symbol punctuation"},"bangbang":{"unicode":"203c","shortname":":bangbang:","aliases":"","keywords":"double exclamation mark symbol punctuation"},"interrobang":{"unicode":"2049","shortname":":interrobang:","aliases":"","keywords":"exclamation question mark symbol punctuation"},"100":{"unicode":"1f4af","shortname":":100:","aliases":"","keywords":"hundred points symbol symbol wow wow win win perfect perfect parties parties"},"low_brightness":{"unicode":"1f505","shortname":":low_brightness:","aliases":"","keywords":"low brightness symbol symbol sun"},"high_brightness":{"unicode":"1f506","shortname":":high_brightness:","aliases":"","keywords":"high brightness symbol symbol sun"},"trident":{"unicode":"1f531","shortname":":trident:","aliases":"","keywords":"trident emblem object symbol"},"fleur-de-lis":{"unicode":"269c","shortname":":fleur-de-lis:","aliases":"","keywords":"fleur-de-lis object symbol"},"part_alternation_mark":{"unicode":"303d","shortname":":part_alternation_mark:","aliases":"","keywords":"part alternation mark symbol"},"warning":{"unicode":"26a0","shortname":":warning:","aliases":"","keywords":"warning sign symbol punctuation"},"children_crossing":{"unicode":"1f6b8","shortname":":children_crossing:","aliases":"","keywords":"children crossing symbol"},"beginner":{"unicode":"1f530","shortname":":beginner:","aliases":"","keywords":"japanese symbol for beginner symbol"},"recycle":{"unicode":"267b","shortname":":recycle:","aliases":"","keywords":"black universal recycling symbol symbol"},"u6307":{"unicode":"1f22f","shortname":":u6307:","aliases":"","keywords":"squared cjk unified ideograph-6307 symbol"},"chart":{"unicode":"1f4b9","shortname":":chart:","aliases":"","keywords":"chart with upwards trend and yen sign symbol money money"},"sparkle":{"unicode":"2747","shortname":":sparkle:","aliases":"","keywords":"sparkle symbol"},"eight_spoked_asterisk":{"unicode":"2733","shortname":":eight_spoked_asterisk:","aliases":"","keywords":"eight spoked asterisk symbol"},"negative_squared_cross_mark":{"unicode":"274e","shortname":":negative_squared_cross_mark:","aliases":"","keywords":"negative squared cross mark symbol"},"white_check_mark":{"unicode":"2705","shortname":":white_check_mark:","aliases":"","keywords":"white heavy check mark symbol"},"diamond_shape_with_a_dot_inside":{"unicode":"1f4a0","shortname":":diamond_shape_with_a_dot_inside:","aliases":"","keywords":"diamond shape with a dot inside symbol"},"cyclone":{"unicode":"1f300","shortname":":cyclone:","aliases":"","keywords":"cyclone symbol drugs drugs"},"loop":{"unicode":"27bf","shortname":":loop:","aliases":"","keywords":"double curly loop symbol"},"globe_with_meridians":{"unicode":"1f310","shortname":":globe_with_meridians:","aliases":"","keywords":"globe with meridians symbol globe globe"},"m":{"unicode":"24c2","shortname":":m:","aliases":"","keywords":"circled latin capital letter m symbol"},"atm":{"unicode":"1f3e7","shortname":":atm:","aliases":"","keywords":"automated teller machine electronics symbol money money"},"sa":{"unicode":"1f202","shortname":":sa:","aliases":"","keywords":"squared katakana sa symbol"},"passport_control":{"unicode":"1f6c2","shortname":":passport_control:","aliases":"","keywords":"passport control symbol"},"customs":{"unicode":"1f6c3","shortname":":customs:","aliases":"","keywords":"customs symbol"},"baggage_claim":{"unicode":"1f6c4","shortname":":baggage_claim:","aliases":"","keywords":"baggage claim symbol"},"left_luggage":{"unicode":"1f6c5","shortname":":left_luggage:","aliases":"","keywords":"left luggage symbol"},"wheelchair":{"unicode":"267f","shortname":":wheelchair:","aliases":"","keywords":"wheelchair symbol symbol"},"no_smoking":{"unicode":"1f6ad","shortname":":no_smoking:","aliases":"","keywords":"no smoking symbol symbol smoking smoking"},"wc":{"unicode":"1f6be","shortname":":wc:","aliases":"","keywords":"water closet symbol"},"parking":{"unicode":"1f17f","shortname":":parking:","aliases":"","keywords":"negative squared latin capital letter p symbol"},"potable_water":{"unicode":"1f6b0","shortname":":potable_water:","aliases":"","keywords":"potable water symbol symbol"},"mens":{"unicode":"1f6b9","shortname":":mens:","aliases":"","keywords":"mens symbol symbol"},"womens":{"unicode":"1f6ba","shortname":":womens:","aliases":"","keywords":"womens symbol symbol"},"baby_symbol":{"unicode":"1f6bc","shortname":":baby_symbol:","aliases":"","keywords":"baby symbol symbol"},"restroom":{"unicode":"1f6bb","shortname":":restroom:","aliases":"","keywords":"restroom symbol"},"put_litter_in_its_place":{"unicode":"1f6ae","shortname":":put_litter_in_its_place:","aliases":"","keywords":"put litter in its place symbol symbol"},"cinema":{"unicode":"1f3a6","shortname":":cinema:","aliases":"","keywords":"cinema symbol camera movie"},"signal_strength":{"unicode":"1f4f6","shortname":":signal_strength:","aliases":"","keywords":"antenna with bars symbol"},"koko":{"unicode":"1f201","shortname":":koko:","aliases":"","keywords":"squared katakana koko symbol"},"ng":{"unicode":"1f196","shortname":":ng:","aliases":"","keywords":"squared ng symbol"},"ok":{"unicode":"1f197","shortname":":ok:","aliases":"","keywords":"squared ok symbol"},"up":{"unicode":"1f199","shortname":":up:","aliases":"","keywords":"squared up with exclamation mark symbol"},"cool":{"unicode":"1f192","shortname":":cool:","aliases":"","keywords":"squared cool symbol"},"new":{"unicode":"1f195","shortname":":new:","aliases":"","keywords":"squared new symbol"},"free":{"unicode":"1f193","shortname":":free:","aliases":"","keywords":"squared free symbol"},"zero":{"unicode":"0030-20e3","shortname":":zero:","aliases":"","keywords":"keycap digit zero number math symbol"},"one":{"unicode":"0031-20e3","shortname":":one:","aliases":"","keywords":"keycap digit one number math symbol"},"two":{"unicode":"0032-20e3","shortname":":two:","aliases":"","keywords":"keycap digit two number math symbol"},"three":{"unicode":"0033-20e3","shortname":":three:","aliases":"","keywords":"keycap digit three number math symbol"},"four":{"unicode":"0034-20e3","shortname":":four:","aliases":"","keywords":"keycap digit four number math symbol"},"five":{"unicode":"0035-20e3","shortname":":five:","aliases":"","keywords":"keycap digit five number math symbol"},"six":{"unicode":"0036-20e3","shortname":":six:","aliases":"","keywords":"keycap digit six number math symbol"},"seven":{"unicode":"0037-20e3","shortname":":seven:","aliases":"","keywords":"keycap digit seven number math symbol"},"eight":{"unicode":"0038-20e3","shortname":":eight:","aliases":"","keywords":"keycap digit eight number math symbol"},"nine":{"unicode":"0039-20e3","shortname":":nine:","aliases":"","keywords":"keycap digit nine number math symbol"},"keycap_ten":{"unicode":"1f51f","shortname":":keycap_ten:","aliases":"","keywords":"keycap ten number math symbol"},"1234":{"unicode":"1f522","shortname":":1234:","aliases":"","keywords":"input symbol for numbers symbol"},"arrow_forward":{"unicode":"25b6","shortname":":arrow_forward:","aliases":"","keywords":"black right-pointing triangle arrow symbol triangle triangle"},"pause_button":{"unicode":"23f8","shortname":":pause_button:","aliases":":double_vertical_bar:","keywords":"double vertical bar symbol"},"play_pause":{"unicode":"23ef","shortname":":play_pause:","aliases":"","keywords":"black right-pointing double triangle with double vertical bar arrow symbol"},"stop_button":{"unicode":"23f9","shortname":":stop_button:","aliases":"","keywords":"black square for stop symbol square square"},"record_button":{"unicode":"23fa","shortname":":record_button:","aliases":"","keywords":"black circle for record symbol circle circle"},"track_next":{"unicode":"23ed","shortname":":track_next:","aliases":":next_track:","keywords":"black right-pointing double triangle with vertical bar arrow symbol"},"track_previous":{"unicode":"23ee","shortname":":track_previous:","aliases":":previous_track:","keywords":"black left-pointing double triangle with vertical bar arrow symbol"},"fast_forward":{"unicode":"23e9","shortname":":fast_forward:","aliases":"","keywords":"black right-pointing double triangle arrow symbol"},"rewind":{"unicode":"23ea","shortname":":rewind:","aliases":"","keywords":"black left-pointing double triangle arrow symbol"},"twisted_rightwards_arrows":{"unicode":"1f500","shortname":":twisted_rightwards_arrows:","aliases":"","keywords":"twisted rightwards arrows arrow symbol"},"repeat":{"unicode":"1f501","shortname":":repeat:","aliases":"","keywords":"clockwise rightwards and leftwards open circle arrows arrow symbol"},"repeat_one":{"unicode":"1f502","shortname":":repeat_one:","aliases":"","keywords":"clockwise rightwards and leftwards open circle arrows with circled one overlay arrow symbol"},"arrow_backward":{"unicode":"25c0","shortname":":arrow_backward:","aliases":"","keywords":"black left-pointing triangle arrow symbol triangle triangle"},"arrow_up_small":{"unicode":"1f53c","shortname":":arrow_up_small:","aliases":"","keywords":"up-pointing small red triangle arrow symbol triangle triangle"},"arrow_down_small":{"unicode":"1f53d","shortname":":arrow_down_small:","aliases":"","keywords":"down-pointing small red triangle arrow symbol triangle triangle"},"arrow_double_up":{"unicode":"23eb","shortname":":arrow_double_up:","aliases":"","keywords":"black up-pointing double triangle arrow symbol"},"arrow_double_down":{"unicode":"23ec","shortname":":arrow_double_down:","aliases":"","keywords":"black down-pointing double triangle arrow symbol"},"arrow_right":{"unicode":"27a1","shortname":":arrow_right:","aliases":"","keywords":"black rightwards arrow arrow symbol"},"arrow_left":{"unicode":"2b05","shortname":":arrow_left:","aliases":"","keywords":"leftwards black arrow arrow symbol"},"arrow_up":{"unicode":"2b06","shortname":":arrow_up:","aliases":"","keywords":"upwards black arrow arrow symbol"},"arrow_down":{"unicode":"2b07","shortname":":arrow_down:","aliases":"","keywords":"downwards black arrow arrow symbol"},"arrow_upper_right":{"unicode":"2197","shortname":":arrow_upper_right:","aliases":"","keywords":"north east arrow arrow symbol"},"arrow_lower_right":{"unicode":"2198","shortname":":arrow_lower_right:","aliases":"","keywords":"south east arrow arrow symbol"},"arrow_lower_left":{"unicode":"2199","shortname":":arrow_lower_left:","aliases":"","keywords":"south west arrow arrow symbol"},"arrow_upper_left":{"unicode":"2196","shortname":":arrow_upper_left:","aliases":"","keywords":"north west arrow arrow symbol"},"arrow_up_down":{"unicode":"2195","shortname":":arrow_up_down:","aliases":"","keywords":"up down arrow arrow symbol"},"left_right_arrow":{"unicode":"2194","shortname":":left_right_arrow:","aliases":"","keywords":"left right arrow arrow symbol"},"arrows_counterclockwise":{"unicode":"1f504","shortname":":arrows_counterclockwise:","aliases":"","keywords":"anticlockwise downwards and upwards open circle arrows arrow symbol"},"arrow_right_hook":{"unicode":"21aa","shortname":":arrow_right_hook:","aliases":"","keywords":"rightwards arrow with hook arrow symbol"},"leftwards_arrow_with_hook":{"unicode":"21a9","shortname":":leftwards_arrow_with_hook:","aliases":"","keywords":"leftwards arrow with hook arrow symbol"},"arrow_heading_up":{"unicode":"2934","shortname":":arrow_heading_up:","aliases":"","keywords":"arrow pointing rightwards then curving upwards arrow symbol"},"arrow_heading_down":{"unicode":"2935","shortname":":arrow_heading_down:","aliases":"","keywords":"arrow pointing rightwards then curving downwards arrow symbol"},"hash":{"unicode":"0023-20e3","shortname":":hash:","aliases":"","keywords":"keycap number sign number symbol"},"asterisk":{"unicode":"002a-20e3","shortname":":asterisk:","aliases":":keycap_asterisk:","keywords":"keycap asterisk symbol"},"information_source":{"unicode":"2139","shortname":":information_source:","aliases":"","keywords":"information source symbol"},"abc":{"unicode":"1f524","shortname":":abc:","aliases":"","keywords":"input symbol for latin letters symbol"},"abcd":{"unicode":"1f521","shortname":":abcd:","aliases":"","keywords":"input symbol for latin small letters symbol"},"capital_abcd":{"unicode":"1f520","shortname":":capital_abcd:","aliases":"","keywords":"input symbol for latin capital letters symbol"},"symbols":{"unicode":"1f523","shortname":":symbols:","aliases":"","keywords":"input symbol for symbols symbol"},"musical_note":{"unicode":"1f3b5","shortname":":musical_note:","aliases":"","keywords":"musical note instruments symbol"},"notes":{"unicode":"1f3b6","shortname":":notes:","aliases":"","keywords":"multiple musical notes instruments symbol"},"wavy_dash":{"unicode":"3030","shortname":":wavy_dash:","aliases":"","keywords":"wavy dash symbol"},"curly_loop":{"unicode":"27b0","shortname":":curly_loop:","aliases":"","keywords":"curly loop symbol"},"heavy_check_mark":{"unicode":"2714","shortname":":heavy_check_mark:","aliases":"","keywords":"heavy check mark symbol"},"arrows_clockwise":{"unicode":"1f503","shortname":":arrows_clockwise:","aliases":"","keywords":"clockwise downwards and upwards open circle arrows arrow symbol"},"heavy_plus_sign":{"unicode":"2795","shortname":":heavy_plus_sign:","aliases":"","keywords":"heavy plus sign math symbol"},"heavy_minus_sign":{"unicode":"2796","shortname":":heavy_minus_sign:","aliases":"","keywords":"heavy minus sign math symbol"},"heavy_division_sign":{"unicode":"2797","shortname":":heavy_division_sign:","aliases":"","keywords":"heavy division sign math symbol"},"heavy_multiplication_x":{"unicode":"2716","shortname":":heavy_multiplication_x:","aliases":"","keywords":"heavy multiplication x math symbol"},"heavy_dollar_sign":{"unicode":"1f4b2","shortname":":heavy_dollar_sign:","aliases":"","keywords":"heavy dollar sign math symbol money money"},"currency_exchange":{"unicode":"1f4b1","shortname":":currency_exchange:","aliases":"","keywords":"currency exchange symbol money money"},"copyright":{"unicode":"00a9","shortname":":copyright:","aliases":"","keywords":"copyright sign symbol"},"registered":{"unicode":"00ae","shortname":":registered:","aliases":"","keywords":"registered sign symbol"},"tm":{"unicode":"2122","shortname":":tm:","aliases":"","keywords":"trade mark sign symbol"},"end":{"unicode":"1f51a","shortname":":end:","aliases":"","keywords":"end with leftwards arrow above arrow symbol"},"back":{"unicode":"1f519","shortname":":back:","aliases":"","keywords":"back with leftwards arrow above arrow symbol"},"on":{"unicode":"1f51b","shortname":":on:","aliases":"","keywords":"on with exclamation mark with left right arrow abo arrow symbol"},"top":{"unicode":"1f51d","shortname":":top:","aliases":"","keywords":"top with upwards arrow above arrow symbol"},"soon":{"unicode":"1f51c","shortname":":soon:","aliases":"","keywords":"soon with rightwards arrow above arrow symbol"},"ballot_box_with_check":{"unicode":"2611","shortname":":ballot_box_with_check:","aliases":"","keywords":"ballot box with check symbol"},"radio_button":{"unicode":"1f518","shortname":":radio_button:","aliases":"","keywords":"radio button symbol circle circle"},"white_circle":{"unicode":"26aa","shortname":":white_circle:","aliases":"","keywords":"medium white circle shapes symbol circle circle"},"black_circle":{"unicode":"26ab","shortname":":black_circle:","aliases":"","keywords":"medium black circle shapes symbol circle circle"},"red_circle":{"unicode":"1f534","shortname":":red_circle:","aliases":"","keywords":"large red circle shapes symbol circle circle"},"large_blue_circle":{"unicode":"1f535","shortname":":large_blue_circle:","aliases":"","keywords":"large blue circle shapes symbol circle circle"},"small_orange_diamond":{"unicode":"1f538","shortname":":small_orange_diamond:","aliases":"","keywords":"small orange diamond shapes symbol"},"small_blue_diamond":{"unicode":"1f539","shortname":":small_blue_diamond:","aliases":"","keywords":"small blue diamond shapes symbol"},"large_orange_diamond":{"unicode":"1f536","shortname":":large_orange_diamond:","aliases":"","keywords":"large orange diamond shapes symbol"},"large_blue_diamond":{"unicode":"1f537","shortname":":large_blue_diamond:","aliases":"","keywords":"large blue diamond shapes symbol"},"small_red_triangle":{"unicode":"1f53a","shortname":":small_red_triangle:","aliases":"","keywords":"up-pointing red triangle shapes symbol triangle triangle"},"black_small_square":{"unicode":"25aa","shortname":":black_small_square:","aliases":"","keywords":"black small square shapes symbol square square"},"white_small_square":{"unicode":"25ab","shortname":":white_small_square:","aliases":"","keywords":"white small square shapes symbol square square"},"black_large_square":{"unicode":"2b1b","shortname":":black_large_square:","aliases":"","keywords":"black large square shapes symbol square square"},"white_large_square":{"unicode":"2b1c","shortname":":white_large_square:","aliases":"","keywords":"white large square shapes symbol square square"},"small_red_triangle_down":{"unicode":"1f53b","shortname":":small_red_triangle_down:","aliases":"","keywords":"down-pointing red triangle shapes symbol triangle triangle"},"black_medium_square":{"unicode":"25fc","shortname":":black_medium_square:","aliases":"","keywords":"black medium square shapes symbol square square"},"white_medium_square":{"unicode":"25fb","shortname":":white_medium_square:","aliases":"","keywords":"white medium square shapes symbol square square"},"black_medium_small_square":{"unicode":"25fe","shortname":":black_medium_small_square:","aliases":"","keywords":"black medium small square shapes symbol square square"},"white_medium_small_square":{"unicode":"25fd","shortname":":white_medium_small_square:","aliases":"","keywords":"white medium small square shapes symbol square square"},"black_square_button":{"unicode":"1f532","shortname":":black_square_button:","aliases":"","keywords":"black square button shapes symbol square square"},"white_square_button":{"unicode":"1f533","shortname":":white_square_button:","aliases":"","keywords":"white square button shapes symbol square square"},"speaker":{"unicode":"1f508","shortname":":speaker:","aliases":"","keywords":"speaker alarm symbol"},"sound":{"unicode":"1f509","shortname":":sound:","aliases":"","keywords":"speaker with one sound wave alarm symbol"},"loud_sound":{"unicode":"1f50a","shortname":":loud_sound:","aliases":"","keywords":"speaker with three sound waves alarm symbol"},"mute":{"unicode":"1f507","shortname":":mute:","aliases":"","keywords":"speaker with cancellation stroke alarm symbol"},"mega":{"unicode":"1f4e3","shortname":":mega:","aliases":"","keywords":"cheering megaphone object sport"},"loudspeaker":{"unicode":"1f4e2","shortname":":loudspeaker:","aliases":"","keywords":"public address loudspeaker object alarm symbol"},"bell":{"unicode":"1f514","shortname":":bell:","aliases":"","keywords":"bell object alarm symbol"},"no_bell":{"unicode":"1f515","shortname":":no_bell:","aliases":"","keywords":"bell with cancellation stroke alarm symbol"},"black_joker":{"unicode":"1f0cf","shortname":":black_joker:","aliases":"","keywords":"playing card black joker object symbol game"},"mahjong":{"unicode":"1f004","shortname":":mahjong:","aliases":"","keywords":"mahjong tile red dragon object symbol game"},"spades":{"unicode":"2660","shortname":":spades:","aliases":"","keywords":"black spade suit symbol game"},"clubs":{"unicode":"2663","shortname":":clubs:","aliases":"","keywords":"black club suit symbol game"},"hearts":{"unicode":"2665","shortname":":hearts:","aliases":"","keywords":"black heart suit love symbol game"},"diamonds":{"unicode":"2666","shortname":":diamonds:","aliases":"","keywords":"black diamond suit shapes symbol game"},"flower_playing_cards":{"unicode":"1f3b4","shortname":":flower_playing_cards:","aliases":"","keywords":"flower playing cards object symbol"},"thought_balloon":{"unicode":"1f4ad","shortname":":thought_balloon:","aliases":"","keywords":"thought balloon symbol"},"anger_right":{"unicode":"1f5ef","shortname":":anger_right:","aliases":":right_anger_bubble:","keywords":"right anger bubble symbol"},"speech_balloon":{"unicode":"1f4ac","shortname":":speech_balloon:","aliases":"","keywords":"speech balloon symbol free speech free speech"},"clock1":{"unicode":"1f550","shortname":":clock1:","aliases":"","keywords":"clock face one oclock symbol time"},"clock2":{"unicode":"1f551","shortname":":clock2:","aliases":"","keywords":"clock face two oclock symbol time"},"clock3":{"unicode":"1f552","shortname":":clock3:","aliases":"","keywords":"clock face three oclock symbol time"},"clock4":{"unicode":"1f553","shortname":":clock4:","aliases":"","keywords":"clock face four oclock symbol time"},"clock5":{"unicode":"1f554","shortname":":clock5:","aliases":"","keywords":"clock face five oclock symbol time"},"clock6":{"unicode":"1f555","shortname":":clock6:","aliases":"","keywords":"clock face six oclock symbol time"},"clock7":{"unicode":"1f556","shortname":":clock7:","aliases":"","keywords":"clock face seven oclock symbol time"},"clock8":{"unicode":"1f557","shortname":":clock8:","aliases":"","keywords":"clock face eight oclock symbol time"},"clock9":{"unicode":"1f558","shortname":":clock9:","aliases":"","keywords":"clock face nine oclock symbol time"},"clock10":{"unicode":"1f559","shortname":":clock10:","aliases":"","keywords":"clock face ten oclock symbol time"},"clock11":{"unicode":"1f55a","shortname":":clock11:","aliases":"","keywords":"clock face eleven oclock symbol time"},"clock12":{"unicode":"1f55b","shortname":":clock12:","aliases":"","keywords":"clock face twelve oclock symbol time"},"clock130":{"unicode":"1f55c","shortname":":clock130:","aliases":"","keywords":"clock face one-thirty symbol time"},"clock230":{"unicode":"1f55d","shortname":":clock230:","aliases":"","keywords":"clock face two-thirty symbol time"},"clock330":{"unicode":"1f55e","shortname":":clock330:","aliases":"","keywords":"clock face three-thirty symbol time"},"clock430":{"unicode":"1f55f","shortname":":clock430:","aliases":"","keywords":"clock face four-thirty symbol time"},"clock530":{"unicode":"1f560","shortname":":clock530:","aliases":"","keywords":"clock face five-thirty symbol time"},"clock630":{"unicode":"1f561","shortname":":clock630:","aliases":"","keywords":"clock face six-thirty symbol time"},"clock730":{"unicode":"1f562","shortname":":clock730:","aliases":"","keywords":"clock face seven-thirty symbol time"},"clock830":{"unicode":"1f563","shortname":":clock830:","aliases":"","keywords":"clock face eight-thirty symbol time"},"clock930":{"unicode":"1f564","shortname":":clock930:","aliases":"","keywords":"clock face nine-thirty symbol time"},"clock1030":{"unicode":"1f565","shortname":":clock1030:","aliases":"","keywords":"clock face ten-thirty symbol time"},"clock1130":{"unicode":"1f566","shortname":":clock1130:","aliases":"","keywords":"clock face eleven-thirty symbol time"},"clock1230":{"unicode":"1f567","shortname":":clock1230:","aliases":"","keywords":"clock face twelve-thirty symbol time"},"eye_in_speech_bubble":{"unicode":"1f441-1f5e8","shortname":":eye_in_speech_bubble:","aliases":"","keywords":"eye in speech bubble object symbol eyes talk"},"flag_ac":{"unicode":"1f1e6-1f1e8","shortname":":flag_ac:","aliases":":ac:","keywords":"ascension country flag flag"},"flag_af":{"unicode":"1f1e6-1f1eb","shortname":":flag_af:","aliases":":af:","keywords":"afghanistan country flag flag"},"flag_al":{"unicode":"1f1e6-1f1f1","shortname":":flag_al:","aliases":":al:","keywords":"albania country flag flag"},"flag_dz":{"unicode":"1f1e9-1f1ff","shortname":":flag_dz:","aliases":":dz:","keywords":"algeria country flag flag"},"flag_ad":{"unicode":"1f1e6-1f1e9","shortname":":flag_ad:","aliases":":ad:","keywords":"andorra country flag flag"},"flag_ao":{"unicode":"1f1e6-1f1f4","shortname":":flag_ao:","aliases":":ao:","keywords":"angola country flag flag"},"flag_ai":{"unicode":"1f1e6-1f1ee","shortname":":flag_ai:","aliases":":ai:","keywords":"anguilla country flag flag"},"flag_ag":{"unicode":"1f1e6-1f1ec","shortname":":flag_ag:","aliases":":ag:","keywords":"antigua and barbuda country flag flag"},"flag_ar":{"unicode":"1f1e6-1f1f7","shortname":":flag_ar:","aliases":":ar:","keywords":"argentina country flag flag"},"flag_am":{"unicode":"1f1e6-1f1f2","shortname":":flag_am:","aliases":":am:","keywords":"armenia country flag flag"},"flag_aw":{"unicode":"1f1e6-1f1fc","shortname":":flag_aw:","aliases":":aw:","keywords":"aruba country flag flag"},"flag_au":{"unicode":"1f1e6-1f1fa","shortname":":flag_au:","aliases":":au:","keywords":"australia country flag flag"},"flag_at":{"unicode":"1f1e6-1f1f9","shortname":":flag_at:","aliases":":at:","keywords":"austria country flag flag"},"flag_az":{"unicode":"1f1e6-1f1ff","shortname":":flag_az:","aliases":":az:","keywords":"azerbaijan country flag flag"},"flag_bs":{"unicode":"1f1e7-1f1f8","shortname":":flag_bs:","aliases":":bs:","keywords":"the bahamas country flag flag"},"flag_bh":{"unicode":"1f1e7-1f1ed","shortname":":flag_bh:","aliases":":bh:","keywords":"bahrain country flag flag"},"flag_bd":{"unicode":"1f1e7-1f1e9","shortname":":flag_bd:","aliases":":bd:","keywords":"bangladesh country flag flag"},"flag_bb":{"unicode":"1f1e7-1f1e7","shortname":":flag_bb:","aliases":":bb:","keywords":"barbados country flag flag"},"flag_by":{"unicode":"1f1e7-1f1fe","shortname":":flag_by:","aliases":":by:","keywords":"belarus country flag flag"},"flag_be":{"unicode":"1f1e7-1f1ea","shortname":":flag_be:","aliases":":be:","keywords":"belgium country flag flag"},"flag_bz":{"unicode":"1f1e7-1f1ff","shortname":":flag_bz:","aliases":":bz:","keywords":"belize country flag flag"},"flag_bj":{"unicode":"1f1e7-1f1ef","shortname":":flag_bj:","aliases":":bj:","keywords":"benin country flag flag"},"flag_bm":{"unicode":"1f1e7-1f1f2","shortname":":flag_bm:","aliases":":bm:","keywords":"bermuda country flag flag"},"flag_bt":{"unicode":"1f1e7-1f1f9","shortname":":flag_bt:","aliases":":bt:","keywords":"bhutan country flag flag"},"flag_bo":{"unicode":"1f1e7-1f1f4","shortname":":flag_bo:","aliases":":bo:","keywords":"bolivia country flag flag"},"flag_ba":{"unicode":"1f1e7-1f1e6","shortname":":flag_ba:","aliases":":ba:","keywords":"bosnia and herzegovina country flag flag"},"flag_bw":{"unicode":"1f1e7-1f1fc","shortname":":flag_bw:","aliases":":bw:","keywords":"botswana country flag flag"},"flag_br":{"unicode":"1f1e7-1f1f7","shortname":":flag_br:","aliases":":br:","keywords":"brazil country flag flag"},"flag_bn":{"unicode":"1f1e7-1f1f3","shortname":":flag_bn:","aliases":":bn:","keywords":"brunei country flag flag"},"flag_bg":{"unicode":"1f1e7-1f1ec","shortname":":flag_bg:","aliases":":bg:","keywords":"bulgaria country flag flag"},"flag_bf":{"unicode":"1f1e7-1f1eb","shortname":":flag_bf:","aliases":":bf:","keywords":"burkina faso country flag flag"},"flag_bi":{"unicode":"1f1e7-1f1ee","shortname":":flag_bi:","aliases":":bi:","keywords":"burundi country flag flag"},"flag_cv":{"unicode":"1f1e8-1f1fb","shortname":":flag_cv:","aliases":":cv:","keywords":"cape verde country flag flag"},"flag_kh":{"unicode":"1f1f0-1f1ed","shortname":":flag_kh:","aliases":":kh:","keywords":"cambodia country flag flag"},"flag_cm":{"unicode":"1f1e8-1f1f2","shortname":":flag_cm:","aliases":":cm:","keywords":"cameroon country flag flag"},"flag_ca":{"unicode":"1f1e8-1f1e6","shortname":":flag_ca:","aliases":":ca:","keywords":"canada country flag flag"},"flag_ky":{"unicode":"1f1f0-1f1fe","shortname":":flag_ky:","aliases":":ky:","keywords":"cayman islands country flag flag"},"flag_cf":{"unicode":"1f1e8-1f1eb","shortname":":flag_cf:","aliases":":cf:","keywords":"central african republic country flag flag"},"flag_td":{"unicode":"1f1f9-1f1e9","shortname":":flag_td:","aliases":":td:","keywords":"chad country flag flag"},"flag_cl":{"unicode":"1f1e8-1f1f1","shortname":":flag_cl:","aliases":":chile:","keywords":"chile country flag flag"},"flag_cn":{"unicode":"1f1e8-1f1f3","shortname":":flag_cn:","aliases":":cn:","keywords":"china country flag flag"},"flag_co":{"unicode":"1f1e8-1f1f4","shortname":":flag_co:","aliases":":co:","keywords":"colombia country flag flag"},"flag_km":{"unicode":"1f1f0-1f1f2","shortname":":flag_km:","aliases":":km:","keywords":"the comoros country flag flag"},"flag_cg":{"unicode":"1f1e8-1f1ec","shortname":":flag_cg:","aliases":":cg:","keywords":"the republic of the congo country flag flag"},"flag_cd":{"unicode":"1f1e8-1f1e9","shortname":":flag_cd:","aliases":":congo:","keywords":"the democratic republic of the congo country flag flag"},"flag_cr":{"unicode":"1f1e8-1f1f7","shortname":":flag_cr:","aliases":":cr:","keywords":"costa rica country flag flag"},"flag_hr":{"unicode":"1f1ed-1f1f7","shortname":":flag_hr:","aliases":":hr:","keywords":"croatia country flag flag"},"flag_cu":{"unicode":"1f1e8-1f1fa","shortname":":flag_cu:","aliases":":cu:","keywords":"cuba country flag flag"},"flag_cy":{"unicode":"1f1e8-1f1fe","shortname":":flag_cy:","aliases":":cy:","keywords":"cyprus country flag flag"},"flag_cz":{"unicode":"1f1e8-1f1ff","shortname":":flag_cz:","aliases":":cz:","keywords":"the czech republic country flag flag"},"flag_dk":{"unicode":"1f1e9-1f1f0","shortname":":flag_dk:","aliases":":dk:","keywords":"denmark country flag flag"},"flag_dj":{"unicode":"1f1e9-1f1ef","shortname":":flag_dj:","aliases":":dj:","keywords":"djibouti country flag flag"},"flag_dm":{"unicode":"1f1e9-1f1f2","shortname":":flag_dm:","aliases":":dm:","keywords":"dominica country flag flag"},"flag_do":{"unicode":"1f1e9-1f1f4","shortname":":flag_do:","aliases":":do:","keywords":"the dominican republic country flag flag"},"flag_ec":{"unicode":"1f1ea-1f1e8","shortname":":flag_ec:","aliases":":ec:","keywords":"ecuador country flag flag"},"flag_eg":{"unicode":"1f1ea-1f1ec","shortname":":flag_eg:","aliases":":eg:","keywords":"egypt country flag flag"},"flag_sv":{"unicode":"1f1f8-1f1fb","shortname":":flag_sv:","aliases":":sv:","keywords":"el salvador country flag flag"},"flag_gq":{"unicode":"1f1ec-1f1f6","shortname":":flag_gq:","aliases":":gq:","keywords":"equatorial guinea country flag flag"},"flag_er":{"unicode":"1f1ea-1f1f7","shortname":":flag_er:","aliases":":er:","keywords":"eritrea country flag flag"},"flag_ee":{"unicode":"1f1ea-1f1ea","shortname":":flag_ee:","aliases":":ee:","keywords":"estonia country flag flag"},"flag_et":{"unicode":"1f1ea-1f1f9","shortname":":flag_et:","aliases":":et:","keywords":"ethiopia country flag flag"},"flag_fk":{"unicode":"1f1eb-1f1f0","shortname":":flag_fk:","aliases":":fk:","keywords":"falkland islands country flag flag"},"flag_fo":{"unicode":"1f1eb-1f1f4","shortname":":flag_fo:","aliases":":fo:","keywords":"faroe islands country flag flag"},"flag_fj":{"unicode":"1f1eb-1f1ef","shortname":":flag_fj:","aliases":":fj:","keywords":"fiji country flag flag"},"flag_fi":{"unicode":"1f1eb-1f1ee","shortname":":flag_fi:","aliases":":fi:","keywords":"finland country flag flag"},"flag_fr":{"unicode":"1f1eb-1f1f7","shortname":":flag_fr:","aliases":":fr:","keywords":"france country flag flag"},"flag_pf":{"unicode":"1f1f5-1f1eb","shortname":":flag_pf:","aliases":":pf:","keywords":"french polynesia country flag flag"},"flag_ga":{"unicode":"1f1ec-1f1e6","shortname":":flag_ga:","aliases":":ga:","keywords":"gabon country flag flag"},"flag_gm":{"unicode":"1f1ec-1f1f2","shortname":":flag_gm:","aliases":":gm:","keywords":"the gambia country flag flag"},"flag_ge":{"unicode":"1f1ec-1f1ea","shortname":":flag_ge:","aliases":":ge:","keywords":"georgia country flag flag"},"flag_de":{"unicode":"1f1e9-1f1ea","shortname":":flag_de:","aliases":":de:","keywords":"germany country flag flag"},"flag_gh":{"unicode":"1f1ec-1f1ed","shortname":":flag_gh:","aliases":":gh:","keywords":"ghana country flag flag"},"flag_gi":{"unicode":"1f1ec-1f1ee","shortname":":flag_gi:","aliases":":gi:","keywords":"gibraltar country flag flag"},"flag_gr":{"unicode":"1f1ec-1f1f7","shortname":":flag_gr:","aliases":":gr:","keywords":"greece country flag flag"},"flag_gl":{"unicode":"1f1ec-1f1f1","shortname":":flag_gl:","aliases":":gl:","keywords":"greenland country flag flag"},"flag_gd":{"unicode":"1f1ec-1f1e9","shortname":":flag_gd:","aliases":":gd:","keywords":"grenada country flag flag"},"flag_gu":{"unicode":"1f1ec-1f1fa","shortname":":flag_gu:","aliases":":gu:","keywords":"guam country flag flag"},"flag_gt":{"unicode":"1f1ec-1f1f9","shortname":":flag_gt:","aliases":":gt:","keywords":"guatemala country flag flag"},"flag_gn":{"unicode":"1f1ec-1f1f3","shortname":":flag_gn:","aliases":":gn:","keywords":"guinea country flag flag"},"flag_gw":{"unicode":"1f1ec-1f1fc","shortname":":flag_gw:","aliases":":gw:","keywords":"guinea-bissau country flag flag"},"flag_gy":{"unicode":"1f1ec-1f1fe","shortname":":flag_gy:","aliases":":gy:","keywords":"guyana country flag flag"},"flag_ht":{"unicode":"1f1ed-1f1f9","shortname":":flag_ht:","aliases":":ht:","keywords":"haiti country flag flag"},"flag_hn":{"unicode":"1f1ed-1f1f3","shortname":":flag_hn:","aliases":":hn:","keywords":"honduras country flag flag"},"flag_hk":{"unicode":"1f1ed-1f1f0","shortname":":flag_hk:","aliases":":hk:","keywords":"hong kong country flag flag"},"flag_hu":{"unicode":"1f1ed-1f1fa","shortname":":flag_hu:","aliases":":hu:","keywords":"hungary country flag flag"},"flag_is":{"unicode":"1f1ee-1f1f8","shortname":":flag_is:","aliases":":is:","keywords":"iceland country flag flag"},"flag_in":{"unicode":"1f1ee-1f1f3","shortname":":flag_in:","aliases":":in:","keywords":"india country flag flag"},"flag_id":{"unicode":"1f1ee-1f1e9","shortname":":flag_id:","aliases":":indonesia:","keywords":"indonesia country flag flag"},"flag_ir":{"unicode":"1f1ee-1f1f7","shortname":":flag_ir:","aliases":":ir:","keywords":"iran country flag flag"},"flag_iq":{"unicode":"1f1ee-1f1f6","shortname":":flag_iq:","aliases":":iq:","keywords":"iraq country flag flag"},"flag_ie":{"unicode":"1f1ee-1f1ea","shortname":":flag_ie:","aliases":":ie:","keywords":"ireland country flag flag"},"flag_il":{"unicode":"1f1ee-1f1f1","shortname":":flag_il:","aliases":":il:","keywords":"israel jew country flag flag"},"flag_it":{"unicode":"1f1ee-1f1f9","shortname":":flag_it:","aliases":":it:","keywords":"italy italian country flag flag"},"flag_ci":{"unicode":"1f1e8-1f1ee","shortname":":flag_ci:","aliases":":ci:","keywords":"c\u00f4te d\u2019ivoire country flag flag"},"flag_jm":{"unicode":"1f1ef-1f1f2","shortname":":flag_jm:","aliases":":jm:","keywords":"jamaica country flag flag"},"flag_jp":{"unicode":"1f1ef-1f1f5","shortname":":flag_jp:","aliases":":jp:","keywords":"japan japan country flag flag"},"flag_je":{"unicode":"1f1ef-1f1ea","shortname":":flag_je:","aliases":":je:","keywords":"jersey country flag flag"},"flag_jo":{"unicode":"1f1ef-1f1f4","shortname":":flag_jo:","aliases":":jo:","keywords":"jordan country flag flag"},"flag_kz":{"unicode":"1f1f0-1f1ff","shortname":":flag_kz:","aliases":":kz:","keywords":"kazakhstan country flag flag"},"flag_ke":{"unicode":"1f1f0-1f1ea","shortname":":flag_ke:","aliases":":ke:","keywords":"kenya country flag flag"},"flag_ki":{"unicode":"1f1f0-1f1ee","shortname":":flag_ki:","aliases":":ki:","keywords":"kiribati country flag flag"},"flag_xk":{"unicode":"1f1fd-1f1f0","shortname":":flag_xk:","aliases":":xk:","keywords":"kosovo country flag flag"},"flag_kw":{"unicode":"1f1f0-1f1fc","shortname":":flag_kw:","aliases":":kw:","keywords":"kuwait country flag flag"},"flag_kg":{"unicode":"1f1f0-1f1ec","shortname":":flag_kg:","aliases":":kg:","keywords":"kyrgyzstan country flag flag"},"flag_la":{"unicode":"1f1f1-1f1e6","shortname":":flag_la:","aliases":":la:","keywords":"laos country flag flag"},"flag_lv":{"unicode":"1f1f1-1f1fb","shortname":":flag_lv:","aliases":":lv:","keywords":"latvia country flag flag"},"flag_lb":{"unicode":"1f1f1-1f1e7","shortname":":flag_lb:","aliases":":lb:","keywords":"lebanon country flag flag"},"flag_ls":{"unicode":"1f1f1-1f1f8","shortname":":flag_ls:","aliases":":ls:","keywords":"lesotho country flag flag"},"flag_lr":{"unicode":"1f1f1-1f1f7","shortname":":flag_lr:","aliases":":lr:","keywords":"liberia country flag flag"},"flag_ly":{"unicode":"1f1f1-1f1fe","shortname":":flag_ly:","aliases":":ly:","keywords":"libya country flag flag"},"flag_li":{"unicode":"1f1f1-1f1ee","shortname":":flag_li:","aliases":":li:","keywords":"liechtenstein country flag flag"},"flag_lt":{"unicode":"1f1f1-1f1f9","shortname":":flag_lt:","aliases":":lt:","keywords":"lithuania country flag flag"},"flag_lu":{"unicode":"1f1f1-1f1fa","shortname":":flag_lu:","aliases":":lu:","keywords":"luxembourg country flag flag"},"flag_mo":{"unicode":"1f1f2-1f1f4","shortname":":flag_mo:","aliases":":mo:","keywords":"macau country flag flag"},"flag_mk":{"unicode":"1f1f2-1f1f0","shortname":":flag_mk:","aliases":":mk:","keywords":"macedonia country flag flag"},"flag_mg":{"unicode":"1f1f2-1f1ec","shortname":":flag_mg:","aliases":":mg:","keywords":"madagascar country flag flag"},"flag_mw":{"unicode":"1f1f2-1f1fc","shortname":":flag_mw:","aliases":":mw:","keywords":"malawi country flag flag"},"flag_my":{"unicode":"1f1f2-1f1fe","shortname":":flag_my:","aliases":":my:","keywords":"malaysia country flag flag"},"flag_mv":{"unicode":"1f1f2-1f1fb","shortname":":flag_mv:","aliases":":mv:","keywords":"maldives country flag flag"},"flag_ml":{"unicode":"1f1f2-1f1f1","shortname":":flag_ml:","aliases":":ml:","keywords":"mali country flag flag"},"flag_mt":{"unicode":"1f1f2-1f1f9","shortname":":flag_mt:","aliases":":mt:","keywords":"malta country flag flag"},"flag_mh":{"unicode":"1f1f2-1f1ed","shortname":":flag_mh:","aliases":":mh:","keywords":"the marshall islands country flag flag"},"flag_mr":{"unicode":"1f1f2-1f1f7","shortname":":flag_mr:","aliases":":mr:","keywords":"mauritania country flag flag"},"flag_mu":{"unicode":"1f1f2-1f1fa","shortname":":flag_mu:","aliases":":mu:","keywords":"mauritius country flag flag"},"flag_mx":{"unicode":"1f1f2-1f1fd","shortname":":flag_mx:","aliases":":mx:","keywords":"mexico country mexican flag flag"},"flag_fm":{"unicode":"1f1eb-1f1f2","shortname":":flag_fm:","aliases":":fm:","keywords":"micronesia country flag flag"},"flag_md":{"unicode":"1f1f2-1f1e9","shortname":":flag_md:","aliases":":md:","keywords":"moldova country flag flag"},"flag_mc":{"unicode":"1f1f2-1f1e8","shortname":":flag_mc:","aliases":":mc:","keywords":"monaco country flag flag"},"flag_mn":{"unicode":"1f1f2-1f1f3","shortname":":flag_mn:","aliases":":mn:","keywords":"mongolia country flag flag"},"flag_me":{"unicode":"1f1f2-1f1ea","shortname":":flag_me:","aliases":":me:","keywords":"montenegro country flag flag"},"flag_ms":{"unicode":"1f1f2-1f1f8","shortname":":flag_ms:","aliases":":ms:","keywords":"montserrat country flag flag"},"flag_ma":{"unicode":"1f1f2-1f1e6","shortname":":flag_ma:","aliases":":ma:","keywords":"morocco country flag flag"},"flag_mz":{"unicode":"1f1f2-1f1ff","shortname":":flag_mz:","aliases":":mz:","keywords":"mozambique country flag flag"},"flag_mm":{"unicode":"1f1f2-1f1f2","shortname":":flag_mm:","aliases":":mm:","keywords":"myanmar country flag flag"},"flag_na":{"unicode":"1f1f3-1f1e6","shortname":":flag_na:","aliases":":na:","keywords":"namibia country flag flag"},"flag_nr":{"unicode":"1f1f3-1f1f7","shortname":":flag_nr:","aliases":":nr:","keywords":"nauru country flag flag"},"flag_np":{"unicode":"1f1f3-1f1f5","shortname":":flag_np:","aliases":":np:","keywords":"nepal country flag flag"},"flag_nl":{"unicode":"1f1f3-1f1f1","shortname":":flag_nl:","aliases":":nl:","keywords":"the netherlands country flag flag"},"flag_nc":{"unicode":"1f1f3-1f1e8","shortname":":flag_nc:","aliases":":nc:","keywords":"new caledonia country flag flag"},"flag_nz":{"unicode":"1f1f3-1f1ff","shortname":":flag_nz:","aliases":":nz:","keywords":"new zealand country flag flag"},"flag_ni":{"unicode":"1f1f3-1f1ee","shortname":":flag_ni:","aliases":":ni:","keywords":"nicaragua country flag flag"},"flag_ne":{"unicode":"1f1f3-1f1ea","shortname":":flag_ne:","aliases":":ne:","keywords":"niger country flag flag"},"flag_ng":{"unicode":"1f1f3-1f1ec","shortname":":flag_ng:","aliases":":nigeria:","keywords":"nigeria country flag flag"},"flag_nu":{"unicode":"1f1f3-1f1fa","shortname":":flag_nu:","aliases":":nu:","keywords":"niue country flag flag"},"flag_kp":{"unicode":"1f1f0-1f1f5","shortname":":flag_kp:","aliases":":kp:","keywords":"north korea country flag flag"},"flag_no":{"unicode":"1f1f3-1f1f4","shortname":":flag_no:","aliases":":no:","keywords":"norway country flag flag"},"flag_om":{"unicode":"1f1f4-1f1f2","shortname":":flag_om:","aliases":":om:","keywords":"oman country flag flag"},"flag_pk":{"unicode":"1f1f5-1f1f0","shortname":":flag_pk:","aliases":":pk:","keywords":"pakistan country flag flag"},"flag_pw":{"unicode":"1f1f5-1f1fc","shortname":":flag_pw:","aliases":":pw:","keywords":"palau country flag flag"},"flag_ps":{"unicode":"1f1f5-1f1f8","shortname":":flag_ps:","aliases":":ps:","keywords":"palestinian authority country flag flag"},"flag_pa":{"unicode":"1f1f5-1f1e6","shortname":":flag_pa:","aliases":":pa:","keywords":"panama country flag flag"},"flag_pg":{"unicode":"1f1f5-1f1ec","shortname":":flag_pg:","aliases":":pg:","keywords":"papua new guinea country flag flag"},"flag_py":{"unicode":"1f1f5-1f1fe","shortname":":flag_py:","aliases":":py:","keywords":"paraguay country flag flag"},"flag_pe":{"unicode":"1f1f5-1f1ea","shortname":":flag_pe:","aliases":":pe:","keywords":"peru country flag flag"},"flag_ph":{"unicode":"1f1f5-1f1ed","shortname":":flag_ph:","aliases":":ph:","keywords":"the philippines country flag flag"},"flag_pl":{"unicode":"1f1f5-1f1f1","shortname":":flag_pl:","aliases":":pl:","keywords":"poland country flag flag"},"flag_pt":{"unicode":"1f1f5-1f1f9","shortname":":flag_pt:","aliases":":pt:","keywords":"portugal country flag flag"},"flag_pr":{"unicode":"1f1f5-1f1f7","shortname":":flag_pr:","aliases":":pr:","keywords":"puerto rico country flag flag"},"flag_qa":{"unicode":"1f1f6-1f1e6","shortname":":flag_qa:","aliases":":qa:","keywords":"qatar country flag flag"},"flag_ro":{"unicode":"1f1f7-1f1f4","shortname":":flag_ro:","aliases":":ro:","keywords":"romania country flag flag"},"flag_ru":{"unicode":"1f1f7-1f1fa","shortname":":flag_ru:","aliases":":ru:","keywords":"russia country flag flag"},"flag_rw":{"unicode":"1f1f7-1f1fc","shortname":":flag_rw:","aliases":":rw:","keywords":"rwanda country flag flag"},"flag_sh":{"unicode":"1f1f8-1f1ed","shortname":":flag_sh:","aliases":":sh:","keywords":"saint helena country flag flag"},"flag_kn":{"unicode":"1f1f0-1f1f3","shortname":":flag_kn:","aliases":":kn:","keywords":"saint kitts and nevis country flag flag"},"flag_lc":{"unicode":"1f1f1-1f1e8","shortname":":flag_lc:","aliases":":lc:","keywords":"saint lucia country flag flag"},"flag_vc":{"unicode":"1f1fb-1f1e8","shortname":":flag_vc:","aliases":":vc:","keywords":"saint vincent and the grenadines country flag flag"},"flag_ws":{"unicode":"1f1fc-1f1f8","shortname":":flag_ws:","aliases":":ws:","keywords":"samoa country flag flag"},"flag_sm":{"unicode":"1f1f8-1f1f2","shortname":":flag_sm:","aliases":":sm:","keywords":"san marino country flag flag"},"flag_st":{"unicode":"1f1f8-1f1f9","shortname":":flag_st:","aliases":":st:","keywords":"s\u00e3o tom\u00e9 and pr\u00edncipe country flag flag"},"flag_sa":{"unicode":"1f1f8-1f1e6","shortname":":flag_sa:","aliases":":saudiarabia: :saudi:","keywords":"saudi arabia country flag flag"},"flag_sn":{"unicode":"1f1f8-1f1f3","shortname":":flag_sn:","aliases":":sn:","keywords":"senegal country flag flag"},"flag_rs":{"unicode":"1f1f7-1f1f8","shortname":":flag_rs:","aliases":":rs:","keywords":"serbia country flag flag"},"flag_sc":{"unicode":"1f1f8-1f1e8","shortname":":flag_sc:","aliases":":sc:","keywords":"the seychelles country flag flag"},"flag_sl":{"unicode":"1f1f8-1f1f1","shortname":":flag_sl:","aliases":":sl:","keywords":"sierra leone country flag flag"},"flag_sg":{"unicode":"1f1f8-1f1ec","shortname":":flag_sg:","aliases":":sg:","keywords":"singapore country flag flag"},"flag_sk":{"unicode":"1f1f8-1f1f0","shortname":":flag_sk:","aliases":":sk:","keywords":"slovakia country flag flag"},"flag_si":{"unicode":"1f1f8-1f1ee","shortname":":flag_si:","aliases":":si:","keywords":"slovenia country flag flag"},"flag_sb":{"unicode":"1f1f8-1f1e7","shortname":":flag_sb:","aliases":":sb:","keywords":"the solomon islands country flag flag"},"flag_so":{"unicode":"1f1f8-1f1f4","shortname":":flag_so:","aliases":":so:","keywords":"somalia country flag flag"},"flag_za":{"unicode":"1f1ff-1f1e6","shortname":":flag_za:","aliases":":za:","keywords":"south africa country flag flag"},"flag_kr":{"unicode":"1f1f0-1f1f7","shortname":":flag_kr:","aliases":":kr:","keywords":"korea country flag flag"},"flag_es":{"unicode":"1f1ea-1f1f8","shortname":":flag_es:","aliases":":es:","keywords":"spain country flag flag"},"flag_lk":{"unicode":"1f1f1-1f1f0","shortname":":flag_lk:","aliases":":lk:","keywords":"sri lanka country flag flag"},"flag_sd":{"unicode":"1f1f8-1f1e9","shortname":":flag_sd:","aliases":":sd:","keywords":"sudan country flag flag"},"flag_sr":{"unicode":"1f1f8-1f1f7","shortname":":flag_sr:","aliases":":sr:","keywords":"suriname country flag flag"},"flag_sz":{"unicode":"1f1f8-1f1ff","shortname":":flag_sz:","aliases":":sz:","keywords":"swaziland country flag flag"},"flag_se":{"unicode":"1f1f8-1f1ea","shortname":":flag_se:","aliases":":se:","keywords":"sweden country flag flag"},"flag_ch":{"unicode":"1f1e8-1f1ed","shortname":":flag_ch:","aliases":":ch:","keywords":"switzerland country neutral flag flag"},"flag_sy":{"unicode":"1f1f8-1f1fe","shortname":":flag_sy:","aliases":":sy:","keywords":"syria country flag flag"},"flag_tw":{"unicode":"1f1f9-1f1fc","shortname":":flag_tw:","aliases":":tw:","keywords":"the republic of china country flag flag"},"flag_tj":{"unicode":"1f1f9-1f1ef","shortname":":flag_tj:","aliases":":tj:","keywords":"tajikistan country flag flag"},"flag_tz":{"unicode":"1f1f9-1f1ff","shortname":":flag_tz:","aliases":":tz:","keywords":"tanzania country flag flag"},"flag_th":{"unicode":"1f1f9-1f1ed","shortname":":flag_th:","aliases":":th:","keywords":"thailand country flag flag"},"flag_tl":{"unicode":"1f1f9-1f1f1","shortname":":flag_tl:","aliases":":tl:","keywords":"timor-leste country flag flag"},"flag_tg":{"unicode":"1f1f9-1f1ec","shortname":":flag_tg:","aliases":":tg:","keywords":"togo country flag flag"},"flag_to":{"unicode":"1f1f9-1f1f4","shortname":":flag_to:","aliases":":to:","keywords":"tonga country flag flag"},"flag_tt":{"unicode":"1f1f9-1f1f9","shortname":":flag_tt:","aliases":":tt:","keywords":"trinidad and tobago country flag flag"},"flag_tn":{"unicode":"1f1f9-1f1f3","shortname":":flag_tn:","aliases":":tn:","keywords":"tunisia country flag flag"},"flag_tr":{"unicode":"1f1f9-1f1f7","shortname":":flag_tr:","aliases":":tr:","keywords":"turkey country flag flag"},"flag_tm":{"unicode":"1f1f9-1f1f2","shortname":":flag_tm:","aliases":":turkmenistan:","keywords":"turkmenistan country flag flag"},"flag_tv":{"unicode":"1f1f9-1f1fb","shortname":":flag_tv:","aliases":":tuvalu:","keywords":"tuvalu country flag flag"},"flag_ug":{"unicode":"1f1fa-1f1ec","shortname":":flag_ug:","aliases":":ug:","keywords":"uganda country flag flag"},"flag_ua":{"unicode":"1f1fa-1f1e6","shortname":":flag_ua:","aliases":":ua:","keywords":"ukraine country flag flag"},"flag_ae":{"unicode":"1f1e6-1f1ea","shortname":":flag_ae:","aliases":":ae:","keywords":"the united arab emirates country flag flag"},"flag_gb":{"unicode":"1f1ec-1f1e7","shortname":":flag_gb:","aliases":":gb:","keywords":"great britain country flag flag"},"flag_us":{"unicode":"1f1fa-1f1f8","shortname":":flag_us:","aliases":":us:","keywords":"united states america country flag flag"},"flag_vi":{"unicode":"1f1fb-1f1ee","shortname":":flag_vi:","aliases":":vi:","keywords":"u.s. virgin islands country flag flag"},"flag_uy":{"unicode":"1f1fa-1f1fe","shortname":":flag_uy:","aliases":":uy:","keywords":"uruguay country flag flag"},"flag_uz":{"unicode":"1f1fa-1f1ff","shortname":":flag_uz:","aliases":":uz:","keywords":"uzbekistan country flag flag"},"flag_vu":{"unicode":"1f1fb-1f1fa","shortname":":flag_vu:","aliases":":vu:","keywords":"vanuatu country flag flag"},"flag_va":{"unicode":"1f1fb-1f1e6","shortname":":flag_va:","aliases":":va:","keywords":"the vatican city country flag flag"},"flag_ve":{"unicode":"1f1fb-1f1ea","shortname":":flag_ve:","aliases":":ve:","keywords":"venezuela country flag flag"},"flag_vn":{"unicode":"1f1fb-1f1f3","shortname":":flag_vn:","aliases":":vn:","keywords":"vietnam country flag flag"},"flag_wf":{"unicode":"1f1fc-1f1eb","shortname":":flag_wf:","aliases":":wf:","keywords":"wallis and futuna country flag flag"},"flag_eh":{"unicode":"1f1ea-1f1ed","shortname":":flag_eh:","aliases":":eh:","keywords":"western sahara country flag flag"},"flag_ye":{"unicode":"1f1fe-1f1ea","shortname":":flag_ye:","aliases":":ye:","keywords":"yemen country flag flag"},"flag_zm":{"unicode":"1f1ff-1f1f2","shortname":":flag_zm:","aliases":":zm:","keywords":"zambia country flag flag"},"flag_zw":{"unicode":"1f1ff-1f1fc","shortname":":flag_zw:","aliases":":zw:","keywords":"zimbabwe country flag flag"},"flag_re":{"unicode":"1f1f7-1f1ea","shortname":":flag_re:","aliases":":re:","keywords":"r\u00e9union country flag flag"},"flag_ax":{"unicode":"1f1e6-1f1fd","shortname":":flag_ax:","aliases":":ax:","keywords":"\u00e5land islands country flag flag"},"flag_ta":{"unicode":"1f1f9-1f1e6","shortname":":flag_ta:","aliases":":ta:","keywords":"tristan da cunha country flag flag"},"flag_io":{"unicode":"1f1ee-1f1f4","shortname":":flag_io:","aliases":":io:","keywords":"british indian ocean territory country flag flag"},"flag_bq":{"unicode":"1f1e7-1f1f6","shortname":":flag_bq:","aliases":":bq:","keywords":"caribbean netherlands country flag flag"},"flag_cx":{"unicode":"1f1e8-1f1fd","shortname":":flag_cx:","aliases":":cx:","keywords":"christmas island country flag flag"},"flag_cc":{"unicode":"1f1e8-1f1e8","shortname":":flag_cc:","aliases":":cc:","keywords":"cocos (keeling) islands country flag flag"},"flag_gg":{"unicode":"1f1ec-1f1ec","shortname":":flag_gg:","aliases":":gg:","keywords":"guernsey country flag flag"},"flag_im":{"unicode":"1f1ee-1f1f2","shortname":":flag_im:","aliases":":im:","keywords":"isle of man country flag flag"},"flag_yt":{"unicode":"1f1fe-1f1f9","shortname":":flag_yt:","aliases":":yt:","keywords":"mayotte country flag flag"},"flag_nf":{"unicode":"1f1f3-1f1eb","shortname":":flag_nf:","aliases":":nf:","keywords":"norfolk island country flag flag"},"flag_pn":{"unicode":"1f1f5-1f1f3","shortname":":flag_pn:","aliases":":pn:","keywords":"pitcairn country flag flag"},"flag_bl":{"unicode":"1f1e7-1f1f1","shortname":":flag_bl:","aliases":":bl:","keywords":"saint barth\u00e9lemy country flag flag"},"flag_pm":{"unicode":"1f1f5-1f1f2","shortname":":flag_pm:","aliases":":pm:","keywords":"saint pierre and miquelon country flag flag"},"flag_gs":{"unicode":"1f1ec-1f1f8","shortname":":flag_gs:","aliases":":gs:","keywords":"south georgia country flag flag"},"flag_tk":{"unicode":"1f1f9-1f1f0","shortname":":flag_tk:","aliases":":tk:","keywords":"tokelau country flag flag"},"flag_bv":{"unicode":"1f1e7-1f1fb","shortname":":flag_bv:","aliases":":bv:","keywords":"bouvet island country flag flag"},"flag_hm":{"unicode":"1f1ed-1f1f2","shortname":":flag_hm:","aliases":":hm:","keywords":"heard island and mcdonald islands country flag flag"},"flag_sj":{"unicode":"1f1f8-1f1ef","shortname":":flag_sj:","aliases":":sj:","keywords":"svalbard and jan mayen country flag flag"},"flag_um":{"unicode":"1f1fa-1f1f2","shortname":":flag_um:","aliases":":um:","keywords":"united states minor outlying islands country flag flag"},"flag_ic":{"unicode":"1f1ee-1f1e8","shortname":":flag_ic:","aliases":":ic:","keywords":"canary islands country flag flag"},"flag_ea":{"unicode":"1f1ea-1f1e6","shortname":":flag_ea:","aliases":":ea:","keywords":"ceuta, melilla country flag flag"},"flag_cp":{"unicode":"1f1e8-1f1f5","shortname":":flag_cp:","aliases":":cp:","keywords":"clipperton island country flag flag"},"flag_dg":{"unicode":"1f1e9-1f1ec","shortname":":flag_dg:","aliases":":dg:","keywords":"diego garcia country flag flag"},"flag_as":{"unicode":"1f1e6-1f1f8","shortname":":flag_as:","aliases":":as:","keywords":"american samoa country flag flag"},"flag_aq":{"unicode":"1f1e6-1f1f6","shortname":":flag_aq:","aliases":":aq:","keywords":"antarctica country flag flag"},"flag_vg":{"unicode":"1f1fb-1f1ec","shortname":":flag_vg:","aliases":":vg:","keywords":"british virgin islands country flag flag"},"flag_ck":{"unicode":"1f1e8-1f1f0","shortname":":flag_ck:","aliases":":ck:","keywords":"cook islands country flag flag"},"flag_cw":{"unicode":"1f1e8-1f1fc","shortname":":flag_cw:","aliases":":cw:","keywords":"cura\u00e7ao country flag flag"},"flag_eu":{"unicode":"1f1ea-1f1fa","shortname":":flag_eu:","aliases":":eu:","keywords":"european union country flag flag"},"flag_gf":{"unicode":"1f1ec-1f1eb","shortname":":flag_gf:","aliases":":gf:","keywords":"french guiana country flag flag"},"flag_tf":{"unicode":"1f1f9-1f1eb","shortname":":flag_tf:","aliases":":tf:","keywords":"french southern territories country flag flag"},"flag_gp":{"unicode":"1f1ec-1f1f5","shortname":":flag_gp:","aliases":":gp:","keywords":"guadeloupe country flag flag"},"flag_mq":{"unicode":"1f1f2-1f1f6","shortname":":flag_mq:","aliases":":mq:","keywords":"martinique country flag flag"},"flag_mp":{"unicode":"1f1f2-1f1f5","shortname":":flag_mp:","aliases":":mp:","keywords":"northern mariana islands country flag flag"},"flag_sx":{"unicode":"1f1f8-1f1fd","shortname":":flag_sx:","aliases":":sx:","keywords":"sint maarten country flag flag"},"flag_ss":{"unicode":"1f1f8-1f1f8","shortname":":flag_ss:","aliases":":ss:","keywords":"south sudan country flag flag"},"flag_tc":{"unicode":"1f1f9-1f1e8","shortname":":flag_tc:","aliases":":tc:","keywords":"turks and caicos islands country flag flag"},"flag_mf":{"unicode":"1f1f2-1f1eb","shortname":":flag_mf:","aliases":":mf:","keywords":"saint martin country flag flag"},"raised_hands_tone1":{"unicode":"1f64c-1f3fb","shortname":":raised_hands_tone1:","aliases":"","keywords":"person raising both hands in celebration tone 1"},"raised_hands_tone2":{"unicode":"1f64c-1f3fc","shortname":":raised_hands_tone2:","aliases":"","keywords":"person raising both hands in celebration tone 2"},"raised_hands_tone3":{"unicode":"1f64c-1f3fd","shortname":":raised_hands_tone3:","aliases":"","keywords":"person raising both hands in celebration tone 3"},"raised_hands_tone4":{"unicode":"1f64c-1f3fe","shortname":":raised_hands_tone4:","aliases":"","keywords":"person raising both hands in celebration tone 4"},"raised_hands_tone5":{"unicode":"1f64c-1f3ff","shortname":":raised_hands_tone5:","aliases":"","keywords":"person raising both hands in celebration tone 5"},"clap_tone1":{"unicode":"1f44f-1f3fb","shortname":":clap_tone1:","aliases":"","keywords":"clapping hands sign tone 1"},"clap_tone2":{"unicode":"1f44f-1f3fc","shortname":":clap_tone2:","aliases":"","keywords":"clapping hands sign tone 2"},"clap_tone3":{"unicode":"1f44f-1f3fd","shortname":":clap_tone3:","aliases":"","keywords":"clapping hands sign tone 3"},"clap_tone4":{"unicode":"1f44f-1f3fe","shortname":":clap_tone4:","aliases":"","keywords":"clapping hands sign tone 4"},"clap_tone5":{"unicode":"1f44f-1f3ff","shortname":":clap_tone5:","aliases":"","keywords":"clapping hands sign tone 5"},"wave_tone1":{"unicode":"1f44b-1f3fb","shortname":":wave_tone1:","aliases":"","keywords":"waving hand sign tone 1"},"wave_tone2":{"unicode":"1f44b-1f3fc","shortname":":wave_tone2:","aliases":"","keywords":"waving hand sign tone 2"},"wave_tone3":{"unicode":"1f44b-1f3fd","shortname":":wave_tone3:","aliases":"","keywords":"waving hand sign tone 3"},"wave_tone4":{"unicode":"1f44b-1f3fe","shortname":":wave_tone4:","aliases":"","keywords":"waving hand sign tone 4"},"wave_tone5":{"unicode":"1f44b-1f3ff","shortname":":wave_tone5:","aliases":"","keywords":"waving hand sign tone 5"},"thumbsup_tone1":{"unicode":"1f44d-1f3fb","shortname":":thumbsup_tone1:","aliases":":+1_tone1: :thumbup_tone1:","keywords":"thumbs up sign tone 1"},"thumbsup_tone2":{"unicode":"1f44d-1f3fc","shortname":":thumbsup_tone2:","aliases":":+1_tone2: :thumbup_tone2:","keywords":"thumbs up sign tone 2"},"thumbsup_tone3":{"unicode":"1f44d-1f3fd","shortname":":thumbsup_tone3:","aliases":":+1_tone3: :thumbup_tone3:","keywords":"thumbs up sign tone 3"},"thumbsup_tone4":{"unicode":"1f44d-1f3fe","shortname":":thumbsup_tone4:","aliases":":+1_tone4: :thumbup_tone4:","keywords":"thumbs up sign tone 4"},"thumbsup_tone5":{"unicode":"1f44d-1f3ff","shortname":":thumbsup_tone5:","aliases":":+1_tone5: :thumbup_tone5:","keywords":"thumbs up sign tone 5"},"thumbsdown_tone1":{"unicode":"1f44e-1f3fb","shortname":":thumbsdown_tone1:","aliases":":-1_tone1: :thumbdown_tone1:","keywords":"thumbs down sign tone 1"},"thumbsdown_tone2":{"unicode":"1f44e-1f3fc","shortname":":thumbsdown_tone2:","aliases":":-1_tone2: :thumbdown_tone2:","keywords":"thumbs down sign tone 2"},"thumbsdown_tone3":{"unicode":"1f44e-1f3fd","shortname":":thumbsdown_tone3:","aliases":":-1_tone3: :thumbdown_tone3:","keywords":"thumbs down sign tone 3"},"thumbsdown_tone4":{"unicode":"1f44e-1f3fe","shortname":":thumbsdown_tone4:","aliases":":-1_tone4: :thumbdown_tone4:","keywords":"thumbs down sign tone 4"},"thumbsdown_tone5":{"unicode":"1f44e-1f3ff","shortname":":thumbsdown_tone5:","aliases":":-1_tone5: :thumbdown_tone5:","keywords":"thumbs down sign tone 5"},"punch_tone1":{"unicode":"1f44a-1f3fb","shortname":":punch_tone1:","aliases":"","keywords":"fisted hand sign tone 1"},"punch_tone2":{"unicode":"1f44a-1f3fc","shortname":":punch_tone2:","aliases":"","keywords":"fisted hand sign tone 2"},"punch_tone3":{"unicode":"1f44a-1f3fd","shortname":":punch_tone3:","aliases":"","keywords":"fisted hand sign tone 3"},"punch_tone4":{"unicode":"1f44a-1f3fe","shortname":":punch_tone4:","aliases":"","keywords":"fisted hand sign tone 4"},"punch_tone5":{"unicode":"1f44a-1f3ff","shortname":":punch_tone5:","aliases":"","keywords":"fisted hand sign tone 5"},"fist_tone1":{"unicode":"270a-1f3fb","shortname":":fist_tone1:","aliases":"","keywords":"raised fist tone 1"},"fist_tone2":{"unicode":"270a-1f3fc","shortname":":fist_tone2:","aliases":"","keywords":"raised fist tone 2"},"fist_tone3":{"unicode":"270a-1f3fd","shortname":":fist_tone3:","aliases":"","keywords":"raised fist tone 3"},"fist_tone4":{"unicode":"270a-1f3fe","shortname":":fist_tone4:","aliases":"","keywords":"raised fist tone 4"},"fist_tone5":{"unicode":"270a-1f3ff","shortname":":fist_tone5:","aliases":"","keywords":"raised fist tone 5"},"v_tone1":{"unicode":"270c-1f3fb","shortname":":v_tone1:","aliases":"","keywords":"victory hand tone 1"},"v_tone2":{"unicode":"270c-1f3fc","shortname":":v_tone2:","aliases":"","keywords":"victory hand tone 2"},"v_tone3":{"unicode":"270c-1f3fd","shortname":":v_tone3:","aliases":"","keywords":"victory hand tone 3"},"v_tone4":{"unicode":"270c-1f3fe","shortname":":v_tone4:","aliases":"","keywords":"victory hand tone 4"},"v_tone5":{"unicode":"270c-1f3ff","shortname":":v_tone5:","aliases":"","keywords":"victory hand tone 5"},"ok_hand_tone1":{"unicode":"1f44c-1f3fb","shortname":":ok_hand_tone1:","aliases":"","keywords":"ok hand sign tone 1"},"ok_hand_tone2":{"unicode":"1f44c-1f3fc","shortname":":ok_hand_tone2:","aliases":"","keywords":"ok hand sign tone 2"},"ok_hand_tone3":{"unicode":"1f44c-1f3fd","shortname":":ok_hand_tone3:","aliases":"","keywords":"ok hand sign tone 3"},"ok_hand_tone4":{"unicode":"1f44c-1f3fe","shortname":":ok_hand_tone4:","aliases":"","keywords":"ok hand sign tone 4"},"ok_hand_tone5":{"unicode":"1f44c-1f3ff","shortname":":ok_hand_tone5:","aliases":"","keywords":"ok hand sign tone 5"},"raised_hand_tone1":{"unicode":"270b-1f3fb","shortname":":raised_hand_tone1:","aliases":"","keywords":"raised hand tone 1"},"raised_hand_tone2":{"unicode":"270b-1f3fc","shortname":":raised_hand_tone2:","aliases":"","keywords":"raised hand tone 2"},"raised_hand_tone3":{"unicode":"270b-1f3fd","shortname":":raised_hand_tone3:","aliases":"","keywords":"raised hand tone 3"},"raised_hand_tone4":{"unicode":"270b-1f3fe","shortname":":raised_hand_tone4:","aliases":"","keywords":"raised hand tone 4"},"raised_hand_tone5":{"unicode":"270b-1f3ff","shortname":":raised_hand_tone5:","aliases":"","keywords":"raised hand tone 5"},"open_hands_tone1":{"unicode":"1f450-1f3fb","shortname":":open_hands_tone1:","aliases":"","keywords":"open hands sign tone 1"},"open_hands_tone2":{"unicode":"1f450-1f3fc","shortname":":open_hands_tone2:","aliases":"","keywords":"open hands sign tone 2"},"open_hands_tone3":{"unicode":"1f450-1f3fd","shortname":":open_hands_tone3:","aliases":"","keywords":"open hands sign tone 3"},"open_hands_tone4":{"unicode":"1f450-1f3fe","shortname":":open_hands_tone4:","aliases":"","keywords":"open hands sign tone 4"},"open_hands_tone5":{"unicode":"1f450-1f3ff","shortname":":open_hands_tone5:","aliases":"","keywords":"open hands sign tone 5"},"muscle_tone1":{"unicode":"1f4aa-1f3fb","shortname":":muscle_tone1:","aliases":"","keywords":"flexed biceps tone 1"},"muscle_tone2":{"unicode":"1f4aa-1f3fc","shortname":":muscle_tone2:","aliases":"","keywords":"flexed biceps tone 2"},"muscle_tone3":{"unicode":"1f4aa-1f3fd","shortname":":muscle_tone3:","aliases":"","keywords":"flexed biceps tone 3"},"muscle_tone4":{"unicode":"1f4aa-1f3fe","shortname":":muscle_tone4:","aliases":"","keywords":"flexed biceps tone 4"},"muscle_tone5":{"unicode":"1f4aa-1f3ff","shortname":":muscle_tone5:","aliases":"","keywords":"flexed biceps tone 5"},"pray_tone1":{"unicode":"1f64f-1f3fb","shortname":":pray_tone1:","aliases":"","keywords":"person with folded hands tone 1"},"pray_tone2":{"unicode":"1f64f-1f3fc","shortname":":pray_tone2:","aliases":"","keywords":"person with folded hands tone 2"},"pray_tone3":{"unicode":"1f64f-1f3fd","shortname":":pray_tone3:","aliases":"","keywords":"person with folded hands tone 3"},"pray_tone4":{"unicode":"1f64f-1f3fe","shortname":":pray_tone4:","aliases":"","keywords":"person with folded hands tone 4"},"pray_tone5":{"unicode":"1f64f-1f3ff","shortname":":pray_tone5:","aliases":"","keywords":"person with folded hands tone 5"},"point_up_tone1":{"unicode":"261d-1f3fb","shortname":":point_up_tone1:","aliases":"","keywords":"white up pointing index tone 1"},"point_up_tone2":{"unicode":"261d-1f3fc","shortname":":point_up_tone2:","aliases":"","keywords":"white up pointing index tone 2"},"point_up_tone3":{"unicode":"261d-1f3fd","shortname":":point_up_tone3:","aliases":"","keywords":"white up pointing index tone 3"},"point_up_tone4":{"unicode":"261d-1f3fe","shortname":":point_up_tone4:","aliases":"","keywords":"white up pointing index tone 4"},"point_up_tone5":{"unicode":"261d-1f3ff","shortname":":point_up_tone5:","aliases":"","keywords":"white up pointing index tone 5"},"point_up_2_tone1":{"unicode":"1f446-1f3fb","shortname":":point_up_2_tone1:","aliases":"","keywords":"white up pointing backhand index tone 1"},"point_up_2_tone2":{"unicode":"1f446-1f3fc","shortname":":point_up_2_tone2:","aliases":"","keywords":"white up pointing backhand index tone 2"},"point_up_2_tone3":{"unicode":"1f446-1f3fd","shortname":":point_up_2_tone3:","aliases":"","keywords":"white up pointing backhand index tone 3"},"point_up_2_tone4":{"unicode":"1f446-1f3fe","shortname":":point_up_2_tone4:","aliases":"","keywords":"white up pointing backhand index tone 4"},"point_up_2_tone5":{"unicode":"1f446-1f3ff","shortname":":point_up_2_tone5:","aliases":"","keywords":"white up pointing backhand index tone 5"},"point_down_tone1":{"unicode":"1f447-1f3fb","shortname":":point_down_tone1:","aliases":"","keywords":"white down pointing backhand index tone 1"},"point_down_tone2":{"unicode":"1f447-1f3fc","shortname":":point_down_tone2:","aliases":"","keywords":"white down pointing backhand index tone 2"},"point_down_tone3":{"unicode":"1f447-1f3fd","shortname":":point_down_tone3:","aliases":"","keywords":"white down pointing backhand index tone 3"},"point_down_tone4":{"unicode":"1f447-1f3fe","shortname":":point_down_tone4:","aliases":"","keywords":"white down pointing backhand index tone 4"},"point_down_tone5":{"unicode":"1f447-1f3ff","shortname":":point_down_tone5:","aliases":"","keywords":"white down pointing backhand index tone 5"},"point_left_tone1":{"unicode":"1f448-1f3fb","shortname":":point_left_tone1:","aliases":"","keywords":"white left pointing backhand index tone 1"},"point_left_tone2":{"unicode":"1f448-1f3fc","shortname":":point_left_tone2:","aliases":"","keywords":"white left pointing backhand index tone 2"},"point_left_tone3":{"unicode":"1f448-1f3fd","shortname":":point_left_tone3:","aliases":"","keywords":"white left pointing backhand index tone 3"},"point_left_tone4":{"unicode":"1f448-1f3fe","shortname":":point_left_tone4:","aliases":"","keywords":"white left pointing backhand index tone 4"},"point_left_tone5":{"unicode":"1f448-1f3ff","shortname":":point_left_tone5:","aliases":"","keywords":"white left pointing backhand index tone 5"},"point_right_tone1":{"unicode":"1f449-1f3fb","shortname":":point_right_tone1:","aliases":"","keywords":"white right pointing backhand index tone 1"},"point_right_tone2":{"unicode":"1f449-1f3fc","shortname":":point_right_tone2:","aliases":"","keywords":"white right pointing backhand index tone 2"},"point_right_tone3":{"unicode":"1f449-1f3fd","shortname":":point_right_tone3:","aliases":"","keywords":"white right pointing backhand index tone 3"},"point_right_tone4":{"unicode":"1f449-1f3fe","shortname":":point_right_tone4:","aliases":"","keywords":"white right pointing backhand index tone 4"},"point_right_tone5":{"unicode":"1f449-1f3ff","shortname":":point_right_tone5:","aliases":"","keywords":"white right pointing backhand index tone 5"},"middle_finger_tone1":{"unicode":"1f595-1f3fb","shortname":":middle_finger_tone1:","aliases":":reversed_hand_with_middle_finger_extended_tone1:","keywords":"reversed hand with middle finger extended tone 1"},"middle_finger_tone2":{"unicode":"1f595-1f3fc","shortname":":middle_finger_tone2:","aliases":":reversed_hand_with_middle_finger_extended_tone2:","keywords":"reversed hand with middle finger extended tone 2"},"middle_finger_tone3":{"unicode":"1f595-1f3fd","shortname":":middle_finger_tone3:","aliases":":reversed_hand_with_middle_finger_extended_tone3:","keywords":"reversed hand with middle finger extended tone 3"},"middle_finger_tone4":{"unicode":"1f595-1f3fe","shortname":":middle_finger_tone4:","aliases":":reversed_hand_with_middle_finger_extended_tone4:","keywords":"reversed hand with middle finger extended tone 4"},"middle_finger_tone5":{"unicode":"1f595-1f3ff","shortname":":middle_finger_tone5:","aliases":":reversed_hand_with_middle_finger_extended_tone5:","keywords":"reversed hand with middle finger extended tone 5"},"hand_splayed_tone1":{"unicode":"1f590-1f3fb","shortname":":hand_splayed_tone1:","aliases":":raised_hand_with_fingers_splayed_tone1:","keywords":"raised hand with fingers splayed tone 1"},"hand_splayed_tone2":{"unicode":"1f590-1f3fc","shortname":":hand_splayed_tone2:","aliases":":raised_hand_with_fingers_splayed_tone2:","keywords":"raised hand with fingers splayed tone 2"},"hand_splayed_tone3":{"unicode":"1f590-1f3fd","shortname":":hand_splayed_tone3:","aliases":":raised_hand_with_fingers_splayed_tone3:","keywords":"raised hand with fingers splayed tone 3"},"hand_splayed_tone4":{"unicode":"1f590-1f3fe","shortname":":hand_splayed_tone4:","aliases":":raised_hand_with_fingers_splayed_tone4:","keywords":"raised hand with fingers splayed tone 4"},"hand_splayed_tone5":{"unicode":"1f590-1f3ff","shortname":":hand_splayed_tone5:","aliases":":raised_hand_with_fingers_splayed_tone5:","keywords":"raised hand with fingers splayed tone 5"},"metal_tone1":{"unicode":"1f918-1f3fb","shortname":":metal_tone1:","aliases":":sign_of_the_horns_tone1:","keywords":"sign of the horns tone 1"},"metal_tone2":{"unicode":"1f918-1f3fc","shortname":":metal_tone2:","aliases":":sign_of_the_horns_tone2:","keywords":"sign of the horns tone 2"},"metal_tone3":{"unicode":"1f918-1f3fd","shortname":":metal_tone3:","aliases":":sign_of_the_horns_tone3:","keywords":"sign of the horns tone 3"},"metal_tone4":{"unicode":"1f918-1f3fe","shortname":":metal_tone4:","aliases":":sign_of_the_horns_tone4:","keywords":"sign of the horns tone 4"},"metal_tone5":{"unicode":"1f918-1f3ff","shortname":":metal_tone5:","aliases":":sign_of_the_horns_tone5:","keywords":"sign of the horns tone 5"},"vulcan_tone1":{"unicode":"1f596-1f3fb","shortname":":vulcan_tone1:","aliases":":raised_hand_with_part_between_middle_and_ring_fingers_tone1:","keywords":"raised hand with part between middle and ring fingers tone 1"},"vulcan_tone2":{"unicode":"1f596-1f3fc","shortname":":vulcan_tone2:","aliases":":raised_hand_with_part_between_middle_and_ring_fingers_tone2:","keywords":"raised hand with part between middle and ring fingers tone 2"},"vulcan_tone3":{"unicode":"1f596-1f3fd","shortname":":vulcan_tone3:","aliases":":raised_hand_with_part_between_middle_and_ring_fingers_tone3:","keywords":"raised hand with part between middle and ring fingers tone 3"},"vulcan_tone4":{"unicode":"1f596-1f3fe","shortname":":vulcan_tone4:","aliases":":raised_hand_with_part_between_middle_and_ring_fingers_tone4:","keywords":"raised hand with part between middle and ring fingers tone 4"},"vulcan_tone5":{"unicode":"1f596-1f3ff","shortname":":vulcan_tone5:","aliases":":raised_hand_with_part_between_middle_and_ring_fingers_tone5:","keywords":"raised hand with part between middle and ring fingers tone 5"},"writing_hand_tone1":{"unicode":"270d-1f3fb","shortname":":writing_hand_tone1:","aliases":"","keywords":"writing hand tone 1"},"writing_hand_tone2":{"unicode":"270d-1f3fc","shortname":":writing_hand_tone2:","aliases":"","keywords":"writing hand tone 2"},"writing_hand_tone3":{"unicode":"270d-1f3fd","shortname":":writing_hand_tone3:","aliases":"","keywords":"writing hand tone 3"},"writing_hand_tone4":{"unicode":"270d-1f3fe","shortname":":writing_hand_tone4:","aliases":"","keywords":"writing hand tone 4"},"writing_hand_tone5":{"unicode":"270d-1f3ff","shortname":":writing_hand_tone5:","aliases":"","keywords":"writing hand tone 5"},"nail_care_tone1":{"unicode":"1f485-1f3fb","shortname":":nail_care_tone1:","aliases":"","keywords":"nail polish tone 1"},"nail_care_tone2":{"unicode":"1f485-1f3fc","shortname":":nail_care_tone2:","aliases":"","keywords":"nail polish tone 2"},"nail_care_tone3":{"unicode":"1f485-1f3fd","shortname":":nail_care_tone3:","aliases":"","keywords":"nail polish tone 3"},"nail_care_tone4":{"unicode":"1f485-1f3fe","shortname":":nail_care_tone4:","aliases":"","keywords":"nail polish tone 4"},"nail_care_tone5":{"unicode":"1f485-1f3ff","shortname":":nail_care_tone5:","aliases":"","keywords":"nail polish tone 5"},"ear_tone1":{"unicode":"1f442-1f3fb","shortname":":ear_tone1:","aliases":"","keywords":"ear tone 1"},"ear_tone2":{"unicode":"1f442-1f3fc","shortname":":ear_tone2:","aliases":"","keywords":"ear tone 2"},"ear_tone3":{"unicode":"1f442-1f3fd","shortname":":ear_tone3:","aliases":"","keywords":"ear tone 3"},"ear_tone4":{"unicode":"1f442-1f3fe","shortname":":ear_tone4:","aliases":"","keywords":"ear tone 4"},"ear_tone5":{"unicode":"1f442-1f3ff","shortname":":ear_tone5:","aliases":"","keywords":"ear tone 5"},"nose_tone1":{"unicode":"1f443-1f3fb","shortname":":nose_tone1:","aliases":"","keywords":"nose tone 1"},"nose_tone2":{"unicode":"1f443-1f3fc","shortname":":nose_tone2:","aliases":"","keywords":"nose tone 2"},"nose_tone3":{"unicode":"1f443-1f3fd","shortname":":nose_tone3:","aliases":"","keywords":"nose tone 3"},"nose_tone4":{"unicode":"1f443-1f3fe","shortname":":nose_tone4:","aliases":"","keywords":"nose tone 4"},"nose_tone5":{"unicode":"1f443-1f3ff","shortname":":nose_tone5:","aliases":"","keywords":"nose tone 5"},"baby_tone1":{"unicode":"1f476-1f3fb","shortname":":baby_tone1:","aliases":"","keywords":"baby tone 1"},"baby_tone2":{"unicode":"1f476-1f3fc","shortname":":baby_tone2:","aliases":"","keywords":"baby tone 2"},"baby_tone3":{"unicode":"1f476-1f3fd","shortname":":baby_tone3:","aliases":"","keywords":"baby tone 3"},"baby_tone4":{"unicode":"1f476-1f3fe","shortname":":baby_tone4:","aliases":"","keywords":"baby tone 4"},"baby_tone5":{"unicode":"1f476-1f3ff","shortname":":baby_tone5:","aliases":"","keywords":"baby tone 5"},"boy_tone1":{"unicode":"1f466-1f3fb","shortname":":boy_tone1:","aliases":"","keywords":"boy tone 1"},"boy_tone2":{"unicode":"1f466-1f3fc","shortname":":boy_tone2:","aliases":"","keywords":"boy tone 2"},"boy_tone3":{"unicode":"1f466-1f3fd","shortname":":boy_tone3:","aliases":"","keywords":"boy tone 3"},"boy_tone4":{"unicode":"1f466-1f3fe","shortname":":boy_tone4:","aliases":"","keywords":"boy tone 4"},"boy_tone5":{"unicode":"1f466-1f3ff","shortname":":boy_tone5:","aliases":"","keywords":"boy tone 5"},"girl_tone1":{"unicode":"1f467-1f3fb","shortname":":girl_tone1:","aliases":"","keywords":"girl tone 1"},"girl_tone2":{"unicode":"1f467-1f3fc","shortname":":girl_tone2:","aliases":"","keywords":"girl tone 2"},"girl_tone3":{"unicode":"1f467-1f3fd","shortname":":girl_tone3:","aliases":"","keywords":"girl tone 3"},"girl_tone4":{"unicode":"1f467-1f3fe","shortname":":girl_tone4:","aliases":"","keywords":"girl tone 4"},"girl_tone5":{"unicode":"1f467-1f3ff","shortname":":girl_tone5:","aliases":"","keywords":"girl tone 5"},"man_tone1":{"unicode":"1f468-1f3fb","shortname":":man_tone1:","aliases":"","keywords":"man tone 1"},"man_tone2":{"unicode":"1f468-1f3fc","shortname":":man_tone2:","aliases":"","keywords":"man tone 2"},"man_tone3":{"unicode":"1f468-1f3fd","shortname":":man_tone3:","aliases":"","keywords":"man tone 3"},"man_tone4":{"unicode":"1f468-1f3fe","shortname":":man_tone4:","aliases":"","keywords":"man tone 4"},"man_tone5":{"unicode":"1f468-1f3ff","shortname":":man_tone5:","aliases":"","keywords":"man tone 5"},"woman_tone1":{"unicode":"1f469-1f3fb","shortname":":woman_tone1:","aliases":"","keywords":"woman tone 1"},"woman_tone2":{"unicode":"1f469-1f3fc","shortname":":woman_tone2:","aliases":"","keywords":"woman tone 2"},"woman_tone3":{"unicode":"1f469-1f3fd","shortname":":woman_tone3:","aliases":"","keywords":"woman tone 3"},"woman_tone4":{"unicode":"1f469-1f3fe","shortname":":woman_tone4:","aliases":"","keywords":"woman tone 4"},"woman_tone5":{"unicode":"1f469-1f3ff","shortname":":woman_tone5:","aliases":"","keywords":"woman tone 5"},"person_with_blond_hair_tone1":{"unicode":"1f471-1f3fb","shortname":":person_with_blond_hair_tone1:","aliases":"","keywords":"person with blond hair tone 1"},"person_with_blond_hair_tone2":{"unicode":"1f471-1f3fc","shortname":":person_with_blond_hair_tone2:","aliases":"","keywords":"person with blond hair tone 2"},"person_with_blond_hair_tone3":{"unicode":"1f471-1f3fd","shortname":":person_with_blond_hair_tone3:","aliases":"","keywords":"person with blond hair tone 3"},"person_with_blond_hair_tone4":{"unicode":"1f471-1f3fe","shortname":":person_with_blond_hair_tone4:","aliases":"","keywords":"person with blond hair tone 4"},"person_with_blond_hair_tone5":{"unicode":"1f471-1f3ff","shortname":":person_with_blond_hair_tone5:","aliases":"","keywords":"person with blond hair tone 5"},"older_man_tone1":{"unicode":"1f474-1f3fb","shortname":":older_man_tone1:","aliases":"","keywords":"older man tone 1"},"older_man_tone2":{"unicode":"1f474-1f3fc","shortname":":older_man_tone2:","aliases":"","keywords":"older man tone 2"},"older_man_tone3":{"unicode":"1f474-1f3fd","shortname":":older_man_tone3:","aliases":"","keywords":"older man tone 3"},"older_man_tone4":{"unicode":"1f474-1f3fe","shortname":":older_man_tone4:","aliases":"","keywords":"older man tone 4"},"older_man_tone5":{"unicode":"1f474-1f3ff","shortname":":older_man_tone5:","aliases":"","keywords":"older man tone 5"},"older_woman_tone1":{"unicode":"1f475-1f3fb","shortname":":older_woman_tone1:","aliases":":grandma_tone1:","keywords":"older woman tone 1"},"older_woman_tone2":{"unicode":"1f475-1f3fc","shortname":":older_woman_tone2:","aliases":":grandma_tone2:","keywords":"older woman tone 2"},"older_woman_tone3":{"unicode":"1f475-1f3fd","shortname":":older_woman_tone3:","aliases":":grandma_tone3:","keywords":"older woman tone 3"},"older_woman_tone4":{"unicode":"1f475-1f3fe","shortname":":older_woman_tone4:","aliases":":grandma_tone4:","keywords":"older woman tone 4"},"older_woman_tone5":{"unicode":"1f475-1f3ff","shortname":":older_woman_tone5:","aliases":":grandma_tone5:","keywords":"older woman tone 5"},"man_with_gua_pi_mao_tone1":{"unicode":"1f472-1f3fb","shortname":":man_with_gua_pi_mao_tone1:","aliases":"","keywords":"man with gua pi mao tone 1"},"man_with_gua_pi_mao_tone2":{"unicode":"1f472-1f3fc","shortname":":man_with_gua_pi_mao_tone2:","aliases":"","keywords":"man with gua pi mao tone 2"},"man_with_gua_pi_mao_tone3":{"unicode":"1f472-1f3fd","shortname":":man_with_gua_pi_mao_tone3:","aliases":"","keywords":"man with gua pi mao tone 3"},"man_with_gua_pi_mao_tone4":{"unicode":"1f472-1f3fe","shortname":":man_with_gua_pi_mao_tone4:","aliases":"","keywords":"man with gua pi mao tone 4"},"man_with_gua_pi_mao_tone5":{"unicode":"1f472-1f3ff","shortname":":man_with_gua_pi_mao_tone5:","aliases":"","keywords":"man with gua pi mao tone 5"},"man_with_turban_tone1":{"unicode":"1f473-1f3fb","shortname":":man_with_turban_tone1:","aliases":"","keywords":"man with turban tone 1"},"man_with_turban_tone2":{"unicode":"1f473-1f3fc","shortname":":man_with_turban_tone2:","aliases":"","keywords":"man with turban tone 2"},"man_with_turban_tone3":{"unicode":"1f473-1f3fd","shortname":":man_with_turban_tone3:","aliases":"","keywords":"man with turban tone 3"},"man_with_turban_tone4":{"unicode":"1f473-1f3fe","shortname":":man_with_turban_tone4:","aliases":"","keywords":"man with turban tone 4"},"man_with_turban_tone5":{"unicode":"1f473-1f3ff","shortname":":man_with_turban_tone5:","aliases":"","keywords":"man with turban tone 5"},"cop_tone1":{"unicode":"1f46e-1f3fb","shortname":":cop_tone1:","aliases":"","keywords":"police officer tone 1"},"cop_tone2":{"unicode":"1f46e-1f3fc","shortname":":cop_tone2:","aliases":"","keywords":"police officer tone 2"},"cop_tone3":{"unicode":"1f46e-1f3fd","shortname":":cop_tone3:","aliases":"","keywords":"police officer tone 3"},"cop_tone4":{"unicode":"1f46e-1f3fe","shortname":":cop_tone4:","aliases":"","keywords":"police officer tone 4"},"cop_tone5":{"unicode":"1f46e-1f3ff","shortname":":cop_tone5:","aliases":"","keywords":"police officer tone 5"},"construction_worker_tone1":{"unicode":"1f477-1f3fb","shortname":":construction_worker_tone1:","aliases":"","keywords":"construction worker tone 1"},"construction_worker_tone2":{"unicode":"1f477-1f3fc","shortname":":construction_worker_tone2:","aliases":"","keywords":"construction worker tone 2"},"construction_worker_tone3":{"unicode":"1f477-1f3fd","shortname":":construction_worker_tone3:","aliases":"","keywords":"construction worker tone 3"},"construction_worker_tone4":{"unicode":"1f477-1f3fe","shortname":":construction_worker_tone4:","aliases":"","keywords":"construction worker tone 4"},"construction_worker_tone5":{"unicode":"1f477-1f3ff","shortname":":construction_worker_tone5:","aliases":"","keywords":"construction worker tone 5"},"guardsman_tone1":{"unicode":"1f482-1f3fb","shortname":":guardsman_tone1:","aliases":"","keywords":"guardsman tone 1"},"guardsman_tone2":{"unicode":"1f482-1f3fc","shortname":":guardsman_tone2:","aliases":"","keywords":"guardsman tone 2"},"guardsman_tone3":{"unicode":"1f482-1f3fd","shortname":":guardsman_tone3:","aliases":"","keywords":"guardsman tone 3"},"guardsman_tone4":{"unicode":"1f482-1f3fe","shortname":":guardsman_tone4:","aliases":"","keywords":"guardsman tone 4"},"guardsman_tone5":{"unicode":"1f482-1f3ff","shortname":":guardsman_tone5:","aliases":"","keywords":"guardsman tone 5"},"santa_tone1":{"unicode":"1f385-1f3fb","shortname":":santa_tone1:","aliases":"","keywords":"father christmas tone 1"},"santa_tone2":{"unicode":"1f385-1f3fc","shortname":":santa_tone2:","aliases":"","keywords":"father christmas tone 2"},"santa_tone3":{"unicode":"1f385-1f3fd","shortname":":santa_tone3:","aliases":"","keywords":"father christmas tone 3"},"santa_tone4":{"unicode":"1f385-1f3fe","shortname":":santa_tone4:","aliases":"","keywords":"father christmas tone 4"},"santa_tone5":{"unicode":"1f385-1f3ff","shortname":":santa_tone5:","aliases":"","keywords":"father christmas tone 5"},"angel_tone1":{"unicode":"1f47c-1f3fb","shortname":":angel_tone1:","aliases":"","keywords":"baby angel tone 1"},"angel_tone2":{"unicode":"1f47c-1f3fc","shortname":":angel_tone2:","aliases":"","keywords":"baby angel tone 2"},"angel_tone3":{"unicode":"1f47c-1f3fd","shortname":":angel_tone3:","aliases":"","keywords":"baby angel tone 3"},"angel_tone4":{"unicode":"1f47c-1f3fe","shortname":":angel_tone4:","aliases":"","keywords":"baby angel tone 4"},"angel_tone5":{"unicode":"1f47c-1f3ff","shortname":":angel_tone5:","aliases":"","keywords":"baby angel tone 5"},"princess_tone1":{"unicode":"1f478-1f3fb","shortname":":princess_tone1:","aliases":"","keywords":"princess tone 1"},"princess_tone2":{"unicode":"1f478-1f3fc","shortname":":princess_tone2:","aliases":"","keywords":"princess tone 2"},"princess_tone3":{"unicode":"1f478-1f3fd","shortname":":princess_tone3:","aliases":"","keywords":"princess tone 3"},"princess_tone4":{"unicode":"1f478-1f3fe","shortname":":princess_tone4:","aliases":"","keywords":"princess tone 4"},"princess_tone5":{"unicode":"1f478-1f3ff","shortname":":princess_tone5:","aliases":"","keywords":"princess tone 5"},"bride_with_veil_tone1":{"unicode":"1f470-1f3fb","shortname":":bride_with_veil_tone1:","aliases":"","keywords":"bride with veil tone 1"},"bride_with_veil_tone2":{"unicode":"1f470-1f3fc","shortname":":bride_with_veil_tone2:","aliases":"","keywords":"bride with veil tone 2"},"bride_with_veil_tone3":{"unicode":"1f470-1f3fd","shortname":":bride_with_veil_tone3:","aliases":"","keywords":"bride with veil tone 3"},"bride_with_veil_tone4":{"unicode":"1f470-1f3fe","shortname":":bride_with_veil_tone4:","aliases":"","keywords":"bride with veil tone 4"},"bride_with_veil_tone5":{"unicode":"1f470-1f3ff","shortname":":bride_with_veil_tone5:","aliases":"","keywords":"bride with veil tone 5"},"walking_tone1":{"unicode":"1f6b6-1f3fb","shortname":":walking_tone1:","aliases":"","keywords":"pedestrian tone 1"},"walking_tone2":{"unicode":"1f6b6-1f3fc","shortname":":walking_tone2:","aliases":"","keywords":"pedestrian tone 2"},"walking_tone3":{"unicode":"1f6b6-1f3fd","shortname":":walking_tone3:","aliases":"","keywords":"pedestrian tone 3"},"walking_tone4":{"unicode":"1f6b6-1f3fe","shortname":":walking_tone4:","aliases":"","keywords":"pedestrian tone 4"},"walking_tone5":{"unicode":"1f6b6-1f3ff","shortname":":walking_tone5:","aliases":"","keywords":"pedestrian tone 5"},"runner_tone1":{"unicode":"1f3c3-1f3fb","shortname":":runner_tone1:","aliases":"","keywords":"runner tone 1"},"runner_tone2":{"unicode":"1f3c3-1f3fc","shortname":":runner_tone2:","aliases":"","keywords":"runner tone 2"},"runner_tone3":{"unicode":"1f3c3-1f3fd","shortname":":runner_tone3:","aliases":"","keywords":"runner tone 3"},"runner_tone4":{"unicode":"1f3c3-1f3fe","shortname":":runner_tone4:","aliases":"","keywords":"runner tone 4"},"runner_tone5":{"unicode":"1f3c3-1f3ff","shortname":":runner_tone5:","aliases":"","keywords":"runner tone 5"},"dancer_tone1":{"unicode":"1f483-1f3fb","shortname":":dancer_tone1:","aliases":"","keywords":"dancer tone 1"},"dancer_tone2":{"unicode":"1f483-1f3fc","shortname":":dancer_tone2:","aliases":"","keywords":"dancer tone 2"},"dancer_tone3":{"unicode":"1f483-1f3fd","shortname":":dancer_tone3:","aliases":"","keywords":"dancer tone 3"},"dancer_tone4":{"unicode":"1f483-1f3fe","shortname":":dancer_tone4:","aliases":"","keywords":"dancer tone 4"},"dancer_tone5":{"unicode":"1f483-1f3ff","shortname":":dancer_tone5:","aliases":"","keywords":"dancer tone 5"},"bow_tone1":{"unicode":"1f647-1f3fb","shortname":":bow_tone1:","aliases":"","keywords":"person bowing deeply tone 1"},"bow_tone2":{"unicode":"1f647-1f3fc","shortname":":bow_tone2:","aliases":"","keywords":"person bowing deeply tone 2"},"bow_tone3":{"unicode":"1f647-1f3fd","shortname":":bow_tone3:","aliases":"","keywords":"person bowing deeply tone 3"},"bow_tone4":{"unicode":"1f647-1f3fe","shortname":":bow_tone4:","aliases":"","keywords":"person bowing deeply tone 4"},"bow_tone5":{"unicode":"1f647-1f3ff","shortname":":bow_tone5:","aliases":"","keywords":"person bowing deeply tone 5"},"information_desk_person_tone1":{"unicode":"1f481-1f3fb","shortname":":information_desk_person_tone1:","aliases":"","keywords":"information desk person tone 1"},"information_desk_person_tone2":{"unicode":"1f481-1f3fc","shortname":":information_desk_person_tone2:","aliases":"","keywords":"information desk person tone 2"},"information_desk_person_tone3":{"unicode":"1f481-1f3fd","shortname":":information_desk_person_tone3:","aliases":"","keywords":"information desk person tone 3"},"information_desk_person_tone4":{"unicode":"1f481-1f3fe","shortname":":information_desk_person_tone4:","aliases":"","keywords":"information desk person tone 4"},"information_desk_person_tone5":{"unicode":"1f481-1f3ff","shortname":":information_desk_person_tone5:","aliases":"","keywords":"information desk person tone 5"},"no_good_tone1":{"unicode":"1f645-1f3fb","shortname":":no_good_tone1:","aliases":"","keywords":"face with no good gesture tone 1"},"no_good_tone2":{"unicode":"1f645-1f3fc","shortname":":no_good_tone2:","aliases":"","keywords":"face with no good gesture tone 2"},"no_good_tone3":{"unicode":"1f645-1f3fd","shortname":":no_good_tone3:","aliases":"","keywords":"face with no good gesture tone 3"},"no_good_tone4":{"unicode":"1f645-1f3fe","shortname":":no_good_tone4:","aliases":"","keywords":"face with no good gesture tone 4"},"no_good_tone5":{"unicode":"1f645-1f3ff","shortname":":no_good_tone5:","aliases":"","keywords":"face with no good gesture tone 5"},"ok_woman_tone1":{"unicode":"1f646-1f3fb","shortname":":ok_woman_tone1:","aliases":"","keywords":"face with ok gesture tone1"},"ok_woman_tone2":{"unicode":"1f646-1f3fc","shortname":":ok_woman_tone2:","aliases":"","keywords":"face with ok gesture tone2"},"ok_woman_tone3":{"unicode":"1f646-1f3fd","shortname":":ok_woman_tone3:","aliases":"","keywords":"face with ok gesture tone3"},"ok_woman_tone4":{"unicode":"1f646-1f3fe","shortname":":ok_woman_tone4:","aliases":"","keywords":"face with ok gesture tone4"},"ok_woman_tone5":{"unicode":"1f646-1f3ff","shortname":":ok_woman_tone5:","aliases":"","keywords":"face with ok gesture tone5"},"raising_hand_tone1":{"unicode":"1f64b-1f3fb","shortname":":raising_hand_tone1:","aliases":"","keywords":"happy person raising one hand tone1"},"raising_hand_tone2":{"unicode":"1f64b-1f3fc","shortname":":raising_hand_tone2:","aliases":"","keywords":"happy person raising one hand tone2"},"raising_hand_tone3":{"unicode":"1f64b-1f3fd","shortname":":raising_hand_tone3:","aliases":"","keywords":"happy person raising one hand tone3"},"raising_hand_tone4":{"unicode":"1f64b-1f3fe","shortname":":raising_hand_tone4:","aliases":"","keywords":"happy person raising one hand tone4"},"raising_hand_tone5":{"unicode":"1f64b-1f3ff","shortname":":raising_hand_tone5:","aliases":"","keywords":"happy person raising one hand tone5"},"person_with_pouting_face_tone1":{"unicode":"1f64e-1f3fb","shortname":":person_with_pouting_face_tone1:","aliases":"","keywords":"person with pouting face tone1"},"person_with_pouting_face_tone2":{"unicode":"1f64e-1f3fc","shortname":":person_with_pouting_face_tone2:","aliases":"","keywords":"person with pouting face tone2"},"person_with_pouting_face_tone3":{"unicode":"1f64e-1f3fd","shortname":":person_with_pouting_face_tone3:","aliases":"","keywords":"person with pouting face tone3"},"person_with_pouting_face_tone4":{"unicode":"1f64e-1f3fe","shortname":":person_with_pouting_face_tone4:","aliases":"","keywords":"person with pouting face tone4"},"person_with_pouting_face_tone5":{"unicode":"1f64e-1f3ff","shortname":":person_with_pouting_face_tone5:","aliases":"","keywords":"person with pouting face tone5"},"person_frowning_tone1":{"unicode":"1f64d-1f3fb","shortname":":person_frowning_tone1:","aliases":"","keywords":"person frowning tone 1"},"person_frowning_tone2":{"unicode":"1f64d-1f3fc","shortname":":person_frowning_tone2:","aliases":"","keywords":"person frowning tone 2"},"person_frowning_tone3":{"unicode":"1f64d-1f3fd","shortname":":person_frowning_tone3:","aliases":"","keywords":"person frowning tone 3"},"person_frowning_tone4":{"unicode":"1f64d-1f3fe","shortname":":person_frowning_tone4:","aliases":"","keywords":"person frowning tone 4"},"person_frowning_tone5":{"unicode":"1f64d-1f3ff","shortname":":person_frowning_tone5:","aliases":"","keywords":"person frowning tone 5"},"haircut_tone1":{"unicode":"1f487-1f3fb","shortname":":haircut_tone1:","aliases":"","keywords":"haircut tone 1"},"haircut_tone2":{"unicode":"1f487-1f3fc","shortname":":haircut_tone2:","aliases":"","keywords":"haircut tone 2"},"haircut_tone3":{"unicode":"1f487-1f3fd","shortname":":haircut_tone3:","aliases":"","keywords":"haircut tone 3"},"haircut_tone4":{"unicode":"1f487-1f3fe","shortname":":haircut_tone4:","aliases":"","keywords":"haircut tone 4"},"haircut_tone5":{"unicode":"1f487-1f3ff","shortname":":haircut_tone5:","aliases":"","keywords":"haircut tone 5"},"massage_tone1":{"unicode":"1f486-1f3fb","shortname":":massage_tone1:","aliases":"","keywords":"face massage tone 1"},"massage_tone2":{"unicode":"1f486-1f3fc","shortname":":massage_tone2:","aliases":"","keywords":"face massage tone 2"},"massage_tone3":{"unicode":"1f486-1f3fd","shortname":":massage_tone3:","aliases":"","keywords":"face massage tone 3"},"massage_tone4":{"unicode":"1f486-1f3fe","shortname":":massage_tone4:","aliases":"","keywords":"face massage tone 4"},"massage_tone5":{"unicode":"1f486-1f3ff","shortname":":massage_tone5:","aliases":"","keywords":"face massage tone 5"},"rowboat_tone1":{"unicode":"1f6a3-1f3fb","shortname":":rowboat_tone1:","aliases":"","keywords":"rowboat tone 1"},"rowboat_tone2":{"unicode":"1f6a3-1f3fc","shortname":":rowboat_tone2:","aliases":"","keywords":"rowboat tone 2"},"rowboat_tone3":{"unicode":"1f6a3-1f3fd","shortname":":rowboat_tone3:","aliases":"","keywords":"rowboat tone 3"},"rowboat_tone4":{"unicode":"1f6a3-1f3fe","shortname":":rowboat_tone4:","aliases":"","keywords":"rowboat tone 4"},"rowboat_tone5":{"unicode":"1f6a3-1f3ff","shortname":":rowboat_tone5:","aliases":"","keywords":"rowboat tone 5"},"swimmer_tone1":{"unicode":"1f3ca-1f3fb","shortname":":swimmer_tone1:","aliases":"","keywords":"swimmer tone 1"},"swimmer_tone2":{"unicode":"1f3ca-1f3fc","shortname":":swimmer_tone2:","aliases":"","keywords":"swimmer tone 2"},"swimmer_tone3":{"unicode":"1f3ca-1f3fd","shortname":":swimmer_tone3:","aliases":"","keywords":"swimmer tone 3"},"swimmer_tone4":{"unicode":"1f3ca-1f3fe","shortname":":swimmer_tone4:","aliases":"","keywords":"swimmer tone 4"},"swimmer_tone5":{"unicode":"1f3ca-1f3ff","shortname":":swimmer_tone5:","aliases":"","keywords":"swimmer tone 5"},"surfer_tone1":{"unicode":"1f3c4-1f3fb","shortname":":surfer_tone1:","aliases":"","keywords":"surfer tone 1"},"surfer_tone2":{"unicode":"1f3c4-1f3fc","shortname":":surfer_tone2:","aliases":"","keywords":"surfer tone 2"},"surfer_tone3":{"unicode":"1f3c4-1f3fd","shortname":":surfer_tone3:","aliases":"","keywords":"surfer tone 3"},"surfer_tone4":{"unicode":"1f3c4-1f3fe","shortname":":surfer_tone4:","aliases":"","keywords":"surfer tone 4"},"surfer_tone5":{"unicode":"1f3c4-1f3ff","shortname":":surfer_tone5:","aliases":"","keywords":"surfer tone 5"},"bath_tone1":{"unicode":"1f6c0-1f3fb","shortname":":bath_tone1:","aliases":"","keywords":"bath tone 1"},"bath_tone2":{"unicode":"1f6c0-1f3fc","shortname":":bath_tone2:","aliases":"","keywords":"bath tone 2"},"bath_tone3":{"unicode":"1f6c0-1f3fd","shortname":":bath_tone3:","aliases":"","keywords":"bath tone 3"},"bath_tone4":{"unicode":"1f6c0-1f3fe","shortname":":bath_tone4:","aliases":"","keywords":"bath tone 4"},"bath_tone5":{"unicode":"1f6c0-1f3ff","shortname":":bath_tone5:","aliases":"","keywords":"bath tone 5"},"basketball_player_tone1":{"unicode":"26f9-1f3fb","shortname":":basketball_player_tone1:","aliases":":person_with_ball_tone1:","keywords":"person with ball tone 1"},"basketball_player_tone2":{"unicode":"26f9-1f3fc","shortname":":basketball_player_tone2:","aliases":":person_with_ball_tone2:","keywords":"person with ball tone 2"},"basketball_player_tone3":{"unicode":"26f9-1f3fd","shortname":":basketball_player_tone3:","aliases":":person_with_ball_tone3:","keywords":"person with ball tone 3"},"basketball_player_tone4":{"unicode":"26f9-1f3fe","shortname":":basketball_player_tone4:","aliases":":person_with_ball_tone4:","keywords":"person with ball tone 4"},"basketball_player_tone5":{"unicode":"26f9-1f3ff","shortname":":basketball_player_tone5:","aliases":":person_with_ball_tone5:","keywords":"person with ball tone 5"},"lifter_tone1":{"unicode":"1f3cb-1f3fb","shortname":":lifter_tone1:","aliases":":weight_lifter_tone1:","keywords":"weight lifter tone 1"},"lifter_tone2":{"unicode":"1f3cb-1f3fc","shortname":":lifter_tone2:","aliases":":weight_lifter_tone2:","keywords":"weight lifter tone 2"},"lifter_tone3":{"unicode":"1f3cb-1f3fd","shortname":":lifter_tone3:","aliases":":weight_lifter_tone3:","keywords":"weight lifter tone 3"},"lifter_tone4":{"unicode":"1f3cb-1f3fe","shortname":":lifter_tone4:","aliases":":weight_lifter_tone4:","keywords":"weight lifter tone 4"},"lifter_tone5":{"unicode":"1f3cb-1f3ff","shortname":":lifter_tone5:","aliases":":weight_lifter_tone5:","keywords":"weight lifter tone 5"},"bicyclist_tone1":{"unicode":"1f6b4-1f3fb","shortname":":bicyclist_tone1:","aliases":"","keywords":"bicyclist tone 1"},"bicyclist_tone2":{"unicode":"1f6b4-1f3fc","shortname":":bicyclist_tone2:","aliases":"","keywords":"bicyclist tone 2"},"bicyclist_tone3":{"unicode":"1f6b4-1f3fd","shortname":":bicyclist_tone3:","aliases":"","keywords":"bicyclist tone 3"},"bicyclist_tone4":{"unicode":"1f6b4-1f3fe","shortname":":bicyclist_tone4:","aliases":"","keywords":"bicyclist tone 4"},"bicyclist_tone5":{"unicode":"1f6b4-1f3ff","shortname":":bicyclist_tone5:","aliases":"","keywords":"bicyclist tone 5"},"mountain_bicyclist_tone1":{"unicode":"1f6b5-1f3fb","shortname":":mountain_bicyclist_tone1:","aliases":"","keywords":"mountain bicyclist tone 1"},"mountain_bicyclist_tone2":{"unicode":"1f6b5-1f3fc","shortname":":mountain_bicyclist_tone2:","aliases":"","keywords":"mountain bicyclist tone 2"},"mountain_bicyclist_tone3":{"unicode":"1f6b5-1f3fd","shortname":":mountain_bicyclist_tone3:","aliases":"","keywords":"mountain bicyclist tone 3"},"mountain_bicyclist_tone4":{"unicode":"1f6b5-1f3fe","shortname":":mountain_bicyclist_tone4:","aliases":"","keywords":"mountain bicyclist tone 4"},"mountain_bicyclist_tone5":{"unicode":"1f6b5-1f3ff","shortname":":mountain_bicyclist_tone5:","aliases":"","keywords":"mountain bicyclist tone 5"},"horse_racing_tone1":{"unicode":"1f3c7-1f3fb","shortname":":horse_racing_tone1:","aliases":"","keywords":"horse racing tone 1"},"horse_racing_tone2":{"unicode":"1f3c7-1f3fc","shortname":":horse_racing_tone2:","aliases":"","keywords":"horse racing tone 2"},"horse_racing_tone3":{"unicode":"1f3c7-1f3fd","shortname":":horse_racing_tone3:","aliases":"","keywords":"horse racing tone 3"},"horse_racing_tone4":{"unicode":"1f3c7-1f3fe","shortname":":horse_racing_tone4:","aliases":"","keywords":"horse racing tone 4"},"horse_racing_tone5":{"unicode":"1f3c7-1f3ff","shortname":":horse_racing_tone5:","aliases":"","keywords":"horse racing tone 5"},"spy_tone1":{"unicode":"1f575-1f3fb","shortname":":spy_tone1:","aliases":":sleuth_or_spy_tone1:","keywords":"sleuth or spy tone 1"},"spy_tone2":{"unicode":"1f575-1f3fc","shortname":":spy_tone2:","aliases":":sleuth_or_spy_tone2:","keywords":"sleuth or spy tone 2"},"spy_tone3":{"unicode":"1f575-1f3fd","shortname":":spy_tone3:","aliases":":sleuth_or_spy_tone3:","keywords":"sleuth or spy tone 3"},"spy_tone4":{"unicode":"1f575-1f3fe","shortname":":spy_tone4:","aliases":":sleuth_or_spy_tone4:","keywords":"sleuth or spy tone 4"},"spy_tone5":{"unicode":"1f575-1f3ff","shortname":":spy_tone5:","aliases":":sleuth_or_spy_tone5:","keywords":"sleuth or spy tone 5"},"tone1":{"unicode":"1f3fb","shortname":":tone1:","aliases":"","keywords":"emoji modifier Fitzpatrick type-1-2"},"tone2":{"unicode":"1f3fc","shortname":":tone2:","aliases":"","keywords":"emoji modifier Fitzpatrick type-3"},"tone3":{"unicode":"1f3fd","shortname":":tone3:","aliases":"","keywords":"emoji modifier Fitzpatrick type-4"},"tone4":{"unicode":"1f3fe","shortname":":tone4:","aliases":"","keywords":"emoji modifier Fitzpatrick type-5"},"tone5":{"unicode":"1f3ff","shortname":":tone5:","aliases":"","keywords":"emoji modifier Fitzpatrick type-6"},"prince_tone1":{"unicode":"1f934-1f3fb","shortname":":prince_tone1:","aliases":"","keywords":"prince tone 1"},"prince_tone2":{"unicode":"1f934-1f3fc","shortname":":prince_tone2:","aliases":"","keywords":"prince tone 2"},"prince_tone3":{"unicode":"1f934-1f3fd","shortname":":prince_tone3:","aliases":"","keywords":"prince tone 3"},"prince_tone4":{"unicode":"1f934-1f3fe","shortname":":prince_tone4:","aliases":"","keywords":"prince tone 4"},"prince_tone5":{"unicode":"1f934-1f3ff","shortname":":prince_tone5:","aliases":"","keywords":"prince tone 5"},"mrs_claus_tone1":{"unicode":"1f936-1f3fb","shortname":":mrs_claus_tone1:","aliases":":mother_christmas_tone1:","keywords":"mother christmas tone 1"},"mrs_claus_tone2":{"unicode":"1f936-1f3fc","shortname":":mrs_claus_tone2:","aliases":":mother_christmas_tone2:","keywords":"mother christmas tone 2"},"mrs_claus_tone3":{"unicode":"1f936-1f3fd","shortname":":mrs_claus_tone3:","aliases":":mother_christmas_tone3:","keywords":"mother christmas tone 3"},"mrs_claus_tone4":{"unicode":"1f936-1f3fe","shortname":":mrs_claus_tone4:","aliases":":mother_christmas_tone4:","keywords":"mother christmas tone 4"},"mrs_claus_tone5":{"unicode":"1f936-1f3ff","shortname":":mrs_claus_tone5:","aliases":":mother_christmas_tone5:","keywords":"mother christmas tone 5"},"man_in_tuxedo_tone1":{"unicode":"1f935-1f3fb","shortname":":man_in_tuxedo_tone1:","aliases":":tuxedo_tone1:","keywords":"man in tuxedo tone 1"},"man_in_tuxedo_tone2":{"unicode":"1f935-1f3fc","shortname":":man_in_tuxedo_tone2:","aliases":":tuxedo_tone2:","keywords":"man in tuxedo tone 2"},"man_in_tuxedo_tone3":{"unicode":"1f935-1f3fd","shortname":":man_in_tuxedo_tone3:","aliases":":tuxedo_tone3:","keywords":"man in tuxedo tone 3"},"man_in_tuxedo_tone4":{"unicode":"1f935-1f3fe","shortname":":man_in_tuxedo_tone4:","aliases":":tuxedo_tone4:","keywords":"man in tuxedo tone 4"},"man_in_tuxedo_tone5":{"unicode":"1f935-1f3ff","shortname":":man_in_tuxedo_tone5:","aliases":":tuxedo_tone5:","keywords":"man in tuxedo tone 5"},"shrug_tone1":{"unicode":"1f937-1f3fb","shortname":":shrug_tone1:","aliases":"","keywords":"shrug tone 1"},"shrug_tone2":{"unicode":"1f937-1f3fc","shortname":":shrug_tone2:","aliases":"","keywords":"shrug tone 2"},"shrug_tone3":{"unicode":"1f937-1f3fd","shortname":":shrug_tone3:","aliases":"","keywords":"shrug tone 3"},"shrug_tone4":{"unicode":"1f937-1f3fe","shortname":":shrug_tone4:","aliases":"","keywords":"shrug tone 4"},"shrug_tone5":{"unicode":"1f937-1f3ff","shortname":":shrug_tone5:","aliases":"","keywords":"shrug tone 5"},"face_palm_tone1":{"unicode":"1f926-1f3fb","shortname":":face_palm_tone1:","aliases":":facepalm_tone1:","keywords":"face palm tone 1"},"face_palm_tone2":{"unicode":"1f926-1f3fc","shortname":":face_palm_tone2:","aliases":":facepalm_tone2:","keywords":"face palm tone 2"},"face_palm_tone3":{"unicode":"1f926-1f3fd","shortname":":face_palm_tone3:","aliases":":facepalm_tone3:","keywords":"face palm tone 3"},"face_palm_tone4":{"unicode":"1f926-1f3fe","shortname":":face_palm_tone4:","aliases":":facepalm_tone4:","keywords":"face palm tone 4"},"face_palm_tone5":{"unicode":"1f926-1f3ff","shortname":":face_palm_tone5:","aliases":":facepalm_tone5:","keywords":"face palm tone 5"},"pregnant_woman_tone1":{"unicode":"1f930-1f3fb","shortname":":pregnant_woman_tone1:","aliases":":expecting_woman_tone1:","keywords":"pregnant woman tone 1"},"pregnant_woman_tone2":{"unicode":"1f930-1f3fc","shortname":":pregnant_woman_tone2:","aliases":":expecting_woman_tone2:","keywords":"pregnant woman tone 2"},"pregnant_woman_tone3":{"unicode":"1f930-1f3fd","shortname":":pregnant_woman_tone3:","aliases":":expecting_woman_tone3:","keywords":"pregnant woman tone 3"},"pregnant_woman_tone4":{"unicode":"1f930-1f3fe","shortname":":pregnant_woman_tone4:","aliases":":expecting_woman_tone4:","keywords":"pregnant woman tone 4"},"pregnant_woman_tone5":{"unicode":"1f930-1f3ff","shortname":":pregnant_woman_tone5:","aliases":":expecting_woman_tone5:","keywords":"pregnant woman tone 5"},"man_dancing_tone1":{"unicode":"1f57a-1f3fb","shortname":":man_dancing_tone1:","aliases":":male_dancer_tone1:","keywords":"man dancing tone 1"},"man_dancing_tone2":{"unicode":"1f57a-1f3fc","shortname":":man_dancing_tone2:","aliases":":male_dancer_tone2:","keywords":"man dancing tone 2"},"man_dancing_tone3":{"unicode":"1f57a-1f3fd","shortname":":man_dancing_tone3:","aliases":":male_dancer_tone3:","keywords":"man dancing tone 3"},"man_dancing_tone4":{"unicode":"1f57a-1f3fe","shortname":":man_dancing_tone4:","aliases":":male_dancer_tone4:","keywords":"man dancing tone 4"},"man_dancing_tone5":{"unicode":"1f57a-1f3ff","shortname":":man_dancing_tone5:","aliases":":male_dancer_tone5:","keywords":"man dancing tone 5"},"selfie_tone1":{"unicode":"1f933-1f3fb","shortname":":selfie_tone1:","aliases":"","keywords":"selfie tone 1"},"selfie_tone2":{"unicode":"1f933-1f3fc","shortname":":selfie_tone2:","aliases":"","keywords":"selfie tone 2"},"selfie_tone3":{"unicode":"1f933-1f3fd","shortname":":selfie_tone3:","aliases":"","keywords":"selfie tone 3"},"selfie_tone4":{"unicode":"1f933-1f3fe","shortname":":selfie_tone4:","aliases":"","keywords":"selfie tone 4"},"selfie_tone5":{"unicode":"1f933-1f3ff","shortname":":selfie_tone5:","aliases":"","keywords":"selfie tone 5"},"fingers_crossed_tone1":{"unicode":"1f91e-1f3fb","shortname":":fingers_crossed_tone1:","aliases":":hand_with_index_and_middle_fingers_crossed_tone1:","keywords":"hand with index and middle fingers crossed tone 1"},"fingers_crossed_tone2":{"unicode":"1f91e-1f3fc","shortname":":fingers_crossed_tone2:","aliases":":hand_with_index_and_middle_fingers_crossed_tone2:","keywords":"hand with index and middle fingers crossed tone 2"},"fingers_crossed_tone3":{"unicode":"1f91e-1f3fd","shortname":":fingers_crossed_tone3:","aliases":":hand_with_index_and_middle_fingers_crossed_tone3:","keywords":"hand with index and middle fingers crossed tone 3"},"fingers_crossed_tone4":{"unicode":"1f91e-1f3fe","shortname":":fingers_crossed_tone4:","aliases":":hand_with_index_and_middle_fingers_crossed_tone4:","keywords":"hand with index and middle fingers crossed tone 4"},"fingers_crossed_tone5":{"unicode":"1f91e-1f3ff","shortname":":fingers_crossed_tone5:","aliases":":hand_with_index_and_middle_fingers_crossed_tone5:","keywords":"hand with index and middle fingers crossed tone 5"},"call_me_tone1":{"unicode":"1f919-1f3fb","shortname":":call_me_tone1:","aliases":":call_me_hand_tone1:","keywords":"call me hand tone 1"},"call_me_tone2":{"unicode":"1f919-1f3fc","shortname":":call_me_tone2:","aliases":":call_me_hand_tone2:","keywords":"call me hand tone 2"},"call_me_tone3":{"unicode":"1f919-1f3fd","shortname":":call_me_tone3:","aliases":":call_me_hand_tone3:","keywords":"call me hand tone 3"},"call_me_tone4":{"unicode":"1f919-1f3fe","shortname":":call_me_tone4:","aliases":":call_me_hand_tone4:","keywords":"call me hand tone 4"},"call_me_tone5":{"unicode":"1f919-1f3ff","shortname":":call_me_tone5:","aliases":":call_me_hand_tone5:","keywords":"call me hand tone 5"},"left_facing_fist_tone1":{"unicode":"1f91b-1f3fb","shortname":":left_facing_fist_tone1:","aliases":":left_fist_tone1:","keywords":"left facing fist tone 1"},"left_facing_fist_tone2":{"unicode":"1f91b-1f3fc","shortname":":left_facing_fist_tone2:","aliases":":left_fist_tone2:","keywords":"left facing fist tone 2"},"left_facing_fist_tone3":{"unicode":"1f91b-1f3fd","shortname":":left_facing_fist_tone3:","aliases":":left_fist_tone3:","keywords":"left facing fist tone 3"},"left_facing_fist_tone4":{"unicode":"1f91b-1f3fe","shortname":":left_facing_fist_tone4:","aliases":":left_fist_tone4:","keywords":"left facing fist tone 4"},"left_facing_fist_tone5":{"unicode":"1f91b-1f3ff","shortname":":left_facing_fist_tone5:","aliases":":left_fist_tone5:","keywords":"left facing fist tone 5"},"right_facing_fist_tone1":{"unicode":"1f91c-1f3fb","shortname":":right_facing_fist_tone1:","aliases":":right_fist_tone1:","keywords":"right facing fist tone 1"},"right_facing_fist_tone2":{"unicode":"1f91c-1f3fc","shortname":":right_facing_fist_tone2:","aliases":":right_fist_tone2:","keywords":"right facing fist tone 2"},"right_facing_fist_tone3":{"unicode":"1f91c-1f3fd","shortname":":right_facing_fist_tone3:","aliases":":right_fist_tone3:","keywords":"right facing fist tone 3"},"right_facing_fist_tone4":{"unicode":"1f91c-1f3fe","shortname":":right_facing_fist_tone4:","aliases":":right_fist_tone4:","keywords":"right facing fist tone 4"},"right_facing_fist_tone5":{"unicode":"1f91c-1f3ff","shortname":":right_facing_fist_tone5:","aliases":":right_fist_tone5:","keywords":"right facing fist tone 5"},"raised_back_of_hand_tone1":{"unicode":"1f91a-1f3fb","shortname":":raised_back_of_hand_tone1:","aliases":":back_of_hand_tone1:","keywords":"raised back of hand tone 1"},"raised_back_of_hand_tone2":{"unicode":"1f91a-1f3fc","shortname":":raised_back_of_hand_tone2:","aliases":":back_of_hand_tone2:","keywords":"raised back of hand tone 2"},"raised_back_of_hand_tone3":{"unicode":"1f91a-1f3fd","shortname":":raised_back_of_hand_tone3:","aliases":":back_of_hand_tone3:","keywords":"raised back of hand tone 3"},"raised_back_of_hand_tone4":{"unicode":"1f91a-1f3fe","shortname":":raised_back_of_hand_tone4:","aliases":":back_of_hand_tone4:","keywords":"raised back of hand tone 4"},"raised_back_of_hand_tone5":{"unicode":"1f91a-1f3ff","shortname":":raised_back_of_hand_tone5:","aliases":":back_of_hand_tone5:","keywords":"raised back of hand tone 5"},"handshake_tone1":{"unicode":"1f91d-1f3fb","shortname":":handshake_tone1:","aliases":":shaking_hands_tone1:","keywords":"handshake tone 1"},"handshake_tone2":{"unicode":"1f91d-1f3fc","shortname":":handshake_tone2:","aliases":":shaking_hands_tone2:","keywords":"handshake tone 2"},"handshake_tone3":{"unicode":"1f91d-1f3fd","shortname":":handshake_tone3:","aliases":":shaking_hands_tone3:","keywords":"handshake tone 3"},"handshake_tone4":{"unicode":"1f91d-1f3fe","shortname":":handshake_tone4:","aliases":":shaking_hands_tone4:","keywords":"handshake tone 4"},"handshake_tone5":{"unicode":"1f91d-1f3ff","shortname":":handshake_tone5:","aliases":":shaking_hands_tone5:","keywords":"handshake tone 5"},"cartwheel_tone1":{"unicode":"1f938-1f3fb","shortname":":cartwheel_tone1:","aliases":":person_doing_cartwheel_tone1:","keywords":"person doing cartwheel tone 1"},"cartwheel_tone2":{"unicode":"1f938-1f3fc","shortname":":cartwheel_tone2:","aliases":":person_doing_cartwheel_tone2:","keywords":"person doing cartwheel tone 2"},"cartwheel_tone3":{"unicode":"1f938-1f3fd","shortname":":cartwheel_tone3:","aliases":":person_doing_cartwheel_tone3:","keywords":"person doing cartwheel tone 3"},"cartwheel_tone4":{"unicode":"1f938-1f3fe","shortname":":cartwheel_tone4:","aliases":":person_doing_cartwheel_tone4:","keywords":"person doing cartwheel tone 4"},"cartwheel_tone5":{"unicode":"1f938-1f3ff","shortname":":cartwheel_tone5:","aliases":":person_doing_cartwheel_tone5:","keywords":"person doing cartwheel tone 5"},"wrestlers_tone1":{"unicode":"1f93c-1f3fb","shortname":":wrestlers_tone1:","aliases":":wrestling_tone1:","keywords":"wrestlers tone 1"},"wrestlers_tone2":{"unicode":"1f93c-1f3fc","shortname":":wrestlers_tone2:","aliases":":wrestling_tone2:","keywords":"wrestlers tone 2"},"wrestlers_tone3":{"unicode":"1f93c-1f3fd","shortname":":wrestlers_tone3:","aliases":":wrestling_tone3:","keywords":"wrestlers tone 3"},"wrestlers_tone4":{"unicode":"1f93c-1f3fe","shortname":":wrestlers_tone4:","aliases":":wrestling_tone4:","keywords":"wrestlers tone 4"},"wrestlers_tone5":{"unicode":"1f93c-1f3ff","shortname":":wrestlers_tone5:","aliases":":wrestling_tone5:","keywords":"wrestlers tone 5"},"water_polo_tone1":{"unicode":"1f93d-1f3fb","shortname":":water_polo_tone1:","aliases":"","keywords":"water polo tone 1"},"water_polo_tone2":{"unicode":"1f93d-1f3fc","shortname":":water_polo_tone2:","aliases":"","keywords":"water polo tone 2"},"water_polo_tone3":{"unicode":"1f93d-1f3fd","shortname":":water_polo_tone3:","aliases":"","keywords":"water polo tone 3"},"water_polo_tone4":{"unicode":"1f93d-1f3fe","shortname":":water_polo_tone4:","aliases":"","keywords":"water polo tone 4"},"water_polo_tone5":{"unicode":"1f93d-1f3ff","shortname":":water_polo_tone5:","aliases":"","keywords":"water polo tone 5"},"handball_tone1":{"unicode":"1f93e-1f3fb","shortname":":handball_tone1:","aliases":"","keywords":"handball tone 1"},"handball_tone2":{"unicode":"1f93e-1f3fc","shortname":":handball_tone2:","aliases":"","keywords":"handball tone 2"},"handball_tone3":{"unicode":"1f93e-1f3fd","shortname":":handball_tone3:","aliases":"","keywords":"handball tone 3"},"handball_tone4":{"unicode":"1f93e-1f3fe","shortname":":handball_tone4:","aliases":"","keywords":"handball tone 4"},"handball_tone5":{"unicode":"1f93e-1f3ff","shortname":":handball_tone5:","aliases":"","keywords":"handball tone 5"},"juggling_tone1":{"unicode":"1f939-1f3fb","shortname":":juggling_tone1:","aliases":":juggler_tone1:","keywords":"juggling tone 1"},"juggling_tone2":{"unicode":"1f939-1f3fc","shortname":":juggling_tone2:","aliases":":juggler_tone2:","keywords":"juggling tone 2"},"juggling_tone3":{"unicode":"1f939-1f3fd","shortname":":juggling_tone3:","aliases":":juggler_tone3:","keywords":"juggling tone 3"},"juggling_tone4":{"unicode":"1f939-1f3fe","shortname":":juggling_tone4:","aliases":":juggler_tone4:","keywords":"juggling tone 4"},"juggling_tone5":{"unicode":"1f939-1f3ff","shortname":":juggling_tone5:","aliases":":juggler_tone5:","keywords":"juggling tone 5"},"speech_left":{"unicode":"1f5e8","shortname":":speech_left:","aliases":":left_speech_bubble:","keywords":"left speech bubble"},"eject":{"unicode":"23cf","shortname":":eject:","aliases":":eject_symbol:","keywords":"eject symbol"},"gay_pride_flag":{"unicode":"1f3f3-1f308","shortname":":gay_pride_flag:","aliases":":rainbow_flag:","keywords":"gay_pride_flag"},"cowboy":{"unicode":"1f920","shortname":":cowboy:","aliases":":face_with_cowboy_hat:","keywords":"face with cowboy hat"},"clown":{"unicode":"1f921","shortname":":clown:","aliases":":clown_face:","keywords":"clown face"},"nauseated_face":{"unicode":"1f922","shortname":":nauseated_face:","aliases":":sick:","keywords":"nauseated face"},"rofl":{"unicode":"1f923","shortname":":rofl:","aliases":":rolling_on_the_floor_laughing:","keywords":"rolling on the floor laughing"},"drooling_face":{"unicode":"1f924","shortname":":drooling_face:","aliases":":drool:","keywords":"drooling face"},"lying_face":{"unicode":"1f925","shortname":":lying_face:","aliases":":liar:","keywords":"lying face"},"sneezing_face":{"unicode":"1f927","shortname":":sneezing_face:","aliases":":sneeze:","keywords":"sneezing face"},"prince":{"unicode":"1f934","shortname":":prince:","aliases":"","keywords":"prince"},"man_in_tuxedo":{"unicode":"1f935","shortname":":man_in_tuxedo:","aliases":"","keywords":"man in tuxedo"},"mrs_claus":{"unicode":"1f936","shortname":":mrs_claus:","aliases":":mother_christmas:","keywords":"mother christmas"},"face_palm":{"unicode":"1f926","shortname":":face_palm:","aliases":":facepalm:","keywords":"face palm"},"shrug":{"unicode":"1f937","shortname":":shrug:","aliases":"","keywords":"shrug"},"pregnant_woman":{"unicode":"1f930","shortname":":pregnant_woman:","aliases":":expecting_woman:","keywords":"pregnant woman"},"selfie":{"unicode":"1f933","shortname":":selfie:","aliases":"","keywords":"selfie"},"man_dancing":{"unicode":"1f57a","shortname":":man_dancing:","aliases":":male_dancer:","keywords":"man dancing"},"call_me":{"unicode":"1f919","shortname":":call_me:","aliases":":call_me_hand:","keywords":"call me hand"},"raised_back_of_hand":{"unicode":"1f91a","shortname":":raised_back_of_hand:","aliases":":back_of_hand:","keywords":"raised back of hand"},"left_facing_fist":{"unicode":"1f91b","shortname":":left_facing_fist:","aliases":":left_fist:","keywords":"left-facing fist"},"right_facing_fist":{"unicode":"1f91c","shortname":":right_facing_fist:","aliases":":right_fist:","keywords":"right-facing fist"},"handshake":{"unicode":"1f91d","shortname":":handshake:","aliases":":shaking_hands:","keywords":"handshake"},"fingers_crossed":{"unicode":"1f91e","shortname":":fingers_crossed:","aliases":":hand_with_index_and_middle_finger_crossed:","keywords":"hand with first and index finger crossed"},"black_heart":{"unicode":"1f5a4","shortname":":black_heart:","aliases":"","keywords":"black heart"},"eagle":{"unicode":"1f985","shortname":":eagle:","aliases":"","keywords":"eagle"},"duck":{"unicode":"1f986","shortname":":duck:","aliases":"","keywords":"duck"},"bat":{"unicode":"1f987","shortname":":bat:","aliases":"","keywords":"bat"},"shark":{"unicode":"1f988","shortname":":shark:","aliases":"","keywords":"shark"},"owl":{"unicode":"1f989","shortname":":owl:","aliases":"","keywords":"owl"},"fox":{"unicode":"1f98a","shortname":":fox:","aliases":":fox_face:","keywords":"fox face"},"butterfly":{"unicode":"1f98b","shortname":":butterfly:","aliases":"","keywords":"butterfly"},"deer":{"unicode":"1f98c","shortname":":deer:","aliases":"","keywords":"deer"},"gorilla":{"unicode":"1f98d","shortname":":gorilla:","aliases":"","keywords":"gorilla"},"lizard":{"unicode":"1f98e","shortname":":lizard:","aliases":"","keywords":"lizard"},"rhino":{"unicode":"1f98f","shortname":":rhino:","aliases":":rhinoceros:","keywords":"rhinoceros"},"wilted_rose":{"unicode":"1f940","shortname":":wilted_rose:","aliases":":wilted_flower:","keywords":"wilted flower"},"croissant":{"unicode":"1f950","shortname":":croissant:","aliases":"","keywords":"croissant"},"avocado":{"unicode":"1f951","shortname":":avocado:","aliases":"","keywords":"avocado"},"cucumber":{"unicode":"1f952","shortname":":cucumber:","aliases":"","keywords":"cucumber"},"bacon":{"unicode":"1f953","shortname":":bacon:","aliases":"","keywords":"bacon pig"},"potato":{"unicode":"1f954","shortname":":potato:","aliases":"","keywords":"potato"},"carrot":{"unicode":"1f955","shortname":":carrot:","aliases":"","keywords":"carrot"},"french_bread":{"unicode":"1f956","shortname":":french_bread:","aliases":":baguette_bread:","keywords":"baguette bread"},"salad":{"unicode":"1f957","shortname":":salad:","aliases":":green_salad:","keywords":"green salad"},"shallow_pan_of_food":{"unicode":"1f958","shortname":":shallow_pan_of_food:","aliases":":paella:","keywords":"shallow pan of food pan of food"},"stuffed_flatbread":{"unicode":"1f959","shortname":":stuffed_flatbread:","aliases":":stuffed_pita:","keywords":"stuffed flatbread"},"champagne_glass":{"unicode":"1f942","shortname":":champagne_glass:","aliases":":clinking_glass:","keywords":"clinking glasses"},"tumbler_glass":{"unicode":"1f943","shortname":":tumbler_glass:","aliases":":whisky:","keywords":"tumbler glass booze"},"spoon":{"unicode":"1f944","shortname":":spoon:","aliases":"","keywords":"spoon"},"octagonal_sign":{"unicode":"1f6d1","shortname":":octagonal_sign:","aliases":":stop_sign:","keywords":"octagonal sign"},"shopping_cart":{"unicode":"1f6d2","shortname":":shopping_cart:","aliases":":shopping_trolley:","keywords":"shopping trolley"},"scooter":{"unicode":"1f6f4","shortname":":scooter:","aliases":"","keywords":"scooter"},"motor_scooter":{"unicode":"1f6f5","shortname":":motor_scooter:","aliases":":motorbike:","keywords":"motor scooter moped"},"canoe":{"unicode":"1f6f6","shortname":":canoe:","aliases":":kayak:","keywords":"canoe"},"cartwheel":{"unicode":"1f938","shortname":":cartwheel:","aliases":":person_doing_cartwheel:","keywords":"person doing cartwheel"},"juggling":{"unicode":"1f939","shortname":":juggling:","aliases":":juggler:","keywords":"juggling"},"wrestlers":{"unicode":"1f93c","shortname":":wrestlers:","aliases":":wrestling:","keywords":"wrestlers"},"boxing_glove":{"unicode":"1f94a","shortname":":boxing_glove:","aliases":":boxing_gloves:","keywords":"boxing glove"},"martial_arts_uniform":{"unicode":"1f94b","shortname":":martial_arts_uniform:","aliases":":karate_uniform:","keywords":"martial arts uniform"},"water_polo":{"unicode":"1f93d","shortname":":water_polo:","aliases":"","keywords":"water polo"},"handball":{"unicode":"1f93e","shortname":":handball:","aliases":"","keywords":"handball"},"goal":{"unicode":"1f945","shortname":":goal:","aliases":":goal_net:","keywords":"goal net"},"fencer":{"unicode":"1f93a","shortname":":fencer:","aliases":":fencing:","keywords":"fencer"},"first_place":{"unicode":"1f947","shortname":":first_place:","aliases":":first_place_medal:","keywords":"first place medal"},"second_place":{"unicode":"1f948","shortname":":second_place:","aliases":":second_place_medal:","keywords":"second place medal"},"third_place":{"unicode":"1f949","shortname":":third_place:","aliases":":third_place_medal:","keywords":"third place medal"},"drum":{"unicode":"1f941","shortname":":drum:","aliases":":drum_with_drumsticks:","keywords":"drum with drumsticks"},"shrimp":{"unicode":"1f990","shortname":":shrimp:","aliases":"","keywords":"shrimp"},"squid":{"unicode":"1f991","shortname":":squid:","aliases":"","keywords":"squid"},"egg":{"unicode":"1f95a","shortname":":egg:","aliases":"","keywords":"egg"},"milk":{"unicode":"1f95b","shortname":":milk:","aliases":":glass_of_milk:","keywords":"glass of milk"},"peanuts":{"unicode":"1f95c","shortname":":peanuts:","aliases":":shelled_peanut:","keywords":"peanuts"},"kiwi":{"unicode":"1f95d","shortname":":kiwi:","aliases":":kiwifruit:","keywords":"kiwifruit"},"pancakes":{"unicode":"1f95e","shortname":":pancakes:","aliases":"","keywords":"pancakes"},"regional_indicator_z":{"unicode":"1f1ff","shortname":":regional_indicator_z:","aliases":"","keywords":"regional indicator symbol letter z"},"regional_indicator_y":{"unicode":"1f1fe","shortname":":regional_indicator_y:","aliases":"","keywords":"regional indicator symbol letter y"},"regional_indicator_x":{"unicode":"1f1fd","shortname":":regional_indicator_x:","aliases":"","keywords":"regional indicator symbol letter x"},"regional_indicator_w":{"unicode":"1f1fc","shortname":":regional_indicator_w:","aliases":"","keywords":"regional indicator symbol letter w"},"regional_indicator_v":{"unicode":"1f1fb","shortname":":regional_indicator_v:","aliases":"","keywords":"regional indicator symbol letter v"},"regional_indicator_u":{"unicode":"1f1fa","shortname":":regional_indicator_u:","aliases":"","keywords":"regional indicator symbol letter u"},"regional_indicator_t":{"unicode":"1f1f9","shortname":":regional_indicator_t:","aliases":"","keywords":"regional indicator symbol letter t"},"regional_indicator_s":{"unicode":"1f1f8","shortname":":regional_indicator_s:","aliases":"","keywords":"regional indicator symbol letter s"},"regional_indicator_r":{"unicode":"1f1f7","shortname":":regional_indicator_r:","aliases":"","keywords":"regional indicator symbol letter r"},"regional_indicator_q":{"unicode":"1f1f6","shortname":":regional_indicator_q:","aliases":"","keywords":"regional indicator symbol letter q"},"regional_indicator_p":{"unicode":"1f1f5","shortname":":regional_indicator_p:","aliases":"","keywords":"regional indicator symbol letter p"},"regional_indicator_o":{"unicode":"1f1f4","shortname":":regional_indicator_o:","aliases":"","keywords":"regional indicator symbol letter o"},"regional_indicator_n":{"unicode":"1f1f3","shortname":":regional_indicator_n:","aliases":"","keywords":"regional indicator symbol letter n"},"regional_indicator_m":{"unicode":"1f1f2","shortname":":regional_indicator_m:","aliases":"","keywords":"regional indicator symbol letter m"},"regional_indicator_l":{"unicode":"1f1f1","shortname":":regional_indicator_l:","aliases":"","keywords":"regional indicator symbol letter l"},"regional_indicator_k":{"unicode":"1f1f0","shortname":":regional_indicator_k:","aliases":"","keywords":"regional indicator symbol letter k"},"regional_indicator_j":{"unicode":"1f1ef","shortname":":regional_indicator_j:","aliases":"","keywords":"regional indicator symbol letter j"},"regional_indicator_i":{"unicode":"1f1ee","shortname":":regional_indicator_i:","aliases":"","keywords":"regional indicator symbol letter i"},"regional_indicator_h":{"unicode":"1f1ed","shortname":":regional_indicator_h:","aliases":"","keywords":"regional indicator symbol letter h"},"regional_indicator_g":{"unicode":"1f1ec","shortname":":regional_indicator_g:","aliases":"","keywords":"regional indicator symbol letter g"},"regional_indicator_f":{"unicode":"1f1eb","shortname":":regional_indicator_f:","aliases":"","keywords":"regional indicator symbol letter f"},"regional_indicator_e":{"unicode":"1f1ea","shortname":":regional_indicator_e:","aliases":"","keywords":"regional indicator symbol letter e"},"regional_indicator_d":{"unicode":"1f1e9","shortname":":regional_indicator_d:","aliases":"","keywords":"regional indicator symbol letter d"},"regional_indicator_c":{"unicode":"1f1e8","shortname":":regional_indicator_c:","aliases":"","keywords":"regional indicator symbol letter c"},"regional_indicator_b":{"unicode":"1f1e7","shortname":":regional_indicator_b:","aliases":"","keywords":"regional indicator symbol letter b"},"regional_indicator_a":{"unicode":"1f1e6","shortname":":regional_indicator_a:","aliases":"","keywords":"regional indicator symbol letter a"}} \ No newline at end of file diff --git a/pagure/static/emoji/emoji_strategy.json b/pagure/static/emoji/emoji_strategy.json deleted file mode 100644 index 169e6ca..0000000 --- a/pagure/static/emoji/emoji_strategy.json +++ /dev/null @@ -1 +0,0 @@ -{"wine_glass": {"keywords": "wine glass alcohol beverage booze bottle drink drunk fermented glass grapes tasting wine winery", "shortname": ":wine_glass:", "unicode": "1F377", "aliases": ""}, "clock830": {"keywords": "clock face eight-thirty clock time", "shortname": ":clock830:", "unicode": "1F563", "aliases": ""}, "rabbit": {"keywords": "rabbit face animal nature", "shortname": ":rabbit:", "unicode": "1F430", "aliases": ""}, "european_post_office": {"keywords": "european post office building", "shortname": ":european_post_office:", "unicode": "1F3E4", "aliases": ""}, "dollar": {"keywords": "banknote with dollar sign bill currency money dollar united states canada australia banknote money currency paper cash bills", "shortname": ":dollar:", "unicode": "1F4B5", "aliases": ""}, "alien": {"keywords": "extraterrestrial alien UFO paul alien ufo", "shortname": ":alien:", "unicode": "1F47D", "aliases": ""}, "crocodile": {"keywords": "crocodile animal nature crocodile croc alligator gator cranky", "shortname": ":crocodile:", "unicode": "1F40A", "aliases": ""}, "smoking": {"keywords": "smoking symbol cigarette kills tobacco smoking cigarette smoke cancer lungs inhale tar nicotine", "shortname": ":smoking:", "unicode": "1F6AC", "aliases": ""}, "white_square_button": {"keywords": "white square button shape", "shortname": ":white_square_button:", "unicode": "1F533", "aliases": ""}, "maple_leaf": {"keywords": "maple leaf canada nature plant vegetable maple leaf syrup canada tree", "shortname": ":maple_leaf:", "unicode": "1F341", "aliases": ""}, "no_bicycles": {"keywords": "no bicycles cyclist prohibited bicycle bike pedal no", "shortname": ":no_bicycles:", "unicode": "1F6B3", "aliases": ""}, "man_with_gua_pi_mao": {"keywords": "man with gua pi mao boy male skullcap chinese asian qing", "shortname": ":man_with_gua_pi_mao:", "unicode": "1F472", "aliases": ""}, "e-mail": {"keywords": "e-mail symbol communication inbox", "shortname": ":e-mail:", "unicode": "1F4E7", "aliases": ":email:"}, "tv": {"keywords": "television oldschool program show technology", "shortname": ":tv:", "unicode": "1F4FA", "aliases": ""}, "open_hands": {"keywords": "open hands sign butterfly fingers", "shortname": ":open_hands:", "unicode": "1F450", "aliases": ""}, "rotating_light": {"keywords": "police cars revolving light 911 ambulance emergency police light police emergency", "shortname": ":rotating_light:", "unicode": "1F6A8", "aliases": ""}, "part_alternation_mark": {"keywords": "part alternation mark graph sing song vocal music karaoke cue letter m japanese", "shortname": ":part_alternation_mark:", "unicode": "303D", "aliases": ""}, "tm": {"keywords": "trade mark sign brand trademark", "shortname": ":tm:", "unicode": "2122", "aliases": ""}, "mountain_cableway": {"keywords": "mountain cableway transportation vehicle mountain cable rail train railway", "shortname": ":mountain_cableway:", "unicode": "1F6A0", "aliases": ""}, "recycle": {"keywords": "black universal recycling symbol arrow environment garbage trash", "shortname": ":recycle:", "unicode": "267B", "aliases": ""}, "smile": {"keywords": "smiling face with open mouth and smiling eyes face funny haha happy joy laugh smile smiley smiling", "shortname": ":smile:", "unicode": "1F604", "aliases": ""}, "large_blue_circle": {"keywords": "large blue circle ", "shortname": ":large_blue_circle:", "unicode": "1F535", "aliases": ""}, "persevere": {"keywords": "persevering face endure persevere face no sick upset", "shortname": ":persevere:", "unicode": "1F623", "aliases": ""}, "open_file_folder": {"keywords": "open file folder documents load", "shortname": ":open_file_folder:", "unicode": "1F4C2", "aliases": ""}, "fax": {"keywords": "fax machine communication technology", "shortname": ":fax:", "unicode": "1F4E0", "aliases": ""}, "woman": {"keywords": "woman female girls", "shortname": ":woman:", "unicode": "1F469", "aliases": ""}, "eight_pointed_black_star": {"keywords": "eight pointed black star ", "shortname": ":eight_pointed_black_star:", "unicode": "2734", "aliases": ""}, "department_store": {"keywords": "department store building mall shopping department store retail sale merchandise", "shortname": ":department_store:", "unicode": "1F3EC", "aliases": ""}, "trident": {"keywords": "trident emblem spear weapon", "shortname": ":trident:", "unicode": "1F531", "aliases": ""}, "oncoming_automobile": {"keywords": "oncoming automobile car transportation vehicle sedan car automobile", "shortname": ":oncoming_automobile:", "unicode": "1F698", "aliases": ""}, "wave": {"keywords": "waving hand sign farewell gesture goodbye hands solong", "shortname": ":wave:", "unicode": "1F44B", "aliases": ""}, "u7a7a": {"keywords": "squared cjk unified ideograph-7a7a chinese empty japanese kanji", "shortname": ":u7a7a:", "unicode": "1F233", "aliases": ""}, "arrow_right": {"keywords": "black rightwards arrow blue-square next", "shortname": ":arrow_right:", "unicode": "27A1", "aliases": ""}, "ticket": {"keywords": "ticket concert event pass ticket show entertainment stub admission proof purchase", "shortname": ":ticket:", "unicode": "1F3AB", "aliases": ""}, "ramen": {"keywords": "steaming bowl chipsticks food japanese noodle ramen noodles bowl steaming soup", "shortname": ":ramen:", "unicode": "1F35C", "aliases": ""}, "twisted_rightwards_arrows": {"keywords": "twisted rightwards arrows blue-square", "shortname": ":twisted_rightwards_arrows:", "unicode": "1F500", "aliases": ""}, "cool": {"keywords": "squared cool blue-square words", "shortname": ":cool:", "unicode": "1F192", "aliases": ""}, "four": {"keywords": "digit four 4 blue-square numbers", "shortname": ":four:", "unicode": "0034-20E3", "aliases": ""}, "school": {"keywords": "school building school university elementary middle high college teach education", "shortname": ":school:", "unicode": "1F3EB", "aliases": ""}, "high_brightness": {"keywords": "high brightness symbol light summer sun", "shortname": ":high_brightness:", "unicode": "1F506", "aliases": ""}, "railway_car": {"keywords": "railway car transportation vehicle railway rail car coach train", "shortname": ":railway_car:", "unicode": "1F683", "aliases": ""}, "notes": {"keywords": "multiple musical notes music score musical music notes music sound melody", "shortname": ":notes:", "unicode": "1F3B6", "aliases": ""}, "white_flower": {"keywords": "white flower japanese white flower teacher school grade score brilliance intelligence homework student assignment praise", "shortname": ":white_flower:", "unicode": "1F4AE", "aliases": ""}, "gun": {"keywords": "pistol violence weapon", "shortname": ":gun:", "unicode": "1F52B", "aliases": ""}, "couple_with_heart": {"keywords": "couple with heart affection dating human like love marriage valentines", "shortname": ":couple_with_heart:", "unicode": "1F491", "aliases": ""}, "no_good": {"keywords": "face with no good gesture female girl woman no stop nope don't not", "shortname": ":no_good:", "unicode": "1F645", "aliases": ""}, "saxophone": {"keywords": "saxophone instrument music saxophone sax music instrument woodwind", "shortname": ":saxophone:", "unicode": "1F3B7", "aliases": ""}, "notebook_with_decorative_cover": {"keywords": "notebook with decorative cover classroom notes paper record", "shortname": ":notebook_with_decorative_cover:", "unicode": "1F4D4", "aliases": ""}, "triumph": {"keywords": "face with look of triumph face gas phew triumph steam breath", "shortname": ":triumph:", "unicode": "1F624", "aliases": ""}, "tea": {"keywords": "teacup without handle bowl breakfast british drink green tea leaf drink teacup hot beverage", "shortname": ":tea:", "unicode": "1F375", "aliases": ""}, "suspension_railway": {"keywords": "suspension railway transportation vehicle suspension railway rail train transportation", "shortname": ":suspension_railway:", "unicode": "1F69F", "aliases": ""}, "arrow_left": {"keywords": "leftwards black arrow arrow blue-square previous", "shortname": ":arrow_left:", "unicode": "2B05", "aliases": ""}, "zero": {"keywords": "digit zero blue-square null numbers", "shortname": ":zero:", "unicode": "0030-20E3", "aliases": ""}, "small_orange_diamond": {"keywords": "small orange diamond shape", "shortname": ":small_orange_diamond:", "unicode": "1F538", "aliases": ""}, "cactus": {"keywords": "cactus nature plant vegetable cactus desert drought spike poke", "shortname": ":cactus:", "unicode": "1F335", "aliases": ""}, "spaghetti": {"keywords": "spaghetti food italian noodle spaghetti noodles tomato sauce italian", "shortname": ":spaghetti:", "unicode": "1F35D", "aliases": ""}, "white_small_square": {"keywords": "white small square shape", "shortname": ":white_small_square:", "unicode": "25AB", "aliases": ""}, "ribbon": {"keywords": "ribbon bowtie decoration girl pink ribbon lace wrap decorate", "shortname": ":ribbon:", "unicode": "1F380", "aliases": ""}, "cinema": {"keywords": "cinema blue-square film movie record cinema movie theater motion picture", "shortname": ":cinema:", "unicode": "1F3A6", "aliases": ""}, "mega": {"keywords": "cheering megaphone sound speaker volume", "shortname": ":mega:", "unicode": "1F4E3", "aliases": ""}, "abc": {"keywords": "input symbol for latin letters alphabet blue-square", "shortname": ":abc:", "unicode": "1F524", "aliases": ""}, "purple_heart": {"keywords": "purple heart affection like love valentines purple violet heart love sensitive understanding compassionate compassion duty honor royalty veteran sacrifice", "shortname": ":purple_heart:", "unicode": "1F49C", "aliases": ""}, "love_letter": {"keywords": "love letter affection email envelope like valentines love letter kiss heart", "shortname": ":love_letter:", "unicode": "1F48C", "aliases": ""}, "file_folder": {"keywords": "file folder documents", "shortname": ":file_folder:", "unicode": "1F4C1", "aliases": ""}, "clipboard": {"keywords": "clipboard documents stationery", "shortname": ":clipboard:", "unicode": "1F4CB", "aliases": ""}, "baby_bottle": {"keywords": "baby bottle container food baby bottle milk mother nipple newborn formula", "shortname": ":baby_bottle:", "unicode": "1F37C", "aliases": ""}, "new": {"keywords": "squared new blue-square", "shortname": ":new:", "unicode": "1F195", "aliases": ""}, "bird": {"keywords": "bird animal fly nature tweet", "shortname": ":bird:", "unicode": "1F426", "aliases": ""}, "1234": {"keywords": "input symbol for numbers blue-square numbers", "shortname": ":1234:", "unicode": "1F522", "aliases": ""}, "smiling_imp": {"keywords": "smiling face with horns devil horns horns devil impish trouble", "shortname": ":smiling_imp:", "unicode": "1F608", "aliases": ""}, "no_smoking": {"keywords": "no smoking symbol cigarette no smoking cigarette smoke cancer lungs inhale tar nicotine", "shortname": ":no_smoking:", "unicode": "1F6AD", "aliases": ""}, "herb": {"keywords": "herb grass lawn medicine plant vegetable weed herb spice plant cook cooking", "shortname": ":herb:", "unicode": "1F33F", "aliases": ""}, "pouting_cat": {"keywords": "pouting cat face animal cats pout annoyed miffed glower frown", "shortname": ":pouting_cat:", "unicode": "1F63E", "aliases": ""}, "u5408": {"keywords": "squared cjk unified ideograph-5408 chinese japanese join kanji", "shortname": ":u5408:", "unicode": "1F234", "aliases": ""}, "punch": {"keywords": "fisted hand sign fist hand", "shortname": ":punch:", "unicode": "1F44A", "aliases": ""}, "surfer": {"keywords": "surfer ocean sea sports surfer surf wave ocean ride swell", "shortname": ":surfer:", "unicode": "1F3C4", "aliases": ""}, "house_with_garden": {"keywords": "house with garden home nature plant", "shortname": ":house_with_garden:", "unicode": "1F3E1", "aliases": ""}, "baseball": {"keywords": "baseball MLB balls sports", "shortname": ":baseball:", "unicode": "26BE", "aliases": ""}, "busstop": {"keywords": "bus stop transportation bus stop city transport transportation", "shortname": ":busstop:", "unicode": "1F68F", "aliases": ""}, "new_moon": {"keywords": "new moon symbol nature moon new sky night cheese phase", "shortname": ":new_moon:", "unicode": "1F311", "aliases": ""}, "100": {"keywords": "hundred points symbol numbers perfect score 100 percent a plus perfect school quiz score test exam", "shortname": ":100:", "unicode": "1F4AF", "aliases": ""}, "thumbsup": {"keywords": "thumbs up sign cool hand like yes", "shortname": ":thumbsup:", "unicode": "1F44D", "aliases": ":+1:"}, "bust_in_silhouette": {"keywords": "bust in silhouette human man person user silhouette person user member account guest icon avatar profile me myself i", "shortname": ":bust_in_silhouette:", "unicode": "1F464", "aliases": ""}, "boy": {"keywords": "boy guy male man", "shortname": ":boy:", "unicode": "1F466", "aliases": ""}, "arrow_lower_left": {"keywords": "south west arrow arrow blue-square", "shortname": ":arrow_lower_left:", "unicode": "2199", "aliases": ""}, "no_entry": {"keywords": "no entry bad denied limit privacy security stop", "shortname": ":no_entry:", "unicode": "26D4", "aliases": ""}, "see_no_evil": {"keywords": "see-no-evil monkey animal monkey nature monkey see eyes vision sight mizaru", "shortname": ":see_no_evil:", "unicode": "1F648", "aliases": ""}, "metro": {"keywords": "metro blue-square mrt transportation tube underground metro subway underground train", "shortname": ":metro:", "unicode": "1F687", "aliases": ""}, "leaves": {"keywords": "leaf fluttering in wind grass lawn nature plant tree vegetable leaves leaf wind float fluttering", "shortname": ":leaves:", "unicode": "1F343", "aliases": ""}, "heavy_plus_sign": {"keywords": "heavy plus sign calculation math", "shortname": ":heavy_plus_sign:", "unicode": "2795", "aliases": ""}, "roller_coaster": {"keywords": "roller coaster carnival fun photo play playground roller coaster amusement park fair ride entertainment", "shortname": ":roller_coaster:", "unicode": "1F3A2", "aliases": ""}, "thought_balloon": {"keywords": "thought balloon bubble cloud speech thought balloon comic think day dream wonder", "shortname": ":thought_balloon:", "unicode": "1F4AD", "aliases": ""}, "bow": {"keywords": "person bowing deeply boy male man sorry bow respect curtsy bend", "shortname": ":bow:", "unicode": "1F647", "aliases": ""}, "dragon_face": {"keywords": "dragon face animal chinese green myth nature dragon head fire legendary myth", "shortname": ":dragon_face:", "unicode": "1F432", "aliases": ""}, "hamster": {"keywords": "hamster face animal nature", "shortname": ":hamster:", "unicode": "1F439", "aliases": ""}, "waxing_gibbous_moon": {"keywords": "waxing gibbous moon symbol nature", "shortname": ":waxing_gibbous_moon:", "unicode": "1F314", "aliases": ""}, "cookie": {"keywords": "cookie chocolate food oreo snack cookie dessert biscuit sweet chocolate", "shortname": ":cookie:", "unicode": "1F36A", "aliases": ""}, "massage": {"keywords": "face massage female girl woman", "shortname": ":massage:", "unicode": "1F486", "aliases": ""}, "children_crossing": {"keywords": "children crossing school children kids caution crossing street crosswalk slow", "shortname": ":children_crossing:", "unicode": "1F6B8", "aliases": ""}, "apple": {"keywords": "red apple fruit mac apple fruit electronics red doctor teacher school core", "shortname": ":apple:", "unicode": "1F34E", "aliases": ""}, "family": {"keywords": "family child dad father home mom mother parents family mother father child girl boy group unit", "shortname": ":family:", "unicode": "1F46A", "aliases": ""}, "arrow_up_down": {"keywords": "up down arrow blue-square", "shortname": ":arrow_up_down:", "unicode": "2195", "aliases": ""}, "mount_fuji": {"keywords": "mount fuji japan mountain nature photo", "shortname": ":mount_fuji:", "unicode": "1F5FB", "aliases": ""}, "keycap_ten": {"keywords": "keycap ten 10 blue-square numbers", "shortname": ":keycap_ten:", "unicode": "1F51F", "aliases": ""}, "outbox_tray": {"keywords": "outbox tray email inbox", "shortname": ":outbox_tray:", "unicode": "1F4E4", "aliases": ""}, "clock330": {"keywords": "clock face three-thirty clock time", "shortname": ":clock330:", "unicode": "1F55E", "aliases": ""}, "cloud": {"keywords": "cloud sky weather", "shortname": ":cloud:", "unicode": "2601", "aliases": ""}, "honey_pot": {"keywords": "honey pot bees sweet honey pot bees pooh bear", "shortname": ":honey_pot:", "unicode": "1F36F", "aliases": ""}, "red_car": {"keywords": "automobile transportation vehicle", "shortname": ":red_car:", "unicode": "1F697", "aliases": ""}, "sake": {"keywords": "sake bottle and cup beverage drink drunk wine sake wine rice ferment alcohol japanese drink", "shortname": ":sake:", "unicode": "1F376", "aliases": ""}, "confounded": {"keywords": "confounded face confused face sick unwell confound amaze perplex puzzle mystify", "shortname": ":confounded:", "unicode": "1F616", "aliases": ""}, "angry": {"keywords": "angry face angry livid mad vexed irritated annoyed face frustrated mad", "shortname": ":angry:", "unicode": "1F620", "aliases": ""}, "poodle": {"keywords": "poodle 101 animal dog nature poodle dog clip showy sophisticated vain", "shortname": ":poodle:", "unicode": "1F429", "aliases": ""}, "frog": {"keywords": "frog face animal nature", "shortname": ":frog:", "unicode": "1F438", "aliases": ""}, "musical_note": {"keywords": "musical note score musical music note music sound", "shortname": ":musical_note:", "unicode": "1F3B5", "aliases": ""}, "camera": {"keywords": "camera gadgets photo", "shortname": ":camera:", "unicode": "1F4F7", "aliases": ""}, "iphone": {"keywords": "mobile phone apple dial gadgets technology", "shortname": ":iphone:", "unicode": "1F4F1", "aliases": ""}, "sweat_smile": {"keywords": "smiling face with open mouth and cold sweat face happy hot smiling cold sweat perspiration", "shortname": ":sweat_smile:", "unicode": "1F605", "aliases": ""}, "aries": {"keywords": "aries aries ram astrology greek constellation stars zodiac sign purple-square sign zodiac horoscope", "shortname": ":aries:", "unicode": "2648", "aliases": ""}, "ear_of_rice": {"keywords": "ear of rice nature plant ear rice food plant seed", "shortname": ":ear_of_rice:", "unicode": "1F33E", "aliases": ""}, "video_camera": {"keywords": "video camera film record", "shortname": ":video_camera:", "unicode": "1F4F9", "aliases": ""}, "mouse2": {"keywords": "mouse animal nature mouse mice rodent", "shortname": ":mouse2:", "unicode": "1F401", "aliases": ""}, "chestnut": {"keywords": "chestnut food squirrel chestnut roasted food tree", "shortname": ":chestnut:", "unicode": "1F330", "aliases": ""}, "pencil": {"keywords": "memo documents paper station write", "shortname": ":pencil:", "unicode": "1F4DD", "aliases": ""}, "guardsman": {"keywords": "guardsman british gb male man uk guardsman guard bearskin hat british queen ceremonial military", "shortname": ":guardsman:", "unicode": "1F482", "aliases": ""}, "door": {"keywords": "door entry exit house door doorway entrance enter exit entry", "shortname": ":door:", "unicode": "1F6AA", "aliases": ""}, "steam_locomotive": {"keywords": "steam locomotive train transportation vehicle locomotive steam train engine", "shortname": ":steam_locomotive:", "unicode": "1F682", "aliases": ""}, "tangerine": {"keywords": "tangerine food fruit nature tangerine citrus orange", "shortname": ":tangerine:", "unicode": "1F34A", "aliases": ""}, "bike": {"keywords": "bicycle bicycle exercise hipster sports bike pedal bicycle transportation", "shortname": ":bike:", "unicode": "1F6B2", "aliases": ""}, "melon": {"keywords": "melon food fruit nature melon cantaloupe honeydew", "shortname": ":melon:", "unicode": "1F348", "aliases": ""}, "train": {"keywords": "Tram Car tram rail", "shortname": ":train:", "unicode": "1F68B", "aliases": ""}, "beers": {"keywords": "clinking beer mugs beverage drink drunk party pub relax beer beers cheers mug toast celebrate pub bar jolly hops clink", "shortname": ":beers:", "unicode": "1F37B", "aliases": ""}, "water_buffalo": {"keywords": "water buffalo animal cow nature ox water buffalo asia bovine milk dairy", "shortname": ":water_buffalo:", "unicode": "1F403", "aliases": ""}, "baby": {"keywords": "baby boy child infant", "shortname": ":baby:", "unicode": "1F476", "aliases": ""}, "mailbox_closed": {"keywords": "closed mailbox with lowered flag communication email inbox", "shortname": ":mailbox_closed:", "unicode": "1F4EA", "aliases": ""}, "curly_loop": {"keywords": "curly loop scribble", "shortname": ":curly_loop:", "unicode": "27B0", "aliases": ""}, "sleeping": {"keywords": "sleeping face face sleepy tired sleep sleepy sleeping snore", "shortname": ":sleeping:", "unicode": "1F634", "aliases": ""}, "pouch": {"keywords": "pouch accessories bag pouch bag cosmetic packing grandma makeup", "shortname": ":pouch:", "unicode": "1F45D", "aliases": ""}, "jack_o_lantern": {"keywords": "jack-o-lantern halloween jack-o-lantern pumpkin halloween holiday carve autumn fall october saints costume spooky horror scary scared dead", "shortname": ":jack_o_lantern:", "unicode": "1F383", "aliases": ""}, "izakaya_lantern": {"keywords": "izakaya lantern light izakaya lantern stay drink alcohol bar sake restaurant", "shortname": ":izakaya_lantern:", "unicode": "1F3EE", "aliases": ""}, "palm_tree": {"keywords": "palm tree nature plant vegetable palm tree coconuts fronds warm tropical", "shortname": ":palm_tree:", "unicode": "1F334", "aliases": ""}, "cat": {"keywords": "cat face animal meow", "shortname": ":cat:", "unicode": "1F431", "aliases": ""}, "dizzy": {"keywords": "dizzy symbol shoot sparkle star dizzy drunk sick intoxicated squeans starburst star", "shortname": ":dizzy:", "unicode": "1F4AB", "aliases": ""}, "nine": {"keywords": "digit nine 9 blue-square numbers", "shortname": ":nine:", "unicode": "0039-20E3", "aliases": ""}, "chocolate_bar": {"keywords": "chocolate bar desert food snack chocolate bar candy coca hershey's", "shortname": ":chocolate_bar:", "unicode": "1F36B", "aliases": ""}, "v": {"keywords": "victory hand fingers hand ohyeah peace two victory", "shortname": ":v:", "unicode": "270C", "aliases": ""}, "running_shirt_with_sash": {"keywords": "running shirt with sash pageant play running run shirt cloths compete sports", "shortname": ":running_shirt_with_sash:", "unicode": "1F3BD", "aliases": ""}, "raised_hands": {"keywords": "person raising both hands in celebration gesture hooray winning woot yay banzai", "shortname": ":raised_hands:", "unicode": "1F64C", "aliases": ""}, "put_litter_in_its_place": {"keywords": "put litter in its place symbol blue-square litter waste trash garbage receptacle can", "shortname": ":put_litter_in_its_place:", "unicode": "1F6AE", "aliases": ""}, "game_die": {"keywords": "game die dice game die dice craps gamble play", "shortname": ":game_die:", "unicode": "1F3B2", "aliases": ""}, "abcd": {"keywords": "input symbol for latin small letters alphabet blue-square", "shortname": ":abcd:", "unicode": "1F521", "aliases": ""}, "heart": {"keywords": "heavy black heart like love red pink black heart love passion romance intense desire death evil cold valentines", "shortname": ":heart:", "unicode": "2764", "aliases": ""}, "chart_with_upwards_trend": {"keywords": "chart with upwards trend graph", "shortname": ":chart_with_upwards_trend:", "unicode": "1F4C8", "aliases": ""}, "green_heart": {"keywords": "green heart affection like love valentines green heart love nature rebirth reborn jealous clingy envious possessive", "shortname": ":green_heart:", "unicode": "1F49A", "aliases": ""}, "hamburger": {"keywords": "hamburger food meat hamburger burger meat cow beef", "shortname": ":hamburger:", "unicode": "1F354", "aliases": ""}, "pushpin": {"keywords": "pushpin stationery", "shortname": ":pushpin:", "unicode": "1F4CC", "aliases": ""}, "lock": {"keywords": "lock password security", "shortname": ":lock:", "unicode": "1F512", "aliases": ""}, "dolphin": {"keywords": "dolphin animal fins fish flipper nature ocean sea", "shortname": ":dolphin:", "unicode": "1F42C", "aliases": ""}, "confused": {"keywords": "confused face confused confuse daze perplex puzzle indifference skeptical undecided uneasy hesitant", "shortname": ":confused:", "unicode": "1F615", "aliases": ""}, "accept": {"keywords": "circled ideograph accept agree chinese good kanji ok yes", "shortname": ":accept:", "unicode": "1F251", "aliases": ""}, "night_with_stars": {"keywords": "night with stars night star cloudless evening planets space sky", "shortname": ":night_with_stars:", "unicode": "1F303", "aliases": ""}, "pig2": {"keywords": "pig animal nature pig piggy pork ham hog bacon oink slop livestock greed greedy", "shortname": ":pig2:", "unicode": "1F416", "aliases": ""}, "white_medium_small_square": {"keywords": "white medium small square shape", "shortname": ":white_medium_small_square:", "unicode": "25FD", "aliases": ""}, "sunglasses": {"keywords": "smiling face with sunglasses cool face smiling sunglasses sun glasses sunny cool smooth", "shortname": ":sunglasses:", "unicode": "1F60E", "aliases": ""}, "airplane": {"keywords": "airplane flight transportation vehicle airplane plane airport travel airlines fly jet jumbo boeing airbus", "shortname": ":airplane:", "unicode": "2708", "aliases": ""}, "dress": {"keywords": "dress clothes fashion", "shortname": ":dress:", "unicode": "1F457", "aliases": ""}, "kissing_closed_eyes": {"keywords": "kissing face with closed eyes affection face infatuation like love valentines kissing kiss passion puckered heart love smooch", "shortname": ":kissing_closed_eyes:", "unicode": "1F61A", "aliases": ""}, "earth_americas": {"keywords": "earth globe americas USA globe international world earth globe space planet north south america americas home", "shortname": ":earth_americas:", "unicode": "1F30E", "aliases": ""}, "scorpius": {"keywords": "scorpius scorpius scorpion scorpio astrology greek constellation stars zodiac sign sign zodiac horoscope", "shortname": ":scorpius:", "unicode": "264F", "aliases": ""}, "sailboat": {"keywords": "sailboat ship transportation", "shortname": ":sailboat:", "unicode": "26F5", "aliases": ""}, "speedboat": {"keywords": "speedboat ship transportation vehicle motor speed ski power boat", "shortname": ":speedboat:", "unicode": "1F6A4", "aliases": ""}, "six": {"keywords": "digit six 6 blue-square numbers", "shortname": ":six:", "unicode": "0036-20E3", "aliases": ""}, "ledger": {"keywords": "ledger notes paper", "shortname": ":ledger:", "unicode": "1F4D2", "aliases": ""}, "id": {"keywords": "squared id purple-square words", "shortname": ":id:", "unicode": "1F194", "aliases": ""}, "tomato": {"keywords": "tomato food fruit nature vegetable tomato fruit sauce italian", "shortname": ":tomato:", "unicode": "1F345", "aliases": ""}, "leftwards_arrow_with_hook": {"keywords": "leftwards arrow with hook ", "shortname": ":leftwards_arrow_with_hook:", "unicode": "21A9", "aliases": ""}, "rewind": {"keywords": "black left-pointing double triangle blue-square play", "shortname": ":rewind:", "unicode": "23EA", "aliases": ""}, "wavy_dash": {"keywords": "wavy dash draw line", "shortname": ":wavy_dash:", "unicode": "3030", "aliases": ""}, "earth_asia": {"keywords": "earth globe asia-australia east globe international world earth globe space planet asia australia home", "shortname": ":earth_asia:", "unicode": "1F30F", "aliases": ""}, "goat": {"keywords": "goat animal nature goat sheep kid billy livestock", "shortname": ":goat:", "unicode": "1F410", "aliases": ""}, "pizza": {"keywords": "slice of pizza food party pizza pie new york italian italy slice peperoni", "shortname": ":pizza:", "unicode": "1F355", "aliases": ""}, "heavy_check_mark": {"keywords": "heavy check mark nike ok", "shortname": ":heavy_check_mark:", "unicode": "2714", "aliases": ""}, "bouquet": {"keywords": "bouquet flowers nature", "shortname": ":bouquet:", "unicode": "1F490", "aliases": ""}, "disappointed_relieved": {"keywords": "disappointed but relieved face face nervous phew sweat disappoint relief", "shortname": ":disappointed_relieved:", "unicode": "1F625", "aliases": ""}, "sunny": {"keywords": "black sun with rays brightness weather", "shortname": ":sunny:", "unicode": "2600", "aliases": ""}, "customs": {"keywords": "customs border passport customs travel foreign goods check authority government", "shortname": ":customs:", "unicode": "1F6C3", "aliases": ""}, "sun_with_face": {"keywords": "sun with face morning sun anthropomorphic face sky", "shortname": ":sun_with_face:", "unicode": "1F31E", "aliases": ""}, "birthday": {"keywords": "birthday cake cake party birthday birth cake dessert wish celebrate", "shortname": ":birthday:", "unicode": "1F382", "aliases": ""}, "fast_forward": {"keywords": "black right-pointing double triangle blue-square", "shortname": ":fast_forward:", "unicode": "23E9", "aliases": ""}, "heartpulse": {"keywords": "growing heart affection like love valentines", "shortname": ":heartpulse:", "unicode": "1F497", "aliases": ""}, "mag": {"keywords": "left-pointing magnifying glass search zoom detective investigator detail details", "shortname": ":mag:", "unicode": "1F50D", "aliases": ""}, "date": {"keywords": "calendar calendar schedule", "shortname": ":date:", "unicode": "1F4C5", "aliases": ""}, "sparkles": {"keywords": "sparkles cool shine shiny stars", "shortname": ":sparkles:", "unicode": "2728", "aliases": ""}, "man": {"keywords": "man classy dad father guy mustashe", "shortname": ":man:", "unicode": "1F468", "aliases": ""}, "a": {"keywords": "negative squared latin capital letter a alphabet letter red-square", "shortname": ":a:", "unicode": "1F170", "aliases": ""}, "headphones": {"keywords": "headphone gadgets music score headphone sound music ears beats buds audio listen", "shortname": ":headphones:", "unicode": "1F3A7", "aliases": ""}, "curry": {"keywords": "curry and rice food hot indian spicy curry spice flavor food meal", "shortname": ":curry:", "unicode": "1F35B", "aliases": ""}, "wheelchair": {"keywords": "wheelchair symbol blue-square disabled", "shortname": ":wheelchair:", "unicode": "267F", "aliases": ""}, "dragon": {"keywords": "dragon animal chinese green myth nature dragon fire legendary myth", "shortname": ":dragon:", "unicode": "1F409", "aliases": ""}, "tulip": {"keywords": "tulip flowers nature plant tulip flower bulb spring easter", "shortname": ":tulip:", "unicode": "1F337", "aliases": ""}, "truck": {"keywords": "delivery truck cars transportation truck delivery package", "shortname": ":truck:", "unicode": "1F69A", "aliases": ""}, "wrench": {"keywords": "wrench diy ikea tools", "shortname": ":wrench:", "unicode": "1F527", "aliases": ""}, "ambulance": {"keywords": "ambulance 911 health ambulance emergency medical help assistance", "shortname": ":ambulance:", "unicode": "1F691", "aliases": ""}, "sa": {"keywords": "squared katakana sa blue-square japanese", "shortname": ":sa:", "unicode": "1F202", "aliases": ""}, "point_up_2": {"keywords": "white up pointing backhand index direction fingers hand", "shortname": ":point_up_2:", "unicode": "1F446", "aliases": ""}, "egg": {"keywords": "cooking breakfast food egg fry pan flat cook frying cooking utensil", "shortname": ":egg:", "unicode": "1F373", "aliases": ""}, "small_red_triangle": {"keywords": "up-pointing red triangle shape", "shortname": ":small_red_triangle:", "unicode": "1F53A", "aliases": ""}, "office": {"keywords": "office building building bureau work", "shortname": ":office:", "unicode": "1F3E2", "aliases": ""}, "mute": {"keywords": "speaker with cancellation stroke sound volume", "shortname": ":mute:", "unicode": "1F507", "aliases": ""}, "clapper": {"keywords": "clapper board film movie record clapper board clapboard movie film take", "shortname": ":clapper:", "unicode": "1F3AC", "aliases": ""}, "haircut": {"keywords": "haircut female girl woman", "shortname": ":haircut:", "unicode": "1F487", "aliases": ""}, "soon": {"keywords": "soon with rightwards arrow above arrow words", "shortname": ":soon:", "unicode": "1F51C", "aliases": ""}, "symbols": {"keywords": "input symbol for symbols blue-square", "shortname": ":symbols:", "unicode": "1F523", "aliases": ""}, "sob": {"keywords": "loudly crying face cry face sad tears upset cry sob tears sad melancholy morn somber hurt", "shortname": ":sob:", "unicode": "1F62D", "aliases": ""}, "wolf": {"keywords": "wolf face animal nature", "shortname": ":wolf:", "unicode": "1F43A", "aliases": ""}, "japan": {"keywords": "silhouette of japan nation", "shortname": ":japan:", "unicode": "1F5FE", "aliases": ""}, "post_office": {"keywords": "japanese post office building communication email", "shortname": ":post_office:", "unicode": "1F3E3", "aliases": ""}, "last_quarter_moon_with_face": {"keywords": "last quarter moon with face nature moon last quarter anthropomorphic face sky night cheese phase", "shortname": ":last_quarter_moon_with_face:", "unicode": "1F31C", "aliases": ""}, "pray": {"keywords": "person with folded hands highfive hope namaste please wish pray high five hands sorrow regret sorry", "shortname": ":pray:", "unicode": "1F64F", "aliases": ""}, "flushed": {"keywords": "flushed face blush face flattered flush blush red pink cheeks shy", "shortname": ":flushed:", "unicode": "1F633", "aliases": ""}, "dizzy_face": {"keywords": "dizzy face dizzy drunk inebriated face spent unconscious xox", "shortname": ":dizzy_face:", "unicode": "1F635", "aliases": ""}, "rugby_football": {"keywords": "rugby football sports rugby football ball sport team england", "shortname": ":rugby_football:", "unicode": "1F3C9", "aliases": ""}, "currency_exchange": {"keywords": "currency exchange dollar money travel", "shortname": ":currency_exchange:", "unicode": "1F4B1", "aliases": ""}, "paperclip": {"keywords": "paperclip documents stationery", "shortname": ":paperclip:", "unicode": "1F4CE", "aliases": ""}, "moneybag": {"keywords": "money bag coins dollar payment", "shortname": ":moneybag:", "unicode": "1F4B0", "aliases": ""}, "mailbox_with_no_mail": {"keywords": "open mailbox with lowered flag email inbox", "shortname": ":mailbox_with_no_mail:", "unicode": "1F4ED", "aliases": ""}, "soccer": {"keywords": "soccer ball balls fifa football sports european football", "shortname": ":soccer:", "unicode": "26BD", "aliases": ""}, "dolls": {"keywords": "japanese dolls japanese kimono toy dolls japan japanese day girls emperor empress pray blessing imperial family royal", "shortname": ":dolls:", "unicode": "1F38E", "aliases": ""}, "poop": {"keywords": "pile of poo poop shit shitface turd poo", "shortname": ":poop:", "unicode": "1F4A9", "aliases": ":shit: :hankey: :poo:"}, "coffee": {"keywords": "hot beverage beverage cafe drink espresso", "shortname": ":coffee:", "unicode": "2615", "aliases": ""}, "full_moon_with_face": {"keywords": "full moon with face night moon full anthropomorphic face sky night cheese phase spooky werewolves monsters", "shortname": ":full_moon_with_face:", "unicode": "1F31D", "aliases": ""}, "neutral_face": {"keywords": "neutral face face indifference neutral objective impartial blank", "shortname": ":neutral_face:", "unicode": "1F610", "aliases": ""}, "elephant": {"keywords": "elephant animal nature nose thailand", "shortname": ":elephant:", "unicode": "1F418", "aliases": ""}, "open_mouth": {"keywords": "face with open mouth face impressed mouth open jaw gapping surprise wow", "shortname": ":open_mouth:", "unicode": "1F62E", "aliases": ""}, "bar_chart": {"keywords": "bar chart graph presentation stats", "shortname": ":bar_chart:", "unicode": "1F4CA", "aliases": ""}, "european_castle": {"keywords": "european castle building history royalty castle european residence royalty disneyland disney fort fortified moat tower princess prince lord king queen fortress nobel stronghold", "shortname": ":european_castle:", "unicode": "1F3F0", "aliases": ""}, "signal_strength": {"keywords": "antenna with bars blue-square", "shortname": ":signal_strength:", "unicode": "1F4F6", "aliases": ""}, "monkey_face": {"keywords": "monkey face animal nature", "shortname": ":monkey_face:", "unicode": "1F435", "aliases": ""}, "snake": {"keywords": "snake animal evil", "shortname": ":snake:", "unicode": "1F40D", "aliases": ""}, "kiss": {"keywords": "kiss mark affection face like lips love valentines", "shortname": ":kiss:", "unicode": "1F48B", "aliases": ""}, "blue_car": {"keywords": "recreational vehicle car suv car wagon automobile", "shortname": ":blue_car:", "unicode": "1F699", "aliases": ""}, "confetti_ball": {"keywords": "confetti ball festival party party congratulations confetti ball celebrate win birthday new years wedding", "shortname": ":confetti_ball:", "unicode": "1F38A", "aliases": ""}, "bath": {"keywords": "bath clean shower bath tub basin wash bubble soak bathroom soap water clean shampoo lather water", "shortname": ":bath:", "unicode": "1F6C0", "aliases": ""}, "bank": {"keywords": "bank building", "shortname": ":bank:", "unicode": "1F3E6", "aliases": ""}, "bread": {"keywords": "bread breakfast food toast wheat bread loaf yeast", "shortname": ":bread:", "unicode": "1F35E", "aliases": ""}, "rice_ball": {"keywords": "rice ball food japanese rice ball white nori seaweed japanese", "shortname": ":rice_ball:", "unicode": "1F359", "aliases": ""}, "oncoming_police_car": {"keywords": "oncoming police car enforcement law vehicle police car emergency ticket citation crime help officer", "shortname": ":oncoming_police_car:", "unicode": "1F694", "aliases": ""}, "tram": {"keywords": "tram transportation vehicle tram transportation transport", "shortname": ":tram:", "unicode": "1F68A", "aliases": ""}, "point_left": {"keywords": "white left pointing backhand index direction fingers hand", "shortname": ":point_left:", "unicode": "1F448", "aliases": ""}, "tokyo_tower": {"keywords": "tokyo tower japan photo", "shortname": ":tokyo_tower:", "unicode": "1F5FC", "aliases": ""}, "sos": {"keywords": "squared sos emergency help red-square words", "shortname": ":sos:", "unicode": "1F198", "aliases": ""}, "weary": {"keywords": "weary face face frustrated sad sleepy tired weary sleepy tired tiredness study finals school exhausted", "shortname": ":weary:", "unicode": "1F629", "aliases": ""}, "clock930": {"keywords": "clock face nine-thirty clock time", "shortname": ":clock930:", "unicode": "1F564", "aliases": ""}, "fishing_pole_and_fish": {"keywords": "fishing pole and fish food hobby fish fishing pole", "shortname": ":fishing_pole_and_fish:", "unicode": "1F3A3", "aliases": ""}, "repeat_one": {"keywords": "clockwise rightwards and leftwards open circle arr blue-square loop", "shortname": ":repeat_one:", "unicode": "1F502", "aliases": ""}, "bowling": {"keywords": "bowling fun play sports bowl bowling ball pin strike spare game", "shortname": ":bowling:", "unicode": "1F3B3", "aliases": ""}, "thumbsdown": {"keywords": "thumbs down sign hand no", "shortname": ":thumbsdown:", "unicode": "1F44E", "aliases": ":-1:"}, "older_woman": {"keywords": "older woman female girl women grandma grandmother", "shortname": ":older_woman:", "unicode": "1F475", "aliases": ":grandma:"}, "smiley_cat": {"keywords": "smiling cat face with open mouth animal cats happy smile smiley cat happy", "shortname": ":smiley_cat:", "unicode": "1F63A", "aliases": ""}, "information_source": {"keywords": "information source alphabet blue-square letter", "shortname": ":information_source:", "unicode": "2139", "aliases": ""}, "telescope": {"keywords": "telescope space stars", "shortname": ":telescope:", "unicode": "1F52D", "aliases": ""}, "beginner": {"keywords": "japanese symbol for beginner badge shield", "shortname": ":beginner:", "unicode": "1F530", "aliases": ""}, "postal_horn": {"keywords": "postal horn instrument music", "shortname": ":postal_horn:", "unicode": "1F4EF", "aliases": ""}, "house": {"keywords": "house building building home house home residence dwelling mansion bungalow ranch craftsman", "shortname": ":house:", "unicode": "1F3E0", "aliases": ""}, "fish": {"keywords": "fish animal food nature", "shortname": ":fish:", "unicode": "1F41F", "aliases": ""}, "construction_worker": {"keywords": "construction worker human male man wip", "shortname": ":construction_worker:", "unicode": "1F477", "aliases": ""}, "u7121": {"keywords": "squared cjk unified ideograph-7121 chinese japanese kanji no nothing orange-square", "shortname": ":u7121:", "unicode": "1F21A", "aliases": ""}, "mobile_phone_off": {"keywords": "mobile phone off mute", "shortname": ":mobile_phone_off:", "unicode": "1F4F4", "aliases": ""}, "unlock": {"keywords": "open lock privacy security", "shortname": ":unlock:", "unicode": "1F513", "aliases": ""}, "books": {"keywords": "books library literature", "shortname": ":books:", "unicode": "1F4DA", "aliases": ""}, "fist": {"keywords": "raised fist fingers grasp hand", "shortname": ":fist:", "unicode": "270A", "aliases": ""}, "beetle": {"keywords": "lady beetle insect nature lady bug ladybug ladybird beetle cow lady cow insect endearment", "shortname": ":beetle:", "unicode": "1F41E", "aliases": ""}, "lock_with_ink_pen": {"keywords": "lock with ink pen secret security", "shortname": ":lock_with_ink_pen:", "unicode": "1F50F", "aliases": ""}, "girl": {"keywords": "girl female woman", "shortname": ":girl:", "unicode": "1F467", "aliases": ""}, "calling": {"keywords": "mobile phone with rightwards arrow at left incoming iphone", "shortname": ":calling:", "unicode": "1F4F2", "aliases": ""}, "sunrise": {"keywords": "sunrise morning photo vacation view sunrise sun morning color sky", "shortname": ":sunrise:", "unicode": "1F305", "aliases": ""}, "briefcase": {"keywords": "briefcase business documents work", "shortname": ":briefcase:", "unicode": "1F4BC", "aliases": ""}, "exclamation": {"keywords": "heavy exclamation mark symbol surprise", "shortname": ":exclamation:", "unicode": "2757", "aliases": ""}, "video_game": {"keywords": "video game PS4 console controller play video game console controller nintendo xbox playstation", "shortname": ":video_game:", "unicode": "1F3AE", "aliases": ""}, "lipstick": {"keywords": "lipstick fashion female girl", "shortname": ":lipstick:", "unicode": "1F484", "aliases": ""}, "smirk": {"keywords": "smirking face mean prank smile smug smirking smirk smug smile half-smile conceited", "shortname": ":smirk:", "unicode": "1F60F", "aliases": ""}, "fish_cake": {"keywords": "fish cake with swirl design food fish cake kamboko swirl ramen noodles naruto", "shortname": ":fish_cake:", "unicode": "1F365", "aliases": ""}, "factory": {"keywords": "factory building", "shortname": ":factory:", "unicode": "1F3ED", "aliases": ""}, "baggage_claim": {"keywords": "baggage claim airport blue-square transport bag baggage luggage travel", "shortname": ":baggage_claim:", "unicode": "1F6C4", "aliases": ""}, "cherry_blossom": {"keywords": "cherry blossom flower nature plant cherry blossom tree flower", "shortname": ":cherry_blossom:", "unicode": "1F338", "aliases": ""}, "sparkle": {"keywords": "sparkle green-square stars", "shortname": ":sparkle:", "unicode": "2747", "aliases": ""}, "fountain": {"keywords": "fountain photo", "shortname": ":fountain:", "unicode": "26F2", "aliases": ""}, "zap": {"keywords": "high voltage sign lightning bolt thunder weather", "shortname": ":zap:", "unicode": "26A1", "aliases": ""}, "speak_no_evil": {"keywords": "speak-no-evil monkey animal monkey monkey mouth talk say words verbal verbalize oral iwazaru", "shortname": ":speak_no_evil:", "unicode": "1F64A", "aliases": ""}, "cyclone": {"keywords": "cyclone blue cloud swirl weather cyclone hurricane typhoon storm ocean", "shortname": ":cyclone:", "unicode": "1F300", "aliases": ""}, "blue_book": {"keywords": "blue book knowledge library read", "shortname": ":blue_book:", "unicode": "1F4D8", "aliases": ""}, "dancers": {"keywords": "woman with bunny ears bunny female girls women dancing dancers showgirl playboy costume bunny cancan", "shortname": ":dancers:", "unicode": "1F46F", "aliases": ""}, "flower_playing_cards": {"keywords": "flower playing cards playing card flower game august moon special", "shortname": ":flower_playing_cards:", "unicode": "1F3B4", "aliases": ""}, "umbrella": {"keywords": "umbrella with rain drops rain weather", "shortname": ":umbrella:", "unicode": "2614", "aliases": ""}, "octopus": {"keywords": "octopus animal creature ocean sea", "shortname": ":octopus:", "unicode": "1F419", "aliases": ""}, "hatching_chick": {"keywords": "hatching chick born chicken egg chick egg baby bird chicken young woman cute", "shortname": ":hatching_chick:", "unicode": "1F423", "aliases": ""}, "free": {"keywords": "squared free blue-square words", "shortname": ":free:", "unicode": "1F193", "aliases": ""}, "traffic_light": {"keywords": "horizontal traffic light traffic transportation traffic light stop go yield horizontal", "shortname": ":traffic_light:", "unicode": "1F6A5", "aliases": ""}, "grimacing": {"keywords": "grimacing face face grimace teeth grimace disapprove pain", "shortname": ":grimacing:", "unicode": "1F62C", "aliases": ""}, "bullettrain_side": {"keywords": "high-speed train transportation vehicle train bullet rail", "shortname": ":bullettrain_side:", "unicode": "1F684", "aliases": ""}, "poultry_leg": {"keywords": "poultry leg food meat poultry leg chicken fried", "shortname": ":poultry_leg:", "unicode": "1F357", "aliases": ""}, "grapes": {"keywords": "grapes food fruit grapes wine vinegar fruit cluster vine", "shortname": ":grapes:", "unicode": "1F347", "aliases": ""}, "smirk_cat": {"keywords": "cat face with wry smile animal cats smirk smirking wry confident confidence", "shortname": ":smirk_cat:", "unicode": "1F63C", "aliases": ""}, "lollipop": {"keywords": "lollipop candy food snack sweet lollipop stick lick sweet sugar candy", "shortname": ":lollipop:", "unicode": "1F36D", "aliases": ""}, "high_heel": {"keywords": "high-heeled shoe fashion female shoes", "shortname": ":high_heel:", "unicode": "1F460", "aliases": ""}, "black_medium_small_square": {"keywords": "black medium small square ", "shortname": ":black_medium_small_square:", "unicode": "25FE", "aliases": ""}, "green_book": {"keywords": "green book knowledge library read", "shortname": ":green_book:", "unicode": "1F4D7", "aliases": ""}, "atm": {"keywords": "automated teller machine atm cash withdrawal money deposit financial bank adam payday bank blue-square cash money payment", "shortname": ":atm:", "unicode": "1F3E7", "aliases": ""}, "fork_and_knife": {"keywords": "fork and knife cutlery kitchen fork knife restaurant meal food eat", "shortname": ":fork_and_knife:", "unicode": "1F374", "aliases": ""}, "passport_control": {"keywords": "passport control blue-square custom passport official travel control foreign identification", "shortname": ":passport_control:", "unicode": "1F6C2", "aliases": ""}, "bookmark": {"keywords": "bookmark favorite", "shortname": ":bookmark:", "unicode": "1F516", "aliases": ""}, "small_blue_diamond": {"keywords": "small blue diamond shape", "shortname": ":small_blue_diamond:", "unicode": "1F539", "aliases": ""}, "yum": {"keywords": "face savouring delicious food face happy joy smile tongue delicious savoring food eat yummy yum tasty savory", "shortname": ":yum:", "unicode": "1F60B", "aliases": ""}, "closed_lock_with_key": {"keywords": "closed lock with key privacy security", "shortname": ":closed_lock_with_key:", "unicode": "1F510", "aliases": ""}, "heartbeat": {"keywords": "beating heart affection like love valentines", "shortname": ":heartbeat:", "unicode": "1F493", "aliases": ""}, "blush": {"keywords": "smiling face with smiling eyes crush embarrassed face flushed happy shy smile smiling smile smiley", "shortname": ":blush:", "unicode": "1F60A", "aliases": ""}, "warning": {"keywords": "warning sign exclamation wip", "shortname": ":warning:", "unicode": "26A0", "aliases": ""}, "ophiuchus": {"keywords": "ophiuchus ophiuchus serpent snake astrology greek constellation stars zodiac purple-square sign horoscope", "shortname": ":ophiuchus:", "unicode": "26CE", "aliases": ""}, "revolving_hearts": {"keywords": "revolving hearts affection like love valentines heart hearts revolving moving circle multiple lovers", "shortname": ":revolving_hearts:", "unicode": "1F49E", "aliases": ""}, "fire_engine": {"keywords": "fire engine cars transportation vehicle fire fighter engine truck emergency medical", "shortname": ":fire_engine:", "unicode": "1F692", "aliases": ""}, "one": {"keywords": "digit one 1 blue-square numbers", "shortname": ":one:", "unicode": "0031-20E3", "aliases": ""}, "feet": {"keywords": "paw prints animal cat dog footprints paw pet tracking paw prints mark imprints footsteps animal lion bear dog cat raccoon critter feet pawsteps", "shortname": ":feet:", "unicode": "1F43E", "aliases": ""}, "sparkler": {"keywords": "firework sparkler night shine stars", "shortname": ":sparkler:", "unicode": "1F387", "aliases": ""}, "cow2": {"keywords": "cow animal beef nature ox cow milk dairy beef bessie moo", "shortname": ":cow2:", "unicode": "1F404", "aliases": ""}, "scissors": {"keywords": "black scissors cut stationery", "shortname": ":scissors:", "unicode": "2702", "aliases": ""}, "ring": {"keywords": "ring marriage propose valentines wedding", "shortname": ":ring:", "unicode": "1F48D", "aliases": ""}, "whale": {"keywords": "spouting whale animal nature ocean sea", "shortname": ":whale:", "unicode": "1F433", "aliases": ""}, "point_right": {"keywords": "white right pointing backhand index direction fingers hand", "shortname": ":point_right:", "unicode": "1F449", "aliases": ""}, "sheep": {"keywords": "sheep animal nature sheep wool flock follower ewe female lamb", "shortname": ":sheep:", "unicode": "1F411", "aliases": ""}, "horse": {"keywords": "horse face animal brown", "shortname": ":horse:", "unicode": "1F434", "aliases": ""}, "basketball": {"keywords": "basketball and hoop NBA balls sports basketball bball dribble hoop net swish rip city", "shortname": ":basketball:", "unicode": "1F3C0", "aliases": ""}, "monkey": {"keywords": "monkey animal nature monkey primate banana silly", "shortname": ":monkey:", "unicode": "1F412", "aliases": ""}, "blossom": {"keywords": "blossom flowers nature yellow blossom daisy flower", "shortname": ":blossom:", "unicode": "1F33C", "aliases": ""}, "gift_heart": {"keywords": "heart with ribbon love valentines", "shortname": ":gift_heart:", "unicode": "1F49D", "aliases": ""}, "top": {"keywords": "top with upwards arrow above blue-square words", "shortname": ":top:", "unicode": "1F51D", "aliases": ""}, "arrow_upper_right": {"keywords": "north east arrow blue-square", "shortname": ":arrow_upper_right:", "unicode": "2197", "aliases": ""}, "clock630": {"keywords": "clock face six-thirty clock time", "shortname": ":clock630:", "unicode": "1F561", "aliases": ""}, "station": {"keywords": "station public transportation vehicle station train subway", "shortname": ":station:", "unicode": "1F689", "aliases": ""}, "clock730": {"keywords": "clock face seven-thirty clock time", "shortname": ":clock730:", "unicode": "1F562", "aliases": ""}, "banana": {"keywords": "banana food fruit banana peel bunch", "shortname": ":banana:", "unicode": "1F34C", "aliases": ""}, "crescent_moon": {"keywords": "crescent moon night moon crescent waxing sky night cheese phase", "shortname": ":crescent_moon:", "unicode": "1F319", "aliases": ""}, "nail_care": {"keywords": "nail polish beauty manicure", "shortname": ":nail_care:", "unicode": "1F485", "aliases": ""}, "eyes": {"keywords": "eyes look peek stalk watch", "shortname": ":eyes:", "unicode": "1F440", "aliases": ""}, "shell": {"keywords": "spiral shell beach nature sea shell spiral beach sand crab nautilus", "shortname": ":shell:", "unicode": "1F41A", "aliases": ""}, "relieved": {"keywords": "relieved face face happiness massage phew relaxed relieved satisfied phew relief", "shortname": ":relieved:", "unicode": "1F60C", "aliases": ""}, "hotel": {"keywords": "hotel accomodation building checkin whotel hotel motel holiday inn hospital", "shortname": ":hotel:", "unicode": "1F3E8", "aliases": ""}, "small_red_triangle_down": {"keywords": "down-pointing red triangle shape", "shortname": ":small_red_triangle_down:", "unicode": "1F53B", "aliases": ""}, "broken_heart": {"keywords": "broken heart sad sorry", "shortname": ":broken_heart:", "unicode": "1F494", "aliases": ""}, "nut_and_bolt": {"keywords": "nut and bolt handy tools", "shortname": ":nut_and_bolt:", "unicode": "1F529", "aliases": ""}, "aerial_tramway": {"keywords": "aerial tramway transportation vehicle aerial tram tramway cable transport", "shortname": ":aerial_tramway:", "unicode": "1F6A1", "aliases": ""}, "sweat_drops": {"keywords": "splashing sweat symbol water", "shortname": ":sweat_drops:", "unicode": "1F4A6", "aliases": ""}, "panda_face": {"keywords": "panda face animal nature panda bear face cub cute endearment friendship love bamboo china black white", "shortname": ":panda_face:", "unicode": "1F43C", "aliases": ""}, "minibus": {"keywords": "minibus car transportation vehicle bus city transport transportation", "shortname": ":minibus:", "unicode": "1F690", "aliases": ""}, "b": {"keywords": "negative squared latin capital letter b alphabet letter red-square", "shortname": ":b:", "unicode": "1F171", "aliases": ""}, "unamused": {"keywords": "unamused face bored face indifference serious straight face unamused not amused depressed unhappy disapprove lame", "shortname": ":unamused:", "unicode": "1F612", "aliases": ""}, "fuelpump": {"keywords": "fuel pump gas station petroleum", "shortname": ":fuelpump:", "unicode": "26FD", "aliases": ""}, "bee": {"keywords": "honeybee animal insect bee queen buzz flower pollen sting honey hive bumble pollination", "shortname": ":bee:", "unicode": "1F41D", "aliases": ""}, "scream_cat": {"keywords": "weary cat face animal cats munch weary sleepy tired tiredness study finals school exhausted scream painting artist", "shortname": ":scream_cat:", "unicode": "1F640", "aliases": ""}, "musical_score": {"keywords": "musical score clef treble music musical score clef g-clef stave staff", "shortname": ":musical_score:", "unicode": "1F3BC", "aliases": ""}, "hourglass_flowing_sand": {"keywords": "hourglass with flowing sand countdown oldschool time", "shortname": ":hourglass_flowing_sand:", "unicode": "23F3", "aliases": ""}, "round_pushpin": {"keywords": "round pushpin stationery", "shortname": ":round_pushpin:", "unicode": "1F4CD", "aliases": ""}, "tophat": {"keywords": "top hat classy gentleman magic top hat cap beaver high tall stove pipe chimney topper london period piece magic magician", "shortname": ":tophat:", "unicode": "1F3A9", "aliases": ""}, "six_pointed_star": {"keywords": "six pointed star with middle dot purple-square", "shortname": ":six_pointed_star:", "unicode": "1F52F", "aliases": ""}, "dog2": {"keywords": "dog animal doge friend nature pet dog puppy pet friend woof bark fido", "shortname": ":dog2:", "unicode": "1F415", "aliases": ""}, "tractor": {"keywords": "tractor agriculture car farming vehicle tractor farm construction machine digger", "shortname": ":tractor:", "unicode": "1F69C", "aliases": ""}, "u6709": {"keywords": "squared cjk unified ideograph-6709 chinese have kanji orange-square", "shortname": ":u6709:", "unicode": "1F236", "aliases": ""}, "u6708": {"keywords": "squared cjk unified ideograph-6708 chinese japanese kanji moon orange-square", "shortname": ":u6708:", "unicode": "1F237", "aliases": ""}, "crying_cat_face": {"keywords": "crying cat face animal cats sad tears weep cry cat sob tears sad melancholy morn somber hurt", "shortname": ":crying_cat_face:", "unicode": "1F63F", "aliases": ""}, "loud_sound": {"keywords": "speaker with three sound waves ", "shortname": ":loud_sound:", "unicode": "1F50A", "aliases": ""}, "arrow_backward": {"keywords": "black left-pointing triangle arrow blue-square", "shortname": ":arrow_backward:", "unicode": "25C0", "aliases": ""}, "runner": {"keywords": "runner exercise man walking run runner jog exercise sprint race dash", "shortname": ":runner:", "unicode": "1F3C3", "aliases": ""}, "ram": {"keywords": "ram animal nature sheep ram sheep male horn horns", "shortname": ":ram:", "unicode": "1F40F", "aliases": ""}, "notebook": {"keywords": "notebook notes paper record stationery", "shortname": ":notebook:", "unicode": "1F4D3", "aliases": ""}, "dash": {"keywords": "dash symbol air fast shoo wind", "shortname": ":dash:", "unicode": "1F4A8", "aliases": ""}, "rat": {"keywords": "rat animal mouse rat rodent crooked snitch", "shortname": ":rat:", "unicode": "1F400", "aliases": ""}, "information_desk_person": {"keywords": "information desk person female girl human woman information help question answer sassy unimpressed attitude snarky", "shortname": ":information_desk_person:", "unicode": "1F481", "aliases": ""}, "anger": {"keywords": "anger symbol anger angry mad", "shortname": ":anger:", "unicode": "1F4A2", "aliases": ""}, "mailbox_with_mail": {"keywords": "open mailbox with raised flag communication email inbox", "shortname": ":mailbox_with_mail:", "unicode": "1F4EC", "aliases": ""}, "milky_way": {"keywords": "milky way photo space milky galaxy star stars planets space sky", "shortname": ":milky_way:", "unicode": "1F30C", "aliases": ""}, "pencil2": {"keywords": "pencil paper stationery write", "shortname": ":pencil2:", "unicode": "270F", "aliases": ""}, "microphone": {"keywords": "microphone PA music sound microphone mic audio sound voice karaoke", "shortname": ":microphone:", "unicode": "1F3A4", "aliases": ""}, "koala": {"keywords": "koala animal nature", "shortname": ":koala:", "unicode": "1F428", "aliases": ""}, "necktie": {"keywords": "necktie cloth fashion formal shirt suitup", "shortname": ":necktie:", "unicode": "1F454", "aliases": ""}, "wink": {"keywords": "winking face face happy mischievous secret wink winking friendly joke", "shortname": ":wink:", "unicode": "1F609", "aliases": ""}, "monorail": {"keywords": "monorail transportation vehicle train mono rail transport", "shortname": ":monorail:", "unicode": "1F69D", "aliases": ""}, "kissing_cat": {"keywords": "kissing cat face with closed eyes animal cats passion kiss puckered heart love", "shortname": ":kissing_cat:", "unicode": "1F63D", "aliases": ""}, "u55b6": {"keywords": "squared cjk unified ideograph-55b6 japanese opening hours", "shortname": ":u55b6:", "unicode": "1F23A", "aliases": ""}, "globe_with_meridians": {"keywords": "globe with meridians earth international world earth meridian globe space planet home", "shortname": ":globe_with_meridians:", "unicode": "1F310", "aliases": ""}, "snowflake": {"keywords": "snowflake christmas cold season weather winter xmas snowflake snow frozen droplet ice crystal cold chilly winter unique special below zero elsa", "shortname": ":snowflake:", "unicode": "2744", "aliases": ""}, "hibiscus": {"keywords": "hibiscus flowers plant vegetable hibiscus flower warm", "shortname": ":hibiscus:", "unicode": "1F33A", "aliases": ""}, "crystal_ball": {"keywords": "crystal ball disco party", "shortname": ":crystal_ball:", "unicode": "1F52E", "aliases": ""}, "koko": {"keywords": "squared katakana koko blue-square destination here japanese katakana", "shortname": ":koko:", "unicode": "1F201", "aliases": ""}, "chart": {"keywords": "chart with upwards trend and yen sign graph green-square", "shortname": ":chart:", "unicode": "1F4B9", "aliases": ""}, "credit_card": {"keywords": "credit card bill dollar money pay payment credit card loan purchase shopping mastercard visa american express wallet signature", "shortname": ":credit_card:", "unicode": "1F4B3", "aliases": ""}, "checkered_flag": {"keywords": "chequered flag contest finishline gokart rase checkered chequred race flag finish complete end", "shortname": ":checkered_flag:", "unicode": "1F3C1", "aliases": ""}, "eight": {"keywords": "digit eight 8 blue-square numbers", "shortname": ":eight:", "unicode": "0038-20E3", "aliases": ""}, "handbag": {"keywords": "handbag accessories accessory bag fashion", "shortname": ":handbag:", "unicode": "1F45C", "aliases": ""}, "pensive": {"keywords": "pensive face face okay sad pensive thoughtful think reflective wistful meditate serious", "shortname": ":pensive:", "unicode": "1F614", "aliases": ""}, "pager": {"keywords": "pager bbcall oldschool", "shortname": ":pager:", "unicode": "1F4DF", "aliases": ""}, "arrows_clockwise": {"keywords": "clockwise downwards and upwards open circle arrows sync", "shortname": ":arrows_clockwise:", "unicode": "1F503", "aliases": ""}, "ballot_box_with_check": {"keywords": "ballot box with check agree ok", "shortname": ":ballot_box_with_check:", "unicode": "2611", "aliases": ""}, "fried_shrimp": {"keywords": "fried shrimp animal food shrimp fried seafood small fish", "shortname": ":fried_shrimp:", "unicode": "1F364", "aliases": ""}, "mans_shoe": {"keywords": "mans shoe fashion male", "shortname": ":mans_shoe:", "unicode": "1F45E", "aliases": ""}, "raised_hand": {"keywords": "raised hand female girl woman", "shortname": ":raised_hand:", "unicode": "270B", "aliases": ""}, "m": {"keywords": "circled latin capital letter m alphabet blue-circle letter", "shortname": ":m:", "unicode": "24C2", "aliases": ""}, "dog": {"keywords": "dog face animal friend nature woof", "shortname": ":dog:", "unicode": "1F436", "aliases": ""}, "police_car": {"keywords": "police car cars enforcement law transportation vehicle police car emergency ticket citation crime help officer", "shortname": ":police_car:", "unicode": "1F693", "aliases": ""}, "new_moon_with_face": {"keywords": "new moon with face nature moon new anthropomorphic face sky night cheese phase", "shortname": ":new_moon_with_face:", "unicode": "1F31A", "aliases": ""}, "ideograph_advantage": {"keywords": "circled ideograph advantage chinese get kanji obtain", "shortname": ":ideograph_advantage:", "unicode": "1F250", "aliases": ""}, "pineapple": {"keywords": "pineapple food fruit nature pineapple pina tropical flower", "shortname": ":pineapple:", "unicode": "1F34D", "aliases": ""}, "black_circle": {"keywords": "medium black circle shape", "shortname": ":black_circle:", "unicode": "26AB", "aliases": ""}, "scream": {"keywords": "face screaming in fear face munch scream painting artist alien", "shortname": ":scream:", "unicode": "1F631", "aliases": ""}, "taxi": {"keywords": "taxi cars transportation uber vehicle taxi car automobile city transport service", "shortname": ":taxi:", "unicode": "1F695", "aliases": ""}, "walking": {"keywords": "pedestrian human man walk pedestrian stroll stride foot feet", "shortname": ":walking:", "unicode": "1F6B6", "aliases": ""}, "golf": {"keywords": "flag in hole business sports", "shortname": ":golf:", "unicode": "26F3", "aliases": ""}, "minidisc": {"keywords": "minidisc data disc disk record technology", "shortname": ":minidisc:", "unicode": "1F4BD", "aliases": ""}, "horse_racing": {"keywords": "horse racing animal betting competition horse race racing jockey triple crown", "shortname": ":horse_racing:", "unicode": "1F3C7", "aliases": ""}, "radio": {"keywords": "radio communication music podcast program", "shortname": ":radio:", "unicode": "1F4FB", "aliases": ""}, "point_down": {"keywords": "white down pointing backhand index direction fingers hand", "shortname": ":point_down:", "unicode": "1F447", "aliases": ""}, "chicken": {"keywords": "chicken animal cluck chicken hen poultry livestock", "shortname": ":chicken:", "unicode": "1F414", "aliases": ""}, "copyright": {"keywords": "copyright sign ip license", "shortname": ":copyright:", "unicode": "00A9", "aliases": ""}, "arrow_lower_right": {"keywords": "south east arrow arrow blue-square", "shortname": ":arrow_lower_right:", "unicode": "2198", "aliases": ""}, "city_sunset": {"keywords": "sunset over buildings photo city scape sunrise dawn light morning metropolitan rise sun", "shortname": ":city_sunset:", "unicode": "1F307", "aliases": ":city_sunrise:"}, "camel": {"keywords": "bactrian camel animal hot nature bactrian camel hump desert central asia heat hot water hump day wednesday sex", "shortname": ":camel:", "unicode": "1F42B", "aliases": ""}, "waning_crescent_moon": {"keywords": "waning crescent moon symbol nature moon crescent waning sky night cheese phase", "shortname": ":waning_crescent_moon:", "unicode": "1F318", "aliases": ""}, "cupid": {"keywords": "heart with arrow affection heart like love valentines", "shortname": ":cupid:", "unicode": "1F498", "aliases": ""}, "mens": {"keywords": "mens symbol restroom toilet wc men bathroom restroom sign boy male avatar", "shortname": ":mens:", "unicode": "1F6B9", "aliases": ""}, "virgo": {"keywords": "virgo sign virgo maiden astrology greek constellation stars zodiac sign zodiac horoscope", "shortname": ":virgo:", "unicode": "264D", "aliases": ""}, "libra": {"keywords": "libra libra scales astrology greek constellation stars zodiac sign purple-square sign zodiac horoscope", "shortname": ":libra:", "unicode": "264E", "aliases": ""}, "busts_in_silhouette": {"keywords": "busts in silhouette group human man person team user silhouette silhouettes people user members accounts relationship shadow", "shortname": ":busts_in_silhouette:", "unicode": "1F465", "aliases": ""}, "rice": {"keywords": "cooked rice food rice white grain food bowl", "shortname": ":rice:", "unicode": "1F35A", "aliases": ""}, "lips": {"keywords": "mouth kiss mouth", "shortname": ":lips:", "unicode": "1F444", "aliases": ""}, "alarm_clock": {"keywords": "alarm clock time wake", "shortname": ":alarm_clock:", "unicode": "23F0", "aliases": ""}, "couplekiss": {"keywords": "kiss dating like love marriage valentines", "shortname": ":couplekiss:", "unicode": "1F48F", "aliases": ""}, "sagittarius": {"keywords": "sagittarius sagittarius centaur archer astrology greek constellation stars zodiac sign sign zodiac horoscope", "shortname": ":sagittarius:", "unicode": "2650", "aliases": ""}, "electric_plug": {"keywords": "electric plug charger power", "shortname": ":electric_plug:", "unicode": "1F50C", "aliases": ""}, "circus_tent": {"keywords": "circus tent carnival festival party circus tent event carnival big top canvas", "shortname": ":circus_tent:", "unicode": "1F3AA", "aliases": ""}, "watch": {"keywords": "watch accessories time", "shortname": ":watch:", "unicode": "231A", "aliases": ""}, "arrow_up": {"keywords": "upwards black arrow blue-square", "shortname": ":arrow_up:", "unicode": "2B06", "aliases": ""}, "bear": {"keywords": "bear face animal nature", "shortname": ":bear:", "unicode": "1F43B", "aliases": ""}, "frowning": {"keywords": "frowning face with open mouth aw face frown sad pout sulk glower", "shortname": ":frowning:", "unicode": "1F626", "aliases": ""}, "incoming_envelope": {"keywords": "incoming envelope email inbox", "shortname": ":incoming_envelope:", "unicode": "1F4E8", "aliases": ""}, "watermelon": {"keywords": "watermelon food fruit melon watermelon summer fruit large", "shortname": ":watermelon:", "unicode": "1F349", "aliases": ""}, "wedding": {"keywords": "wedding affection bride couple groom like love marriage", "shortname": ":wedding:", "unicode": "1F492", "aliases": ""}, "yellow_heart": {"keywords": "yellow heart affection like love valentines yellow gold heart love friendship happy happiness trust compassionate respectful honest caring selfless", "shortname": ":yellow_heart:", "unicode": "1F49B", "aliases": ""}, "no_mobile_phones": {"keywords": "no mobile phones iphone mute", "shortname": ":no_mobile_phones:", "unicode": "1F4F5", "aliases": ""}, "negative_squared_cross_mark": {"keywords": "negative squared cross mark deny green-square no x", "shortname": ":negative_squared_cross_mark:", "unicode": "274E", "aliases": ""}, "cry": {"keywords": "crying face face sad sad cry tear weep tears", "shortname": ":cry:", "unicode": "1F622", "aliases": ""}, "worried": {"keywords": "worried face concern face nervous worried anxious distressed nervous tense", "shortname": ":worried:", "unicode": "1F61F", "aliases": ""}, "microscope": {"keywords": "microscope experiment laboratory zoomin", "shortname": ":microscope:", "unicode": "1F52C", "aliases": ""}, "older_man": {"keywords": "older man human male men", "shortname": ":older_man:", "unicode": "1F474", "aliases": ""}, "whale2": {"keywords": "whale animal nature ocean sea whale blubber bloated fat large massive", "shortname": ":whale2:", "unicode": "1F40B", "aliases": ""}, "x": {"keywords": "cross mark delete no remove", "shortname": ":x:", "unicode": "274C", "aliases": ""}, "interrobang": {"keywords": "exclamation question mark punctuation surprise wat", "shortname": ":interrobang:", "unicode": "2049", "aliases": ""}, "japanese_ogre": {"keywords": "japanese ogre monster japanese oni demon troll ogre folklore monster devil mask theater horns teeth", "shortname": ":japanese_ogre:", "unicode": "1F479", "aliases": ""}, "evergreen_tree": {"keywords": "evergreen tree nature plant evergreen tree needles christmas", "shortname": ":evergreen_tree:", "unicode": "1F332", "aliases": ""}, "oncoming_taxi": {"keywords": "oncoming taxi cars uber vehicle taxi car automobile city transport service", "shortname": ":oncoming_taxi:", "unicode": "1F696", "aliases": ""}, "man_with_turban": {"keywords": "man with turban male turban headdress headwear pagri india indian mummy wisdom peace", "shortname": ":man_with_turban:", "unicode": "1F473", "aliases": ""}, "arrow_up_small": {"keywords": "up-pointing small red triangle blue-square", "shortname": ":arrow_up_small:", "unicode": "1F53C", "aliases": ""}, "art": {"keywords": "artist palette design draw paint artist palette art colors paint draw brush pastels oils", "shortname": ":art:", "unicode": "1F3A8", "aliases": ""}, "cocktail": {"keywords": "cocktail glass alcohol beverage drink drunk cocktail mixed drink alcohol glass martini bar", "shortname": ":cocktail:", "unicode": "1F378", "aliases": ""}, "fries": {"keywords": "french fries chips food fries french potato fry russet idaho", "shortname": ":fries:", "unicode": "1F35F", "aliases": ""}, "hear_no_evil": {"keywords": "hear-no-evil monkey animal monkey monkey ears hear sound kikazaru", "shortname": ":hear_no_evil:", "unicode": "1F649", "aliases": ""}, "convenience_store": {"keywords": "convenience store building", "shortname": ":convenience_store:", "unicode": "1F3EA", "aliases": ""}, "seat": {"keywords": "seat sit", "shortname": ":seat:", "unicode": "1F4BA", "aliases": ""}, "computer": {"keywords": "personal computer laptop tech", "shortname": ":computer:", "unicode": "1F4BB", "aliases": ""}, "arrow_down": {"keywords": "downwards black arrow arrow blue-square", "shortname": ":arrow_down:", "unicode": "2B07", "aliases": ""}, "arrow_upper_left": {"keywords": "north west arrow blue-square", "shortname": ":arrow_upper_left:", "unicode": "2196", "aliases": ""}, "parking": {"keywords": "negative squared latin capital letter p alphabet blue-square cars letter", "shortname": ":parking:", "unicode": "1F17F", "aliases": ""}, "pisces": {"keywords": "pisces pisces fish astrology greek constellation stars zodiac sign purple-square sign zodiac horoscope", "shortname": ":pisces:", "unicode": "2653", "aliases": ""}, "calendar": {"keywords": "tear-off calendar schedule", "shortname": ":calendar:", "unicode": "1F4C6", "aliases": ""}, "hammer": {"keywords": "hammer done judge law ruling tools verdict", "shortname": ":hammer:", "unicode": "1F528", "aliases": ""}, "bomb": {"keywords": "bomb boom explode", "shortname": ":bomb:", "unicode": "1F4A3", "aliases": ""}, "hourglass": {"keywords": "hourglass clock oldschool time", "shortname": ":hourglass:", "unicode": "231B", "aliases": ""}, "loudspeaker": {"keywords": "public address loudspeaker sound volume", "shortname": ":loudspeaker:", "unicode": "1F4E2", "aliases": ""}, "shower": {"keywords": "shower bath clean wash bathroom shower soap water clean shampoo lather", "shortname": ":shower:", "unicode": "1F6BF", "aliases": ""}, "black_joker": {"keywords": "playing card black joker cards game poker", "shortname": ":black_joker:", "unicode": "1F0CF", "aliases": ""}, "ferris_wheel": {"keywords": "ferris wheel carnival londoneye photo farris wheel amusement park fair ride entertainment", "shortname": ":ferris_wheel:", "unicode": "1F3A1", "aliases": ""}, "bicyclist": {"keywords": "bicyclist bike exercise hipster sports bicyclist road bike pedal bicycle transportation", "shortname": ":bicyclist:", "unicode": "1F6B4", "aliases": ""}, "no_mouth": {"keywords": "face without mouth face hellokitty mouth silent vapid", "shortname": ":no_mouth:", "unicode": "1F636", "aliases": ""}, "postbox": {"keywords": "postbox email envelope letter", "shortname": ":postbox:", "unicode": "1F4EE", "aliases": ""}, "large_blue_diamond": {"keywords": "large blue diamond shape", "shortname": ":large_blue_diamond:", "unicode": "1F537", "aliases": ""}, "non-potable_water": {"keywords": "non-potable water symbol drink faucet tap non-potable water not drinkable dirty gross aqua h20", "shortname": ":non-potable_water:", "unicode": "1F6B1", "aliases": ""}, "icecream": {"keywords": "soft ice cream desert food hot icecream ice cream dairy dessert cold soft serve cone yogurt", "shortname": ":icecream:", "unicode": "1F366", "aliases": ""}, "diamonds": {"keywords": "black diamond suit cards poker", "shortname": ":diamonds:", "unicode": "2666", "aliases": ""}, "princess": {"keywords": "princess blond crown female girl woman princess royal royalty king queen daughter disney high-maintenance", "shortname": ":princess:", "unicode": "1F478", "aliases": ""}, "no_entry_sign": {"keywords": "no entry sign denied disallow forbid limit stop no stop entry", "shortname": ":no_entry_sign:", "unicode": "1F6AB", "aliases": ""}, "shaved_ice": {"keywords": "shaved ice desert hot shaved ice dessert treat syrup flavoring", "shortname": ":shaved_ice:", "unicode": "1F367", "aliases": ""}, "tent": {"keywords": "tent camp outdoors photo", "shortname": ":tent:", "unicode": "26FA", "aliases": ""}, "flashlight": {"keywords": "electric torch dark", "shortname": ":flashlight:", "unicode": "1F526", "aliases": ""}, "raising_hand": {"keywords": "happy person raising one hand female girl woman hand raise notice attention answer", "shortname": ":raising_hand:", "unicode": "1F64B", "aliases": ""}, "wc": {"keywords": "water closet blue-square restroom toilet water closet toilet bathroom throne porcelain waste flush plumbing", "shortname": ":wc:", "unicode": "1F6BE", "aliases": ""}, "joy": {"keywords": "face with tears of joy cry face haha happy tears tears cry joy happy weep", "shortname": ":joy:", "unicode": "1F602", "aliases": ""}, "moyai": {"keywords": "moyai island stone", "shortname": ":moyai:", "unicode": "1F5FF", "aliases": ""}, "aquarius": {"keywords": "aquarius aquarius water bearer astrology greek constellation stars zodiac sign purple-square sign zodiac horoscope", "shortname": ":aquarius:", "unicode": "2652", "aliases": ""}, "mailbox": {"keywords": "closed mailbox with raised flag communication email inbox", "shortname": ":mailbox:", "unicode": "1F4EB", "aliases": ""}, "guitar": {"keywords": "guitar instrument music guitar string music instrument jam rock acoustic electric", "shortname": ":guitar:", "unicode": "1F3B8", "aliases": ""}, "ok_woman": {"keywords": "face with ok gesture female girl human pink women yes ok okay accept", "shortname": ":ok_woman:", "unicode": "1F646", "aliases": ""}, "key": {"keywords": "key door lock password", "shortname": ":key:", "unicode": "1F511", "aliases": ""}, "blue_heart": {"keywords": "blue heart affection like love valentines blue heart love stability truth loyalty trust", "shortname": ":blue_heart:", "unicode": "1F499", "aliases": ""}, "statue_of_liberty": {"keywords": "statue of liberty american newyork", "shortname": ":statue_of_liberty:", "unicode": "1F5FD", "aliases": ""}, "cop": {"keywords": "police officer arrest enforcement law man police", "shortname": ":cop:", "unicode": "1F46E", "aliases": ""}, "clock1230": {"keywords": "clock face twelve-thirty clock time", "shortname": ":clock1230:", "unicode": "1F567", "aliases": ""}, "tropical_drink": {"keywords": "tropical drink beverage tropical drink mixed pineapple coconut pina fruit umbrella", "shortname": ":tropical_drink:", "unicode": "1F379", "aliases": ""}, "cow": {"keywords": "cow face animal beef ox", "shortname": ":cow:", "unicode": "1F42E", "aliases": ""}, "restroom": {"keywords": "restroom blue-square woman man unisex bathroom restroom sign shared toilet", "shortname": ":restroom:", "unicode": "1F6BB", "aliases": ""}, "white_large_square": {"keywords": "white large square shape", "shortname": ":white_large_square:", "unicode": "2B1C", "aliases": ""}, "eggplant": {"keywords": "aubergine aubergine food nature vegetable eggplant aubergine fruit purple penis", "shortname": ":eggplant:", "unicode": "1F346", "aliases": ""}, "low_brightness": {"keywords": "low brightness symbol summer sun", "shortname": ":low_brightness:", "unicode": "1F505", "aliases": ""}, "four_leaf_clover": {"keywords": "four leaf clover lucky nature plant vegetable clover four leaf luck irish saint patrick green", "shortname": ":four_leaf_clover:", "unicode": "1F340", "aliases": ""}, "space_invader": {"keywords": "alien monster arcade game", "shortname": ":space_invader:", "unicode": "1F47E", "aliases": ""}, "pig_nose": {"keywords": "pig nose animal oink pig nose snout food eat cute oink pink smell truffle", "shortname": ":pig_nose:", "unicode": "1F43D", "aliases": ""}, "cancer": {"keywords": "cancer cancer crab astrology greek constellation stars zodiac sign sign zodiac horoscope", "shortname": ":cancer:", "unicode": "264B", "aliases": ""}, "bell": {"keywords": "bell chime christmas notification sound xmas", "shortname": ":bell:", "unicode": "1F514", "aliases": ""}, "battery": {"keywords": "battery energy power sustain", "shortname": ":battery:", "unicode": "1F50B", "aliases": ""}, "jeans": {"keywords": "jeans fashion shopping jeans pants blue denim levi's levi designer work skinny", "shortname": ":jeans:", "unicode": "1F456", "aliases": ""}, "leo": {"keywords": "leo leo lion astrology greek constellation stars zodiac sign purple-square sign zodiac horoscope", "shortname": ":leo:", "unicode": "264C", "aliases": ""}, "cd": {"keywords": "optical disc disc disk dvd technology", "shortname": ":cd:", "unicode": "1F4BF", "aliases": ""}, "dancer": {"keywords": "dancer female fun girl woman dance dancer dress fancy boogy party celebrate ballet tango cha cha music", "shortname": ":dancer:", "unicode": "1F483", "aliases": ""}, "page_facing_up": {"keywords": "page facing up documents", "shortname": ":page_facing_up:", "unicode": "1F4C4", "aliases": ""}, "church": {"keywords": "church building christ religion", "shortname": ":church:", "unicode": "26EA", "aliases": ""}, "boar": {"keywords": "boar animal nature", "shortname": ":boar:", "unicode": "1F417", "aliases": ""}, "trumpet": {"keywords": "trumpet brass music trumpet brass music instrument", "shortname": ":trumpet:", "unicode": "1F3BA", "aliases": ""}, "angel": {"keywords": "baby angel baby angel halo cupid wings halo heaven wings jesus", "shortname": ":angel:", "unicode": "1F47C", "aliases": ""}, "imp": {"keywords": "imp angry devil evil horns cute devil", "shortname": ":imp:", "unicode": "1F47F", "aliases": ""}, "underage": {"keywords": "no one under eighteen symbol 18 drink night pub", "shortname": ":underage:", "unicode": "1F51E", "aliases": ""}, "three": {"keywords": "digit three 3 blue-square numbers prime", "shortname": ":three:", "unicode": "0033-20E3", "aliases": ""}, "oden": {"keywords": "oden food japanese oden seafood casserole stew", "shortname": ":oden:", "unicode": "1F362", "aliases": ""}, "beer": {"keywords": "beer mug beverage drink drunk party pub relax beer hops mug barley malt yeast portland oregon brewery micro pint boot", "shortname": ":beer:", "unicode": "1F37A", "aliases": ""}, "clock430": {"keywords": "clock face four-thirty clock time", "shortname": ":clock430:", "unicode": "1F55F", "aliases": ""}, "stuck_out_tongue_closed_eyes": {"keywords": "face with stuck-out tongue and tightly-closed eyes face mischievous playful prank tongue kidding silly playful ecstatic", "shortname": ":stuck_out_tongue_closed_eyes:", "unicode": "1F61D", "aliases": ""}, "helicopter": {"keywords": "helicopter transportation vehicle helicopter helo gyro gyrocopter", "shortname": ":helicopter:", "unicode": "1F681", "aliases": ""}, "heavy_division_sign": {"keywords": "heavy division sign calculation divide math", "shortname": ":heavy_division_sign:", "unicode": "2797", "aliases": ""}, "disappointed": {"keywords": "disappointed face disappointed disappoint frown depressed discouraged face sad upset", "shortname": ":disappointed:", "unicode": "1F61E", "aliases": ""}, "performing_arts": {"keywords": "performing arts acting drama theater performing arts performance entertainment acting story mask masks", "shortname": ":performing_arts:", "unicode": "1F3AD", "aliases": ""}, "mushroom": {"keywords": "mushroom plant vegetable mushroom fungi food fungus", "shortname": ":mushroom:", "unicode": "1F344", "aliases": ""}, "fire": {"keywords": "fire cook hot flame", "shortname": ":fire:", "unicode": "1F525", "aliases": ":flame:"}, "two_hearts": {"keywords": "two hearts affection like love valentines heart hearts two love emotion", "shortname": ":two_hearts:", "unicode": "1F495", "aliases": ""}, "arrow_down_small": {"keywords": "down-pointing small red triangle arrow blue-square", "shortname": ":arrow_down_small:", "unicode": "1F53D", "aliases": ""}, "tiger": {"keywords": "tiger face animal", "shortname": ":tiger:", "unicode": "1F42F", "aliases": ""}, "cold_sweat": {"keywords": "face with open mouth and cold sweat face nervous sweat exasperated frustrated", "shortname": ":cold_sweat:", "unicode": "1F630", "aliases": ""}, "bulb": {"keywords": "electric light bulb electricity light idea bulb light", "shortname": ":bulb:", "unicode": "1F4A1", "aliases": ""}, "heart_eyes": {"keywords": "smiling face with heart-shaped eyes affection crush face infatuation like love valentines smiling heart lovestruck love flirt smile heart-shaped", "shortname": ":heart_eyes:", "unicode": "1F60D", "aliases": ""}, "sound": {"keywords": "speaker with one sound wave speaker volume", "shortname": ":sound:", "unicode": "1F509", "aliases": ""}, "ant": {"keywords": "ant animal insect ant queen insect team", "shortname": ":ant:", "unicode": "1F41C", "aliases": ""}, "blowfish": {"keywords": "blowfish food nature ocean sea blowfish pufferfish puffer ballonfish toadfish fugu fish sushi", "shortname": ":blowfish:", "unicode": "1F421", "aliases": ""}, "speech_balloon": {"keywords": "speech balloon bubble words speech balloon talk conversation communication comic dialogue", "shortname": ":speech_balloon:", "unicode": "1F4AC", "aliases": ""}, "earth_africa": {"keywords": "earth globe europe-africa globe international world earth globe space planet africa europe home", "shortname": ":earth_africa:", "unicode": "1F30D", "aliases": ""}, "arrow_right_hook": {"keywords": "rightwards arrow with hook blue-square", "shortname": ":arrow_right_hook:", "unicode": "21AA", "aliases": ""}, "seedling": {"keywords": "seedling grass lawn nature plant seedling plant new start grow", "shortname": ":seedling:", "unicode": "1F331", "aliases": ""}, "fearful": {"keywords": "fearful face face nervous oops scared terrified fear fearful scared frightened", "shortname": ":fearful:", "unicode": "1F628", "aliases": ""}, "envelope_with_arrow": {"keywords": "envelope with downwards arrow above email", "shortname": ":envelope_with_arrow:", "unicode": "1F4E9", "aliases": ""}, "gem": {"keywords": "gem stone blue ruby", "shortname": ":gem:", "unicode": "1F48E", "aliases": ""}, "grinning": {"keywords": "grinning face face happy joy smile grin grinning smiling smile smiley", "shortname": ":grinning:", "unicode": "1F600", "aliases": ""}, "bikini": {"keywords": "bikini beach fashion female girl swimming woman", "shortname": ":bikini:", "unicode": "1F459", "aliases": ""}, "gemini": {"keywords": "gemini gemini twins astrology greek constellation stars zodiac sign sign zodiac horoscope", "shortname": ":gemini:", "unicode": "264A", "aliases": ""}, "vertical_traffic_light": {"keywords": "vertical traffic light transportation traffic light stop go yield vertical", "shortname": ":vertical_traffic_light:", "unicode": "1F6A6", "aliases": ""}, "newspaper": {"keywords": "newspaper headline press", "shortname": ":newspaper:", "unicode": "1F4F0", "aliases": ""}, "kissing": {"keywords": "kissing face 3 face infatuation like love valentines kissing kiss pucker lips smooch", "shortname": ":kissing:", "unicode": "1F617", "aliases": ""}, "bathtub": {"keywords": "bathtub clean shower bath tub basin wash bubble soak bathroom soap water clean shampoo lather water", "shortname": ":bathtub:", "unicode": "1F6C1", "aliases": ""}, "anchor": {"keywords": "anchor ferry ship anchor ship boat ocean harbor marina shipyard sailor tattoo", "shortname": ":anchor:", "unicode": "2693", "aliases": ""}, "loop": {"keywords": "double curly loop curly", "shortname": ":loop:", "unicode": "27BF", "aliases": ""}, "swimmer": {"keywords": "swimmer sports swimmer swim water pool laps freestyle butterfly breaststroke backstroke", "shortname": ":swimmer:", "unicode": "1F3CA", "aliases": ""}, "seven": {"keywords": "digit seven 7 blue-square numbers prime", "shortname": ":seven:", "unicode": "0037-20E3", "aliases": ""}, "pound": {"keywords": "banknote with pound sign bills british currency england money sterling uk pound britain british banknote money currency paper cash bills", "shortname": ":pound:", "unicode": "1F4B7", "aliases": ""}, "two_women_holding_hands": {"keywords": "two women holding hands couple female friends like love women hands girlfriends friends sisters mother daughter gay homosexual couple unity", "shortname": ":two_women_holding_hands:", "unicode": "1F46D", "aliases": ""}, "sushi": {"keywords": "sushi food japanese sushi fish raw nigiri japanese", "shortname": ":sushi:", "unicode": "1F363", "aliases": ""}, "purse": {"keywords": "purse accessories fashion money purse clutch bag handbag coin bag accessory money ladies shopping", "shortname": ":purse:", "unicode": "1F45B", "aliases": ""}, "telephone": {"keywords": "black telephone communication dial technology", "shortname": ":telephone:", "unicode": "260E", "aliases": ""}, "u5272": {"keywords": "squared cjk unified ideograph-5272 chinese cut divide kanji pink", "shortname": ":u5272:", "unicode": "1F239", "aliases": ""}, "rooster": {"keywords": "rooster animal chicken nature rooster cockerel cock male cock-a-doodle-doo crowing", "shortname": ":rooster:", "unicode": "1F413", "aliases": ""}, "rice_scene": {"keywords": "moon viewing ceremony photo moon viewing observing otsukimi tsukimi rice scene festival autumn", "shortname": ":rice_scene:", "unicode": "1F391", "aliases": ""}, "vs": {"keywords": "squared vs orange-square words", "shortname": ":vs:", "unicode": "1F19A", "aliases": ""}, "arrow_forward": {"keywords": "black right-pointing triangle arrow blue-square", "shortname": ":arrow_forward:", "unicode": "25B6", "aliases": ""}, "violin": {"keywords": "violin instrument music violin fiddle music instrument", "shortname": ":violin:", "unicode": "1F3BB", "aliases": ""}, "bullettrain_front": {"keywords": "high-speed train with bullet nose transportation train bullet rail", "shortname": ":bullettrain_front:", "unicode": "1F685", "aliases": ""}, "mouse": {"keywords": "mouse face animal nature", "shortname": ":mouse:", "unicode": "1F42D", "aliases": ""}, "bookmark_tabs": {"keywords": "bookmark tabs favorite", "shortname": ":bookmark_tabs:", "unicode": "1F4D1", "aliases": ""}, "shirt": {"keywords": "t-shirt cloth fashion", "shortname": ":shirt:", "unicode": "1F455", "aliases": ""}, "white_circle": {"keywords": "medium white circle shape", "shortname": ":white_circle:", "unicode": "26AA", "aliases": ""}, "balloon": {"keywords": "balloon celebration party balloon birthday celebration helium gas children float", "shortname": ":balloon:", "unicode": "1F388", "aliases": ""}, "heart_decoration": {"keywords": "heart decoration like love purple-square", "shortname": ":heart_decoration:", "unicode": "1F49F", "aliases": ""}, "joy_cat": {"keywords": "cat face with tears of joy animal cats haha happy tears happy tears cry joy", "shortname": ":joy_cat:", "unicode": "1F639", "aliases": ""}, "kimono": {"keywords": "kimono dress fashion female japanese women", "shortname": ":kimono:", "unicode": "1F458", "aliases": ""}, "speaker": {"keywords": "speaker sound listen hear noise", "shortname": ":speaker:", "unicode": "1F508", "aliases": ""}, "train2": {"keywords": "train transportation vehicle train locomotive rail", "shortname": ":train2:", "unicode": "1F686", "aliases": ""}, "first_quarter_moon": {"keywords": "first quarter moon symbol nature moon quarter first sky night cheese phase", "shortname": ":first_quarter_moon:", "unicode": "1F313", "aliases": ""}, "left_luggage": {"keywords": "left luggage blue-square travel bag baggage luggage travel", "shortname": ":left_luggage:", "unicode": "1F6C5", "aliases": ""}, "meat_on_bone": {"keywords": "meat on bone food good meat bone animal cooked", "shortname": ":meat_on_bone:", "unicode": "1F356", "aliases": ""}, "light_rail": {"keywords": "light rail transportation vehicle train rail light", "shortname": ":light_rail:", "unicode": "1F688", "aliases": ""}, "satellite": {"keywords": "satellite antenna communication", "shortname": ":satellite:", "unicode": "1F4E1", "aliases": ""}, "arrow_heading_up": {"keywords": "arrow pointing rightwards then curving upwards arrow blue-square", "shortname": ":arrow_heading_up:", "unicode": "2934", "aliases": ""}, "snail": {"keywords": "snail animal shell slow snail slow escargot french appetizer", "shortname": ":snail:", "unicode": "1F40C", "aliases": ""}, "rainbow": {"keywords": "rainbow happy nature photo sky unicorn rainbow color pride diversity spectrum refract leprechaun gold", "shortname": ":rainbow:", "unicode": "1F308", "aliases": ""}, "u6307": {"keywords": "squared cjk unified ideograph-6307 chinese green-square kanji point", "shortname": ":u6307:", "unicode": "1F22F", "aliases": ""}, "leopard": {"keywords": "leopard animal nature leopard cat spot spotted sexy", "shortname": ":leopard:", "unicode": "1F406", "aliases": ""}, "diamond_shape_with_a_dot_inside": {"keywords": "diamond shape with a dot inside diamond cute cuteness kawaii japanese glyph adorable", "shortname": ":diamond_shape_with_a_dot_inside:", "unicode": "1F4A0", "aliases": ""}, "barber": {"keywords": "barber pole hair salon style", "shortname": ":barber:", "unicode": "1F488", "aliases": ""}, "christmas_tree": {"keywords": "christmas tree celebration december festival vacation xmas christmas xmas santa holiday winter december santa evergreen ornaments jesus gifts presents", "shortname": ":christmas_tree:", "unicode": "1F384", "aliases": ""}, "slot_machine": {"keywords": "slot machine bet gamble vegas slot machine gamble one-armed bandit slots luck", "shortname": ":slot_machine:", "unicode": "1F3B0", "aliases": ""}, "ice_cream": {"keywords": "ice cream desert food hot icecream ice cream dairy dessert cold soft serve cone waffle", "shortname": ":ice_cream:", "unicode": "1F368", "aliases": ""}, "foggy": {"keywords": "foggy mountain photo bridge weather fog foggy", "shortname": ":foggy:", "unicode": "1F301", "aliases": ""}, "euro": {"keywords": "banknote with euro sign currency dollar money euro europe banknote money currency paper cash bills", "shortname": ":euro:", "unicode": "1F4B6", "aliases": ""}, "crossed_flags": {"keywords": "crossed flags japan", "shortname": ":crossed_flags:", "unicode": "1F38C", "aliases": ""}, "smile_cat": {"keywords": "grinning cat face with smiling eyes animal cats cat smile grin grinning", "shortname": ":smile_cat:", "unicode": "1F638", "aliases": ""}, "hushed": {"keywords": "hushed face face woo quiet hush whisper silent", "shortname": ":hushed:", "unicode": "1F62F", "aliases": ""}, "triangular_ruler": {"keywords": "triangular ruler architect math sketch stationery", "shortname": ":triangular_ruler:", "unicode": "1F4D0", "aliases": ""}, "ocean": {"keywords": "water wave sea water wave ocean wave surf beach tide", "shortname": ":ocean:", "unicode": "1F30A", "aliases": ""}, "page_with_curl": {"keywords": "page with curl documents", "shortname": ":page_with_curl:", "unicode": "1F4C3", "aliases": ""}, "flags": {"keywords": "carp streamer banner carp fish japanese koinobori children kids boys celebration happiness carp streamers japanese holiday flags", "shortname": ":flags:", "unicode": "1F38F", "aliases": ""}, "hearts": {"keywords": "black heart suit cards poker", "shortname": ":hearts:", "unicode": "2665", "aliases": ""}, "muscle": {"keywords": "flexed biceps arm flex hand strong muscle bicep", "shortname": ":muscle:", "unicode": "1F4AA", "aliases": ""}, "love_hotel": {"keywords": "love hotel affection dating like love hotel love sex romance leisure adultery prostitution hospital birth happy", "shortname": ":love_hotel:", "unicode": "1F3E9", "aliases": ""}, "snowman": {"keywords": "snowman without snow christmas cold season weather winter xmas", "shortname": ":snowman:", "unicode": "26C4", "aliases": ""}, "eyeglasses": {"keywords": "eyeglasses accessories eyesight fashion eyeglasses spectacles eye sight nearsightedness myopia farsightedness hyperopia frames vision see blurry contacts", "shortname": ":eyeglasses:", "unicode": "1F453", "aliases": ""}, "rocket": {"keywords": "rocket launch ship staffmode rocket space spacecraft astronaut cosmonaut", "shortname": ":rocket:", "unicode": "1F680", "aliases": ""}, "yen": {"keywords": "banknote with yen sign currency dollar japanese money yen japan japanese banknote money currency paper cash bill", "shortname": ":yen:", "unicode": "1F4B4", "aliases": ""}, "straight_ruler": {"keywords": "straight ruler stationery", "shortname": ":straight_ruler:", "unicode": "1F4CF", "aliases": ""}, "u7533": {"keywords": "squared cjk unified ideograph-7533 chinese japanese kanji", "shortname": ":u7533:", "unicode": "1F238", "aliases": ""}, "racehorse": {"keywords": "horse animal gamble horse powerful draft calvary cowboy cowgirl mounted race ride gallop trot colt filly mare stallion gelding yearling thoroughbred pony", "shortname": ":racehorse:", "unicode": "1F40E", "aliases": ""}, "sleepy": {"keywords": "sleepy face face rest tired sleepy tired exhausted", "shortname": ":sleepy:", "unicode": "1F62A", "aliases": ""}, "green_apple": {"keywords": "green apple fruit nature apple fruit green pie granny smith core", "shortname": ":green_apple:", "unicode": "1F34F", "aliases": ""}, "bridge_at_night": {"keywords": "bridge at night photo sanfrancisco bridge night water road evening suspension golden gate", "shortname": ":bridge_at_night:", "unicode": "1F309", "aliases": ""}, "doughnut": {"keywords": "doughnut desert food snack sweet doughnut donut pastry fried dessert breakfast police homer sweet", "shortname": ":doughnut:", "unicode": "1F369", "aliases": ""}, "first_quarter_moon_with_face": {"keywords": "first quarter moon with face nature moon first quarter anthropomorphic face sky night cheese phase", "shortname": ":first_quarter_moon_with_face:", "unicode": "1F31B", "aliases": ""}, "womans_hat": {"keywords": "womans hat accessories fashion female", "shortname": ":womans_hat:", "unicode": "1F452", "aliases": ""}, "sandal": {"keywords": "womans sandal fashion shoes", "shortname": ":sandal:", "unicode": "1F461", "aliases": ""}, "white_medium_square": {"keywords": "white medium square shape", "shortname": ":white_medium_square:", "unicode": "25FB", "aliases": ""}, "snowboarder": {"keywords": "snowboarder sports winter snow boarding sports freestyle halfpipe board mountain alpine winter", "shortname": ":snowboarder:", "unicode": "1F3C2", "aliases": ""}, "sunflower": {"keywords": "sunflower nature plant sunflower sun flower seeds yellow", "shortname": ":sunflower:", "unicode": "1F33B", "aliases": ""}, "grey_exclamation": {"keywords": "white exclamation mark ornament surprise", "shortname": ":grey_exclamation:", "unicode": "2755", "aliases": ""}, "rose": {"keywords": "rose flowers love valentines rose fragrant flower thorns love petals romance", "shortname": ":rose:", "unicode": "1F339", "aliases": ""}, "cl": {"keywords": "squared cl alphabet red-square words", "shortname": ":cl:", "unicode": "1F191", "aliases": ""}, "tropical_fish": {"keywords": "tropical fish animal swim", "shortname": ":tropical_fish:", "unicode": "1F420", "aliases": ""}, "cherries": {"keywords": "cherries food fruit cherry cherries tree fruit pit", "shortname": ":cherries:", "unicode": "1F352", "aliases": ""}, "innocent": {"keywords": "smiling face with halo angel face halo halo angel innocent ring circle heaven", "shortname": ":innocent:", "unicode": "1F607", "aliases": ""}, "rice_cracker": {"keywords": "rice cracker food japanese rice cracker seaweed food japanese", "shortname": ":rice_cracker:", "unicode": "1F358", "aliases": ""}, "ski": {"keywords": "ski and ski boot cold sports winter ski downhill cross-country poles snow winter mountain alpine powder slalom freestyle", "shortname": ":ski:", "unicode": "1F3BF", "aliases": ""}, "pill": {"keywords": "pill health medicine", "shortname": ":pill:", "unicode": "1F48A", "aliases": ""}, "musical_keyboard": {"keywords": "musical keyboard instrument piano music keyboard piano organ instrument electric", "shortname": ":musical_keyboard:", "unicode": "1F3B9", "aliases": ""}, "boom": {"keywords": "collision symbol bomb explode explosion boom bang collision fire emphasis wow bam", "shortname": ":boom:", "unicode": "1F4A5", "aliases": ""}, "full_moon": {"keywords": "full moon symbol nature yellow moon full sky night cheese phase monster spooky werewolves twilight", "shortname": ":full_moon:", "unicode": "1F315", "aliases": ""}, "orange_book": {"keywords": "orange book knowledge library read", "shortname": ":orange_book:", "unicode": "1F4D9", "aliases": ""}, "couple": {"keywords": "man and woman holding hands affection date dating human like love marriage people valentines", "shortname": ":couple:", "unicode": "1F46B", "aliases": ""}, "japanese_goblin": {"keywords": "japanese goblin evil mask red japanese tengu supernatural avian demon goblin mask theater nose frown mustache anger frustration", "shortname": ":japanese_goblin:", "unicode": "1F47A", "aliases": ""}, "inbox_tray": {"keywords": "inbox tray documents email", "shortname": ":inbox_tray:", "unicode": "1F4E5", "aliases": ""}, "clock1": {"keywords": "clock face one oclock clock time", "shortname": ":clock1:", "unicode": "1F550", "aliases": ""}, "clock2": {"keywords": "clock face two oclock clock time", "shortname": ":clock2:", "unicode": "1F551", "aliases": ""}, "clock3": {"keywords": "clock face three oclock clock time", "shortname": ":clock3:", "unicode": "1F552", "aliases": ""}, "five": {"keywords": "digit five blue-square numbers prime", "shortname": ":five:", "unicode": "0035-20E3", "aliases": ""}, "clock5": {"keywords": "clock face five oclock clock time", "shortname": ":clock5:", "unicode": "1F554", "aliases": ""}, "clock6": {"keywords": "clock face six oclock clock time", "shortname": ":clock6:", "unicode": "1F555", "aliases": ""}, "clock7": {"keywords": "clock face seven oclock clock time", "shortname": ":clock7:", "unicode": "1F556", "aliases": ""}, "clock8": {"keywords": "clock face eight oclock clock time", "shortname": ":clock8:", "unicode": "1F557", "aliases": ""}, "clock9": {"keywords": "clock face nine oclock clock time", "shortname": ":clock9:", "unicode": "1F558", "aliases": ""}, "clock130": {"keywords": "clock face one-thirty clock time", "shortname": ":clock130:", "unicode": "1F55C", "aliases": ""}, "name_badge": {"keywords": "name badge fire forbid", "shortname": ":name_badge:", "unicode": "1F4DB", "aliases": ""}, "grin": {"keywords": "grinning face with smiling eyes face happy joy smile grin grinning smiling smile smiley", "shortname": ":grin:", "unicode": "1F601", "aliases": ""}, "womans_clothes": {"keywords": "womans clothes fashion woman clothing clothes blouse shirt wardrobe breasts cleavage shopping shop dressing dressed", "shortname": ":womans_clothes:", "unicode": "1F45A", "aliases": ""}, "gift": {"keywords": "wrapped present birthday christmas present xmas gift present wrap package birthday wedding", "shortname": ":gift:", "unicode": "1F381", "aliases": ""}, "bangbang": {"keywords": "double exclamation mark exclamation surprise", "shortname": ":bangbang:", "unicode": "203C", "aliases": ""}, "stuck_out_tongue_winking_eye": {"keywords": "face with stuck-out tongue and winking eye childish face mischievous playful prank tongue wink winking kidding silly playful crazy", "shortname": ":stuck_out_tongue_winking_eye:", "unicode": "1F61C", "aliases": ""}, "candy": {"keywords": "candy desert snack candy sugar sweet hard", "shortname": ":candy:", "unicode": "1F36C", "aliases": ""}, "arrows_counterclockwise": {"keywords": "anticlockwise downwards and upwards open circle ar blue-square sync", "shortname": ":arrows_counterclockwise:", "unicode": "1F504", "aliases": ""}, "capricorn": {"keywords": "capricorn capricorn sea-goat goat-horned astrology greek constellation stars zodiac sign sign zodiac horoscope", "shortname": ":capricorn:", "unicode": "2651", "aliases": ""}, "hotsprings": {"keywords": "hot springs bath relax warm", "shortname": ":hotsprings:", "unicode": "2668", "aliases": ""}, "laughing": {"keywords": "smiling face with open mouth and tightly-closed ey happy joy lol smiling laughing laugh", "shortname": ":laughing:", "unicode": "1F606", "aliases": ":satisfied:"}, "trolleybus": {"keywords": "trolleybus bart transportation vehicle trolley bus city transport transportation", "shortname": ":trolleybus:", "unicode": "1F68E", "aliases": ""}, "potable_water": {"keywords": "potable water symbol blue-square cleaning faucet liquid restroom potable water drinkable pure clear clean aqua h20", "shortname": ":potable_water:", "unicode": "1F6B0", "aliases": ""}, "city_dusk": {"keywords": "cityscape at dusk photo city scape sunset dusk lights evening metropolitan night dark", "shortname": ":city_dusk:", "unicode": "1F306", "aliases": ""}, "clap": {"keywords": "clapping hands sign applause congrats hands praise clapping appreciation approval sound encouragement enthusiasm", "shortname": ":clap:", "unicode": "1F44F", "aliases": ""}, "clock230": {"keywords": "clock face two-thirty clock time", "shortname": ":clock230:", "unicode": "1F55D", "aliases": ""}, "left_right_arrow": {"keywords": "left right arrow shape", "shortname": ":left_right_arrow:", "unicode": "2194", "aliases": ""}, "japanese_castle": {"keywords": "japanese castle building photo castle japanese residence royalty fort fortified fortress", "shortname": ":japanese_castle:", "unicode": "1F3EF", "aliases": ""}, "waning_gibbous_moon": {"keywords": "waning gibbous moon symbol nature moon waning gibbous sky night cheese phase", "shortname": ":waning_gibbous_moon:", "unicode": "1F316", "aliases": ""}, "crown": {"keywords": "crown king kod leader royalty", "shortname": ":crown:", "unicode": "1F451", "aliases": ""}, "back": {"keywords": "back with leftwards arrow above arrow", "shortname": ":back:", "unicode": "1F519", "aliases": ""}, "sparkling_heart": {"keywords": "sparkling heart affection like love valentines", "shortname": ":sparkling_heart:", "unicode": "1F496", "aliases": ""}, "clubs": {"keywords": "black club suit cards poker", "shortname": ":clubs:", "unicode": "2663", "aliases": ""}, "rage": {"keywords": "pouting face angry despise hate mad pout anger rage irate", "shortname": ":rage:", "unicode": "1F621", "aliases": ""}, "person_with_pouting_face": {"keywords": "person with pouting face female girl woman pout sexy cute annoyed", "shortname": ":person_with_pouting_face:", "unicode": "1F64E", "aliases": ""}, "rabbit2": {"keywords": "rabbit animal nature rabbit bunny easter reproduction prolific", "shortname": ":rabbit2:", "unicode": "1F407", "aliases": ""}, "two_men_holding_hands": {"keywords": "two men holding hands bromance couple friends like love men gay homosexual friends hands holding team unity", "shortname": ":two_men_holding_hands:", "unicode": "1F46C", "aliases": ""}, "tired_face": {"keywords": "tired face face frustrated sick upset whine exhausted sleepy tired", "shortname": ":tired_face:", "unicode": "1F62B", "aliases": ""}, "anguished": {"keywords": "anguished face face nervous stunned pain anguish ouch misery distress grief", "shortname": ":anguished:", "unicode": "1F627", "aliases": ""}, "tanabata_tree": {"keywords": "tanabata tree nature plant tanabata tree festival star wish holiday", "shortname": ":tanabata_tree:", "unicode": "1F38B", "aliases": ""}, "carousel_horse": {"keywords": "carousel horse carnival horse photo carousel horse amusement park ride entertainment park fair", "shortname": ":carousel_horse:", "unicode": "1F3A0", "aliases": ""}, "large_orange_diamond": {"keywords": "large orange diamond shape", "shortname": ":large_orange_diamond:", "unicode": "1F536", "aliases": ""}, "deciduous_tree": {"keywords": "deciduous tree nature plant deciduous tree leaves fall color", "shortname": ":deciduous_tree:", "unicode": "1F333", "aliases": ""}, "o2": {"keywords": "negative squared latin capital letter o alphabet letter red-square", "shortname": ":o2:", "unicode": "1F17E", "aliases": ""}, "knife": {"keywords": "hocho ", "shortname": ":knife:", "unicode": "1F52A", "aliases": ""}, "nose": {"keywords": "nose smell sniff", "shortname": ":nose:", "unicode": "1F443", "aliases": ""}, "point_up": {"keywords": "white up pointing index direction fingers hand", "shortname": ":point_up:", "unicode": "261D", "aliases": ""}, "heavy_minus_sign": {"keywords": "heavy minus sign calculation math", "shortname": ":heavy_minus_sign:", "unicode": "2796", "aliases": ""}, "zzz": {"keywords": "sleeping symbol sleepy tired", "shortname": ":zzz:", "unicode": "1F4A4", "aliases": ""}, "corn": {"keywords": "ear of maize food plant vegetable corn maize food iowa kernel popcorn husk yellow stalk cob ear", "shortname": ":corn:", "unicode": "1F33D", "aliases": ""}, "kissing_smiling_eyes": {"keywords": "kissing face with smiling eyes affection face infatuation valentines kissing kiss smile pucker lips smooch", "shortname": ":kissing_smiling_eyes:", "unicode": "1F619", "aliases": ""}, "clock4": {"keywords": "clock face four oclock clock time", "shortname": ":clock4:", "unicode": "1F553", "aliases": ""}, "closed_umbrella": {"keywords": "closed umbrella drizzle rain weather umbrella closed rain moisture protection sun ultraviolet uv", "shortname": ":closed_umbrella:", "unicode": "1F302", "aliases": ""}, "stew": {"keywords": "pot of food food meat stew hearty soup thick hot pot", "shortname": ":stew:", "unicode": "1F372", "aliases": ""}, "santa": {"keywords": "father christmas christmas father christmas festival male man xmas santa saint nick jolly ho ho ho north pole presents gifts naughty nice sleigh father christmas holiday", "shortname": ":santa:", "unicode": "1F385", "aliases": ""}, "volcano": {"keywords": "volcano nature photo volcano lava magma hot explode", "shortname": ":volcano:", "unicode": "1F30B", "aliases": ""}, "kissing_heart": {"keywords": "face throwing a kiss affection face infatuation kiss blowing kiss heart love lips like love valentines", "shortname": ":kissing_heart:", "unicode": "1F618", "aliases": ""}, "no_pedestrians": {"keywords": "no pedestrians crossing rules walking no walk pedestrian stroll stride foot feet", "shortname": ":no_pedestrians:", "unicode": "1F6B7", "aliases": ""}, "bamboo": {"keywords": "pine decoration nature plant vegetable pine bamboo decoration new years spirits harvest prosperity longevity fortune luck welcome farming agriculture", "shortname": ":bamboo:", "unicode": "1F38D", "aliases": ""}, "eight_spoked_asterisk": {"keywords": "eight spoked asterisk green-square sparkle star", "shortname": ":eight_spoked_asterisk:", "unicode": "2733", "aliases": ""}, "person_with_blond_hair": {"keywords": "person with blond hair male man blonde young western westerner occidental", "shortname": ":person_with_blond_hair:", "unicode": "1F471", "aliases": ""}, "trophy": {"keywords": "trophy award ceremony contest ftw place win trophy first show place win reward achievement medal", "shortname": ":trophy:", "unicode": "1F3C6", "aliases": ""}, "on": {"keywords": "on with exclamation mark with left right arrow abo arrow words", "shortname": ":on:", "unicode": "1F51B", "aliases": ""}, "ok": {"keywords": "squared ok agree blue-square good yes", "shortname": ":ok:", "unicode": "1F197", "aliases": ""}, "package": {"keywords": "package gift mail", "shortname": ":package:", "unicode": "1F4E6", "aliases": ""}, "black_small_square": {"keywords": "black small square ", "shortname": ":black_small_square:", "unicode": "25AA", "aliases": ""}, "school_satchel": {"keywords": "school satchel bag education student school satchel backpack bag packing pack hike education adventure travel sightsee", "shortname": ":school_satchel:", "unicode": "1F392", "aliases": ""}, "o": {"keywords": "heavy large circle circle round", "shortname": ":o:", "unicode": "2B55", "aliases": ""}, "clock12": {"keywords": "clock face twelve oclock clock time", "shortname": ":clock12:", "unicode": "1F55B", "aliases": ""}, "chart_with_downwards_trend": {"keywords": "chart with downwards trend graph", "shortname": ":chart_with_downwards_trend:", "unicode": "1F4C9", "aliases": ""}, "clock10": {"keywords": "clock face ten oclock clock time", "shortname": ":clock10:", "unicode": "1F559", "aliases": ""}, "clock11": {"keywords": "clock face eleven oclock clock time", "shortname": ":clock11:", "unicode": "1F55A", "aliases": ""}, "no_bell": {"keywords": "bell with cancellation stroke mute sound volume", "shortname": ":no_bell:", "unicode": "1F515", "aliases": ""}, "sweat": {"keywords": "face with cold sweat cold sweat sick anxious worried clammy diaphoresis face hot", "shortname": ":sweat:", "unicode": "1F613", "aliases": ""}, "ox": {"keywords": "ox animal beef cow", "shortname": ":ox:", "unicode": "1F402", "aliases": ""}, "mountain_railway": {"keywords": "mountain railway transportation mountain railway rail train transport", "shortname": ":mountain_railway:", "unicode": "1F69E", "aliases": ""}, "tongue": {"keywords": "tongue mouth playful tongue mouth taste buds food silly playful tease kiss french kiss lick tasty playfulness silliness intimacy", "shortname": ":tongue:", "unicode": "1F445", "aliases": ""}, "womens": {"keywords": "womens symbol purple-square woman bathroom restroom sign girl female avatar", "shortname": ":womens:", "unicode": "1F6BA", "aliases": ""}, "baby_symbol": {"keywords": "baby symbol child orange-square baby crawl newborn human diaper small babe", "shortname": ":baby_symbol:", "unicode": "1F6BC", "aliases": ""}, "hospital": {"keywords": "hospital building doctor health surgery", "shortname": ":hospital:", "unicode": "1F3E5", "aliases": ""}, "baby_chick": {"keywords": "baby chick animal chicken chick baby bird chicken young woman cute", "shortname": ":baby_chick:", "unicode": "1F424", "aliases": ""}, "turtle": {"keywords": "turtle animal slow turtle shell tortoise chelonian reptile slow snap steady", "shortname": ":turtle:", "unicode": "1F422", "aliases": ""}, "black_square_button": {"keywords": "black square button frame", "shortname": ":black_square_button:", "unicode": "1F532", "aliases": ""}, "do_not_litter": {"keywords": "do not litter symbol bin garbage trash litter garbage waste no can trash", "shortname": ":do_not_litter:", "unicode": "1F6AF", "aliases": ""}, "wind_chime": {"keywords": "wind chime ding nature wind chime bell f\u016brin instrument music spirits soothing protective spiritual sound", "shortname": ":wind_chime:", "unicode": "1F390", "aliases": ""}, "waxing_crescent_moon": {"keywords": "waxing crescent moon symbol nature moon waxing sky night cheese phase", "shortname": ":waxing_crescent_moon:", "unicode": "1F312", "aliases": ""}, "tiger2": {"keywords": "tiger animal nature tiger cat striped tony tigger hobs", "shortname": ":tiger2:", "unicode": "1F405", "aliases": ""}, "two": {"keywords": "digit two 2 blue-square numbers prime", "shortname": ":two:", "unicode": "0032-20E3", "aliases": ""}, "dango": {"keywords": "dango food dango japanese dumpling mochi balls skewer", "shortname": ":dango:", "unicode": "1F361", "aliases": ""}, "red_circle": {"keywords": "large red circle shape", "shortname": ":red_circle:", "unicode": "1F534", "aliases": ""}, "syringe": {"keywords": "syringe blood drugs health hospital medicine needle", "shortname": ":syringe:", "unicode": "1F489", "aliases": ""}, "last_quarter_moon": {"keywords": "last quarter moon symbol nature moon last quarter sky night cheese phase", "shortname": ":last_quarter_moon:", "unicode": "1F317", "aliases": ""}, "tada": {"keywords": "party popper contulations party party popper tada celebration victory announcement climax congratulations", "shortname": ":tada:", "unicode": "1F389", "aliases": ""}, "ok_hand": {"keywords": "ok hand sign fingers limbs perfect okay ok smoke smoking marijuana joint pot 420", "shortname": ":ok_hand:", "unicode": "1F44C", "aliases": ""}, "custard": {"keywords": "custard desert food custard cream rich butter dessert cr\u00e8me br\u00fbl\u00e9e french", "shortname": ":custard:", "unicode": "1F36E", "aliases": ""}, "rowboat": {"keywords": "rowboat hobby ship sports water boat row oar paddle", "shortname": ":rowboat:", "unicode": "1F6A3", "aliases": ""}, "clock530": {"keywords": "clock face five-thirty clock time", "shortname": ":clock530:", "unicode": "1F560", "aliases": ""}, "heavy_multiplication_x": {"keywords": "heavy multiplication x calculation math", "shortname": ":heavy_multiplication_x:", "unicode": "2716", "aliases": ""}, "white_check_mark": {"keywords": "white heavy check mark agree green-square ok", "shortname": ":white_check_mark:", "unicode": "2705", "aliases": ""}, "tennis": {"keywords": "tennis racquet and ball balls green sports tennis racket racquet ball game net court love", "shortname": ":tennis:", "unicode": "1F3BE", "aliases": ""}, "question": {"keywords": "black question mark ornament confused doubt", "shortname": ":question:", "unicode": "2753", "aliases": ""}, "secret": {"keywords": "circled ideograph secret privacy", "shortname": ":secret:", "unicode": "3299", "aliases": ""}, "stars": {"keywords": "shooting star night photo shooting shoot star sky night comet meteoroid", "shortname": ":stars:", "unicode": "1F320", "aliases": ""}, "capital_abcd": {"keywords": "input symbol for latin capital letters alphabet blue-square words", "shortname": ":capital_abcd:", "unicode": "1F520", "aliases": ""}, "mahjong": {"keywords": "mahjong tile red dragon chinese game kanji", "shortname": ":mahjong:", "unicode": "1F004", "aliases": ""}, "bus": {"keywords": "bus car transportation vehicle bus school city transportation public", "shortname": ":bus:", "unicode": "1F68C", "aliases": ""}, "registered": {"keywords": "registered sign alphabet circle", "shortname": ":registered:", "unicode": "00AE", "aliases": ""}, "fireworks": {"keywords": "fireworks carnival congratulations festival photo fireworks independence celebration explosion july 4th rocket sky idea excitement", "shortname": ":fireworks:", "unicode": "1F386", "aliases": ""}, "construction": {"keywords": "construction sign caution progress wip", "shortname": ":construction:", "unicode": "1F6A7", "aliases": ""}, "link": {"keywords": "link symbol rings url", "shortname": ":link:", "unicode": "1F517", "aliases": ""}, "fallen_leaf": {"keywords": "fallen leaf leaves nature plant vegetable leaf fall color deciduous autumn", "shortname": ":fallen_leaf:", "unicode": "1F342", "aliases": ""}, "astonished": {"keywords": "astonished face face xox shocked surprise astonished", "shortname": ":astonished:", "unicode": "1F632", "aliases": ""}, "card_index": {"keywords": "card index business stationery", "shortname": ":card_index:", "unicode": "1F4C7", "aliases": ""}, "ear": {"keywords": "ear face hear listen sound", "shortname": ":ear:", "unicode": "1F442", "aliases": ""}, "radio_button": {"keywords": "radio button input", "shortname": ":radio_button:", "unicode": "1F518", "aliases": ""}, "bug": {"keywords": "bug insect nature bug insect virus error", "shortname": ":bug:", "unicode": "1F41B", "aliases": ""}, "penguin": {"keywords": "penguin animal nature", "shortname": ":penguin:", "unicode": "1F427", "aliases": ""}, "football": {"keywords": "american football NFL balls sports football ball sport america american", "shortname": ":football:", "unicode": "1F3C8", "aliases": ""}, "arrow_heading_down": {"keywords": "arrow pointing rightwards then curving downwards arrow blue-square", "shortname": ":arrow_heading_down:", "unicode": "2935", "aliases": ""}, "congratulations": {"keywords": "circled ideograph congratulation chinese japanese kanji", "shortname": ":congratulations:", "unicode": "3297", "aliases": ""}, "dromedary_camel": {"keywords": "dromedary camel animal desert hot dromedary camel hump desert middle east heat hot water hump day wednesday sex", "shortname": ":dromedary_camel:", "unicode": "1F42A", "aliases": ""}, "skull": {"keywords": "skull dead skeleton dying", "shortname": ":skull:", "unicode": "1F480", "aliases": ":skeleton:"}, "bride_with_veil": {"keywords": "bride with veil couple marriage wedding bride wedding planning veil gown dress engagement white", "shortname": ":bride_with_veil:", "unicode": "1F470", "aliases": ""}, "stuck_out_tongue": {"keywords": "face with stuck-out tongue childish face mischievous playful prank tongue silly playful cheeky", "shortname": ":stuck_out_tongue:", "unicode": "1F61B", "aliases": ""}, "relaxed": {"keywords": "white smiling face blush face happiness massage smile", "shortname": ":relaxed:", "unicode": "263A", "aliases": ""}, "grey_question": {"keywords": "white question mark ornament doubts", "shortname": ":grey_question:", "unicode": "2754", "aliases": ""}, "vhs": {"keywords": "videocassette oldschool record video", "shortname": ":vhs:", "unicode": "1F4FC", "aliases": ""}, "strawberry": {"keywords": "strawberry food fruit nature strawberry short cake berry", "shortname": ":strawberry:", "unicode": "1F353", "aliases": ""}, "cat2": {"keywords": "cat animal meow pet cat kitten meow", "shortname": ":cat2:", "unicode": "1F408", "aliases": ""}, "athletic_shoe": {"keywords": "athletic shoe shoes sports", "shortname": ":athletic_shoe:", "unicode": "1F45F", "aliases": ""}, "star2": {"keywords": "glowing star night sparkle glow glowing star five points classic", "shortname": ":star2:", "unicode": "1F31F", "aliases": ""}, "cake": {"keywords": "shortcake desert food cake short dessert strawberry", "shortname": ":cake:", "unicode": "1F370", "aliases": ""}, "arrow_double_up": {"keywords": "black up-pointing double triangle arrow blue-square", "shortname": ":arrow_double_up:", "unicode": "23EB", "aliases": ""}, "toilet": {"keywords": "toilet restroom wc toilet bathroom throne porcelain waste flush plumbing", "shortname": ":toilet:", "unicode": "1F6BD", "aliases": ""}, "ab": {"keywords": "negative squared ab alphabet red-square", "shortname": ":ab:", "unicode": "1F18E", "aliases": ""}, "hash": {"keywords": "number sign symbol", "shortname": ":hash:", "unicode": "0023-20E3", "aliases": ""}, "sweet_potato": {"keywords": "roasted sweet potato food nature sweet potato potassium roasted roast", "shortname": ":sweet_potato:", "unicode": "1F360", "aliases": ""}, "mortar_board": {"keywords": "graduation cap cap college degree graduation hat school university graduation cap mortarboard academic education ceremony square tassel", "shortname": ":mortar_board:", "unicode": "1F393", "aliases": ""}, "up": {"keywords": "squared up with exclamation mark blue-square", "shortname": ":up:", "unicode": "1F199", "aliases": ""}, "hatched_chick": {"keywords": "front-facing baby chick baby chicken chick baby bird chicken young woman cute", "shortname": ":hatched_chick:", "unicode": "1F425", "aliases": ""}, "triangular_flag_on_post": {"keywords": "triangular flag on post triangle triangular flag golf post flagpole", "shortname": ":triangular_flag_on_post:", "unicode": "1F6A9", "aliases": ""}, "black_nib": {"keywords": "black nib pen stationery", "shortname": ":black_nib:", "unicode": "2712", "aliases": ""}, "pig": {"keywords": "pig face animal oink", "shortname": ":pig:", "unicode": "1F437", "aliases": ""}, "floppy_disk": {"keywords": "floppy disk oldschool save technology floppy disk storage information computer drive megabyte", "shortname": ":floppy_disk:", "unicode": "1F4BE", "aliases": ""}, "black_large_square": {"keywords": "black large square shape", "shortname": ":black_large_square:", "unicode": "2B1B", "aliases": ""}, "ship": {"keywords": "ship titanic transportation ferry ship boat", "shortname": ":ship:", "unicode": "1F6A2", "aliases": ""}, "8ball": {"keywords": "billiards pool billiards eight ball pool pocket ball cue", "shortname": ":8ball:", "unicode": "1F3B1", "aliases": ""}, "telephone_receiver": {"keywords": "telephone receiver communication dial technology", "shortname": ":telephone_receiver:", "unicode": "1F4DE", "aliases": ""}, "u7981": {"keywords": "squared cjk unified ideograph-7981 chinese forbidden japanese kanji limit restricted", "shortname": ":u7981:", "unicode": "1F232", "aliases": ""}, "person_frowning": {"keywords": "person frowning female girl woman dejected rejected sad frown", "shortname": ":person_frowning:", "unicode": "1F64D", "aliases": ""}, "movie_camera": {"keywords": "movie camera film record movie camera camcorder video motion picture", "shortname": ":movie_camera:", "unicode": "1F3A5", "aliases": ""}, "lemon": {"keywords": "lemon fruit nature lemon yellow citrus", "shortname": ":lemon:", "unicode": "1F34B", "aliases": ""}, "arrow_double_down": {"keywords": "black down-pointing double triangle arrow blue-square", "shortname": ":arrow_double_down:", "unicode": "23EC", "aliases": ""}, "peach": {"keywords": "peach food fruit nature peach fruit juicy pit", "shortname": ":peach:", "unicode": "1F351", "aliases": ""}, "boot": {"keywords": "womans boots fashion shoes", "shortname": ":boot:", "unicode": "1F462", "aliases": ""}, "ng": {"keywords": "squared ng blue-square", "shortname": ":ng:", "unicode": "1F196", "aliases": ""}, "end": {"keywords": "end with leftwards arrow above arrow words", "shortname": ":end:", "unicode": "1F51A", "aliases": ""}, "mountain_bicyclist": {"keywords": "mountain bicyclist human sports transportation bicyclist mountain bike pedal bicycle transportation", "shortname": ":mountain_bicyclist:", "unicode": "1F6B5", "aliases": ""}, "book": {"keywords": "open book library literature", "shortname": ":book:", "unicode": "1F4D6", "aliases": ""}, "clock1130": {"keywords": "clock face eleven-thirty clock time", "shortname": ":clock1130:", "unicode": "1F566", "aliases": ""}, "oncoming_bus": {"keywords": "oncoming bus transportation vehicle bus school city transportation public", "shortname": ":oncoming_bus:", "unicode": "1F68D", "aliases": ""}, "clock1030": {"keywords": "clock face ten-thirty clock time", "shortname": ":clock1030:", "unicode": "1F565", "aliases": ""}, "heart_eyes_cat": {"keywords": "smiling cat face with heart-shaped eyes affection animal cats like love valentines lovestruck love heart", "shortname": ":heart_eyes_cat:", "unicode": "1F63B", "aliases": ""}, "repeat": {"keywords": "clockwise rightwards and leftwards open circle arr loop record", "shortname": ":repeat:", "unicode": "1F501", "aliases": ""}, "star": {"keywords": "white medium star night yellow", "shortname": ":star:", "unicode": "2B50", "aliases": ""}, "dart": {"keywords": "direct hit bar game direct hit bullseye dart archery game fletching arrow sport", "shortname": ":dart:", "unicode": "1F3AF", "aliases": ""}, "envelope": {"keywords": "envelope communication letter mail postal", "shortname": ":envelope:", "unicode": "2709", "aliases": ""}, "footprints": {"keywords": "footprints feet", "shortname": ":footprints:", "unicode": "1F463", "aliases": ""}, "smiley": {"keywords": "smiling face with open mouth face haha happy joy smiling smile smiley", "shortname": ":smiley:", "unicode": "1F603", "aliases": ""}, "pear": {"keywords": "pear fruit nature pear fruit shape", "shortname": ":pear:", "unicode": "1F350", "aliases": ""}, "taurus": {"keywords": "taurus purple-square sign taurus bull astrology greek constellation stars zodiac sign zodiac horoscope", "shortname": ":taurus:", "unicode": "2649", "aliases": ""}, "articulated_lorry": {"keywords": "articulated lorry cars transportation vehicle truck delivery semi lorry articulated", "shortname": ":articulated_lorry:", "unicode": "1F69B", "aliases": ""}, "u6e80": {"keywords": "squared cjk unified ideograph-6e80 chinese full japanese kanji red-square", "shortname": ":u6e80:", "unicode": "1F235", "aliases": ""}, "money_with_wings": {"keywords": "money with wings bills dollar payment money wings easy spend work lost blown burned gift cash dollar", "shortname": ":money_with_wings:", "unicode": "1F4B8", "aliases": ""}, "black_medium_square": {"keywords": "black medium square shape", "shortname": ":black_medium_square:", "unicode": "25FC", "aliases": ""}, "closed_book": {"keywords": "closed book knowledge library read", "shortname": ":closed_book:", "unicode": "1F4D5", "aliases": ""}, "ghost": {"keywords": "ghost halloween", "shortname": ":ghost:", "unicode": "1F47B", "aliases": ""}, "droplet": {"keywords": "droplet drip faucet water drop droplet h20 water aqua tear sweat rain moisture wet moist spit", "shortname": ":droplet:", "unicode": "1F4A7", "aliases": ""}, "spades": {"keywords": "black spade suit cards poker", "shortname": ":spades:", "unicode": "2660", "aliases": ""}, "vibration_mode": {"keywords": "vibration mode orange-square phone", "shortname": ":vibration_mode:", "unicode": "1F4F3", "aliases": ""}, "expressionless": {"keywords": "expressionless face expressionless blank void vapid without expression face indifferent", "shortname": ":expressionless:", "unicode": "1F611", "aliases": ""}, "dvd": {"keywords": "dvd cd disc disk", "shortname": ":dvd:", "unicode": "1F4C0", "aliases": ""}, "mask": {"keywords": "face with medical mask face ill sick sick virus flu medical mask", "shortname": ":mask:", "unicode": "1F637", "aliases": ""}, "mag_right": {"keywords": "right-pointing magnifying glass search zoom detective investigator detail details", "shortname": ":mag_right:", "unicode": "1F50E", "aliases": ""}, "bento": {"keywords": "bento box box food japanese bento japanese rice meal box obento convenient lunchbox", "shortname": ":bento:", "unicode": "1F371", "aliases": ""}, "sunrise_over_mountains": {"keywords": "sunrise over mountains photo vacation view sunrise sun morning mountain rural color sky", "shortname": ":sunrise_over_mountains:", "unicode": "1F304", "aliases": ""}, "partly_sunny": {"keywords": "sun behind cloud cloud morning nature weather", "shortname": ":partly_sunny:", "unicode": "26C5", "aliases": ""}, "heavy_dollar_sign": {"keywords": "heavy dollar sign currency money payment dollar currency money cash sale purchase value", "shortname": ":heavy_dollar_sign:", "unicode": "1F4B2", "aliases": ""}, "scroll": {"keywords": "scroll documents", "shortname": ":scroll:", "unicode": "1F4DC", "aliases": ""}} \ No newline at end of file diff --git a/pagure/static/emoji/emoji_strategy.json b/pagure/static/emoji/emoji_strategy.json new file mode 120000 index 0000000..c3cfcc4 --- /dev/null +++ b/pagure/static/emoji/emoji_strategy.json @@ -0,0 +1 @@ +emoji_strategy-2.2.6.json \ No newline at end of file diff --git a/pagure/static/emoji/emojione-2.2.6.js b/pagure/static/emoji/emojione-2.2.6.js new file mode 100644 index 0000000..83499f2 --- /dev/null +++ b/pagure/static/emoji/emojione-2.2.6.js @@ -0,0 +1,509 @@ +/* jshint maxerr: 10000 */ +/* jslint unused: true */ +/* jshint shadow: true */ +/* jshint -W075 */ +(function(ns){ + // this list must be ordered from largest length of the value array, index 0, to the shortest + ns.emojioneList = {":kiss_ww:":{"unicode":["1f469-200d-2764-fe0f-200d-1f48b-200d-1f469","1f469-2764-1f48b-1f469"],"isCanonical": true},":couplekiss_ww:":{"unicode":["1f469-200d-2764-fe0f-200d-1f48b-200d-1f469","1f469-2764-1f48b-1f469"],"isCanonical": false},":kiss_mm:":{"unicode":["1f468-200d-2764-fe0f-200d-1f48b-200d-1f468","1f468-2764-1f48b-1f468"],"isCanonical": true},":couplekiss_mm:":{"unicode":["1f468-200d-2764-fe0f-200d-1f48b-200d-1f468","1f468-2764-1f48b-1f468"],"isCanonical": false},":family_mmbb:":{"unicode":["1f468-200d-1f468-200d-1f466-200d-1f466","1f468-1f468-1f466-1f466"],"isCanonical": true},":family_mmgb:":{"unicode":["1f468-200d-1f468-200d-1f467-200d-1f466","1f468-1f468-1f467-1f466"],"isCanonical": true},":family_mmgg:":{"unicode":["1f468-200d-1f468-200d-1f467-200d-1f467","1f468-1f468-1f467-1f467"],"isCanonical": true},":family_mwbb:":{"unicode":["1f468-200d-1f469-200d-1f466-200d-1f466","1f468-1f469-1f466-1f466"],"isCanonical": true},":family_mwgb:":{"unicode":["1f468-200d-1f469-200d-1f467-200d-1f466","1f468-1f469-1f467-1f466"],"isCanonical": true},":family_mwgg:":{"unicode":["1f468-200d-1f469-200d-1f467-200d-1f467","1f468-1f469-1f467-1f467"],"isCanonical": true},":family_wwbb:":{"unicode":["1f469-200d-1f469-200d-1f466-200d-1f466","1f469-1f469-1f466-1f466"],"isCanonical": true},":family_wwgb:":{"unicode":["1f469-200d-1f469-200d-1f467-200d-1f466","1f469-1f469-1f467-1f466"],"isCanonical": true},":family_wwgg:":{"unicode":["1f469-200d-1f469-200d-1f467-200d-1f467","1f469-1f469-1f467-1f467"],"isCanonical": true},":couple_ww:":{"unicode":["1f469-200d-2764-fe0f-200d-1f469","1f469-2764-1f469"],"isCanonical": true},":couple_with_heart_ww:":{"unicode":["1f469-200d-2764-fe0f-200d-1f469","1f469-2764-1f469"],"isCanonical": false},":couple_mm:":{"unicode":["1f468-200d-2764-fe0f-200d-1f468","1f468-2764-1f468"],"isCanonical": true},":couple_with_heart_mm:":{"unicode":["1f468-200d-2764-fe0f-200d-1f468","1f468-2764-1f468"],"isCanonical": false},":family_mmb:":{"unicode":["1f468-200d-1f468-200d-1f466","1f468-1f468-1f466"],"isCanonical": true},":family_mmg:":{"unicode":["1f468-200d-1f468-200d-1f467","1f468-1f468-1f467"],"isCanonical": true},":family_mwg:":{"unicode":["1f468-200d-1f469-200d-1f467","1f468-1f469-1f467"],"isCanonical": true},":family_wwb:":{"unicode":["1f469-200d-1f469-200d-1f466","1f469-1f469-1f466"],"isCanonical": true},":family_wwg:":{"unicode":["1f469-200d-1f469-200d-1f467","1f469-1f469-1f467"],"isCanonical": true},":eye_in_speech_bubble:":{"unicode":["1f441-200d-1f5e8","1f441-1f5e8"],"isCanonical": true},":hash:":{"unicode":["0023-fe0f-20e3","0023-20e3"],"isCanonical": true},":zero:":{"unicode":["0030-fe0f-20e3","0030-20e3"],"isCanonical": true},":one:":{"unicode":["0031-fe0f-20e3","0031-20e3"],"isCanonical": true},":two:":{"unicode":["0032-fe0f-20e3","0032-20e3"],"isCanonical": true},":three:":{"unicode":["0033-fe0f-20e3","0033-20e3"],"isCanonical": true},":four:":{"unicode":["0034-fe0f-20e3","0034-20e3"],"isCanonical": true},":five:":{"unicode":["0035-fe0f-20e3","0035-20e3"],"isCanonical": true},":six:":{"unicode":["0036-fe0f-20e3","0036-20e3"],"isCanonical": true},":seven:":{"unicode":["0037-fe0f-20e3","0037-20e3"],"isCanonical": true},":eight:":{"unicode":["0038-fe0f-20e3","0038-20e3"],"isCanonical": true},":nine:":{"unicode":["0039-fe0f-20e3","0039-20e3"],"isCanonical": true},":asterisk:":{"unicode":["002a-fe0f-20e3","002a-20e3"],"isCanonical": true},":keycap_asterisk:":{"unicode":["002a-fe0f-20e3","002a-20e3"],"isCanonical": false},":handball_tone5:":{"unicode":["1f93e-1f3ff"],"isCanonical": true},":handball_tone4:":{"unicode":["1f93e-1f3fe"],"isCanonical": true},":handball_tone3:":{"unicode":["1f93e-1f3fd"],"isCanonical": true},":handball_tone2:":{"unicode":["1f93e-1f3fc"],"isCanonical": true},":handball_tone1:":{"unicode":["1f93e-1f3fb"],"isCanonical": true},":water_polo_tone5:":{"unicode":["1f93d-1f3ff"],"isCanonical": true},":water_polo_tone4:":{"unicode":["1f93d-1f3fe"],"isCanonical": true},":water_polo_tone3:":{"unicode":["1f93d-1f3fd"],"isCanonical": true},":water_polo_tone2:":{"unicode":["1f93d-1f3fc"],"isCanonical": true},":water_polo_tone1:":{"unicode":["1f93d-1f3fb"],"isCanonical": true},":wrestlers_tone5:":{"unicode":["1f93c-1f3ff"],"isCanonical": true},":wrestling_tone5:":{"unicode":["1f93c-1f3ff"],"isCanonical": false},":wrestlers_tone4:":{"unicode":["1f93c-1f3fe"],"isCanonical": true},":wrestling_tone4:":{"unicode":["1f93c-1f3fe"],"isCanonical": false},":wrestlers_tone3:":{"unicode":["1f93c-1f3fd"],"isCanonical": true},":wrestling_tone3:":{"unicode":["1f93c-1f3fd"],"isCanonical": false},":wrestlers_tone2:":{"unicode":["1f93c-1f3fc"],"isCanonical": true},":wrestling_tone2:":{"unicode":["1f93c-1f3fc"],"isCanonical": false},":wrestlers_tone1:":{"unicode":["1f93c-1f3fb"],"isCanonical": true},":wrestling_tone1:":{"unicode":["1f93c-1f3fb"],"isCanonical": false},":juggling_tone5:":{"unicode":["1f939-1f3ff"],"isCanonical": true},":juggler_tone5:":{"unicode":["1f939-1f3ff"],"isCanonical": false},":juggling_tone4:":{"unicode":["1f939-1f3fe"],"isCanonical": true},":juggler_tone4:":{"unicode":["1f939-1f3fe"],"isCanonical": false},":juggling_tone3:":{"unicode":["1f939-1f3fd"],"isCanonical": true},":juggler_tone3:":{"unicode":["1f939-1f3fd"],"isCanonical": false},":juggling_tone2:":{"unicode":["1f939-1f3fc"],"isCanonical": true},":juggler_tone2:":{"unicode":["1f939-1f3fc"],"isCanonical": false},":juggling_tone1:":{"unicode":["1f939-1f3fb"],"isCanonical": true},":juggler_tone1:":{"unicode":["1f939-1f3fb"],"isCanonical": false},":cartwheel_tone5:":{"unicode":["1f938-1f3ff"],"isCanonical": true},":person_doing_cartwheel_tone5:":{"unicode":["1f938-1f3ff"],"isCanonical": false},":cartwheel_tone4:":{"unicode":["1f938-1f3fe"],"isCanonical": true},":person_doing_cartwheel_tone4:":{"unicode":["1f938-1f3fe"],"isCanonical": false},":cartwheel_tone3:":{"unicode":["1f938-1f3fd"],"isCanonical": true},":person_doing_cartwheel_tone3:":{"unicode":["1f938-1f3fd"],"isCanonical": false},":cartwheel_tone2:":{"unicode":["1f938-1f3fc"],"isCanonical": true},":person_doing_cartwheel_tone2:":{"unicode":["1f938-1f3fc"],"isCanonical": false},":cartwheel_tone1:":{"unicode":["1f938-1f3fb"],"isCanonical": true},":person_doing_cartwheel_tone1:":{"unicode":["1f938-1f3fb"],"isCanonical": false},":shrug_tone5:":{"unicode":["1f937-1f3ff"],"isCanonical": true},":shrug_tone4:":{"unicode":["1f937-1f3fe"],"isCanonical": true},":shrug_tone3:":{"unicode":["1f937-1f3fd"],"isCanonical": true},":shrug_tone2:":{"unicode":["1f937-1f3fc"],"isCanonical": true},":shrug_tone1:":{"unicode":["1f937-1f3fb"],"isCanonical": true},":mrs_claus_tone5:":{"unicode":["1f936-1f3ff"],"isCanonical": true},":mother_christmas_tone5:":{"unicode":["1f936-1f3ff"],"isCanonical": false},":mrs_claus_tone4:":{"unicode":["1f936-1f3fe"],"isCanonical": true},":mother_christmas_tone4:":{"unicode":["1f936-1f3fe"],"isCanonical": false},":mrs_claus_tone3:":{"unicode":["1f936-1f3fd"],"isCanonical": true},":mother_christmas_tone3:":{"unicode":["1f936-1f3fd"],"isCanonical": false},":mrs_claus_tone2:":{"unicode":["1f936-1f3fc"],"isCanonical": true},":mother_christmas_tone2:":{"unicode":["1f936-1f3fc"],"isCanonical": false},":mrs_claus_tone1:":{"unicode":["1f936-1f3fb"],"isCanonical": true},":mother_christmas_tone1:":{"unicode":["1f936-1f3fb"],"isCanonical": false},":man_in_tuxedo_tone5:":{"unicode":["1f935-1f3ff"],"isCanonical": true},":tuxedo_tone5:":{"unicode":["1f935-1f3ff"],"isCanonical": false},":man_in_tuxedo_tone4:":{"unicode":["1f935-1f3fe"],"isCanonical": true},":tuxedo_tone4:":{"unicode":["1f935-1f3fe"],"isCanonical": false},":man_in_tuxedo_tone3:":{"unicode":["1f935-1f3fd"],"isCanonical": true},":tuxedo_tone3:":{"unicode":["1f935-1f3fd"],"isCanonical": false},":man_in_tuxedo_tone2:":{"unicode":["1f935-1f3fc"],"isCanonical": true},":tuxedo_tone2:":{"unicode":["1f935-1f3fc"],"isCanonical": false},":man_in_tuxedo_tone1:":{"unicode":["1f935-1f3fb"],"isCanonical": true},":tuxedo_tone1:":{"unicode":["1f935-1f3fb"],"isCanonical": false},":prince_tone5:":{"unicode":["1f934-1f3ff"],"isCanonical": true},":prince_tone4:":{"unicode":["1f934-1f3fe"],"isCanonical": true},":prince_tone3:":{"unicode":["1f934-1f3fd"],"isCanonical": true},":prince_tone2:":{"unicode":["1f934-1f3fc"],"isCanonical": true},":prince_tone1:":{"unicode":["1f934-1f3fb"],"isCanonical": true},":selfie_tone5:":{"unicode":["1f933-1f3ff"],"isCanonical": true},":selfie_tone4:":{"unicode":["1f933-1f3fe"],"isCanonical": true},":selfie_tone3:":{"unicode":["1f933-1f3fd"],"isCanonical": true},":selfie_tone2:":{"unicode":["1f933-1f3fc"],"isCanonical": true},":selfie_tone1:":{"unicode":["1f933-1f3fb"],"isCanonical": true},":pregnant_woman_tone5:":{"unicode":["1f930-1f3ff"],"isCanonical": true},":expecting_woman_tone5:":{"unicode":["1f930-1f3ff"],"isCanonical": false},":pregnant_woman_tone4:":{"unicode":["1f930-1f3fe"],"isCanonical": true},":expecting_woman_tone4:":{"unicode":["1f930-1f3fe"],"isCanonical": false},":pregnant_woman_tone3:":{"unicode":["1f930-1f3fd"],"isCanonical": true},":expecting_woman_tone3:":{"unicode":["1f930-1f3fd"],"isCanonical": false},":pregnant_woman_tone2:":{"unicode":["1f930-1f3fc"],"isCanonical": true},":expecting_woman_tone2:":{"unicode":["1f930-1f3fc"],"isCanonical": false},":pregnant_woman_tone1:":{"unicode":["1f930-1f3fb"],"isCanonical": true},":expecting_woman_tone1:":{"unicode":["1f930-1f3fb"],"isCanonical": false},":face_palm_tone5:":{"unicode":["1f926-1f3ff"],"isCanonical": true},":facepalm_tone5:":{"unicode":["1f926-1f3ff"],"isCanonical": false},":face_palm_tone4:":{"unicode":["1f926-1f3fe"],"isCanonical": true},":facepalm_tone4:":{"unicode":["1f926-1f3fe"],"isCanonical": false},":face_palm_tone3:":{"unicode":["1f926-1f3fd"],"isCanonical": true},":facepalm_tone3:":{"unicode":["1f926-1f3fd"],"isCanonical": false},":face_palm_tone2:":{"unicode":["1f926-1f3fc"],"isCanonical": true},":facepalm_tone2:":{"unicode":["1f926-1f3fc"],"isCanonical": false},":face_palm_tone1:":{"unicode":["1f926-1f3fb"],"isCanonical": true},":facepalm_tone1:":{"unicode":["1f926-1f3fb"],"isCanonical": false},":fingers_crossed_tone5:":{"unicode":["1f91e-1f3ff"],"isCanonical": true},":hand_with_index_and_middle_fingers_crossed_tone5:":{"unicode":["1f91e-1f3ff"],"isCanonical": false},":fingers_crossed_tone4:":{"unicode":["1f91e-1f3fe"],"isCanonical": true},":hand_with_index_and_middle_fingers_crossed_tone4:":{"unicode":["1f91e-1f3fe"],"isCanonical": false},":fingers_crossed_tone3:":{"unicode":["1f91e-1f3fd"],"isCanonical": true},":hand_with_index_and_middle_fingers_crossed_tone3:":{"unicode":["1f91e-1f3fd"],"isCanonical": false},":fingers_crossed_tone2:":{"unicode":["1f91e-1f3fc"],"isCanonical": true},":hand_with_index_and_middle_fingers_crossed_tone2:":{"unicode":["1f91e-1f3fc"],"isCanonical": false},":fingers_crossed_tone1:":{"unicode":["1f91e-1f3fb"],"isCanonical": true},":hand_with_index_and_middle_fingers_crossed_tone1:":{"unicode":["1f91e-1f3fb"],"isCanonical": false},":handshake_tone5:":{"unicode":["1f91d-1f3ff"],"isCanonical": true},":shaking_hands_tone5:":{"unicode":["1f91d-1f3ff"],"isCanonical": false},":handshake_tone4:":{"unicode":["1f91d-1f3fe"],"isCanonical": true},":shaking_hands_tone4:":{"unicode":["1f91d-1f3fe"],"isCanonical": false},":handshake_tone3:":{"unicode":["1f91d-1f3fd"],"isCanonical": true},":shaking_hands_tone3:":{"unicode":["1f91d-1f3fd"],"isCanonical": false},":handshake_tone2:":{"unicode":["1f91d-1f3fc"],"isCanonical": true},":shaking_hands_tone2:":{"unicode":["1f91d-1f3fc"],"isCanonical": false},":handshake_tone1:":{"unicode":["1f91d-1f3fb"],"isCanonical": true},":shaking_hands_tone1:":{"unicode":["1f91d-1f3fb"],"isCanonical": false},":right_facing_fist_tone5:":{"unicode":["1f91c-1f3ff"],"isCanonical": true},":right_fist_tone5:":{"unicode":["1f91c-1f3ff"],"isCanonical": false},":right_facing_fist_tone4:":{"unicode":["1f91c-1f3fe"],"isCanonical": true},":right_fist_tone4:":{"unicode":["1f91c-1f3fe"],"isCanonical": false},":right_facing_fist_tone3:":{"unicode":["1f91c-1f3fd"],"isCanonical": true},":right_fist_tone3:":{"unicode":["1f91c-1f3fd"],"isCanonical": false},":right_facing_fist_tone2:":{"unicode":["1f91c-1f3fc"],"isCanonical": true},":right_fist_tone2:":{"unicode":["1f91c-1f3fc"],"isCanonical": false},":right_facing_fist_tone1:":{"unicode":["1f91c-1f3fb"],"isCanonical": true},":right_fist_tone1:":{"unicode":["1f91c-1f3fb"],"isCanonical": false},":left_facing_fist_tone5:":{"unicode":["1f91b-1f3ff"],"isCanonical": true},":left_fist_tone5:":{"unicode":["1f91b-1f3ff"],"isCanonical": false},":left_facing_fist_tone4:":{"unicode":["1f91b-1f3fe"],"isCanonical": true},":left_fist_tone4:":{"unicode":["1f91b-1f3fe"],"isCanonical": false},":left_facing_fist_tone3:":{"unicode":["1f91b-1f3fd"],"isCanonical": true},":left_fist_tone3:":{"unicode":["1f91b-1f3fd"],"isCanonical": false},":left_facing_fist_tone2:":{"unicode":["1f91b-1f3fc"],"isCanonical": true},":left_fist_tone2:":{"unicode":["1f91b-1f3fc"],"isCanonical": false},":left_facing_fist_tone1:":{"unicode":["1f91b-1f3fb"],"isCanonical": true},":left_fist_tone1:":{"unicode":["1f91b-1f3fb"],"isCanonical": false},":raised_back_of_hand_tone5:":{"unicode":["1f91a-1f3ff"],"isCanonical": true},":back_of_hand_tone5:":{"unicode":["1f91a-1f3ff"],"isCanonical": false},":raised_back_of_hand_tone4:":{"unicode":["1f91a-1f3fe"],"isCanonical": true},":back_of_hand_tone4:":{"unicode":["1f91a-1f3fe"],"isCanonical": false},":raised_back_of_hand_tone3:":{"unicode":["1f91a-1f3fd"],"isCanonical": true},":back_of_hand_tone3:":{"unicode":["1f91a-1f3fd"],"isCanonical": false},":raised_back_of_hand_tone2:":{"unicode":["1f91a-1f3fc"],"isCanonical": true},":back_of_hand_tone2:":{"unicode":["1f91a-1f3fc"],"isCanonical": false},":raised_back_of_hand_tone1:":{"unicode":["1f91a-1f3fb"],"isCanonical": true},":back_of_hand_tone1:":{"unicode":["1f91a-1f3fb"],"isCanonical": false},":call_me_tone5:":{"unicode":["1f919-1f3ff"],"isCanonical": true},":call_me_hand_tone5:":{"unicode":["1f919-1f3ff"],"isCanonical": false},":call_me_tone4:":{"unicode":["1f919-1f3fe"],"isCanonical": true},":call_me_hand_tone4:":{"unicode":["1f919-1f3fe"],"isCanonical": false},":call_me_tone3:":{"unicode":["1f919-1f3fd"],"isCanonical": true},":call_me_hand_tone3:":{"unicode":["1f919-1f3fd"],"isCanonical": false},":call_me_tone2:":{"unicode":["1f919-1f3fc"],"isCanonical": true},":call_me_hand_tone2:":{"unicode":["1f919-1f3fc"],"isCanonical": false},":call_me_tone1:":{"unicode":["1f919-1f3fb"],"isCanonical": true},":call_me_hand_tone1:":{"unicode":["1f919-1f3fb"],"isCanonical": false},":metal_tone5:":{"unicode":["1f918-1f3ff"],"isCanonical": true},":sign_of_the_horns_tone5:":{"unicode":["1f918-1f3ff"],"isCanonical": false},":metal_tone4:":{"unicode":["1f918-1f3fe"],"isCanonical": true},":sign_of_the_horns_tone4:":{"unicode":["1f918-1f3fe"],"isCanonical": false},":metal_tone3:":{"unicode":["1f918-1f3fd"],"isCanonical": true},":sign_of_the_horns_tone3:":{"unicode":["1f918-1f3fd"],"isCanonical": false},":metal_tone2:":{"unicode":["1f918-1f3fc"],"isCanonical": true},":sign_of_the_horns_tone2:":{"unicode":["1f918-1f3fc"],"isCanonical": false},":metal_tone1:":{"unicode":["1f918-1f3fb"],"isCanonical": true},":sign_of_the_horns_tone1:":{"unicode":["1f918-1f3fb"],"isCanonical": false},":bath_tone5:":{"unicode":["1f6c0-1f3ff"],"isCanonical": true},":bath_tone4:":{"unicode":["1f6c0-1f3fe"],"isCanonical": true},":bath_tone3:":{"unicode":["1f6c0-1f3fd"],"isCanonical": true},":bath_tone2:":{"unicode":["1f6c0-1f3fc"],"isCanonical": true},":bath_tone1:":{"unicode":["1f6c0-1f3fb"],"isCanonical": true},":walking_tone5:":{"unicode":["1f6b6-1f3ff"],"isCanonical": true},":walking_tone4:":{"unicode":["1f6b6-1f3fe"],"isCanonical": true},":walking_tone3:":{"unicode":["1f6b6-1f3fd"],"isCanonical": true},":walking_tone2:":{"unicode":["1f6b6-1f3fc"],"isCanonical": true},":walking_tone1:":{"unicode":["1f6b6-1f3fb"],"isCanonical": true},":mountain_bicyclist_tone5:":{"unicode":["1f6b5-1f3ff"],"isCanonical": true},":mountain_bicyclist_tone4:":{"unicode":["1f6b5-1f3fe"],"isCanonical": true},":mountain_bicyclist_tone3:":{"unicode":["1f6b5-1f3fd"],"isCanonical": true},":mountain_bicyclist_tone2:":{"unicode":["1f6b5-1f3fc"],"isCanonical": true},":mountain_bicyclist_tone1:":{"unicode":["1f6b5-1f3fb"],"isCanonical": true},":bicyclist_tone5:":{"unicode":["1f6b4-1f3ff"],"isCanonical": true},":bicyclist_tone4:":{"unicode":["1f6b4-1f3fe"],"isCanonical": true},":bicyclist_tone3:":{"unicode":["1f6b4-1f3fd"],"isCanonical": true},":bicyclist_tone2:":{"unicode":["1f6b4-1f3fc"],"isCanonical": true},":bicyclist_tone1:":{"unicode":["1f6b4-1f3fb"],"isCanonical": true},":rowboat_tone5:":{"unicode":["1f6a3-1f3ff"],"isCanonical": true},":rowboat_tone4:":{"unicode":["1f6a3-1f3fe"],"isCanonical": true},":rowboat_tone3:":{"unicode":["1f6a3-1f3fd"],"isCanonical": true},":rowboat_tone2:":{"unicode":["1f6a3-1f3fc"],"isCanonical": true},":rowboat_tone1:":{"unicode":["1f6a3-1f3fb"],"isCanonical": true},":pray_tone5:":{"unicode":["1f64f-1f3ff"],"isCanonical": true},":pray_tone4:":{"unicode":["1f64f-1f3fe"],"isCanonical": true},":pray_tone3:":{"unicode":["1f64f-1f3fd"],"isCanonical": true},":pray_tone2:":{"unicode":["1f64f-1f3fc"],"isCanonical": true},":pray_tone1:":{"unicode":["1f64f-1f3fb"],"isCanonical": true},":person_with_pouting_face_tone5:":{"unicode":["1f64e-1f3ff"],"isCanonical": true},":person_with_pouting_face_tone4:":{"unicode":["1f64e-1f3fe"],"isCanonical": true},":person_with_pouting_face_tone3:":{"unicode":["1f64e-1f3fd"],"isCanonical": true},":person_with_pouting_face_tone2:":{"unicode":["1f64e-1f3fc"],"isCanonical": true},":person_with_pouting_face_tone1:":{"unicode":["1f64e-1f3fb"],"isCanonical": true},":person_frowning_tone5:":{"unicode":["1f64d-1f3ff"],"isCanonical": true},":person_frowning_tone4:":{"unicode":["1f64d-1f3fe"],"isCanonical": true},":person_frowning_tone3:":{"unicode":["1f64d-1f3fd"],"isCanonical": true},":person_frowning_tone2:":{"unicode":["1f64d-1f3fc"],"isCanonical": true},":person_frowning_tone1:":{"unicode":["1f64d-1f3fb"],"isCanonical": true},":raised_hands_tone5:":{"unicode":["1f64c-1f3ff"],"isCanonical": true},":raised_hands_tone4:":{"unicode":["1f64c-1f3fe"],"isCanonical": true},":raised_hands_tone3:":{"unicode":["1f64c-1f3fd"],"isCanonical": true},":raised_hands_tone2:":{"unicode":["1f64c-1f3fc"],"isCanonical": true},":raised_hands_tone1:":{"unicode":["1f64c-1f3fb"],"isCanonical": true},":raising_hand_tone5:":{"unicode":["1f64b-1f3ff"],"isCanonical": true},":raising_hand_tone4:":{"unicode":["1f64b-1f3fe"],"isCanonical": true},":raising_hand_tone3:":{"unicode":["1f64b-1f3fd"],"isCanonical": true},":raising_hand_tone2:":{"unicode":["1f64b-1f3fc"],"isCanonical": true},":raising_hand_tone1:":{"unicode":["1f64b-1f3fb"],"isCanonical": true},":bow_tone5:":{"unicode":["1f647-1f3ff"],"isCanonical": true},":bow_tone4:":{"unicode":["1f647-1f3fe"],"isCanonical": true},":bow_tone3:":{"unicode":["1f647-1f3fd"],"isCanonical": true},":bow_tone2:":{"unicode":["1f647-1f3fc"],"isCanonical": true},":bow_tone1:":{"unicode":["1f647-1f3fb"],"isCanonical": true},":ok_woman_tone5:":{"unicode":["1f646-1f3ff"],"isCanonical": true},":ok_woman_tone4:":{"unicode":["1f646-1f3fe"],"isCanonical": true},":ok_woman_tone3:":{"unicode":["1f646-1f3fd"],"isCanonical": true},":ok_woman_tone2:":{"unicode":["1f646-1f3fc"],"isCanonical": true},":ok_woman_tone1:":{"unicode":["1f646-1f3fb"],"isCanonical": true},":no_good_tone5:":{"unicode":["1f645-1f3ff"],"isCanonical": true},":no_good_tone4:":{"unicode":["1f645-1f3fe"],"isCanonical": true},":no_good_tone3:":{"unicode":["1f645-1f3fd"],"isCanonical": true},":no_good_tone2:":{"unicode":["1f645-1f3fc"],"isCanonical": true},":no_good_tone1:":{"unicode":["1f645-1f3fb"],"isCanonical": true},":vulcan_tone5:":{"unicode":["1f596-1f3ff"],"isCanonical": true},":raised_hand_with_part_between_middle_and_ring_fingers_tone5:":{"unicode":["1f596-1f3ff"],"isCanonical": false},":vulcan_tone4:":{"unicode":["1f596-1f3fe"],"isCanonical": true},":raised_hand_with_part_between_middle_and_ring_fingers_tone4:":{"unicode":["1f596-1f3fe"],"isCanonical": false},":vulcan_tone3:":{"unicode":["1f596-1f3fd"],"isCanonical": true},":raised_hand_with_part_between_middle_and_ring_fingers_tone3:":{"unicode":["1f596-1f3fd"],"isCanonical": false},":vulcan_tone2:":{"unicode":["1f596-1f3fc"],"isCanonical": true},":raised_hand_with_part_between_middle_and_ring_fingers_tone2:":{"unicode":["1f596-1f3fc"],"isCanonical": false},":vulcan_tone1:":{"unicode":["1f596-1f3fb"],"isCanonical": true},":raised_hand_with_part_between_middle_and_ring_fingers_tone1:":{"unicode":["1f596-1f3fb"],"isCanonical": false},":middle_finger_tone5:":{"unicode":["1f595-1f3ff"],"isCanonical": true},":reversed_hand_with_middle_finger_extended_tone5:":{"unicode":["1f595-1f3ff"],"isCanonical": false},":middle_finger_tone4:":{"unicode":["1f595-1f3fe"],"isCanonical": true},":reversed_hand_with_middle_finger_extended_tone4:":{"unicode":["1f595-1f3fe"],"isCanonical": false},":middle_finger_tone3:":{"unicode":["1f595-1f3fd"],"isCanonical": true},":reversed_hand_with_middle_finger_extended_tone3:":{"unicode":["1f595-1f3fd"],"isCanonical": false},":middle_finger_tone2:":{"unicode":["1f595-1f3fc"],"isCanonical": true},":reversed_hand_with_middle_finger_extended_tone2:":{"unicode":["1f595-1f3fc"],"isCanonical": false},":middle_finger_tone1:":{"unicode":["1f595-1f3fb"],"isCanonical": true},":reversed_hand_with_middle_finger_extended_tone1:":{"unicode":["1f595-1f3fb"],"isCanonical": false},":hand_splayed_tone5:":{"unicode":["1f590-1f3ff"],"isCanonical": true},":raised_hand_with_fingers_splayed_tone5:":{"unicode":["1f590-1f3ff"],"isCanonical": false},":hand_splayed_tone4:":{"unicode":["1f590-1f3fe"],"isCanonical": true},":raised_hand_with_fingers_splayed_tone4:":{"unicode":["1f590-1f3fe"],"isCanonical": false},":hand_splayed_tone3:":{"unicode":["1f590-1f3fd"],"isCanonical": true},":raised_hand_with_fingers_splayed_tone3:":{"unicode":["1f590-1f3fd"],"isCanonical": false},":hand_splayed_tone2:":{"unicode":["1f590-1f3fc"],"isCanonical": true},":raised_hand_with_fingers_splayed_tone2:":{"unicode":["1f590-1f3fc"],"isCanonical": false},":hand_splayed_tone1:":{"unicode":["1f590-1f3fb"],"isCanonical": true},":raised_hand_with_fingers_splayed_tone1:":{"unicode":["1f590-1f3fb"],"isCanonical": false},":man_dancing_tone5:":{"unicode":["1f57a-1f3ff"],"isCanonical": true},":male_dancer_tone5:":{"unicode":["1f57a-1f3ff"],"isCanonical": false},":man_dancing_tone4:":{"unicode":["1f57a-1f3fe"],"isCanonical": true},":male_dancer_tone4:":{"unicode":["1f57a-1f3fe"],"isCanonical": false},":man_dancing_tone3:":{"unicode":["1f57a-1f3fd"],"isCanonical": true},":male_dancer_tone3:":{"unicode":["1f57a-1f3fd"],"isCanonical": false},":man_dancing_tone2:":{"unicode":["1f57a-1f3fc"],"isCanonical": true},":male_dancer_tone2:":{"unicode":["1f57a-1f3fc"],"isCanonical": false},":man_dancing_tone1:":{"unicode":["1f57a-1f3fb"],"isCanonical": true},":male_dancer_tone1:":{"unicode":["1f57a-1f3fb"],"isCanonical": false},":spy_tone5:":{"unicode":["1f575-1f3ff"],"isCanonical": true},":sleuth_or_spy_tone5:":{"unicode":["1f575-1f3ff"],"isCanonical": false},":spy_tone4:":{"unicode":["1f575-1f3fe"],"isCanonical": true},":sleuth_or_spy_tone4:":{"unicode":["1f575-1f3fe"],"isCanonical": false},":spy_tone3:":{"unicode":["1f575-1f3fd"],"isCanonical": true},":sleuth_or_spy_tone3:":{"unicode":["1f575-1f3fd"],"isCanonical": false},":spy_tone2:":{"unicode":["1f575-1f3fc"],"isCanonical": true},":sleuth_or_spy_tone2:":{"unicode":["1f575-1f3fc"],"isCanonical": false},":spy_tone1:":{"unicode":["1f575-1f3fb"],"isCanonical": true},":sleuth_or_spy_tone1:":{"unicode":["1f575-1f3fb"],"isCanonical": false},":muscle_tone5:":{"unicode":["1f4aa-1f3ff"],"isCanonical": true},":muscle_tone4:":{"unicode":["1f4aa-1f3fe"],"isCanonical": true},":muscle_tone3:":{"unicode":["1f4aa-1f3fd"],"isCanonical": true},":muscle_tone2:":{"unicode":["1f4aa-1f3fc"],"isCanonical": true},":muscle_tone1:":{"unicode":["1f4aa-1f3fb"],"isCanonical": true},":haircut_tone5:":{"unicode":["1f487-1f3ff"],"isCanonical": true},":haircut_tone4:":{"unicode":["1f487-1f3fe"],"isCanonical": true},":haircut_tone3:":{"unicode":["1f487-1f3fd"],"isCanonical": true},":haircut_tone2:":{"unicode":["1f487-1f3fc"],"isCanonical": true},":haircut_tone1:":{"unicode":["1f487-1f3fb"],"isCanonical": true},":massage_tone5:":{"unicode":["1f486-1f3ff"],"isCanonical": true},":massage_tone4:":{"unicode":["1f486-1f3fe"],"isCanonical": true},":massage_tone3:":{"unicode":["1f486-1f3fd"],"isCanonical": true},":massage_tone2:":{"unicode":["1f486-1f3fc"],"isCanonical": true},":massage_tone1:":{"unicode":["1f486-1f3fb"],"isCanonical": true},":nail_care_tone5:":{"unicode":["1f485-1f3ff"],"isCanonical": true},":nail_care_tone4:":{"unicode":["1f485-1f3fe"],"isCanonical": true},":nail_care_tone3:":{"unicode":["1f485-1f3fd"],"isCanonical": true},":nail_care_tone2:":{"unicode":["1f485-1f3fc"],"isCanonical": true},":nail_care_tone1:":{"unicode":["1f485-1f3fb"],"isCanonical": true},":dancer_tone5:":{"unicode":["1f483-1f3ff"],"isCanonical": true},":dancer_tone4:":{"unicode":["1f483-1f3fe"],"isCanonical": true},":dancer_tone3:":{"unicode":["1f483-1f3fd"],"isCanonical": true},":dancer_tone2:":{"unicode":["1f483-1f3fc"],"isCanonical": true},":dancer_tone1:":{"unicode":["1f483-1f3fb"],"isCanonical": true},":guardsman_tone5:":{"unicode":["1f482-1f3ff"],"isCanonical": true},":guardsman_tone4:":{"unicode":["1f482-1f3fe"],"isCanonical": true},":guardsman_tone3:":{"unicode":["1f482-1f3fd"],"isCanonical": true},":guardsman_tone2:":{"unicode":["1f482-1f3fc"],"isCanonical": true},":guardsman_tone1:":{"unicode":["1f482-1f3fb"],"isCanonical": true},":information_desk_person_tone5:":{"unicode":["1f481-1f3ff"],"isCanonical": true},":information_desk_person_tone4:":{"unicode":["1f481-1f3fe"],"isCanonical": true},":information_desk_person_tone3:":{"unicode":["1f481-1f3fd"],"isCanonical": true},":information_desk_person_tone2:":{"unicode":["1f481-1f3fc"],"isCanonical": true},":information_desk_person_tone1:":{"unicode":["1f481-1f3fb"],"isCanonical": true},":angel_tone5:":{"unicode":["1f47c-1f3ff"],"isCanonical": true},":angel_tone4:":{"unicode":["1f47c-1f3fe"],"isCanonical": true},":angel_tone3:":{"unicode":["1f47c-1f3fd"],"isCanonical": true},":angel_tone2:":{"unicode":["1f47c-1f3fc"],"isCanonical": true},":angel_tone1:":{"unicode":["1f47c-1f3fb"],"isCanonical": true},":princess_tone5:":{"unicode":["1f478-1f3ff"],"isCanonical": true},":princess_tone4:":{"unicode":["1f478-1f3fe"],"isCanonical": true},":princess_tone3:":{"unicode":["1f478-1f3fd"],"isCanonical": true},":princess_tone2:":{"unicode":["1f478-1f3fc"],"isCanonical": true},":princess_tone1:":{"unicode":["1f478-1f3fb"],"isCanonical": true},":construction_worker_tone5:":{"unicode":["1f477-1f3ff"],"isCanonical": true},":construction_worker_tone4:":{"unicode":["1f477-1f3fe"],"isCanonical": true},":construction_worker_tone3:":{"unicode":["1f477-1f3fd"],"isCanonical": true},":construction_worker_tone2:":{"unicode":["1f477-1f3fc"],"isCanonical": true},":construction_worker_tone1:":{"unicode":["1f477-1f3fb"],"isCanonical": true},":baby_tone5:":{"unicode":["1f476-1f3ff"],"isCanonical": true},":baby_tone4:":{"unicode":["1f476-1f3fe"],"isCanonical": true},":baby_tone3:":{"unicode":["1f476-1f3fd"],"isCanonical": true},":baby_tone2:":{"unicode":["1f476-1f3fc"],"isCanonical": true},":baby_tone1:":{"unicode":["1f476-1f3fb"],"isCanonical": true},":older_woman_tone5:":{"unicode":["1f475-1f3ff"],"isCanonical": true},":grandma_tone5:":{"unicode":["1f475-1f3ff"],"isCanonical": false},":older_woman_tone4:":{"unicode":["1f475-1f3fe"],"isCanonical": true},":grandma_tone4:":{"unicode":["1f475-1f3fe"],"isCanonical": false},":older_woman_tone3:":{"unicode":["1f475-1f3fd"],"isCanonical": true},":grandma_tone3:":{"unicode":["1f475-1f3fd"],"isCanonical": false},":older_woman_tone2:":{"unicode":["1f475-1f3fc"],"isCanonical": true},":grandma_tone2:":{"unicode":["1f475-1f3fc"],"isCanonical": false},":older_woman_tone1:":{"unicode":["1f475-1f3fb"],"isCanonical": true},":grandma_tone1:":{"unicode":["1f475-1f3fb"],"isCanonical": false},":older_man_tone5:":{"unicode":["1f474-1f3ff"],"isCanonical": true},":older_man_tone4:":{"unicode":["1f474-1f3fe"],"isCanonical": true},":older_man_tone3:":{"unicode":["1f474-1f3fd"],"isCanonical": true},":older_man_tone2:":{"unicode":["1f474-1f3fc"],"isCanonical": true},":older_man_tone1:":{"unicode":["1f474-1f3fb"],"isCanonical": true},":man_with_turban_tone5:":{"unicode":["1f473-1f3ff"],"isCanonical": true},":man_with_turban_tone4:":{"unicode":["1f473-1f3fe"],"isCanonical": true},":man_with_turban_tone3:":{"unicode":["1f473-1f3fd"],"isCanonical": true},":man_with_turban_tone2:":{"unicode":["1f473-1f3fc"],"isCanonical": true},":man_with_turban_tone1:":{"unicode":["1f473-1f3fb"],"isCanonical": true},":man_with_gua_pi_mao_tone5:":{"unicode":["1f472-1f3ff"],"isCanonical": true},":man_with_gua_pi_mao_tone4:":{"unicode":["1f472-1f3fe"],"isCanonical": true},":man_with_gua_pi_mao_tone3:":{"unicode":["1f472-1f3fd"],"isCanonical": true},":man_with_gua_pi_mao_tone2:":{"unicode":["1f472-1f3fc"],"isCanonical": true},":man_with_gua_pi_mao_tone1:":{"unicode":["1f472-1f3fb"],"isCanonical": true},":person_with_blond_hair_tone5:":{"unicode":["1f471-1f3ff"],"isCanonical": true},":person_with_blond_hair_tone4:":{"unicode":["1f471-1f3fe"],"isCanonical": true},":person_with_blond_hair_tone3:":{"unicode":["1f471-1f3fd"],"isCanonical": true},":person_with_blond_hair_tone2:":{"unicode":["1f471-1f3fc"],"isCanonical": true},":person_with_blond_hair_tone1:":{"unicode":["1f471-1f3fb"],"isCanonical": true},":bride_with_veil_tone5:":{"unicode":["1f470-1f3ff"],"isCanonical": true},":bride_with_veil_tone4:":{"unicode":["1f470-1f3fe"],"isCanonical": true},":bride_with_veil_tone3:":{"unicode":["1f470-1f3fd"],"isCanonical": true},":bride_with_veil_tone2:":{"unicode":["1f470-1f3fc"],"isCanonical": true},":bride_with_veil_tone1:":{"unicode":["1f470-1f3fb"],"isCanonical": true},":cop_tone5:":{"unicode":["1f46e-1f3ff"],"isCanonical": true},":cop_tone4:":{"unicode":["1f46e-1f3fe"],"isCanonical": true},":cop_tone3:":{"unicode":["1f46e-1f3fd"],"isCanonical": true},":cop_tone2:":{"unicode":["1f46e-1f3fc"],"isCanonical": true},":cop_tone1:":{"unicode":["1f46e-1f3fb"],"isCanonical": true},":woman_tone5:":{"unicode":["1f469-1f3ff"],"isCanonical": true},":woman_tone4:":{"unicode":["1f469-1f3fe"],"isCanonical": true},":woman_tone3:":{"unicode":["1f469-1f3fd"],"isCanonical": true},":woman_tone2:":{"unicode":["1f469-1f3fc"],"isCanonical": true},":woman_tone1:":{"unicode":["1f469-1f3fb"],"isCanonical": true},":man_tone5:":{"unicode":["1f468-1f3ff"],"isCanonical": true},":man_tone4:":{"unicode":["1f468-1f3fe"],"isCanonical": true},":man_tone3:":{"unicode":["1f468-1f3fd"],"isCanonical": true},":man_tone2:":{"unicode":["1f468-1f3fc"],"isCanonical": true},":man_tone1:":{"unicode":["1f468-1f3fb"],"isCanonical": true},":girl_tone5:":{"unicode":["1f467-1f3ff"],"isCanonical": true},":girl_tone4:":{"unicode":["1f467-1f3fe"],"isCanonical": true},":girl_tone3:":{"unicode":["1f467-1f3fd"],"isCanonical": true},":girl_tone2:":{"unicode":["1f467-1f3fc"],"isCanonical": true},":girl_tone1:":{"unicode":["1f467-1f3fb"],"isCanonical": true},":boy_tone5:":{"unicode":["1f466-1f3ff"],"isCanonical": true},":boy_tone4:":{"unicode":["1f466-1f3fe"],"isCanonical": true},":boy_tone3:":{"unicode":["1f466-1f3fd"],"isCanonical": true},":boy_tone2:":{"unicode":["1f466-1f3fc"],"isCanonical": true},":boy_tone1:":{"unicode":["1f466-1f3fb"],"isCanonical": true},":open_hands_tone5:":{"unicode":["1f450-1f3ff"],"isCanonical": true},":open_hands_tone4:":{"unicode":["1f450-1f3fe"],"isCanonical": true},":open_hands_tone3:":{"unicode":["1f450-1f3fd"],"isCanonical": true},":open_hands_tone2:":{"unicode":["1f450-1f3fc"],"isCanonical": true},":open_hands_tone1:":{"unicode":["1f450-1f3fb"],"isCanonical": true},":clap_tone5:":{"unicode":["1f44f-1f3ff"],"isCanonical": true},":clap_tone4:":{"unicode":["1f44f-1f3fe"],"isCanonical": true},":clap_tone3:":{"unicode":["1f44f-1f3fd"],"isCanonical": true},":clap_tone2:":{"unicode":["1f44f-1f3fc"],"isCanonical": true},":clap_tone1:":{"unicode":["1f44f-1f3fb"],"isCanonical": true},":thumbsdown_tone5:":{"unicode":["1f44e-1f3ff"],"isCanonical": true},":-1_tone5:":{"unicode":["1f44e-1f3ff"],"isCanonical": false},":thumbdown_tone5:":{"unicode":["1f44e-1f3ff"],"isCanonical": false},":thumbsdown_tone4:":{"unicode":["1f44e-1f3fe"],"isCanonical": true},":-1_tone4:":{"unicode":["1f44e-1f3fe"],"isCanonical": false},":thumbdown_tone4:":{"unicode":["1f44e-1f3fe"],"isCanonical": false},":thumbsdown_tone3:":{"unicode":["1f44e-1f3fd"],"isCanonical": true},":-1_tone3:":{"unicode":["1f44e-1f3fd"],"isCanonical": false},":thumbdown_tone3:":{"unicode":["1f44e-1f3fd"],"isCanonical": false},":thumbsdown_tone2:":{"unicode":["1f44e-1f3fc"],"isCanonical": true},":-1_tone2:":{"unicode":["1f44e-1f3fc"],"isCanonical": false},":thumbdown_tone2:":{"unicode":["1f44e-1f3fc"],"isCanonical": false},":thumbsdown_tone1:":{"unicode":["1f44e-1f3fb"],"isCanonical": true},":-1_tone1:":{"unicode":["1f44e-1f3fb"],"isCanonical": false},":thumbdown_tone1:":{"unicode":["1f44e-1f3fb"],"isCanonical": false},":thumbsup_tone5:":{"unicode":["1f44d-1f3ff"],"isCanonical": true},":+1_tone5:":{"unicode":["1f44d-1f3ff"],"isCanonical": false},":thumbup_tone5:":{"unicode":["1f44d-1f3ff"],"isCanonical": false},":thumbsup_tone4:":{"unicode":["1f44d-1f3fe"],"isCanonical": true},":+1_tone4:":{"unicode":["1f44d-1f3fe"],"isCanonical": false},":thumbup_tone4:":{"unicode":["1f44d-1f3fe"],"isCanonical": false},":thumbsup_tone3:":{"unicode":["1f44d-1f3fd"],"isCanonical": true},":+1_tone3:":{"unicode":["1f44d-1f3fd"],"isCanonical": false},":thumbup_tone3:":{"unicode":["1f44d-1f3fd"],"isCanonical": false},":thumbsup_tone2:":{"unicode":["1f44d-1f3fc"],"isCanonical": true},":+1_tone2:":{"unicode":["1f44d-1f3fc"],"isCanonical": false},":thumbup_tone2:":{"unicode":["1f44d-1f3fc"],"isCanonical": false},":thumbsup_tone1:":{"unicode":["1f44d-1f3fb"],"isCanonical": true},":+1_tone1:":{"unicode":["1f44d-1f3fb"],"isCanonical": false},":thumbup_tone1:":{"unicode":["1f44d-1f3fb"],"isCanonical": false},":ok_hand_tone5:":{"unicode":["1f44c-1f3ff"],"isCanonical": true},":ok_hand_tone4:":{"unicode":["1f44c-1f3fe"],"isCanonical": true},":ok_hand_tone3:":{"unicode":["1f44c-1f3fd"],"isCanonical": true},":ok_hand_tone2:":{"unicode":["1f44c-1f3fc"],"isCanonical": true},":ok_hand_tone1:":{"unicode":["1f44c-1f3fb"],"isCanonical": true},":wave_tone5:":{"unicode":["1f44b-1f3ff"],"isCanonical": true},":wave_tone4:":{"unicode":["1f44b-1f3fe"],"isCanonical": true},":wave_tone3:":{"unicode":["1f44b-1f3fd"],"isCanonical": true},":wave_tone2:":{"unicode":["1f44b-1f3fc"],"isCanonical": true},":wave_tone1:":{"unicode":["1f44b-1f3fb"],"isCanonical": true},":punch_tone5:":{"unicode":["1f44a-1f3ff"],"isCanonical": true},":punch_tone4:":{"unicode":["1f44a-1f3fe"],"isCanonical": true},":punch_tone3:":{"unicode":["1f44a-1f3fd"],"isCanonical": true},":punch_tone2:":{"unicode":["1f44a-1f3fc"],"isCanonical": true},":punch_tone1:":{"unicode":["1f44a-1f3fb"],"isCanonical": true},":point_right_tone5:":{"unicode":["1f449-1f3ff"],"isCanonical": true},":point_right_tone4:":{"unicode":["1f449-1f3fe"],"isCanonical": true},":point_right_tone3:":{"unicode":["1f449-1f3fd"],"isCanonical": true},":point_right_tone2:":{"unicode":["1f449-1f3fc"],"isCanonical": true},":point_right_tone1:":{"unicode":["1f449-1f3fb"],"isCanonical": true},":point_left_tone5:":{"unicode":["1f448-1f3ff"],"isCanonical": true},":point_left_tone4:":{"unicode":["1f448-1f3fe"],"isCanonical": true},":point_left_tone3:":{"unicode":["1f448-1f3fd"],"isCanonical": true},":point_left_tone2:":{"unicode":["1f448-1f3fc"],"isCanonical": true},":point_left_tone1:":{"unicode":["1f448-1f3fb"],"isCanonical": true},":point_down_tone5:":{"unicode":["1f447-1f3ff"],"isCanonical": true},":point_down_tone4:":{"unicode":["1f447-1f3fe"],"isCanonical": true},":point_down_tone3:":{"unicode":["1f447-1f3fd"],"isCanonical": true},":point_down_tone2:":{"unicode":["1f447-1f3fc"],"isCanonical": true},":point_down_tone1:":{"unicode":["1f447-1f3fb"],"isCanonical": true},":point_up_2_tone5:":{"unicode":["1f446-1f3ff"],"isCanonical": true},":point_up_2_tone4:":{"unicode":["1f446-1f3fe"],"isCanonical": true},":point_up_2_tone3:":{"unicode":["1f446-1f3fd"],"isCanonical": true},":point_up_2_tone2:":{"unicode":["1f446-1f3fc"],"isCanonical": true},":point_up_2_tone1:":{"unicode":["1f446-1f3fb"],"isCanonical": true},":nose_tone5:":{"unicode":["1f443-1f3ff"],"isCanonical": true},":nose_tone4:":{"unicode":["1f443-1f3fe"],"isCanonical": true},":nose_tone3:":{"unicode":["1f443-1f3fd"],"isCanonical": true},":nose_tone2:":{"unicode":["1f443-1f3fc"],"isCanonical": true},":nose_tone1:":{"unicode":["1f443-1f3fb"],"isCanonical": true},":ear_tone5:":{"unicode":["1f442-1f3ff"],"isCanonical": true},":ear_tone4:":{"unicode":["1f442-1f3fe"],"isCanonical": true},":ear_tone3:":{"unicode":["1f442-1f3fd"],"isCanonical": true},":ear_tone2:":{"unicode":["1f442-1f3fc"],"isCanonical": true},":ear_tone1:":{"unicode":["1f442-1f3fb"],"isCanonical": true},":gay_pride_flag:":{"unicode":["1f3f3-1f308"],"isCanonical": true},":rainbow_flag:":{"unicode":["1f3f3-1f308"],"isCanonical": false},":lifter_tone5:":{"unicode":["1f3cb-1f3ff"],"isCanonical": true},":weight_lifter_tone5:":{"unicode":["1f3cb-1f3ff"],"isCanonical": false},":lifter_tone4:":{"unicode":["1f3cb-1f3fe"],"isCanonical": true},":weight_lifter_tone4:":{"unicode":["1f3cb-1f3fe"],"isCanonical": false},":lifter_tone3:":{"unicode":["1f3cb-1f3fd"],"isCanonical": true},":weight_lifter_tone3:":{"unicode":["1f3cb-1f3fd"],"isCanonical": false},":lifter_tone2:":{"unicode":["1f3cb-1f3fc"],"isCanonical": true},":weight_lifter_tone2:":{"unicode":["1f3cb-1f3fc"],"isCanonical": false},":lifter_tone1:":{"unicode":["1f3cb-1f3fb"],"isCanonical": true},":weight_lifter_tone1:":{"unicode":["1f3cb-1f3fb"],"isCanonical": false},":swimmer_tone5:":{"unicode":["1f3ca-1f3ff"],"isCanonical": true},":swimmer_tone4:":{"unicode":["1f3ca-1f3fe"],"isCanonical": true},":swimmer_tone3:":{"unicode":["1f3ca-1f3fd"],"isCanonical": true},":swimmer_tone2:":{"unicode":["1f3ca-1f3fc"],"isCanonical": true},":swimmer_tone1:":{"unicode":["1f3ca-1f3fb"],"isCanonical": true},":horse_racing_tone5:":{"unicode":["1f3c7-1f3ff"],"isCanonical": true},":horse_racing_tone4:":{"unicode":["1f3c7-1f3fe"],"isCanonical": true},":horse_racing_tone3:":{"unicode":["1f3c7-1f3fd"],"isCanonical": true},":horse_racing_tone2:":{"unicode":["1f3c7-1f3fc"],"isCanonical": true},":horse_racing_tone1:":{"unicode":["1f3c7-1f3fb"],"isCanonical": true},":surfer_tone5:":{"unicode":["1f3c4-1f3ff"],"isCanonical": true},":surfer_tone4:":{"unicode":["1f3c4-1f3fe"],"isCanonical": true},":surfer_tone3:":{"unicode":["1f3c4-1f3fd"],"isCanonical": true},":surfer_tone2:":{"unicode":["1f3c4-1f3fc"],"isCanonical": true},":surfer_tone1:":{"unicode":["1f3c4-1f3fb"],"isCanonical": true},":runner_tone5:":{"unicode":["1f3c3-1f3ff"],"isCanonical": true},":runner_tone4:":{"unicode":["1f3c3-1f3fe"],"isCanonical": true},":runner_tone3:":{"unicode":["1f3c3-1f3fd"],"isCanonical": true},":runner_tone2:":{"unicode":["1f3c3-1f3fc"],"isCanonical": true},":runner_tone1:":{"unicode":["1f3c3-1f3fb"],"isCanonical": true},":santa_tone5:":{"unicode":["1f385-1f3ff"],"isCanonical": true},":santa_tone4:":{"unicode":["1f385-1f3fe"],"isCanonical": true},":santa_tone3:":{"unicode":["1f385-1f3fd"],"isCanonical": true},":santa_tone2:":{"unicode":["1f385-1f3fc"],"isCanonical": true},":santa_tone1:":{"unicode":["1f385-1f3fb"],"isCanonical": true},":flag_zw:":{"unicode":["1f1ff-1f1fc"],"isCanonical": true},":zw:":{"unicode":["1f1ff-1f1fc"],"isCanonical": false},":flag_zm:":{"unicode":["1f1ff-1f1f2"],"isCanonical": true},":zm:":{"unicode":["1f1ff-1f1f2"],"isCanonical": false},":flag_za:":{"unicode":["1f1ff-1f1e6"],"isCanonical": true},":za:":{"unicode":["1f1ff-1f1e6"],"isCanonical": false},":flag_yt:":{"unicode":["1f1fe-1f1f9"],"isCanonical": true},":yt:":{"unicode":["1f1fe-1f1f9"],"isCanonical": false},":flag_ye:":{"unicode":["1f1fe-1f1ea"],"isCanonical": true},":ye:":{"unicode":["1f1fe-1f1ea"],"isCanonical": false},":flag_xk:":{"unicode":["1f1fd-1f1f0"],"isCanonical": true},":xk:":{"unicode":["1f1fd-1f1f0"],"isCanonical": false},":flag_ws:":{"unicode":["1f1fc-1f1f8"],"isCanonical": true},":ws:":{"unicode":["1f1fc-1f1f8"],"isCanonical": false},":flag_wf:":{"unicode":["1f1fc-1f1eb"],"isCanonical": true},":wf:":{"unicode":["1f1fc-1f1eb"],"isCanonical": false},":flag_vu:":{"unicode":["1f1fb-1f1fa"],"isCanonical": true},":vu:":{"unicode":["1f1fb-1f1fa"],"isCanonical": false},":flag_vn:":{"unicode":["1f1fb-1f1f3"],"isCanonical": true},":vn:":{"unicode":["1f1fb-1f1f3"],"isCanonical": false},":flag_vi:":{"unicode":["1f1fb-1f1ee"],"isCanonical": true},":vi:":{"unicode":["1f1fb-1f1ee"],"isCanonical": false},":flag_vg:":{"unicode":["1f1fb-1f1ec"],"isCanonical": true},":vg:":{"unicode":["1f1fb-1f1ec"],"isCanonical": false},":flag_ve:":{"unicode":["1f1fb-1f1ea"],"isCanonical": true},":ve:":{"unicode":["1f1fb-1f1ea"],"isCanonical": false},":flag_vc:":{"unicode":["1f1fb-1f1e8"],"isCanonical": true},":vc:":{"unicode":["1f1fb-1f1e8"],"isCanonical": false},":flag_va:":{"unicode":["1f1fb-1f1e6"],"isCanonical": true},":va:":{"unicode":["1f1fb-1f1e6"],"isCanonical": false},":flag_uz:":{"unicode":["1f1fa-1f1ff"],"isCanonical": true},":uz:":{"unicode":["1f1fa-1f1ff"],"isCanonical": false},":flag_uy:":{"unicode":["1f1fa-1f1fe"],"isCanonical": true},":uy:":{"unicode":["1f1fa-1f1fe"],"isCanonical": false},":flag_us:":{"unicode":["1f1fa-1f1f8"],"isCanonical": true},":us:":{"unicode":["1f1fa-1f1f8"],"isCanonical": false},":flag_um:":{"unicode":["1f1fa-1f1f2"],"isCanonical": true},":um:":{"unicode":["1f1fa-1f1f2"],"isCanonical": false},":flag_ug:":{"unicode":["1f1fa-1f1ec"],"isCanonical": true},":ug:":{"unicode":["1f1fa-1f1ec"],"isCanonical": false},":flag_ua:":{"unicode":["1f1fa-1f1e6"],"isCanonical": true},":ua:":{"unicode":["1f1fa-1f1e6"],"isCanonical": false},":flag_tz:":{"unicode":["1f1f9-1f1ff"],"isCanonical": true},":tz:":{"unicode":["1f1f9-1f1ff"],"isCanonical": false},":flag_tw:":{"unicode":["1f1f9-1f1fc"],"isCanonical": true},":tw:":{"unicode":["1f1f9-1f1fc"],"isCanonical": false},":flag_tv:":{"unicode":["1f1f9-1f1fb"],"isCanonical": true},":tuvalu:":{"unicode":["1f1f9-1f1fb"],"isCanonical": false},":flag_tt:":{"unicode":["1f1f9-1f1f9"],"isCanonical": true},":tt:":{"unicode":["1f1f9-1f1f9"],"isCanonical": false},":flag_tr:":{"unicode":["1f1f9-1f1f7"],"isCanonical": true},":tr:":{"unicode":["1f1f9-1f1f7"],"isCanonical": false},":flag_to:":{"unicode":["1f1f9-1f1f4"],"isCanonical": true},":to:":{"unicode":["1f1f9-1f1f4"],"isCanonical": false},":flag_tn:":{"unicode":["1f1f9-1f1f3"],"isCanonical": true},":tn:":{"unicode":["1f1f9-1f1f3"],"isCanonical": false},":flag_tm:":{"unicode":["1f1f9-1f1f2"],"isCanonical": true},":turkmenistan:":{"unicode":["1f1f9-1f1f2"],"isCanonical": false},":flag_tl:":{"unicode":["1f1f9-1f1f1"],"isCanonical": true},":tl:":{"unicode":["1f1f9-1f1f1"],"isCanonical": false},":flag_tk:":{"unicode":["1f1f9-1f1f0"],"isCanonical": true},":tk:":{"unicode":["1f1f9-1f1f0"],"isCanonical": false},":flag_tj:":{"unicode":["1f1f9-1f1ef"],"isCanonical": true},":tj:":{"unicode":["1f1f9-1f1ef"],"isCanonical": false},":flag_th:":{"unicode":["1f1f9-1f1ed"],"isCanonical": true},":th:":{"unicode":["1f1f9-1f1ed"],"isCanonical": false},":flag_tg:":{"unicode":["1f1f9-1f1ec"],"isCanonical": true},":tg:":{"unicode":["1f1f9-1f1ec"],"isCanonical": false},":flag_tf:":{"unicode":["1f1f9-1f1eb"],"isCanonical": true},":tf:":{"unicode":["1f1f9-1f1eb"],"isCanonical": false},":flag_td:":{"unicode":["1f1f9-1f1e9"],"isCanonical": true},":td:":{"unicode":["1f1f9-1f1e9"],"isCanonical": false},":flag_tc:":{"unicode":["1f1f9-1f1e8"],"isCanonical": true},":tc:":{"unicode":["1f1f9-1f1e8"],"isCanonical": false},":flag_ta:":{"unicode":["1f1f9-1f1e6"],"isCanonical": true},":ta:":{"unicode":["1f1f9-1f1e6"],"isCanonical": false},":flag_sz:":{"unicode":["1f1f8-1f1ff"],"isCanonical": true},":sz:":{"unicode":["1f1f8-1f1ff"],"isCanonical": false},":flag_sy:":{"unicode":["1f1f8-1f1fe"],"isCanonical": true},":sy:":{"unicode":["1f1f8-1f1fe"],"isCanonical": false},":flag_sx:":{"unicode":["1f1f8-1f1fd"],"isCanonical": true},":sx:":{"unicode":["1f1f8-1f1fd"],"isCanonical": false},":flag_sv:":{"unicode":["1f1f8-1f1fb"],"isCanonical": true},":sv:":{"unicode":["1f1f8-1f1fb"],"isCanonical": false},":flag_st:":{"unicode":["1f1f8-1f1f9"],"isCanonical": true},":st:":{"unicode":["1f1f8-1f1f9"],"isCanonical": false},":flag_ss:":{"unicode":["1f1f8-1f1f8"],"isCanonical": true},":ss:":{"unicode":["1f1f8-1f1f8"],"isCanonical": false},":flag_sr:":{"unicode":["1f1f8-1f1f7"],"isCanonical": true},":sr:":{"unicode":["1f1f8-1f1f7"],"isCanonical": false},":flag_so:":{"unicode":["1f1f8-1f1f4"],"isCanonical": true},":so:":{"unicode":["1f1f8-1f1f4"],"isCanonical": false},":flag_sn:":{"unicode":["1f1f8-1f1f3"],"isCanonical": true},":sn:":{"unicode":["1f1f8-1f1f3"],"isCanonical": false},":flag_sm:":{"unicode":["1f1f8-1f1f2"],"isCanonical": true},":sm:":{"unicode":["1f1f8-1f1f2"],"isCanonical": false},":flag_sl:":{"unicode":["1f1f8-1f1f1"],"isCanonical": true},":sl:":{"unicode":["1f1f8-1f1f1"],"isCanonical": false},":flag_sk:":{"unicode":["1f1f8-1f1f0"],"isCanonical": true},":sk:":{"unicode":["1f1f8-1f1f0"],"isCanonical": false},":flag_sj:":{"unicode":["1f1f8-1f1ef"],"isCanonical": true},":sj:":{"unicode":["1f1f8-1f1ef"],"isCanonical": false},":flag_si:":{"unicode":["1f1f8-1f1ee"],"isCanonical": true},":si:":{"unicode":["1f1f8-1f1ee"],"isCanonical": false},":flag_sh:":{"unicode":["1f1f8-1f1ed"],"isCanonical": true},":sh:":{"unicode":["1f1f8-1f1ed"],"isCanonical": false},":flag_sg:":{"unicode":["1f1f8-1f1ec"],"isCanonical": true},":sg:":{"unicode":["1f1f8-1f1ec"],"isCanonical": false},":flag_se:":{"unicode":["1f1f8-1f1ea"],"isCanonical": true},":se:":{"unicode":["1f1f8-1f1ea"],"isCanonical": false},":flag_sd:":{"unicode":["1f1f8-1f1e9"],"isCanonical": true},":sd:":{"unicode":["1f1f8-1f1e9"],"isCanonical": false},":flag_sc:":{"unicode":["1f1f8-1f1e8"],"isCanonical": true},":sc:":{"unicode":["1f1f8-1f1e8"],"isCanonical": false},":flag_sb:":{"unicode":["1f1f8-1f1e7"],"isCanonical": true},":sb:":{"unicode":["1f1f8-1f1e7"],"isCanonical": false},":flag_sa:":{"unicode":["1f1f8-1f1e6"],"isCanonical": true},":saudiarabia:":{"unicode":["1f1f8-1f1e6"],"isCanonical": false},":saudi:":{"unicode":["1f1f8-1f1e6"],"isCanonical": false},":flag_rw:":{"unicode":["1f1f7-1f1fc"],"isCanonical": true},":rw:":{"unicode":["1f1f7-1f1fc"],"isCanonical": false},":flag_ru:":{"unicode":["1f1f7-1f1fa"],"isCanonical": true},":ru:":{"unicode":["1f1f7-1f1fa"],"isCanonical": false},":flag_rs:":{"unicode":["1f1f7-1f1f8"],"isCanonical": true},":rs:":{"unicode":["1f1f7-1f1f8"],"isCanonical": false},":flag_ro:":{"unicode":["1f1f7-1f1f4"],"isCanonical": true},":ro:":{"unicode":["1f1f7-1f1f4"],"isCanonical": false},":flag_re:":{"unicode":["1f1f7-1f1ea"],"isCanonical": true},":re:":{"unicode":["1f1f7-1f1ea"],"isCanonical": false},":flag_qa:":{"unicode":["1f1f6-1f1e6"],"isCanonical": true},":qa:":{"unicode":["1f1f6-1f1e6"],"isCanonical": false},":flag_py:":{"unicode":["1f1f5-1f1fe"],"isCanonical": true},":py:":{"unicode":["1f1f5-1f1fe"],"isCanonical": false},":flag_pw:":{"unicode":["1f1f5-1f1fc"],"isCanonical": true},":pw:":{"unicode":["1f1f5-1f1fc"],"isCanonical": false},":flag_pt:":{"unicode":["1f1f5-1f1f9"],"isCanonical": true},":pt:":{"unicode":["1f1f5-1f1f9"],"isCanonical": false},":flag_ps:":{"unicode":["1f1f5-1f1f8"],"isCanonical": true},":ps:":{"unicode":["1f1f5-1f1f8"],"isCanonical": false},":flag_pr:":{"unicode":["1f1f5-1f1f7"],"isCanonical": true},":pr:":{"unicode":["1f1f5-1f1f7"],"isCanonical": false},":flag_pn:":{"unicode":["1f1f5-1f1f3"],"isCanonical": true},":pn:":{"unicode":["1f1f5-1f1f3"],"isCanonical": false},":flag_pm:":{"unicode":["1f1f5-1f1f2"],"isCanonical": true},":pm:":{"unicode":["1f1f5-1f1f2"],"isCanonical": false},":flag_pl:":{"unicode":["1f1f5-1f1f1"],"isCanonical": true},":pl:":{"unicode":["1f1f5-1f1f1"],"isCanonical": false},":flag_pk:":{"unicode":["1f1f5-1f1f0"],"isCanonical": true},":pk:":{"unicode":["1f1f5-1f1f0"],"isCanonical": false},":flag_ph:":{"unicode":["1f1f5-1f1ed"],"isCanonical": true},":ph:":{"unicode":["1f1f5-1f1ed"],"isCanonical": false},":flag_pg:":{"unicode":["1f1f5-1f1ec"],"isCanonical": true},":pg:":{"unicode":["1f1f5-1f1ec"],"isCanonical": false},":flag_pf:":{"unicode":["1f1f5-1f1eb"],"isCanonical": true},":pf:":{"unicode":["1f1f5-1f1eb"],"isCanonical": false},":flag_pe:":{"unicode":["1f1f5-1f1ea"],"isCanonical": true},":pe:":{"unicode":["1f1f5-1f1ea"],"isCanonical": false},":flag_pa:":{"unicode":["1f1f5-1f1e6"],"isCanonical": true},":pa:":{"unicode":["1f1f5-1f1e6"],"isCanonical": false},":flag_om:":{"unicode":["1f1f4-1f1f2"],"isCanonical": true},":om:":{"unicode":["1f1f4-1f1f2"],"isCanonical": false},":flag_nz:":{"unicode":["1f1f3-1f1ff"],"isCanonical": true},":nz:":{"unicode":["1f1f3-1f1ff"],"isCanonical": false},":flag_nu:":{"unicode":["1f1f3-1f1fa"],"isCanonical": true},":nu:":{"unicode":["1f1f3-1f1fa"],"isCanonical": false},":flag_nr:":{"unicode":["1f1f3-1f1f7"],"isCanonical": true},":nr:":{"unicode":["1f1f3-1f1f7"],"isCanonical": false},":flag_np:":{"unicode":["1f1f3-1f1f5"],"isCanonical": true},":np:":{"unicode":["1f1f3-1f1f5"],"isCanonical": false},":flag_no:":{"unicode":["1f1f3-1f1f4"],"isCanonical": true},":no:":{"unicode":["1f1f3-1f1f4"],"isCanonical": false},":flag_nl:":{"unicode":["1f1f3-1f1f1"],"isCanonical": true},":nl:":{"unicode":["1f1f3-1f1f1"],"isCanonical": false},":flag_ni:":{"unicode":["1f1f3-1f1ee"],"isCanonical": true},":ni:":{"unicode":["1f1f3-1f1ee"],"isCanonical": false},":flag_ng:":{"unicode":["1f1f3-1f1ec"],"isCanonical": true},":nigeria:":{"unicode":["1f1f3-1f1ec"],"isCanonical": false},":flag_nf:":{"unicode":["1f1f3-1f1eb"],"isCanonical": true},":nf:":{"unicode":["1f1f3-1f1eb"],"isCanonical": false},":flag_ne:":{"unicode":["1f1f3-1f1ea"],"isCanonical": true},":ne:":{"unicode":["1f1f3-1f1ea"],"isCanonical": false},":flag_nc:":{"unicode":["1f1f3-1f1e8"],"isCanonical": true},":nc:":{"unicode":["1f1f3-1f1e8"],"isCanonical": false},":flag_na:":{"unicode":["1f1f3-1f1e6"],"isCanonical": true},":na:":{"unicode":["1f1f3-1f1e6"],"isCanonical": false},":flag_mz:":{"unicode":["1f1f2-1f1ff"],"isCanonical": true},":mz:":{"unicode":["1f1f2-1f1ff"],"isCanonical": false},":flag_my:":{"unicode":["1f1f2-1f1fe"],"isCanonical": true},":my:":{"unicode":["1f1f2-1f1fe"],"isCanonical": false},":flag_mx:":{"unicode":["1f1f2-1f1fd"],"isCanonical": true},":mx:":{"unicode":["1f1f2-1f1fd"],"isCanonical": false},":flag_mw:":{"unicode":["1f1f2-1f1fc"],"isCanonical": true},":mw:":{"unicode":["1f1f2-1f1fc"],"isCanonical": false},":flag_mv:":{"unicode":["1f1f2-1f1fb"],"isCanonical": true},":mv:":{"unicode":["1f1f2-1f1fb"],"isCanonical": false},":flag_mu:":{"unicode":["1f1f2-1f1fa"],"isCanonical": true},":mu:":{"unicode":["1f1f2-1f1fa"],"isCanonical": false},":flag_mt:":{"unicode":["1f1f2-1f1f9"],"isCanonical": true},":mt:":{"unicode":["1f1f2-1f1f9"],"isCanonical": false},":flag_ms:":{"unicode":["1f1f2-1f1f8"],"isCanonical": true},":ms:":{"unicode":["1f1f2-1f1f8"],"isCanonical": false},":flag_mr:":{"unicode":["1f1f2-1f1f7"],"isCanonical": true},":mr:":{"unicode":["1f1f2-1f1f7"],"isCanonical": false},":flag_mq:":{"unicode":["1f1f2-1f1f6"],"isCanonical": true},":mq:":{"unicode":["1f1f2-1f1f6"],"isCanonical": false},":flag_mp:":{"unicode":["1f1f2-1f1f5"],"isCanonical": true},":mp:":{"unicode":["1f1f2-1f1f5"],"isCanonical": false},":flag_mo:":{"unicode":["1f1f2-1f1f4"],"isCanonical": true},":mo:":{"unicode":["1f1f2-1f1f4"],"isCanonical": false},":flag_mn:":{"unicode":["1f1f2-1f1f3"],"isCanonical": true},":mn:":{"unicode":["1f1f2-1f1f3"],"isCanonical": false},":flag_mm:":{"unicode":["1f1f2-1f1f2"],"isCanonical": true},":mm:":{"unicode":["1f1f2-1f1f2"],"isCanonical": false},":flag_ml:":{"unicode":["1f1f2-1f1f1"],"isCanonical": true},":ml:":{"unicode":["1f1f2-1f1f1"],"isCanonical": false},":flag_mk:":{"unicode":["1f1f2-1f1f0"],"isCanonical": true},":mk:":{"unicode":["1f1f2-1f1f0"],"isCanonical": false},":flag_mh:":{"unicode":["1f1f2-1f1ed"],"isCanonical": true},":mh:":{"unicode":["1f1f2-1f1ed"],"isCanonical": false},":flag_mg:":{"unicode":["1f1f2-1f1ec"],"isCanonical": true},":mg:":{"unicode":["1f1f2-1f1ec"],"isCanonical": false},":flag_mf:":{"unicode":["1f1f2-1f1eb"],"isCanonical": true},":mf:":{"unicode":["1f1f2-1f1eb"],"isCanonical": false},":flag_me:":{"unicode":["1f1f2-1f1ea"],"isCanonical": true},":me:":{"unicode":["1f1f2-1f1ea"],"isCanonical": false},":flag_md:":{"unicode":["1f1f2-1f1e9"],"isCanonical": true},":md:":{"unicode":["1f1f2-1f1e9"],"isCanonical": false},":flag_mc:":{"unicode":["1f1f2-1f1e8"],"isCanonical": true},":mc:":{"unicode":["1f1f2-1f1e8"],"isCanonical": false},":flag_ma:":{"unicode":["1f1f2-1f1e6"],"isCanonical": true},":ma:":{"unicode":["1f1f2-1f1e6"],"isCanonical": false},":flag_ly:":{"unicode":["1f1f1-1f1fe"],"isCanonical": true},":ly:":{"unicode":["1f1f1-1f1fe"],"isCanonical": false},":flag_lv:":{"unicode":["1f1f1-1f1fb"],"isCanonical": true},":lv:":{"unicode":["1f1f1-1f1fb"],"isCanonical": false},":flag_lu:":{"unicode":["1f1f1-1f1fa"],"isCanonical": true},":lu:":{"unicode":["1f1f1-1f1fa"],"isCanonical": false},":flag_lt:":{"unicode":["1f1f1-1f1f9"],"isCanonical": true},":lt:":{"unicode":["1f1f1-1f1f9"],"isCanonical": false},":flag_ls:":{"unicode":["1f1f1-1f1f8"],"isCanonical": true},":ls:":{"unicode":["1f1f1-1f1f8"],"isCanonical": false},":flag_lr:":{"unicode":["1f1f1-1f1f7"],"isCanonical": true},":lr:":{"unicode":["1f1f1-1f1f7"],"isCanonical": false},":flag_lk:":{"unicode":["1f1f1-1f1f0"],"isCanonical": true},":lk:":{"unicode":["1f1f1-1f1f0"],"isCanonical": false},":flag_li:":{"unicode":["1f1f1-1f1ee"],"isCanonical": true},":li:":{"unicode":["1f1f1-1f1ee"],"isCanonical": false},":flag_lc:":{"unicode":["1f1f1-1f1e8"],"isCanonical": true},":lc:":{"unicode":["1f1f1-1f1e8"],"isCanonical": false},":flag_lb:":{"unicode":["1f1f1-1f1e7"],"isCanonical": true},":lb:":{"unicode":["1f1f1-1f1e7"],"isCanonical": false},":flag_la:":{"unicode":["1f1f1-1f1e6"],"isCanonical": true},":la:":{"unicode":["1f1f1-1f1e6"],"isCanonical": false},":flag_kz:":{"unicode":["1f1f0-1f1ff"],"isCanonical": true},":kz:":{"unicode":["1f1f0-1f1ff"],"isCanonical": false},":flag_ky:":{"unicode":["1f1f0-1f1fe"],"isCanonical": true},":ky:":{"unicode":["1f1f0-1f1fe"],"isCanonical": false},":flag_kw:":{"unicode":["1f1f0-1f1fc"],"isCanonical": true},":kw:":{"unicode":["1f1f0-1f1fc"],"isCanonical": false},":flag_kr:":{"unicode":["1f1f0-1f1f7"],"isCanonical": true},":kr:":{"unicode":["1f1f0-1f1f7"],"isCanonical": false},":flag_kp:":{"unicode":["1f1f0-1f1f5"],"isCanonical": true},":kp:":{"unicode":["1f1f0-1f1f5"],"isCanonical": false},":flag_kn:":{"unicode":["1f1f0-1f1f3"],"isCanonical": true},":kn:":{"unicode":["1f1f0-1f1f3"],"isCanonical": false},":flag_km:":{"unicode":["1f1f0-1f1f2"],"isCanonical": true},":km:":{"unicode":["1f1f0-1f1f2"],"isCanonical": false},":flag_ki:":{"unicode":["1f1f0-1f1ee"],"isCanonical": true},":ki:":{"unicode":["1f1f0-1f1ee"],"isCanonical": false},":flag_kh:":{"unicode":["1f1f0-1f1ed"],"isCanonical": true},":kh:":{"unicode":["1f1f0-1f1ed"],"isCanonical": false},":flag_kg:":{"unicode":["1f1f0-1f1ec"],"isCanonical": true},":kg:":{"unicode":["1f1f0-1f1ec"],"isCanonical": false},":flag_ke:":{"unicode":["1f1f0-1f1ea"],"isCanonical": true},":ke:":{"unicode":["1f1f0-1f1ea"],"isCanonical": false},":flag_jp:":{"unicode":["1f1ef-1f1f5"],"isCanonical": true},":jp:":{"unicode":["1f1ef-1f1f5"],"isCanonical": false},":flag_jo:":{"unicode":["1f1ef-1f1f4"],"isCanonical": true},":jo:":{"unicode":["1f1ef-1f1f4"],"isCanonical": false},":flag_jm:":{"unicode":["1f1ef-1f1f2"],"isCanonical": true},":jm:":{"unicode":["1f1ef-1f1f2"],"isCanonical": false},":flag_je:":{"unicode":["1f1ef-1f1ea"],"isCanonical": true},":je:":{"unicode":["1f1ef-1f1ea"],"isCanonical": false},":flag_it:":{"unicode":["1f1ee-1f1f9"],"isCanonical": true},":it:":{"unicode":["1f1ee-1f1f9"],"isCanonical": false},":flag_is:":{"unicode":["1f1ee-1f1f8"],"isCanonical": true},":is:":{"unicode":["1f1ee-1f1f8"],"isCanonical": false},":flag_ir:":{"unicode":["1f1ee-1f1f7"],"isCanonical": true},":ir:":{"unicode":["1f1ee-1f1f7"],"isCanonical": false},":flag_iq:":{"unicode":["1f1ee-1f1f6"],"isCanonical": true},":iq:":{"unicode":["1f1ee-1f1f6"],"isCanonical": false},":flag_io:":{"unicode":["1f1ee-1f1f4"],"isCanonical": true},":io:":{"unicode":["1f1ee-1f1f4"],"isCanonical": false},":flag_in:":{"unicode":["1f1ee-1f1f3"],"isCanonical": true},":in:":{"unicode":["1f1ee-1f1f3"],"isCanonical": false},":flag_im:":{"unicode":["1f1ee-1f1f2"],"isCanonical": true},":im:":{"unicode":["1f1ee-1f1f2"],"isCanonical": false},":flag_il:":{"unicode":["1f1ee-1f1f1"],"isCanonical": true},":il:":{"unicode":["1f1ee-1f1f1"],"isCanonical": false},":flag_ie:":{"unicode":["1f1ee-1f1ea"],"isCanonical": true},":ie:":{"unicode":["1f1ee-1f1ea"],"isCanonical": false},":flag_id:":{"unicode":["1f1ee-1f1e9"],"isCanonical": true},":indonesia:":{"unicode":["1f1ee-1f1e9"],"isCanonical": false},":flag_ic:":{"unicode":["1f1ee-1f1e8"],"isCanonical": true},":ic:":{"unicode":["1f1ee-1f1e8"],"isCanonical": false},":flag_hu:":{"unicode":["1f1ed-1f1fa"],"isCanonical": true},":hu:":{"unicode":["1f1ed-1f1fa"],"isCanonical": false},":flag_ht:":{"unicode":["1f1ed-1f1f9"],"isCanonical": true},":ht:":{"unicode":["1f1ed-1f1f9"],"isCanonical": false},":flag_hr:":{"unicode":["1f1ed-1f1f7"],"isCanonical": true},":hr:":{"unicode":["1f1ed-1f1f7"],"isCanonical": false},":flag_hn:":{"unicode":["1f1ed-1f1f3"],"isCanonical": true},":hn:":{"unicode":["1f1ed-1f1f3"],"isCanonical": false},":flag_hm:":{"unicode":["1f1ed-1f1f2"],"isCanonical": true},":hm:":{"unicode":["1f1ed-1f1f2"],"isCanonical": false},":flag_hk:":{"unicode":["1f1ed-1f1f0"],"isCanonical": true},":hk:":{"unicode":["1f1ed-1f1f0"],"isCanonical": false},":flag_gy:":{"unicode":["1f1ec-1f1fe"],"isCanonical": true},":gy:":{"unicode":["1f1ec-1f1fe"],"isCanonical": false},":flag_gw:":{"unicode":["1f1ec-1f1fc"],"isCanonical": true},":gw:":{"unicode":["1f1ec-1f1fc"],"isCanonical": false},":flag_gu:":{"unicode":["1f1ec-1f1fa"],"isCanonical": true},":gu:":{"unicode":["1f1ec-1f1fa"],"isCanonical": false},":flag_gt:":{"unicode":["1f1ec-1f1f9"],"isCanonical": true},":gt:":{"unicode":["1f1ec-1f1f9"],"isCanonical": false},":flag_gs:":{"unicode":["1f1ec-1f1f8"],"isCanonical": true},":gs:":{"unicode":["1f1ec-1f1f8"],"isCanonical": false},":flag_gr:":{"unicode":["1f1ec-1f1f7"],"isCanonical": true},":gr:":{"unicode":["1f1ec-1f1f7"],"isCanonical": false},":flag_gq:":{"unicode":["1f1ec-1f1f6"],"isCanonical": true},":gq:":{"unicode":["1f1ec-1f1f6"],"isCanonical": false},":flag_gp:":{"unicode":["1f1ec-1f1f5"],"isCanonical": true},":gp:":{"unicode":["1f1ec-1f1f5"],"isCanonical": false},":flag_gn:":{"unicode":["1f1ec-1f1f3"],"isCanonical": true},":gn:":{"unicode":["1f1ec-1f1f3"],"isCanonical": false},":flag_gm:":{"unicode":["1f1ec-1f1f2"],"isCanonical": true},":gm:":{"unicode":["1f1ec-1f1f2"],"isCanonical": false},":flag_gl:":{"unicode":["1f1ec-1f1f1"],"isCanonical": true},":gl:":{"unicode":["1f1ec-1f1f1"],"isCanonical": false},":flag_gi:":{"unicode":["1f1ec-1f1ee"],"isCanonical": true},":gi:":{"unicode":["1f1ec-1f1ee"],"isCanonical": false},":flag_gh:":{"unicode":["1f1ec-1f1ed"],"isCanonical": true},":gh:":{"unicode":["1f1ec-1f1ed"],"isCanonical": false},":flag_gg:":{"unicode":["1f1ec-1f1ec"],"isCanonical": true},":gg:":{"unicode":["1f1ec-1f1ec"],"isCanonical": false},":flag_gf:":{"unicode":["1f1ec-1f1eb"],"isCanonical": true},":gf:":{"unicode":["1f1ec-1f1eb"],"isCanonical": false},":flag_ge:":{"unicode":["1f1ec-1f1ea"],"isCanonical": true},":ge:":{"unicode":["1f1ec-1f1ea"],"isCanonical": false},":flag_gd:":{"unicode":["1f1ec-1f1e9"],"isCanonical": true},":gd:":{"unicode":["1f1ec-1f1e9"],"isCanonical": false},":flag_gb:":{"unicode":["1f1ec-1f1e7"],"isCanonical": true},":gb:":{"unicode":["1f1ec-1f1e7"],"isCanonical": false},":flag_ga:":{"unicode":["1f1ec-1f1e6"],"isCanonical": true},":ga:":{"unicode":["1f1ec-1f1e6"],"isCanonical": false},":flag_fr:":{"unicode":["1f1eb-1f1f7"],"isCanonical": true},":fr:":{"unicode":["1f1eb-1f1f7"],"isCanonical": false},":flag_fo:":{"unicode":["1f1eb-1f1f4"],"isCanonical": true},":fo:":{"unicode":["1f1eb-1f1f4"],"isCanonical": false},":flag_fm:":{"unicode":["1f1eb-1f1f2"],"isCanonical": true},":fm:":{"unicode":["1f1eb-1f1f2"],"isCanonical": false},":flag_fk:":{"unicode":["1f1eb-1f1f0"],"isCanonical": true},":fk:":{"unicode":["1f1eb-1f1f0"],"isCanonical": false},":flag_fj:":{"unicode":["1f1eb-1f1ef"],"isCanonical": true},":fj:":{"unicode":["1f1eb-1f1ef"],"isCanonical": false},":flag_fi:":{"unicode":["1f1eb-1f1ee"],"isCanonical": true},":fi:":{"unicode":["1f1eb-1f1ee"],"isCanonical": false},":flag_eu:":{"unicode":["1f1ea-1f1fa"],"isCanonical": true},":eu:":{"unicode":["1f1ea-1f1fa"],"isCanonical": false},":flag_et:":{"unicode":["1f1ea-1f1f9"],"isCanonical": true},":et:":{"unicode":["1f1ea-1f1f9"],"isCanonical": false},":flag_es:":{"unicode":["1f1ea-1f1f8"],"isCanonical": true},":es:":{"unicode":["1f1ea-1f1f8"],"isCanonical": false},":flag_er:":{"unicode":["1f1ea-1f1f7"],"isCanonical": true},":er:":{"unicode":["1f1ea-1f1f7"],"isCanonical": false},":flag_eh:":{"unicode":["1f1ea-1f1ed"],"isCanonical": true},":eh:":{"unicode":["1f1ea-1f1ed"],"isCanonical": false},":flag_eg:":{"unicode":["1f1ea-1f1ec"],"isCanonical": true},":eg:":{"unicode":["1f1ea-1f1ec"],"isCanonical": false},":flag_ee:":{"unicode":["1f1ea-1f1ea"],"isCanonical": true},":ee:":{"unicode":["1f1ea-1f1ea"],"isCanonical": false},":flag_ec:":{"unicode":["1f1ea-1f1e8"],"isCanonical": true},":ec:":{"unicode":["1f1ea-1f1e8"],"isCanonical": false},":flag_ea:":{"unicode":["1f1ea-1f1e6"],"isCanonical": true},":ea:":{"unicode":["1f1ea-1f1e6"],"isCanonical": false},":flag_dz:":{"unicode":["1f1e9-1f1ff"],"isCanonical": true},":dz:":{"unicode":["1f1e9-1f1ff"],"isCanonical": false},":flag_do:":{"unicode":["1f1e9-1f1f4"],"isCanonical": true},":do:":{"unicode":["1f1e9-1f1f4"],"isCanonical": false},":flag_dm:":{"unicode":["1f1e9-1f1f2"],"isCanonical": true},":dm:":{"unicode":["1f1e9-1f1f2"],"isCanonical": false},":flag_dk:":{"unicode":["1f1e9-1f1f0"],"isCanonical": true},":dk:":{"unicode":["1f1e9-1f1f0"],"isCanonical": false},":flag_dj:":{"unicode":["1f1e9-1f1ef"],"isCanonical": true},":dj:":{"unicode":["1f1e9-1f1ef"],"isCanonical": false},":flag_dg:":{"unicode":["1f1e9-1f1ec"],"isCanonical": true},":dg:":{"unicode":["1f1e9-1f1ec"],"isCanonical": false},":flag_de:":{"unicode":["1f1e9-1f1ea"],"isCanonical": true},":de:":{"unicode":["1f1e9-1f1ea"],"isCanonical": false},":flag_cz:":{"unicode":["1f1e8-1f1ff"],"isCanonical": true},":cz:":{"unicode":["1f1e8-1f1ff"],"isCanonical": false},":flag_cy:":{"unicode":["1f1e8-1f1fe"],"isCanonical": true},":cy:":{"unicode":["1f1e8-1f1fe"],"isCanonical": false},":flag_cx:":{"unicode":["1f1e8-1f1fd"],"isCanonical": true},":cx:":{"unicode":["1f1e8-1f1fd"],"isCanonical": false},":flag_cw:":{"unicode":["1f1e8-1f1fc"],"isCanonical": true},":cw:":{"unicode":["1f1e8-1f1fc"],"isCanonical": false},":flag_cv:":{"unicode":["1f1e8-1f1fb"],"isCanonical": true},":cv:":{"unicode":["1f1e8-1f1fb"],"isCanonical": false},":flag_cu:":{"unicode":["1f1e8-1f1fa"],"isCanonical": true},":cu:":{"unicode":["1f1e8-1f1fa"],"isCanonical": false},":flag_cr:":{"unicode":["1f1e8-1f1f7"],"isCanonical": true},":cr:":{"unicode":["1f1e8-1f1f7"],"isCanonical": false},":flag_cp:":{"unicode":["1f1e8-1f1f5"],"isCanonical": true},":cp:":{"unicode":["1f1e8-1f1f5"],"isCanonical": false},":flag_co:":{"unicode":["1f1e8-1f1f4"],"isCanonical": true},":co:":{"unicode":["1f1e8-1f1f4"],"isCanonical": false},":flag_cn:":{"unicode":["1f1e8-1f1f3"],"isCanonical": true},":cn:":{"unicode":["1f1e8-1f1f3"],"isCanonical": false},":flag_cm:":{"unicode":["1f1e8-1f1f2"],"isCanonical": true},":cm:":{"unicode":["1f1e8-1f1f2"],"isCanonical": false},":flag_cl:":{"unicode":["1f1e8-1f1f1"],"isCanonical": true},":chile:":{"unicode":["1f1e8-1f1f1"],"isCanonical": false},":flag_ck:":{"unicode":["1f1e8-1f1f0"],"isCanonical": true},":ck:":{"unicode":["1f1e8-1f1f0"],"isCanonical": false},":flag_ci:":{"unicode":["1f1e8-1f1ee"],"isCanonical": true},":ci:":{"unicode":["1f1e8-1f1ee"],"isCanonical": false},":flag_ch:":{"unicode":["1f1e8-1f1ed"],"isCanonical": true},":ch:":{"unicode":["1f1e8-1f1ed"],"isCanonical": false},":flag_cg:":{"unicode":["1f1e8-1f1ec"],"isCanonical": true},":cg:":{"unicode":["1f1e8-1f1ec"],"isCanonical": false},":flag_cf:":{"unicode":["1f1e8-1f1eb"],"isCanonical": true},":cf:":{"unicode":["1f1e8-1f1eb"],"isCanonical": false},":flag_cd:":{"unicode":["1f1e8-1f1e9"],"isCanonical": true},":congo:":{"unicode":["1f1e8-1f1e9"],"isCanonical": false},":flag_cc:":{"unicode":["1f1e8-1f1e8"],"isCanonical": true},":cc:":{"unicode":["1f1e8-1f1e8"],"isCanonical": false},":flag_ca:":{"unicode":["1f1e8-1f1e6"],"isCanonical": true},":ca:":{"unicode":["1f1e8-1f1e6"],"isCanonical": false},":flag_bz:":{"unicode":["1f1e7-1f1ff"],"isCanonical": true},":bz:":{"unicode":["1f1e7-1f1ff"],"isCanonical": false},":flag_by:":{"unicode":["1f1e7-1f1fe"],"isCanonical": true},":by:":{"unicode":["1f1e7-1f1fe"],"isCanonical": false},":flag_bw:":{"unicode":["1f1e7-1f1fc"],"isCanonical": true},":bw:":{"unicode":["1f1e7-1f1fc"],"isCanonical": false},":flag_bv:":{"unicode":["1f1e7-1f1fb"],"isCanonical": true},":bv:":{"unicode":["1f1e7-1f1fb"],"isCanonical": false},":flag_bt:":{"unicode":["1f1e7-1f1f9"],"isCanonical": true},":bt:":{"unicode":["1f1e7-1f1f9"],"isCanonical": false},":flag_bs:":{"unicode":["1f1e7-1f1f8"],"isCanonical": true},":bs:":{"unicode":["1f1e7-1f1f8"],"isCanonical": false},":flag_br:":{"unicode":["1f1e7-1f1f7"],"isCanonical": true},":br:":{"unicode":["1f1e7-1f1f7"],"isCanonical": false},":flag_bq:":{"unicode":["1f1e7-1f1f6"],"isCanonical": true},":bq:":{"unicode":["1f1e7-1f1f6"],"isCanonical": false},":flag_bo:":{"unicode":["1f1e7-1f1f4"],"isCanonical": true},":bo:":{"unicode":["1f1e7-1f1f4"],"isCanonical": false},":flag_bn:":{"unicode":["1f1e7-1f1f3"],"isCanonical": true},":bn:":{"unicode":["1f1e7-1f1f3"],"isCanonical": false},":flag_bm:":{"unicode":["1f1e7-1f1f2"],"isCanonical": true},":bm:":{"unicode":["1f1e7-1f1f2"],"isCanonical": false},":flag_bl:":{"unicode":["1f1e7-1f1f1"],"isCanonical": true},":bl:":{"unicode":["1f1e7-1f1f1"],"isCanonical": false},":flag_bj:":{"unicode":["1f1e7-1f1ef"],"isCanonical": true},":bj:":{"unicode":["1f1e7-1f1ef"],"isCanonical": false},":flag_bi:":{"unicode":["1f1e7-1f1ee"],"isCanonical": true},":bi:":{"unicode":["1f1e7-1f1ee"],"isCanonical": false},":flag_bh:":{"unicode":["1f1e7-1f1ed"],"isCanonical": true},":bh:":{"unicode":["1f1e7-1f1ed"],"isCanonical": false},":flag_bg:":{"unicode":["1f1e7-1f1ec"],"isCanonical": true},":bg:":{"unicode":["1f1e7-1f1ec"],"isCanonical": false},":flag_bf:":{"unicode":["1f1e7-1f1eb"],"isCanonical": true},":bf:":{"unicode":["1f1e7-1f1eb"],"isCanonical": false},":flag_be:":{"unicode":["1f1e7-1f1ea"],"isCanonical": true},":be:":{"unicode":["1f1e7-1f1ea"],"isCanonical": false},":flag_bd:":{"unicode":["1f1e7-1f1e9"],"isCanonical": true},":bd:":{"unicode":["1f1e7-1f1e9"],"isCanonical": false},":flag_bb:":{"unicode":["1f1e7-1f1e7"],"isCanonical": true},":bb:":{"unicode":["1f1e7-1f1e7"],"isCanonical": false},":flag_ba:":{"unicode":["1f1e7-1f1e6"],"isCanonical": true},":ba:":{"unicode":["1f1e7-1f1e6"],"isCanonical": false},":flag_az:":{"unicode":["1f1e6-1f1ff"],"isCanonical": true},":az:":{"unicode":["1f1e6-1f1ff"],"isCanonical": false},":flag_ax:":{"unicode":["1f1e6-1f1fd"],"isCanonical": true},":ax:":{"unicode":["1f1e6-1f1fd"],"isCanonical": false},":flag_aw:":{"unicode":["1f1e6-1f1fc"],"isCanonical": true},":aw:":{"unicode":["1f1e6-1f1fc"],"isCanonical": false},":flag_au:":{"unicode":["1f1e6-1f1fa"],"isCanonical": true},":au:":{"unicode":["1f1e6-1f1fa"],"isCanonical": false},":flag_at:":{"unicode":["1f1e6-1f1f9"],"isCanonical": true},":at:":{"unicode":["1f1e6-1f1f9"],"isCanonical": false},":flag_as:":{"unicode":["1f1e6-1f1f8"],"isCanonical": true},":as:":{"unicode":["1f1e6-1f1f8"],"isCanonical": false},":flag_ar:":{"unicode":["1f1e6-1f1f7"],"isCanonical": true},":ar:":{"unicode":["1f1e6-1f1f7"],"isCanonical": false},":flag_aq:":{"unicode":["1f1e6-1f1f6"],"isCanonical": true},":aq:":{"unicode":["1f1e6-1f1f6"],"isCanonical": false},":flag_ao:":{"unicode":["1f1e6-1f1f4"],"isCanonical": true},":ao:":{"unicode":["1f1e6-1f1f4"],"isCanonical": false},":flag_am:":{"unicode":["1f1e6-1f1f2"],"isCanonical": true},":am:":{"unicode":["1f1e6-1f1f2"],"isCanonical": false},":flag_al:":{"unicode":["1f1e6-1f1f1"],"isCanonical": true},":al:":{"unicode":["1f1e6-1f1f1"],"isCanonical": false},":flag_ai:":{"unicode":["1f1e6-1f1ee"],"isCanonical": true},":ai:":{"unicode":["1f1e6-1f1ee"],"isCanonical": false},":flag_ag:":{"unicode":["1f1e6-1f1ec"],"isCanonical": true},":ag:":{"unicode":["1f1e6-1f1ec"],"isCanonical": false},":flag_af:":{"unicode":["1f1e6-1f1eb"],"isCanonical": true},":af:":{"unicode":["1f1e6-1f1eb"],"isCanonical": false},":flag_ae:":{"unicode":["1f1e6-1f1ea"],"isCanonical": true},":ae:":{"unicode":["1f1e6-1f1ea"],"isCanonical": false},":flag_ad:":{"unicode":["1f1e6-1f1e9"],"isCanonical": true},":ad:":{"unicode":["1f1e6-1f1e9"],"isCanonical": false},":flag_ac:":{"unicode":["1f1e6-1f1e8"],"isCanonical": true},":ac:":{"unicode":["1f1e6-1f1e8"],"isCanonical": false},":mahjong:":{"unicode":["1f004-fe0f","1f004"],"isCanonical": true},":parking:":{"unicode":["1f17f-fe0f","1f17f"],"isCanonical": true},":sa:":{"unicode":["1f202-fe0f","1f202"],"isCanonical": true},":u7121:":{"unicode":["1f21a-fe0f","1f21a"],"isCanonical": true},":u6307:":{"unicode":["1f22f-fe0f","1f22f"],"isCanonical": true},":u6708:":{"unicode":["1f237-fe0f","1f237"],"isCanonical": true},":film_frames:":{"unicode":["1f39e-fe0f","1f39e"],"isCanonical": true},":tickets:":{"unicode":["1f39f-fe0f","1f39f"],"isCanonical": true},":admission_tickets:":{"unicode":["1f39f-fe0f","1f39f"],"isCanonical": false},":lifter:":{"unicode":["1f3cb-fe0f","1f3cb"],"isCanonical": true},":weight_lifter:":{"unicode":["1f3cb-fe0f","1f3cb"],"isCanonical": false},":golfer:":{"unicode":["1f3cc-fe0f","1f3cc"],"isCanonical": true},":motorcycle:":{"unicode":["1f3cd-fe0f","1f3cd"],"isCanonical": true},":racing_motorcycle:":{"unicode":["1f3cd-fe0f","1f3cd"],"isCanonical": false},":race_car:":{"unicode":["1f3ce-fe0f","1f3ce"],"isCanonical": true},":racing_car:":{"unicode":["1f3ce-fe0f","1f3ce"],"isCanonical": false},":military_medal:":{"unicode":["1f396-fe0f","1f396"],"isCanonical": true},":reminder_ribbon:":{"unicode":["1f397-fe0f","1f397"],"isCanonical": true},":hot_pepper:":{"unicode":["1f336-fe0f","1f336"],"isCanonical": true},":cloud_rain:":{"unicode":["1f327-fe0f","1f327"],"isCanonical": true},":cloud_with_rain:":{"unicode":["1f327-fe0f","1f327"],"isCanonical": false},":cloud_snow:":{"unicode":["1f328-fe0f","1f328"],"isCanonical": true},":cloud_with_snow:":{"unicode":["1f328-fe0f","1f328"],"isCanonical": false},":cloud_lightning:":{"unicode":["1f329-fe0f","1f329"],"isCanonical": true},":cloud_with_lightning:":{"unicode":["1f329-fe0f","1f329"],"isCanonical": false},":cloud_tornado:":{"unicode":["1f32a-fe0f","1f32a"],"isCanonical": true},":cloud_with_tornado:":{"unicode":["1f32a-fe0f","1f32a"],"isCanonical": false},":fog:":{"unicode":["1f32b-fe0f","1f32b"],"isCanonical": true},":wind_blowing_face:":{"unicode":["1f32c-fe0f","1f32c"],"isCanonical": true},":chipmunk:":{"unicode":["1f43f-fe0f","1f43f"],"isCanonical": true},":spider:":{"unicode":["1f577-fe0f","1f577"],"isCanonical": true},":spider_web:":{"unicode":["1f578-fe0f","1f578"],"isCanonical": true},":thermometer:":{"unicode":["1f321-fe0f","1f321"],"isCanonical": true},":microphone2:":{"unicode":["1f399-fe0f","1f399"],"isCanonical": true},":studio_microphone:":{"unicode":["1f399-fe0f","1f399"],"isCanonical": false},":level_slider:":{"unicode":["1f39a-fe0f","1f39a"],"isCanonical": true},":control_knobs:":{"unicode":["1f39b-fe0f","1f39b"],"isCanonical": true},":flag_white:":{"unicode":["1f3f3-fe0f","1f3f3"],"isCanonical": true},":waving_white_flag:":{"unicode":["1f3f3-fe0f","1f3f3"],"isCanonical": false},":rosette:":{"unicode":["1f3f5-fe0f","1f3f5"],"isCanonical": true},":label:":{"unicode":["1f3f7-fe0f","1f3f7"],"isCanonical": true},":projector:":{"unicode":["1f4fd-fe0f","1f4fd"],"isCanonical": true},":film_projector:":{"unicode":["1f4fd-fe0f","1f4fd"],"isCanonical": false},":om_symbol:":{"unicode":["1f549-fe0f","1f549"],"isCanonical": true},":dove:":{"unicode":["1f54a-fe0f","1f54a"],"isCanonical": true},":dove_of_peace:":{"unicode":["1f54a-fe0f","1f54a"],"isCanonical": false},":candle:":{"unicode":["1f56f-fe0f","1f56f"],"isCanonical": true},":clock:":{"unicode":["1f570-fe0f","1f570"],"isCanonical": true},":mantlepiece_clock:":{"unicode":["1f570-fe0f","1f570"],"isCanonical": false},":hole:":{"unicode":["1f573-fe0f","1f573"],"isCanonical": true},":dark_sunglasses:":{"unicode":["1f576-fe0f","1f576"],"isCanonical": true},":joystick:":{"unicode":["1f579-fe0f","1f579"],"isCanonical": true},":paperclips:":{"unicode":["1f587-fe0f","1f587"],"isCanonical": true},":linked_paperclips:":{"unicode":["1f587-fe0f","1f587"],"isCanonical": false},":pen_ballpoint:":{"unicode":["1f58a-fe0f","1f58a"],"isCanonical": true},":lower_left_ballpoint_pen:":{"unicode":["1f58a-fe0f","1f58a"],"isCanonical": false},":pen_fountain:":{"unicode":["1f58b-fe0f","1f58b"],"isCanonical": true},":lower_left_fountain_pen:":{"unicode":["1f58b-fe0f","1f58b"],"isCanonical": false},":paintbrush:":{"unicode":["1f58c-fe0f","1f58c"],"isCanonical": true},":lower_left_paintbrush:":{"unicode":["1f58c-fe0f","1f58c"],"isCanonical": false},":crayon:":{"unicode":["1f58d-fe0f","1f58d"],"isCanonical": true},":lower_left_crayon:":{"unicode":["1f58d-fe0f","1f58d"],"isCanonical": false},":desktop:":{"unicode":["1f5a5-fe0f","1f5a5"],"isCanonical": true},":desktop_computer:":{"unicode":["1f5a5-fe0f","1f5a5"],"isCanonical": false},":printer:":{"unicode":["1f5a8-fe0f","1f5a8"],"isCanonical": true},":trackball:":{"unicode":["1f5b2-fe0f","1f5b2"],"isCanonical": true},":frame_photo:":{"unicode":["1f5bc-fe0f","1f5bc"],"isCanonical": true},":frame_with_picture:":{"unicode":["1f5bc-fe0f","1f5bc"],"isCanonical": false},":dividers:":{"unicode":["1f5c2-fe0f","1f5c2"],"isCanonical": true},":card_index_dividers:":{"unicode":["1f5c2-fe0f","1f5c2"],"isCanonical": false},":card_box:":{"unicode":["1f5c3-fe0f","1f5c3"],"isCanonical": true},":card_file_box:":{"unicode":["1f5c3-fe0f","1f5c3"],"isCanonical": false},":file_cabinet:":{"unicode":["1f5c4-fe0f","1f5c4"],"isCanonical": true},":wastebasket:":{"unicode":["1f5d1-fe0f","1f5d1"],"isCanonical": true},":notepad_spiral:":{"unicode":["1f5d2-fe0f","1f5d2"],"isCanonical": true},":spiral_note_pad:":{"unicode":["1f5d2-fe0f","1f5d2"],"isCanonical": false},":calendar_spiral:":{"unicode":["1f5d3-fe0f","1f5d3"],"isCanonical": true},":spiral_calendar_pad:":{"unicode":["1f5d3-fe0f","1f5d3"],"isCanonical": false},":compression:":{"unicode":["1f5dc-fe0f","1f5dc"],"isCanonical": true},":key2:":{"unicode":["1f5dd-fe0f","1f5dd"],"isCanonical": true},":old_key:":{"unicode":["1f5dd-fe0f","1f5dd"],"isCanonical": false},":newspaper2:":{"unicode":["1f5de-fe0f","1f5de"],"isCanonical": true},":rolled_up_newspaper:":{"unicode":["1f5de-fe0f","1f5de"],"isCanonical": false},":dagger:":{"unicode":["1f5e1-fe0f","1f5e1"],"isCanonical": true},":dagger_knife:":{"unicode":["1f5e1-fe0f","1f5e1"],"isCanonical": false},":speaking_head:":{"unicode":["1f5e3-fe0f","1f5e3"],"isCanonical": true},":speaking_head_in_silhouette:":{"unicode":["1f5e3-fe0f","1f5e3"],"isCanonical": false},":speech_left:":{"unicode":["1f5e8-fe0f","1f5e8"],"isCanonical": true},":left_speech_bubble:":{"unicode":["1f5e8-fe0f","1f5e8"],"isCanonical": false},":anger_right:":{"unicode":["1f5ef-fe0f","1f5ef"],"isCanonical": true},":right_anger_bubble:":{"unicode":["1f5ef-fe0f","1f5ef"],"isCanonical": false},":ballot_box:":{"unicode":["1f5f3-fe0f","1f5f3"],"isCanonical": true},":ballot_box_with_ballot:":{"unicode":["1f5f3-fe0f","1f5f3"],"isCanonical": false},":map:":{"unicode":["1f5fa-fe0f","1f5fa"],"isCanonical": true},":world_map:":{"unicode":["1f5fa-fe0f","1f5fa"],"isCanonical": false},":tools:":{"unicode":["1f6e0-fe0f","1f6e0"],"isCanonical": true},":hammer_and_wrench:":{"unicode":["1f6e0-fe0f","1f6e0"],"isCanonical": false},":shield:":{"unicode":["1f6e1-fe0f","1f6e1"],"isCanonical": true},":oil:":{"unicode":["1f6e2-fe0f","1f6e2"],"isCanonical": true},":oil_drum:":{"unicode":["1f6e2-fe0f","1f6e2"],"isCanonical": false},":satellite_orbital:":{"unicode":["1f6f0-fe0f","1f6f0"],"isCanonical": true},":fork_knife_plate:":{"unicode":["1f37d-fe0f","1f37d"],"isCanonical": true},":fork_and_knife_with_plate:":{"unicode":["1f37d-fe0f","1f37d"],"isCanonical": false},":eye:":{"unicode":["1f441-fe0f","1f441"],"isCanonical": true},":levitate:":{"unicode":["1f574-fe0f","1f574"],"isCanonical": true},":man_in_business_suit_levitating:":{"unicode":["1f574-fe0f","1f574"],"isCanonical": false},":spy:":{"unicode":["1f575-fe0f","1f575"],"isCanonical": true},":sleuth_or_spy:":{"unicode":["1f575-fe0f","1f575"],"isCanonical": false},":hand_splayed:":{"unicode":["1f590-fe0f","1f590"],"isCanonical": true},":raised_hand_with_fingers_splayed:":{"unicode":["1f590-fe0f","1f590"],"isCanonical": false},":mountain_snow:":{"unicode":["1f3d4-fe0f","1f3d4"],"isCanonical": true},":snow_capped_mountain:":{"unicode":["1f3d4-fe0f","1f3d4"],"isCanonical": false},":camping:":{"unicode":["1f3d5-fe0f","1f3d5"],"isCanonical": true},":beach:":{"unicode":["1f3d6-fe0f","1f3d6"],"isCanonical": true},":beach_with_umbrella:":{"unicode":["1f3d6-fe0f","1f3d6"],"isCanonical": false},":construction_site:":{"unicode":["1f3d7-fe0f","1f3d7"],"isCanonical": true},":building_construction:":{"unicode":["1f3d7-fe0f","1f3d7"],"isCanonical": false},":homes:":{"unicode":["1f3d8-fe0f","1f3d8"],"isCanonical": true},":house_buildings:":{"unicode":["1f3d8-fe0f","1f3d8"],"isCanonical": false},":cityscape:":{"unicode":["1f3d9-fe0f","1f3d9"],"isCanonical": true},":house_abandoned:":{"unicode":["1f3da-fe0f","1f3da"],"isCanonical": true},":derelict_house_building:":{"unicode":["1f3da-fe0f","1f3da"],"isCanonical": false},":classical_building:":{"unicode":["1f3db-fe0f","1f3db"],"isCanonical": true},":desert:":{"unicode":["1f3dc-fe0f","1f3dc"],"isCanonical": true},":island:":{"unicode":["1f3dd-fe0f","1f3dd"],"isCanonical": true},":desert_island:":{"unicode":["1f3dd-fe0f","1f3dd"],"isCanonical": false},":park:":{"unicode":["1f3de-fe0f","1f3de"],"isCanonical": true},":national_park:":{"unicode":["1f3de-fe0f","1f3de"],"isCanonical": false},":stadium:":{"unicode":["1f3df-fe0f","1f3df"],"isCanonical": true},":couch:":{"unicode":["1f6cb-fe0f","1f6cb"],"isCanonical": true},":couch_and_lamp:":{"unicode":["1f6cb-fe0f","1f6cb"],"isCanonical": false},":shopping_bags:":{"unicode":["1f6cd-fe0f","1f6cd"],"isCanonical": true},":bellhop:":{"unicode":["1f6ce-fe0f","1f6ce"],"isCanonical": true},":bellhop_bell:":{"unicode":["1f6ce-fe0f","1f6ce"],"isCanonical": false},":bed:":{"unicode":["1f6cf-fe0f","1f6cf"],"isCanonical": true},":motorway:":{"unicode":["1f6e3-fe0f","1f6e3"],"isCanonical": true},":railway_track:":{"unicode":["1f6e4-fe0f","1f6e4"],"isCanonical": true},":railroad_track:":{"unicode":["1f6e4-fe0f","1f6e4"],"isCanonical": false},":motorboat:":{"unicode":["1f6e5-fe0f","1f6e5"],"isCanonical": true},":airplane_small:":{"unicode":["1f6e9-fe0f","1f6e9"],"isCanonical": true},":small_airplane:":{"unicode":["1f6e9-fe0f","1f6e9"],"isCanonical": false},":cruise_ship:":{"unicode":["1f6f3-fe0f","1f6f3"],"isCanonical": true},":passenger_ship:":{"unicode":["1f6f3-fe0f","1f6f3"],"isCanonical": false},":white_sun_small_cloud:":{"unicode":["1f324-fe0f","1f324"],"isCanonical": true},":white_sun_with_small_cloud:":{"unicode":["1f324-fe0f","1f324"],"isCanonical": false},":white_sun_cloud:":{"unicode":["1f325-fe0f","1f325"],"isCanonical": true},":white_sun_behind_cloud:":{"unicode":["1f325-fe0f","1f325"],"isCanonical": false},":white_sun_rain_cloud:":{"unicode":["1f326-fe0f","1f326"],"isCanonical": true},":white_sun_behind_cloud_with_rain:":{"unicode":["1f326-fe0f","1f326"],"isCanonical": false},":mouse_three_button:":{"unicode":["1f5b1-fe0f","1f5b1"],"isCanonical": true},":three_button_mouse:":{"unicode":["1f5b1-fe0f","1f5b1"],"isCanonical": false},":point_up_tone1:":{"unicode":["261d-1f3fb"],"isCanonical": true},":point_up_tone2:":{"unicode":["261d-1f3fc"],"isCanonical": true},":point_up_tone3:":{"unicode":["261d-1f3fd"],"isCanonical": true},":point_up_tone4:":{"unicode":["261d-1f3fe"],"isCanonical": true},":point_up_tone5:":{"unicode":["261d-1f3ff"],"isCanonical": true},":v_tone1:":{"unicode":["270c-1f3fb"],"isCanonical": true},":v_tone2:":{"unicode":["270c-1f3fc"],"isCanonical": true},":v_tone3:":{"unicode":["270c-1f3fd"],"isCanonical": true},":v_tone4:":{"unicode":["270c-1f3fe"],"isCanonical": true},":v_tone5:":{"unicode":["270c-1f3ff"],"isCanonical": true},":fist_tone1:":{"unicode":["270a-1f3fb"],"isCanonical": true},":fist_tone2:":{"unicode":["270a-1f3fc"],"isCanonical": true},":fist_tone3:":{"unicode":["270a-1f3fd"],"isCanonical": true},":fist_tone4:":{"unicode":["270a-1f3fe"],"isCanonical": true},":fist_tone5:":{"unicode":["270a-1f3ff"],"isCanonical": true},":raised_hand_tone1:":{"unicode":["270b-1f3fb"],"isCanonical": true},":raised_hand_tone2:":{"unicode":["270b-1f3fc"],"isCanonical": true},":raised_hand_tone3:":{"unicode":["270b-1f3fd"],"isCanonical": true},":raised_hand_tone4:":{"unicode":["270b-1f3fe"],"isCanonical": true},":raised_hand_tone5:":{"unicode":["270b-1f3ff"],"isCanonical": true},":writing_hand_tone1:":{"unicode":["270d-1f3fb"],"isCanonical": true},":writing_hand_tone2:":{"unicode":["270d-1f3fc"],"isCanonical": true},":writing_hand_tone3:":{"unicode":["270d-1f3fd"],"isCanonical": true},":writing_hand_tone4:":{"unicode":["270d-1f3fe"],"isCanonical": true},":writing_hand_tone5:":{"unicode":["270d-1f3ff"],"isCanonical": true},":basketball_player_tone1:":{"unicode":["26f9-1f3fb"],"isCanonical": true},":person_with_ball_tone1:":{"unicode":["26f9-1f3fb"],"isCanonical": false},":basketball_player_tone2:":{"unicode":["26f9-1f3fc"],"isCanonical": true},":person_with_ball_tone2:":{"unicode":["26f9-1f3fc"],"isCanonical": false},":basketball_player_tone3:":{"unicode":["26f9-1f3fd"],"isCanonical": true},":person_with_ball_tone3:":{"unicode":["26f9-1f3fd"],"isCanonical": false},":basketball_player_tone4:":{"unicode":["26f9-1f3fe"],"isCanonical": true},":person_with_ball_tone4:":{"unicode":["26f9-1f3fe"],"isCanonical": false},":basketball_player_tone5:":{"unicode":["26f9-1f3ff"],"isCanonical": true},":person_with_ball_tone5:":{"unicode":["26f9-1f3ff"],"isCanonical": false},":copyright:":{"unicode":["00a9-fe0f","00a9"],"isCanonical": true},":registered:":{"unicode":["00ae-fe0f","00ae"],"isCanonical": true},":bangbang:":{"unicode":["203c-fe0f","203c"],"isCanonical": true},":interrobang:":{"unicode":["2049-fe0f","2049"],"isCanonical": true},":tm:":{"unicode":["2122-fe0f","2122"],"isCanonical": true},":information_source:":{"unicode":["2139-fe0f","2139"],"isCanonical": true},":left_right_arrow:":{"unicode":["2194-fe0f","2194"],"isCanonical": true},":arrow_up_down:":{"unicode":["2195-fe0f","2195"],"isCanonical": true},":arrow_upper_left:":{"unicode":["2196-fe0f","2196"],"isCanonical": true},":arrow_upper_right:":{"unicode":["2197-fe0f","2197"],"isCanonical": true},":arrow_lower_right:":{"unicode":["2198-fe0f","2198"],"isCanonical": true},":arrow_lower_left:":{"unicode":["2199-fe0f","2199"],"isCanonical": true},":leftwards_arrow_with_hook:":{"unicode":["21a9-fe0f","21a9"],"isCanonical": true},":arrow_right_hook:":{"unicode":["21aa-fe0f","21aa"],"isCanonical": true},":watch:":{"unicode":["231a-fe0f","231a"],"isCanonical": true},":hourglass:":{"unicode":["231b-fe0f","231b"],"isCanonical": true},":m:":{"unicode":["24c2-fe0f","24c2"],"isCanonical": true},":black_small_square:":{"unicode":["25aa-fe0f","25aa"],"isCanonical": true},":white_small_square:":{"unicode":["25ab-fe0f","25ab"],"isCanonical": true},":arrow_forward:":{"unicode":["25b6-fe0f","25b6"],"isCanonical": true},":arrow_backward:":{"unicode":["25c0-fe0f","25c0"],"isCanonical": true},":white_medium_square:":{"unicode":["25fb-fe0f","25fb"],"isCanonical": true},":black_medium_square:":{"unicode":["25fc-fe0f","25fc"],"isCanonical": true},":white_medium_small_square:":{"unicode":["25fd-fe0f","25fd"],"isCanonical": true},":black_medium_small_square:":{"unicode":["25fe-fe0f","25fe"],"isCanonical": true},":sunny:":{"unicode":["2600-fe0f","2600"],"isCanonical": true},":cloud:":{"unicode":["2601-fe0f","2601"],"isCanonical": true},":telephone:":{"unicode":["260e-fe0f","260e"],"isCanonical": true},":ballot_box_with_check:":{"unicode":["2611-fe0f","2611"],"isCanonical": true},":umbrella:":{"unicode":["2614-fe0f","2614"],"isCanonical": true},":coffee:":{"unicode":["2615-fe0f","2615"],"isCanonical": true},":point_up:":{"unicode":["261d-fe0f","261d"],"isCanonical": true},":relaxed:":{"unicode":["263a-fe0f","263a"],"isCanonical": true},":aries:":{"unicode":["2648-fe0f","2648"],"isCanonical": true},":taurus:":{"unicode":["2649-fe0f","2649"],"isCanonical": true},":gemini:":{"unicode":["264a-fe0f","264a"],"isCanonical": true},":cancer:":{"unicode":["264b-fe0f","264b"],"isCanonical": true},":leo:":{"unicode":["264c-fe0f","264c"],"isCanonical": true},":virgo:":{"unicode":["264d-fe0f","264d"],"isCanonical": true},":libra:":{"unicode":["264e-fe0f","264e"],"isCanonical": true},":scorpius:":{"unicode":["264f-fe0f","264f"],"isCanonical": true},":sagittarius:":{"unicode":["2650-fe0f","2650"],"isCanonical": true},":capricorn:":{"unicode":["2651-fe0f","2651"],"isCanonical": true},":aquarius:":{"unicode":["2652-fe0f","2652"],"isCanonical": true},":pisces:":{"unicode":["2653-fe0f","2653"],"isCanonical": true},":spades:":{"unicode":["2660-fe0f","2660"],"isCanonical": true},":clubs:":{"unicode":["2663-fe0f","2663"],"isCanonical": true},":hearts:":{"unicode":["2665-fe0f","2665"],"isCanonical": true},":diamonds:":{"unicode":["2666-fe0f","2666"],"isCanonical": true},":hotsprings:":{"unicode":["2668-fe0f","2668"],"isCanonical": true},":recycle:":{"unicode":["267b-fe0f","267b"],"isCanonical": true},":wheelchair:":{"unicode":["267f-fe0f","267f"],"isCanonical": true},":anchor:":{"unicode":["2693-fe0f","2693"],"isCanonical": true},":warning:":{"unicode":["26a0-fe0f","26a0"],"isCanonical": true},":zap:":{"unicode":["26a1-fe0f","26a1"],"isCanonical": true},":white_circle:":{"unicode":["26aa-fe0f","26aa"],"isCanonical": true},":black_circle:":{"unicode":["26ab-fe0f","26ab"],"isCanonical": true},":soccer:":{"unicode":["26bd-fe0f","26bd"],"isCanonical": true},":baseball:":{"unicode":["26be-fe0f","26be"],"isCanonical": true},":snowman:":{"unicode":["26c4-fe0f","26c4"],"isCanonical": true},":partly_sunny:":{"unicode":["26c5-fe0f","26c5"],"isCanonical": true},":no_entry:":{"unicode":["26d4-fe0f","26d4"],"isCanonical": true},":church:":{"unicode":["26ea-fe0f","26ea"],"isCanonical": true},":fountain:":{"unicode":["26f2-fe0f","26f2"],"isCanonical": true},":golf:":{"unicode":["26f3-fe0f","26f3"],"isCanonical": true},":sailboat:":{"unicode":["26f5-fe0f","26f5"],"isCanonical": true},":tent:":{"unicode":["26fa-fe0f","26fa"],"isCanonical": true},":fuelpump:":{"unicode":["26fd-fe0f","26fd"],"isCanonical": true},":scissors:":{"unicode":["2702-fe0f","2702"],"isCanonical": true},":airplane:":{"unicode":["2708-fe0f","2708"],"isCanonical": true},":envelope:":{"unicode":["2709-fe0f","2709"],"isCanonical": true},":v:":{"unicode":["270c-fe0f","270c"],"isCanonical": true},":pencil2:":{"unicode":["270f-fe0f","270f"],"isCanonical": true},":black_nib:":{"unicode":["2712-fe0f","2712"],"isCanonical": true},":heavy_check_mark:":{"unicode":["2714-fe0f","2714"],"isCanonical": true},":heavy_multiplication_x:":{"unicode":["2716-fe0f","2716"],"isCanonical": true},":eight_spoked_asterisk:":{"unicode":["2733-fe0f","2733"],"isCanonical": true},":eight_pointed_black_star:":{"unicode":["2734-fe0f","2734"],"isCanonical": true},":snowflake:":{"unicode":["2744-fe0f","2744"],"isCanonical": true},":sparkle:":{"unicode":["2747-fe0f","2747"],"isCanonical": true},":exclamation:":{"unicode":["2757-fe0f","2757"],"isCanonical": true},":heart:":{"unicode":["2764-fe0f","2764"],"isCanonical": true},":arrow_right:":{"unicode":["27a1-fe0f","27a1"],"isCanonical": true},":arrow_heading_up:":{"unicode":["2934-fe0f","2934"],"isCanonical": true},":arrow_heading_down:":{"unicode":["2935-fe0f","2935"],"isCanonical": true},":arrow_left:":{"unicode":["2b05-fe0f","2b05"],"isCanonical": true},":arrow_up:":{"unicode":["2b06-fe0f","2b06"],"isCanonical": true},":arrow_down:":{"unicode":["2b07-fe0f","2b07"],"isCanonical": true},":black_large_square:":{"unicode":["2b1b-fe0f","2b1b"],"isCanonical": true},":white_large_square:":{"unicode":["2b1c-fe0f","2b1c"],"isCanonical": true},":star:":{"unicode":["2b50-fe0f","2b50"],"isCanonical": true},":o:":{"unicode":["2b55-fe0f","2b55"],"isCanonical": true},":wavy_dash:":{"unicode":["3030-fe0f","3030"],"isCanonical": true},":part_alternation_mark:":{"unicode":["303d-fe0f","303d"],"isCanonical": true},":congratulations:":{"unicode":["3297-fe0f","3297"],"isCanonical": true},":secret:":{"unicode":["3299-fe0f","3299"],"isCanonical": true},":cross:":{"unicode":["271d-fe0f","271d"],"isCanonical": true},":latin_cross:":{"unicode":["271d-fe0f","271d"],"isCanonical": false},":keyboard:":{"unicode":["2328-fe0f","2328"],"isCanonical": true},":writing_hand:":{"unicode":["270d-fe0f","270d"],"isCanonical": true},":eject:":{"unicode":["23cf-fe0f","23cf"],"isCanonical": true},":eject_symbol:":{"unicode":["23cf-fe0f","23cf"],"isCanonical": false},":track_next:":{"unicode":["23ed-fe0f","23ed"],"isCanonical": true},":next_track:":{"unicode":["23ed-fe0f","23ed"],"isCanonical": false},":track_previous:":{"unicode":["23ee-fe0f","23ee"],"isCanonical": true},":previous_track:":{"unicode":["23ee-fe0f","23ee"],"isCanonical": false},":play_pause:":{"unicode":["23ef-fe0f","23ef"],"isCanonical": true},":stopwatch:":{"unicode":["23f1-fe0f","23f1"],"isCanonical": true},":timer:":{"unicode":["23f2-fe0f","23f2"],"isCanonical": true},":timer_clock:":{"unicode":["23f2-fe0f","23f2"],"isCanonical": false},":pause_button:":{"unicode":["23f8-fe0f","23f8"],"isCanonical": true},":double_vertical_bar:":{"unicode":["23f8-fe0f","23f8"],"isCanonical": false},":stop_button:":{"unicode":["23f9-fe0f","23f9"],"isCanonical": true},":record_button:":{"unicode":["23fa-fe0f","23fa"],"isCanonical": true},":umbrella2:":{"unicode":["2602-fe0f","2602"],"isCanonical": true},":snowman2:":{"unicode":["2603-fe0f","2603"],"isCanonical": true},":comet:":{"unicode":["2604-fe0f","2604"],"isCanonical": true},":shamrock:":{"unicode":["2618-fe0f","2618"],"isCanonical": true},":skull_crossbones:":{"unicode":["2620-fe0f","2620"],"isCanonical": true},":skull_and_crossbones:":{"unicode":["2620-fe0f","2620"],"isCanonical": false},":radioactive:":{"unicode":["2622-fe0f","2622"],"isCanonical": true},":radioactive_sign:":{"unicode":["2622-fe0f","2622"],"isCanonical": false},":biohazard:":{"unicode":["2623-fe0f","2623"],"isCanonical": true},":biohazard_sign:":{"unicode":["2623-fe0f","2623"],"isCanonical": false},":orthodox_cross:":{"unicode":["2626-fe0f","2626"],"isCanonical": true},":star_and_crescent:":{"unicode":["262a-fe0f","262a"],"isCanonical": true},":peace:":{"unicode":["262e-fe0f","262e"],"isCanonical": true},":peace_symbol:":{"unicode":["262e-fe0f","262e"],"isCanonical": false},":yin_yang:":{"unicode":["262f-fe0f","262f"],"isCanonical": true},":wheel_of_dharma:":{"unicode":["2638-fe0f","2638"],"isCanonical": true},":frowning2:":{"unicode":["2639-fe0f","2639"],"isCanonical": true},":white_frowning_face:":{"unicode":["2639-fe0f","2639"],"isCanonical": false},":hammer_pick:":{"unicode":["2692-fe0f","2692"],"isCanonical": true},":hammer_and_pick:":{"unicode":["2692-fe0f","2692"],"isCanonical": false},":crossed_swords:":{"unicode":["2694-fe0f","2694"],"isCanonical": true},":scales:":{"unicode":["2696-fe0f","2696"],"isCanonical": true},":alembic:":{"unicode":["2697-fe0f","2697"],"isCanonical": true},":gear:":{"unicode":["2699-fe0f","2699"],"isCanonical": true},":atom:":{"unicode":["269b-fe0f","269b"],"isCanonical": true},":atom_symbol:":{"unicode":["269b-fe0f","269b"],"isCanonical": false},":fleur-de-lis:":{"unicode":["269c-fe0f","269c"],"isCanonical": true},":coffin:":{"unicode":["26b0-fe0f","26b0"],"isCanonical": true},":urn:":{"unicode":["26b1-fe0f","26b1"],"isCanonical": true},":funeral_urn:":{"unicode":["26b1-fe0f","26b1"],"isCanonical": false},":thunder_cloud_rain:":{"unicode":["26c8-fe0f","26c8"],"isCanonical": true},":thunder_cloud_and_rain:":{"unicode":["26c8-fe0f","26c8"],"isCanonical": false},":pick:":{"unicode":["26cf-fe0f","26cf"],"isCanonical": true},":helmet_with_cross:":{"unicode":["26d1-fe0f","26d1"],"isCanonical": true},":helmet_with_white_cross:":{"unicode":["26d1-fe0f","26d1"],"isCanonical": false},":chains:":{"unicode":["26d3-fe0f","26d3"],"isCanonical": true},":shinto_shrine:":{"unicode":["26e9-fe0f","26e9"],"isCanonical": true},":mountain:":{"unicode":["26f0-fe0f","26f0"],"isCanonical": true},":beach_umbrella:":{"unicode":["26f1-fe0f","26f1"],"isCanonical": true},":umbrella_on_ground:":{"unicode":["26f1-fe0f","26f1"],"isCanonical": false},":ferry:":{"unicode":["26f4-fe0f","26f4"],"isCanonical": true},":skier:":{"unicode":["26f7-fe0f","26f7"],"isCanonical": true},":ice_skate:":{"unicode":["26f8-fe0f","26f8"],"isCanonical": true},":basketball_player:":{"unicode":["26f9-fe0f","26f9"],"isCanonical": true},":person_with_ball:":{"unicode":["26f9-fe0f","26f9"],"isCanonical": false},":star_of_david:":{"unicode":["2721-fe0f","2721"],"isCanonical": true},":heart_exclamation:":{"unicode":["2763-fe0f","2763"],"isCanonical": true},":heavy_heart_exclamation_mark_ornament:":{"unicode":["2763-fe0f","2763"],"isCanonical": false},":third_place:":{"unicode":["1f949"],"isCanonical": true},":third_place_medal:":{"unicode":["1f949"],"isCanonical": false},":second_place:":{"unicode":["1f948"],"isCanonical": true},":second_place_medal:":{"unicode":["1f948"],"isCanonical": false},":first_place:":{"unicode":["1f947"],"isCanonical": true},":first_place_medal:":{"unicode":["1f947"],"isCanonical": false},":fencer:":{"unicode":["1f93a"],"isCanonical": true},":fencing:":{"unicode":["1f93a"],"isCanonical": false},":goal:":{"unicode":["1f945"],"isCanonical": true},":goal_net:":{"unicode":["1f945"],"isCanonical": false},":handball:":{"unicode":["1f93e"],"isCanonical": true},":regional_indicator_z:":{"unicode":["1f1ff"],"isCanonical": true},":water_polo:":{"unicode":["1f93d"],"isCanonical": true},":martial_arts_uniform:":{"unicode":["1f94b"],"isCanonical": true},":karate_uniform:":{"unicode":["1f94b"],"isCanonical": false},":boxing_glove:":{"unicode":["1f94a"],"isCanonical": true},":boxing_gloves:":{"unicode":["1f94a"],"isCanonical": false},":wrestlers:":{"unicode":["1f93c"],"isCanonical": true},":wrestling:":{"unicode":["1f93c"],"isCanonical": false},":juggling:":{"unicode":["1f939"],"isCanonical": true},":juggler:":{"unicode":["1f939"],"isCanonical": false},":cartwheel:":{"unicode":["1f938"],"isCanonical": true},":person_doing_cartwheel:":{"unicode":["1f938"],"isCanonical": false},":canoe:":{"unicode":["1f6f6"],"isCanonical": true},":kayak:":{"unicode":["1f6f6"],"isCanonical": false},":motor_scooter:":{"unicode":["1f6f5"],"isCanonical": true},":motorbike:":{"unicode":["1f6f5"],"isCanonical": false},":scooter:":{"unicode":["1f6f4"],"isCanonical": true},":shopping_cart:":{"unicode":["1f6d2"],"isCanonical": true},":shopping_trolley:":{"unicode":["1f6d2"],"isCanonical": false},":black_joker:":{"unicode":["1f0cf"],"isCanonical": true},":a:":{"unicode":["1f170"],"isCanonical": true},":b:":{"unicode":["1f171"],"isCanonical": true},":o2:":{"unicode":["1f17e"],"isCanonical": true},":octagonal_sign:":{"unicode":["1f6d1"],"isCanonical": true},":stop_sign:":{"unicode":["1f6d1"],"isCanonical": false},":ab:":{"unicode":["1f18e"],"isCanonical": true},":cl:":{"unicode":["1f191"],"isCanonical": true},":regional_indicator_y:":{"unicode":["1f1fe"],"isCanonical": true},":cool:":{"unicode":["1f192"],"isCanonical": true},":free:":{"unicode":["1f193"],"isCanonical": true},":id:":{"unicode":["1f194"],"isCanonical": true},":new:":{"unicode":["1f195"],"isCanonical": true},":ng:":{"unicode":["1f196"],"isCanonical": true},":ok:":{"unicode":["1f197"],"isCanonical": true},":sos:":{"unicode":["1f198"],"isCanonical": true},":spoon:":{"unicode":["1f944"],"isCanonical": true},":up:":{"unicode":["1f199"],"isCanonical": true},":vs:":{"unicode":["1f19a"],"isCanonical": true},":champagne_glass:":{"unicode":["1f942"],"isCanonical": true},":clinking_glass:":{"unicode":["1f942"],"isCanonical": false},":tumbler_glass:":{"unicode":["1f943"],"isCanonical": true},":whisky:":{"unicode":["1f943"],"isCanonical": false},":koko:":{"unicode":["1f201"],"isCanonical": true},":stuffed_flatbread:":{"unicode":["1f959"],"isCanonical": true},":stuffed_pita:":{"unicode":["1f959"],"isCanonical": false},":u7981:":{"unicode":["1f232"],"isCanonical": true},":u7a7a:":{"unicode":["1f233"],"isCanonical": true},":u5408:":{"unicode":["1f234"],"isCanonical": true},":u6e80:":{"unicode":["1f235"],"isCanonical": true},":u6709:":{"unicode":["1f236"],"isCanonical": true},":shallow_pan_of_food:":{"unicode":["1f958"],"isCanonical": true},":paella:":{"unicode":["1f958"],"isCanonical": false},":u7533:":{"unicode":["1f238"],"isCanonical": true},":u5272:":{"unicode":["1f239"],"isCanonical": true},":salad:":{"unicode":["1f957"],"isCanonical": true},":green_salad:":{"unicode":["1f957"],"isCanonical": false},":u55b6:":{"unicode":["1f23a"],"isCanonical": true},":ideograph_advantage:":{"unicode":["1f250"],"isCanonical": true},":accept:":{"unicode":["1f251"],"isCanonical": true},":cyclone:":{"unicode":["1f300"],"isCanonical": true},":french_bread:":{"unicode":["1f956"],"isCanonical": true},":baguette_bread:":{"unicode":["1f956"],"isCanonical": false},":foggy:":{"unicode":["1f301"],"isCanonical": true},":closed_umbrella:":{"unicode":["1f302"],"isCanonical": true},":night_with_stars:":{"unicode":["1f303"],"isCanonical": true},":sunrise_over_mountains:":{"unicode":["1f304"],"isCanonical": true},":sunrise:":{"unicode":["1f305"],"isCanonical": true},":city_dusk:":{"unicode":["1f306"],"isCanonical": true},":carrot:":{"unicode":["1f955"],"isCanonical": true},":city_sunset:":{"unicode":["1f307"],"isCanonical": true},":city_sunrise:":{"unicode":["1f307"],"isCanonical": false},":rainbow:":{"unicode":["1f308"],"isCanonical": true},":potato:":{"unicode":["1f954"],"isCanonical": true},":bridge_at_night:":{"unicode":["1f309"],"isCanonical": true},":ocean:":{"unicode":["1f30a"],"isCanonical": true},":volcano:":{"unicode":["1f30b"],"isCanonical": true},":milky_way:":{"unicode":["1f30c"],"isCanonical": true},":earth_asia:":{"unicode":["1f30f"],"isCanonical": true},":new_moon:":{"unicode":["1f311"],"isCanonical": true},":bacon:":{"unicode":["1f953"],"isCanonical": true},":first_quarter_moon:":{"unicode":["1f313"],"isCanonical": true},":waxing_gibbous_moon:":{"unicode":["1f314"],"isCanonical": true},":full_moon:":{"unicode":["1f315"],"isCanonical": true},":crescent_moon:":{"unicode":["1f319"],"isCanonical": true},":first_quarter_moon_with_face:":{"unicode":["1f31b"],"isCanonical": true},":star2:":{"unicode":["1f31f"],"isCanonical": true},":cucumber:":{"unicode":["1f952"],"isCanonical": true},":stars:":{"unicode":["1f320"],"isCanonical": true},":chestnut:":{"unicode":["1f330"],"isCanonical": true},":avocado:":{"unicode":["1f951"],"isCanonical": true},":seedling:":{"unicode":["1f331"],"isCanonical": true},":palm_tree:":{"unicode":["1f334"],"isCanonical": true},":cactus:":{"unicode":["1f335"],"isCanonical": true},":tulip:":{"unicode":["1f337"],"isCanonical": true},":cherry_blossom:":{"unicode":["1f338"],"isCanonical": true},":rose:":{"unicode":["1f339"],"isCanonical": true},":hibiscus:":{"unicode":["1f33a"],"isCanonical": true},":sunflower:":{"unicode":["1f33b"],"isCanonical": true},":blossom:":{"unicode":["1f33c"],"isCanonical": true},":corn:":{"unicode":["1f33d"],"isCanonical": true},":croissant:":{"unicode":["1f950"],"isCanonical": true},":ear_of_rice:":{"unicode":["1f33e"],"isCanonical": true},":herb:":{"unicode":["1f33f"],"isCanonical": true},":four_leaf_clover:":{"unicode":["1f340"],"isCanonical": true},":maple_leaf:":{"unicode":["1f341"],"isCanonical": true},":fallen_leaf:":{"unicode":["1f342"],"isCanonical": true},":leaves:":{"unicode":["1f343"],"isCanonical": true},":mushroom:":{"unicode":["1f344"],"isCanonical": true},":tomato:":{"unicode":["1f345"],"isCanonical": true},":eggplant:":{"unicode":["1f346"],"isCanonical": true},":grapes:":{"unicode":["1f347"],"isCanonical": true},":melon:":{"unicode":["1f348"],"isCanonical": true},":watermelon:":{"unicode":["1f349"],"isCanonical": true},":tangerine:":{"unicode":["1f34a"],"isCanonical": true},":wilted_rose:":{"unicode":["1f940"],"isCanonical": true},":wilted_flower:":{"unicode":["1f940"],"isCanonical": false},":banana:":{"unicode":["1f34c"],"isCanonical": true},":pineapple:":{"unicode":["1f34d"],"isCanonical": true},":apple:":{"unicode":["1f34e"],"isCanonical": true},":green_apple:":{"unicode":["1f34f"],"isCanonical": true},":peach:":{"unicode":["1f351"],"isCanonical": true},":cherries:":{"unicode":["1f352"],"isCanonical": true},":strawberry:":{"unicode":["1f353"],"isCanonical": true},":rhino:":{"unicode":["1f98f"],"isCanonical": true},":rhinoceros:":{"unicode":["1f98f"],"isCanonical": false},":hamburger:":{"unicode":["1f354"],"isCanonical": true},":pizza:":{"unicode":["1f355"],"isCanonical": true},":meat_on_bone:":{"unicode":["1f356"],"isCanonical": true},":lizard:":{"unicode":["1f98e"],"isCanonical": true},":poultry_leg:":{"unicode":["1f357"],"isCanonical": true},":rice_cracker:":{"unicode":["1f358"],"isCanonical": true},":rice_ball:":{"unicode":["1f359"],"isCanonical": true},":gorilla:":{"unicode":["1f98d"],"isCanonical": true},":rice:":{"unicode":["1f35a"],"isCanonical": true},":curry:":{"unicode":["1f35b"],"isCanonical": true},":deer:":{"unicode":["1f98c"],"isCanonical": true},":ramen:":{"unicode":["1f35c"],"isCanonical": true},":spaghetti:":{"unicode":["1f35d"],"isCanonical": true},":bread:":{"unicode":["1f35e"],"isCanonical": true},":fries:":{"unicode":["1f35f"],"isCanonical": true},":butterfly:":{"unicode":["1f98b"],"isCanonical": true},":sweet_potato:":{"unicode":["1f360"],"isCanonical": true},":dango:":{"unicode":["1f361"],"isCanonical": true},":fox:":{"unicode":["1f98a"],"isCanonical": true},":fox_face:":{"unicode":["1f98a"],"isCanonical": false},":oden:":{"unicode":["1f362"],"isCanonical": true},":sushi:":{"unicode":["1f363"],"isCanonical": true},":owl:":{"unicode":["1f989"],"isCanonical": true},":fried_shrimp:":{"unicode":["1f364"],"isCanonical": true},":fish_cake:":{"unicode":["1f365"],"isCanonical": true},":shark:":{"unicode":["1f988"],"isCanonical": true},":icecream:":{"unicode":["1f366"],"isCanonical": true},":bat:":{"unicode":["1f987"],"isCanonical": true},":shaved_ice:":{"unicode":["1f367"],"isCanonical": true},":regional_indicator_x:":{"unicode":["1f1fd"],"isCanonical": true},":ice_cream:":{"unicode":["1f368"],"isCanonical": true},":duck:":{"unicode":["1f986"],"isCanonical": true},":doughnut:":{"unicode":["1f369"],"isCanonical": true},":eagle:":{"unicode":["1f985"],"isCanonical": true},":cookie:":{"unicode":["1f36a"],"isCanonical": true},":black_heart:":{"unicode":["1f5a4"],"isCanonical": true},":chocolate_bar:":{"unicode":["1f36b"],"isCanonical": true},":candy:":{"unicode":["1f36c"],"isCanonical": true},":lollipop:":{"unicode":["1f36d"],"isCanonical": true},":custard:":{"unicode":["1f36e"],"isCanonical": true},":pudding:":{"unicode":["1f36e"],"isCanonical": false},":flan:":{"unicode":["1f36e"],"isCanonical": false},":honey_pot:":{"unicode":["1f36f"],"isCanonical": true},":fingers_crossed:":{"unicode":["1f91e"],"isCanonical": true},":hand_with_index_and_middle_finger_crossed:":{"unicode":["1f91e"],"isCanonical": false},":cake:":{"unicode":["1f370"],"isCanonical": true},":bento:":{"unicode":["1f371"],"isCanonical": true},":stew:":{"unicode":["1f372"],"isCanonical": true},":handshake:":{"unicode":["1f91d"],"isCanonical": true},":shaking_hands:":{"unicode":["1f91d"],"isCanonical": false},":cooking:":{"unicode":["1f373"],"isCanonical": true},":fork_and_knife:":{"unicode":["1f374"],"isCanonical": true},":tea:":{"unicode":["1f375"],"isCanonical": true},":sake:":{"unicode":["1f376"],"isCanonical": true},":wine_glass:":{"unicode":["1f377"],"isCanonical": true},":cocktail:":{"unicode":["1f378"],"isCanonical": true},":tropical_drink:":{"unicode":["1f379"],"isCanonical": true},":beer:":{"unicode":["1f37a"],"isCanonical": true},":beers:":{"unicode":["1f37b"],"isCanonical": true},":ribbon:":{"unicode":["1f380"],"isCanonical": true},":gift:":{"unicode":["1f381"],"isCanonical": true},":birthday:":{"unicode":["1f382"],"isCanonical": true},":jack_o_lantern:":{"unicode":["1f383"],"isCanonical": true},":left_facing_fist:":{"unicode":["1f91b"],"isCanonical": true},":left_fist:":{"unicode":["1f91b"],"isCanonical": false},":right_facing_fist:":{"unicode":["1f91c"],"isCanonical": true},":right_fist:":{"unicode":["1f91c"],"isCanonical": false},":christmas_tree:":{"unicode":["1f384"],"isCanonical": true},":santa:":{"unicode":["1f385"],"isCanonical": true},":fireworks:":{"unicode":["1f386"],"isCanonical": true},":raised_back_of_hand:":{"unicode":["1f91a"],"isCanonical": true},":back_of_hand:":{"unicode":["1f91a"],"isCanonical": false},":sparkler:":{"unicode":["1f387"],"isCanonical": true},":balloon:":{"unicode":["1f388"],"isCanonical": true},":tada:":{"unicode":["1f389"],"isCanonical": true},":confetti_ball:":{"unicode":["1f38a"],"isCanonical": true},":tanabata_tree:":{"unicode":["1f38b"],"isCanonical": true},":crossed_flags:":{"unicode":["1f38c"],"isCanonical": true},":call_me:":{"unicode":["1f919"],"isCanonical": true},":call_me_hand:":{"unicode":["1f919"],"isCanonical": false},":bamboo:":{"unicode":["1f38d"],"isCanonical": true},":man_dancing:":{"unicode":["1f57a"],"isCanonical": true},":male_dancer:":{"unicode":["1f57a"],"isCanonical": false},":dolls:":{"unicode":["1f38e"],"isCanonical": true},":selfie:":{"unicode":["1f933"],"isCanonical": true},":flags:":{"unicode":["1f38f"],"isCanonical": true},":pregnant_woman:":{"unicode":["1f930"],"isCanonical": true},":expecting_woman:":{"unicode":["1f930"],"isCanonical": false},":wind_chime:":{"unicode":["1f390"],"isCanonical": true},":face_palm:":{"unicode":["1f926"],"isCanonical": true},":facepalm:":{"unicode":["1f926"],"isCanonical": false},":shrug:":{"unicode":["1f937"],"isCanonical": true},":rice_scene:":{"unicode":["1f391"],"isCanonical": true},":school_satchel:":{"unicode":["1f392"],"isCanonical": true},":mortar_board:":{"unicode":["1f393"],"isCanonical": true},":carousel_horse:":{"unicode":["1f3a0"],"isCanonical": true},":ferris_wheel:":{"unicode":["1f3a1"],"isCanonical": true},":roller_coaster:":{"unicode":["1f3a2"],"isCanonical": true},":fishing_pole_and_fish:":{"unicode":["1f3a3"],"isCanonical": true},":microphone:":{"unicode":["1f3a4"],"isCanonical": true},":movie_camera:":{"unicode":["1f3a5"],"isCanonical": true},":cinema:":{"unicode":["1f3a6"],"isCanonical": true},":headphones:":{"unicode":["1f3a7"],"isCanonical": true},":mrs_claus:":{"unicode":["1f936"],"isCanonical": true},":mother_christmas:":{"unicode":["1f936"],"isCanonical": false},":art:":{"unicode":["1f3a8"],"isCanonical": true},":man_in_tuxedo:":{"unicode":["1f935"],"isCanonical": true},":tophat:":{"unicode":["1f3a9"],"isCanonical": true},":circus_tent:":{"unicode":["1f3aa"],"isCanonical": true},":prince:":{"unicode":["1f934"],"isCanonical": true},":ticket:":{"unicode":["1f3ab"],"isCanonical": true},":clapper:":{"unicode":["1f3ac"],"isCanonical": true},":performing_arts:":{"unicode":["1f3ad"],"isCanonical": true},":sneezing_face:":{"unicode":["1f927"],"isCanonical": true},":sneeze:":{"unicode":["1f927"],"isCanonical": false},":video_game:":{"unicode":["1f3ae"],"isCanonical": true},":dart:":{"unicode":["1f3af"],"isCanonical": true},":slot_machine:":{"unicode":["1f3b0"],"isCanonical": true},":8ball:":{"unicode":["1f3b1"],"isCanonical": true},":game_die:":{"unicode":["1f3b2"],"isCanonical": true},":bowling:":{"unicode":["1f3b3"],"isCanonical": true},":flower_playing_cards:":{"unicode":["1f3b4"],"isCanonical": true},":lying_face:":{"unicode":["1f925"],"isCanonical": true},":liar:":{"unicode":["1f925"],"isCanonical": false},":musical_note:":{"unicode":["1f3b5"],"isCanonical": true},":notes:":{"unicode":["1f3b6"],"isCanonical": true},":saxophone:":{"unicode":["1f3b7"],"isCanonical": true},":drooling_face:":{"unicode":["1f924"],"isCanonical": true},":drool:":{"unicode":["1f924"],"isCanonical": false},":guitar:":{"unicode":["1f3b8"],"isCanonical": true},":musical_keyboard:":{"unicode":["1f3b9"],"isCanonical": true},":trumpet:":{"unicode":["1f3ba"],"isCanonical": true},":rofl:":{"unicode":["1f923"],"isCanonical": true},":rolling_on_the_floor_laughing:":{"unicode":["1f923"],"isCanonical": false},":violin:":{"unicode":["1f3bb"],"isCanonical": true},":musical_score:":{"unicode":["1f3bc"],"isCanonical": true},":running_shirt_with_sash:":{"unicode":["1f3bd"],"isCanonical": true},":nauseated_face:":{"unicode":["1f922"],"isCanonical": true},":sick:":{"unicode":["1f922"],"isCanonical": false},":tennis:":{"unicode":["1f3be"],"isCanonical": true},":ski:":{"unicode":["1f3bf"],"isCanonical": true},":basketball:":{"unicode":["1f3c0"],"isCanonical": true},":checkered_flag:":{"unicode":["1f3c1"],"isCanonical": true},":clown:":{"unicode":["1f921"],"isCanonical": true},":clown_face:":{"unicode":["1f921"],"isCanonical": false},":snowboarder:":{"unicode":["1f3c2"],"isCanonical": true},":runner:":{"unicode":["1f3c3"],"isCanonical": true},":surfer:":{"unicode":["1f3c4"],"isCanonical": true},":trophy:":{"unicode":["1f3c6"],"isCanonical": true},":football:":{"unicode":["1f3c8"],"isCanonical": true},":swimmer:":{"unicode":["1f3ca"],"isCanonical": true},":house:":{"unicode":["1f3e0"],"isCanonical": true},":house_with_garden:":{"unicode":["1f3e1"],"isCanonical": true},":office:":{"unicode":["1f3e2"],"isCanonical": true},":post_office:":{"unicode":["1f3e3"],"isCanonical": true},":hospital:":{"unicode":["1f3e5"],"isCanonical": true},":bank:":{"unicode":["1f3e6"],"isCanonical": true},":atm:":{"unicode":["1f3e7"],"isCanonical": true},":hotel:":{"unicode":["1f3e8"],"isCanonical": true},":love_hotel:":{"unicode":["1f3e9"],"isCanonical": true},":convenience_store:":{"unicode":["1f3ea"],"isCanonical": true},":school:":{"unicode":["1f3eb"],"isCanonical": true},":department_store:":{"unicode":["1f3ec"],"isCanonical": true},":cowboy:":{"unicode":["1f920"],"isCanonical": true},":face_with_cowboy_hat:":{"unicode":["1f920"],"isCanonical": false},":factory:":{"unicode":["1f3ed"],"isCanonical": true},":izakaya_lantern:":{"unicode":["1f3ee"],"isCanonical": true},":japanese_castle:":{"unicode":["1f3ef"],"isCanonical": true},":european_castle:":{"unicode":["1f3f0"],"isCanonical": true},":snail:":{"unicode":["1f40c"],"isCanonical": true},":snake:":{"unicode":["1f40d"],"isCanonical": true},":racehorse:":{"unicode":["1f40e"],"isCanonical": true},":sheep:":{"unicode":["1f411"],"isCanonical": true},":monkey:":{"unicode":["1f412"],"isCanonical": true},":chicken:":{"unicode":["1f414"],"isCanonical": true},":boar:":{"unicode":["1f417"],"isCanonical": true},":elephant:":{"unicode":["1f418"],"isCanonical": true},":octopus:":{"unicode":["1f419"],"isCanonical": true},":shell:":{"unicode":["1f41a"],"isCanonical": true},":bug:":{"unicode":["1f41b"],"isCanonical": true},":ant:":{"unicode":["1f41c"],"isCanonical": true},":bee:":{"unicode":["1f41d"],"isCanonical": true},":beetle:":{"unicode":["1f41e"],"isCanonical": true},":fish:":{"unicode":["1f41f"],"isCanonical": true},":tropical_fish:":{"unicode":["1f420"],"isCanonical": true},":blowfish:":{"unicode":["1f421"],"isCanonical": true},":turtle:":{"unicode":["1f422"],"isCanonical": true},":hatching_chick:":{"unicode":["1f423"],"isCanonical": true},":baby_chick:":{"unicode":["1f424"],"isCanonical": true},":hatched_chick:":{"unicode":["1f425"],"isCanonical": true},":bird:":{"unicode":["1f426"],"isCanonical": true},":penguin:":{"unicode":["1f427"],"isCanonical": true},":koala:":{"unicode":["1f428"],"isCanonical": true},":poodle:":{"unicode":["1f429"],"isCanonical": true},":camel:":{"unicode":["1f42b"],"isCanonical": true},":dolphin:":{"unicode":["1f42c"],"isCanonical": true},":mouse:":{"unicode":["1f42d"],"isCanonical": true},":cow:":{"unicode":["1f42e"],"isCanonical": true},":tiger:":{"unicode":["1f42f"],"isCanonical": true},":rabbit:":{"unicode":["1f430"],"isCanonical": true},":cat:":{"unicode":["1f431"],"isCanonical": true},":dragon_face:":{"unicode":["1f432"],"isCanonical": true},":whale:":{"unicode":["1f433"],"isCanonical": true},":horse:":{"unicode":["1f434"],"isCanonical": true},":monkey_face:":{"unicode":["1f435"],"isCanonical": true},":dog:":{"unicode":["1f436"],"isCanonical": true},":pig:":{"unicode":["1f437"],"isCanonical": true},":frog:":{"unicode":["1f438"],"isCanonical": true},":hamster:":{"unicode":["1f439"],"isCanonical": true},":wolf:":{"unicode":["1f43a"],"isCanonical": true},":bear:":{"unicode":["1f43b"],"isCanonical": true},":panda_face:":{"unicode":["1f43c"],"isCanonical": true},":pig_nose:":{"unicode":["1f43d"],"isCanonical": true},":feet:":{"unicode":["1f43e"],"isCanonical": true},":paw_prints:":{"unicode":["1f43e"],"isCanonical": false},":eyes:":{"unicode":["1f440"],"isCanonical": true},":ear:":{"unicode":["1f442"],"isCanonical": true},":nose:":{"unicode":["1f443"],"isCanonical": true},":lips:":{"unicode":["1f444"],"isCanonical": true},":tongue:":{"unicode":["1f445"],"isCanonical": true},":point_up_2:":{"unicode":["1f446"],"isCanonical": true},":point_down:":{"unicode":["1f447"],"isCanonical": true},":point_left:":{"unicode":["1f448"],"isCanonical": true},":point_right:":{"unicode":["1f449"],"isCanonical": true},":punch:":{"unicode":["1f44a"],"isCanonical": true},":wave:":{"unicode":["1f44b"],"isCanonical": true},":ok_hand:":{"unicode":["1f44c"],"isCanonical": true},":thumbsup:":{"unicode":["1f44d"],"isCanonical": true},":+1:":{"unicode":["1f44d"],"isCanonical": false},":thumbup:":{"unicode":["1f44d"],"isCanonical": false},":thumbsdown:":{"unicode":["1f44e"],"isCanonical": true},":-1:":{"unicode":["1f44e"],"isCanonical": false},":thumbdown:":{"unicode":["1f44e"],"isCanonical": false},":clap:":{"unicode":["1f44f"],"isCanonical": true},":open_hands:":{"unicode":["1f450"],"isCanonical": true},":crown:":{"unicode":["1f451"],"isCanonical": true},":womans_hat:":{"unicode":["1f452"],"isCanonical": true},":eyeglasses:":{"unicode":["1f453"],"isCanonical": true},":necktie:":{"unicode":["1f454"],"isCanonical": true},":shirt:":{"unicode":["1f455"],"isCanonical": true},":jeans:":{"unicode":["1f456"],"isCanonical": true},":dress:":{"unicode":["1f457"],"isCanonical": true},":kimono:":{"unicode":["1f458"],"isCanonical": true},":bikini:":{"unicode":["1f459"],"isCanonical": true},":womans_clothes:":{"unicode":["1f45a"],"isCanonical": true},":purse:":{"unicode":["1f45b"],"isCanonical": true},":handbag:":{"unicode":["1f45c"],"isCanonical": true},":pouch:":{"unicode":["1f45d"],"isCanonical": true},":mans_shoe:":{"unicode":["1f45e"],"isCanonical": true},":athletic_shoe:":{"unicode":["1f45f"],"isCanonical": true},":high_heel:":{"unicode":["1f460"],"isCanonical": true},":sandal:":{"unicode":["1f461"],"isCanonical": true},":boot:":{"unicode":["1f462"],"isCanonical": true},":footprints:":{"unicode":["1f463"],"isCanonical": true},":bust_in_silhouette:":{"unicode":["1f464"],"isCanonical": true},":boy:":{"unicode":["1f466"],"isCanonical": true},":girl:":{"unicode":["1f467"],"isCanonical": true},":man:":{"unicode":["1f468"],"isCanonical": true},":woman:":{"unicode":["1f469"],"isCanonical": true},":family:":{"unicode":["1f46a"],"isCanonical": true},":couple:":{"unicode":["1f46b"],"isCanonical": true},":cop:":{"unicode":["1f46e"],"isCanonical": true},":dancers:":{"unicode":["1f46f"],"isCanonical": true},":bride_with_veil:":{"unicode":["1f470"],"isCanonical": true},":person_with_blond_hair:":{"unicode":["1f471"],"isCanonical": true},":man_with_gua_pi_mao:":{"unicode":["1f472"],"isCanonical": true},":man_with_turban:":{"unicode":["1f473"],"isCanonical": true},":older_man:":{"unicode":["1f474"],"isCanonical": true},":older_woman:":{"unicode":["1f475"],"isCanonical": true},":grandma:":{"unicode":["1f475"],"isCanonical": false},":baby:":{"unicode":["1f476"],"isCanonical": true},":construction_worker:":{"unicode":["1f477"],"isCanonical": true},":princess:":{"unicode":["1f478"],"isCanonical": true},":japanese_ogre:":{"unicode":["1f479"],"isCanonical": true},":japanese_goblin:":{"unicode":["1f47a"],"isCanonical": true},":ghost:":{"unicode":["1f47b"],"isCanonical": true},":angel:":{"unicode":["1f47c"],"isCanonical": true},":alien:":{"unicode":["1f47d"],"isCanonical": true},":space_invader:":{"unicode":["1f47e"],"isCanonical": true},":imp:":{"unicode":["1f47f"],"isCanonical": true},":skull:":{"unicode":["1f480"],"isCanonical": true},":skeleton:":{"unicode":["1f480"],"isCanonical": false},":card_index:":{"unicode":["1f4c7"],"isCanonical": true},":information_desk_person:":{"unicode":["1f481"],"isCanonical": true},":guardsman:":{"unicode":["1f482"],"isCanonical": true},":dancer:":{"unicode":["1f483"],"isCanonical": true},":lipstick:":{"unicode":["1f484"],"isCanonical": true},":nail_care:":{"unicode":["1f485"],"isCanonical": true},":ledger:":{"unicode":["1f4d2"],"isCanonical": true},":massage:":{"unicode":["1f486"],"isCanonical": true},":notebook:":{"unicode":["1f4d3"],"isCanonical": true},":haircut:":{"unicode":["1f487"],"isCanonical": true},":notebook_with_decorative_cover:":{"unicode":["1f4d4"],"isCanonical": true},":barber:":{"unicode":["1f488"],"isCanonical": true},":closed_book:":{"unicode":["1f4d5"],"isCanonical": true},":syringe:":{"unicode":["1f489"],"isCanonical": true},":book:":{"unicode":["1f4d6"],"isCanonical": true},":pill:":{"unicode":["1f48a"],"isCanonical": true},":green_book:":{"unicode":["1f4d7"],"isCanonical": true},":kiss:":{"unicode":["1f48b"],"isCanonical": true},":blue_book:":{"unicode":["1f4d8"],"isCanonical": true},":love_letter:":{"unicode":["1f48c"],"isCanonical": true},":orange_book:":{"unicode":["1f4d9"],"isCanonical": true},":ring:":{"unicode":["1f48d"],"isCanonical": true},":books:":{"unicode":["1f4da"],"isCanonical": true},":gem:":{"unicode":["1f48e"],"isCanonical": true},":name_badge:":{"unicode":["1f4db"],"isCanonical": true},":couplekiss:":{"unicode":["1f48f"],"isCanonical": true},":scroll:":{"unicode":["1f4dc"],"isCanonical": true},":bouquet:":{"unicode":["1f490"],"isCanonical": true},":pencil:":{"unicode":["1f4dd"],"isCanonical": true},":couple_with_heart:":{"unicode":["1f491"],"isCanonical": true},":telephone_receiver:":{"unicode":["1f4de"],"isCanonical": true},":wedding:":{"unicode":["1f492"],"isCanonical": true},":pager:":{"unicode":["1f4df"],"isCanonical": true},":fax:":{"unicode":["1f4e0"],"isCanonical": true},":heartbeat:":{"unicode":["1f493"],"isCanonical": true},":satellite:":{"unicode":["1f4e1"],"isCanonical": true},":loudspeaker:":{"unicode":["1f4e2"],"isCanonical": true},":broken_heart:":{"unicode":["1f494"],"isCanonical": true},":mega:":{"unicode":["1f4e3"],"isCanonical": true},":outbox_tray:":{"unicode":["1f4e4"],"isCanonical": true},":two_hearts:":{"unicode":["1f495"],"isCanonical": true},":inbox_tray:":{"unicode":["1f4e5"],"isCanonical": true},":package:":{"unicode":["1f4e6"],"isCanonical": true},":sparkling_heart:":{"unicode":["1f496"],"isCanonical": true},":e-mail:":{"unicode":["1f4e7"],"isCanonical": true},":email:":{"unicode":["1f4e7"],"isCanonical": false},":incoming_envelope:":{"unicode":["1f4e8"],"isCanonical": true},":heartpulse:":{"unicode":["1f497"],"isCanonical": true},":envelope_with_arrow:":{"unicode":["1f4e9"],"isCanonical": true},":mailbox_closed:":{"unicode":["1f4ea"],"isCanonical": true},":cupid:":{"unicode":["1f498"],"isCanonical": true},":mailbox:":{"unicode":["1f4eb"],"isCanonical": true},":postbox:":{"unicode":["1f4ee"],"isCanonical": true},":blue_heart:":{"unicode":["1f499"],"isCanonical": true},":newspaper:":{"unicode":["1f4f0"],"isCanonical": true},":iphone:":{"unicode":["1f4f1"],"isCanonical": true},":green_heart:":{"unicode":["1f49a"],"isCanonical": true},":calling:":{"unicode":["1f4f2"],"isCanonical": true},":vibration_mode:":{"unicode":["1f4f3"],"isCanonical": true},":yellow_heart:":{"unicode":["1f49b"],"isCanonical": true},":mobile_phone_off:":{"unicode":["1f4f4"],"isCanonical": true},":signal_strength:":{"unicode":["1f4f6"],"isCanonical": true},":purple_heart:":{"unicode":["1f49c"],"isCanonical": true},":camera:":{"unicode":["1f4f7"],"isCanonical": true},":video_camera:":{"unicode":["1f4f9"],"isCanonical": true},":gift_heart:":{"unicode":["1f49d"],"isCanonical": true},":tv:":{"unicode":["1f4fa"],"isCanonical": true},":radio:":{"unicode":["1f4fb"],"isCanonical": true},":revolving_hearts:":{"unicode":["1f49e"],"isCanonical": true},":vhs:":{"unicode":["1f4fc"],"isCanonical": true},":arrows_clockwise:":{"unicode":["1f503"],"isCanonical": true},":heart_decoration:":{"unicode":["1f49f"],"isCanonical": true},":loud_sound:":{"unicode":["1f50a"],"isCanonical": true},":battery:":{"unicode":["1f50b"],"isCanonical": true},":diamond_shape_with_a_dot_inside:":{"unicode":["1f4a0"],"isCanonical": true},":electric_plug:":{"unicode":["1f50c"],"isCanonical": true},":mag:":{"unicode":["1f50d"],"isCanonical": true},":bulb:":{"unicode":["1f4a1"],"isCanonical": true},":mag_right:":{"unicode":["1f50e"],"isCanonical": true},":lock_with_ink_pen:":{"unicode":["1f50f"],"isCanonical": true},":anger:":{"unicode":["1f4a2"],"isCanonical": true},":closed_lock_with_key:":{"unicode":["1f510"],"isCanonical": true},":key:":{"unicode":["1f511"],"isCanonical": true},":bomb:":{"unicode":["1f4a3"],"isCanonical": true},":lock:":{"unicode":["1f512"],"isCanonical": true},":unlock:":{"unicode":["1f513"],"isCanonical": true},":zzz:":{"unicode":["1f4a4"],"isCanonical": true},":bell:":{"unicode":["1f514"],"isCanonical": true},":bookmark:":{"unicode":["1f516"],"isCanonical": true},":boom:":{"unicode":["1f4a5"],"isCanonical": true},":link:":{"unicode":["1f517"],"isCanonical": true},":radio_button:":{"unicode":["1f518"],"isCanonical": true},":sweat_drops:":{"unicode":["1f4a6"],"isCanonical": true},":back:":{"unicode":["1f519"],"isCanonical": true},":end:":{"unicode":["1f51a"],"isCanonical": true},":droplet:":{"unicode":["1f4a7"],"isCanonical": true},":on:":{"unicode":["1f51b"],"isCanonical": true},":soon:":{"unicode":["1f51c"],"isCanonical": true},":dash:":{"unicode":["1f4a8"],"isCanonical": true},":top:":{"unicode":["1f51d"],"isCanonical": true},":underage:":{"unicode":["1f51e"],"isCanonical": true},":poop:":{"unicode":["1f4a9"],"isCanonical": true},":shit:":{"unicode":["1f4a9"],"isCanonical": false},":hankey:":{"unicode":["1f4a9"],"isCanonical": false},":poo:":{"unicode":["1f4a9"],"isCanonical": false},":keycap_ten:":{"unicode":["1f51f"],"isCanonical": true},":muscle:":{"unicode":["1f4aa"],"isCanonical": true},":capital_abcd:":{"unicode":["1f520"],"isCanonical": true},":abcd:":{"unicode":["1f521"],"isCanonical": true},":dizzy:":{"unicode":["1f4ab"],"isCanonical": true},":1234:":{"unicode":["1f522"],"isCanonical": true},":symbols:":{"unicode":["1f523"],"isCanonical": true},":speech_balloon:":{"unicode":["1f4ac"],"isCanonical": true},":abc:":{"unicode":["1f524"],"isCanonical": true},":fire:":{"unicode":["1f525"],"isCanonical": true},":flame:":{"unicode":["1f525"],"isCanonical": false},":white_flower:":{"unicode":["1f4ae"],"isCanonical": true},":flashlight:":{"unicode":["1f526"],"isCanonical": true},":wrench:":{"unicode":["1f527"],"isCanonical": true},":100:":{"unicode":["1f4af"],"isCanonical": true},":hammer:":{"unicode":["1f528"],"isCanonical": true},":nut_and_bolt:":{"unicode":["1f529"],"isCanonical": true},":moneybag:":{"unicode":["1f4b0"],"isCanonical": true},":knife:":{"unicode":["1f52a"],"isCanonical": true},":gun:":{"unicode":["1f52b"],"isCanonical": true},":currency_exchange:":{"unicode":["1f4b1"],"isCanonical": true},":crystal_ball:":{"unicode":["1f52e"],"isCanonical": true},":heavy_dollar_sign:":{"unicode":["1f4b2"],"isCanonical": true},":six_pointed_star:":{"unicode":["1f52f"],"isCanonical": true},":credit_card:":{"unicode":["1f4b3"],"isCanonical": true},":beginner:":{"unicode":["1f530"],"isCanonical": true},":trident:":{"unicode":["1f531"],"isCanonical": true},":yen:":{"unicode":["1f4b4"],"isCanonical": true},":black_square_button:":{"unicode":["1f532"],"isCanonical": true},":white_square_button:":{"unicode":["1f533"],"isCanonical": true},":dollar:":{"unicode":["1f4b5"],"isCanonical": true},":red_circle:":{"unicode":["1f534"],"isCanonical": true},":large_blue_circle:":{"unicode":["1f535"],"isCanonical": true},":money_with_wings:":{"unicode":["1f4b8"],"isCanonical": true},":large_orange_diamond:":{"unicode":["1f536"],"isCanonical": true},":large_blue_diamond:":{"unicode":["1f537"],"isCanonical": true},":chart:":{"unicode":["1f4b9"],"isCanonical": true},":small_orange_diamond:":{"unicode":["1f538"],"isCanonical": true},":small_blue_diamond:":{"unicode":["1f539"],"isCanonical": true},":seat:":{"unicode":["1f4ba"],"isCanonical": true},":small_red_triangle:":{"unicode":["1f53a"],"isCanonical": true},":small_red_triangle_down:":{"unicode":["1f53b"],"isCanonical": true},":computer:":{"unicode":["1f4bb"],"isCanonical": true},":arrow_up_small:":{"unicode":["1f53c"],"isCanonical": true},":briefcase:":{"unicode":["1f4bc"],"isCanonical": true},":arrow_down_small:":{"unicode":["1f53d"],"isCanonical": true},":clock1:":{"unicode":["1f550"],"isCanonical": true},":minidisc:":{"unicode":["1f4bd"],"isCanonical": true},":clock2:":{"unicode":["1f551"],"isCanonical": true},":floppy_disk:":{"unicode":["1f4be"],"isCanonical": true},":clock3:":{"unicode":["1f552"],"isCanonical": true},":cd:":{"unicode":["1f4bf"],"isCanonical": true},":clock4:":{"unicode":["1f553"],"isCanonical": true},":dvd:":{"unicode":["1f4c0"],"isCanonical": true},":clock5:":{"unicode":["1f554"],"isCanonical": true},":clock6:":{"unicode":["1f555"],"isCanonical": true},":file_folder:":{"unicode":["1f4c1"],"isCanonical": true},":clock7:":{"unicode":["1f556"],"isCanonical": true},":clock8:":{"unicode":["1f557"],"isCanonical": true},":open_file_folder:":{"unicode":["1f4c2"],"isCanonical": true},":clock9:":{"unicode":["1f558"],"isCanonical": true},":clock10:":{"unicode":["1f559"],"isCanonical": true},":page_with_curl:":{"unicode":["1f4c3"],"isCanonical": true},":clock11:":{"unicode":["1f55a"],"isCanonical": true},":clock12:":{"unicode":["1f55b"],"isCanonical": true},":page_facing_up:":{"unicode":["1f4c4"],"isCanonical": true},":mount_fuji:":{"unicode":["1f5fb"],"isCanonical": true},":tokyo_tower:":{"unicode":["1f5fc"],"isCanonical": true},":date:":{"unicode":["1f4c5"],"isCanonical": true},":statue_of_liberty:":{"unicode":["1f5fd"],"isCanonical": true},":japan:":{"unicode":["1f5fe"],"isCanonical": true},":calendar:":{"unicode":["1f4c6"],"isCanonical": true},":moyai:":{"unicode":["1f5ff"],"isCanonical": true},":grin:":{"unicode":["1f601"],"isCanonical": true},":joy:":{"unicode":["1f602"],"isCanonical": true},":smiley:":{"unicode":["1f603"],"isCanonical": true},":chart_with_upwards_trend:":{"unicode":["1f4c8"],"isCanonical": true},":smile:":{"unicode":["1f604"],"isCanonical": true},":sweat_smile:":{"unicode":["1f605"],"isCanonical": true},":chart_with_downwards_trend:":{"unicode":["1f4c9"],"isCanonical": true},":laughing:":{"unicode":["1f606"],"isCanonical": true},":satisfied:":{"unicode":["1f606"],"isCanonical": false},":wink:":{"unicode":["1f609"],"isCanonical": true},":bar_chart:":{"unicode":["1f4ca"],"isCanonical": true},":blush:":{"unicode":["1f60a"],"isCanonical": true},":yum:":{"unicode":["1f60b"],"isCanonical": true},":clipboard:":{"unicode":["1f4cb"],"isCanonical": true},":relieved:":{"unicode":["1f60c"],"isCanonical": true},":heart_eyes:":{"unicode":["1f60d"],"isCanonical": true},":pushpin:":{"unicode":["1f4cc"],"isCanonical": true},":smirk:":{"unicode":["1f60f"],"isCanonical": true},":unamused:":{"unicode":["1f612"],"isCanonical": true},":round_pushpin:":{"unicode":["1f4cd"],"isCanonical": true},":sweat:":{"unicode":["1f613"],"isCanonical": true},":pensive:":{"unicode":["1f614"],"isCanonical": true},":paperclip:":{"unicode":["1f4ce"],"isCanonical": true},":confounded:":{"unicode":["1f616"],"isCanonical": true},":kissing_heart:":{"unicode":["1f618"],"isCanonical": true},":straight_ruler:":{"unicode":["1f4cf"],"isCanonical": true},":kissing_closed_eyes:":{"unicode":["1f61a"],"isCanonical": true},":stuck_out_tongue_winking_eye:":{"unicode":["1f61c"],"isCanonical": true},":triangular_ruler:":{"unicode":["1f4d0"],"isCanonical": true},":stuck_out_tongue_closed_eyes:":{"unicode":["1f61d"],"isCanonical": true},":disappointed:":{"unicode":["1f61e"],"isCanonical": true},":bookmark_tabs:":{"unicode":["1f4d1"],"isCanonical": true},":angry:":{"unicode":["1f620"],"isCanonical": true},":rage:":{"unicode":["1f621"],"isCanonical": true},":cry:":{"unicode":["1f622"],"isCanonical": true},":persevere:":{"unicode":["1f623"],"isCanonical": true},":triumph:":{"unicode":["1f624"],"isCanonical": true},":disappointed_relieved:":{"unicode":["1f625"],"isCanonical": true},":fearful:":{"unicode":["1f628"],"isCanonical": true},":weary:":{"unicode":["1f629"],"isCanonical": true},":sleepy:":{"unicode":["1f62a"],"isCanonical": true},":tired_face:":{"unicode":["1f62b"],"isCanonical": true},":sob:":{"unicode":["1f62d"],"isCanonical": true},":cold_sweat:":{"unicode":["1f630"],"isCanonical": true},":scream:":{"unicode":["1f631"],"isCanonical": true},":astonished:":{"unicode":["1f632"],"isCanonical": true},":flushed:":{"unicode":["1f633"],"isCanonical": true},":dizzy_face:":{"unicode":["1f635"],"isCanonical": true},":mask:":{"unicode":["1f637"],"isCanonical": true},":smile_cat:":{"unicode":["1f638"],"isCanonical": true},":joy_cat:":{"unicode":["1f639"],"isCanonical": true},":smiley_cat:":{"unicode":["1f63a"],"isCanonical": true},":heart_eyes_cat:":{"unicode":["1f63b"],"isCanonical": true},":smirk_cat:":{"unicode":["1f63c"],"isCanonical": true},":kissing_cat:":{"unicode":["1f63d"],"isCanonical": true},":pouting_cat:":{"unicode":["1f63e"],"isCanonical": true},":crying_cat_face:":{"unicode":["1f63f"],"isCanonical": true},":scream_cat:":{"unicode":["1f640"],"isCanonical": true},":no_good:":{"unicode":["1f645"],"isCanonical": true},":ok_woman:":{"unicode":["1f646"],"isCanonical": true},":bow:":{"unicode":["1f647"],"isCanonical": true},":see_no_evil:":{"unicode":["1f648"],"isCanonical": true},":hear_no_evil:":{"unicode":["1f649"],"isCanonical": true},":speak_no_evil:":{"unicode":["1f64a"],"isCanonical": true},":raising_hand:":{"unicode":["1f64b"],"isCanonical": true},":raised_hands:":{"unicode":["1f64c"],"isCanonical": true},":person_frowning:":{"unicode":["1f64d"],"isCanonical": true},":person_with_pouting_face:":{"unicode":["1f64e"],"isCanonical": true},":pray:":{"unicode":["1f64f"],"isCanonical": true},":rocket:":{"unicode":["1f680"],"isCanonical": true},":railway_car:":{"unicode":["1f683"],"isCanonical": true},":bullettrain_side:":{"unicode":["1f684"],"isCanonical": true},":bullettrain_front:":{"unicode":["1f685"],"isCanonical": true},":metro:":{"unicode":["1f687"],"isCanonical": true},":station:":{"unicode":["1f689"],"isCanonical": true},":bus:":{"unicode":["1f68c"],"isCanonical": true},":busstop:":{"unicode":["1f68f"],"isCanonical": true},":ambulance:":{"unicode":["1f691"],"isCanonical": true},":fire_engine:":{"unicode":["1f692"],"isCanonical": true},":police_car:":{"unicode":["1f693"],"isCanonical": true},":taxi:":{"unicode":["1f695"],"isCanonical": true},":red_car:":{"unicode":["1f697"],"isCanonical": true},":blue_car:":{"unicode":["1f699"],"isCanonical": true},":truck:":{"unicode":["1f69a"],"isCanonical": true},":ship:":{"unicode":["1f6a2"],"isCanonical": true},":speedboat:":{"unicode":["1f6a4"],"isCanonical": true},":traffic_light:":{"unicode":["1f6a5"],"isCanonical": true},":construction:":{"unicode":["1f6a7"],"isCanonical": true},":rotating_light:":{"unicode":["1f6a8"],"isCanonical": true},":triangular_flag_on_post:":{"unicode":["1f6a9"],"isCanonical": true},":door:":{"unicode":["1f6aa"],"isCanonical": true},":no_entry_sign:":{"unicode":["1f6ab"],"isCanonical": true},":smoking:":{"unicode":["1f6ac"],"isCanonical": true},":no_smoking:":{"unicode":["1f6ad"],"isCanonical": true},":bike:":{"unicode":["1f6b2"],"isCanonical": true},":walking:":{"unicode":["1f6b6"],"isCanonical": true},":mens:":{"unicode":["1f6b9"],"isCanonical": true},":womens:":{"unicode":["1f6ba"],"isCanonical": true},":restroom:":{"unicode":["1f6bb"],"isCanonical": true},":baby_symbol:":{"unicode":["1f6bc"],"isCanonical": true},":toilet:":{"unicode":["1f6bd"],"isCanonical": true},":wc:":{"unicode":["1f6be"],"isCanonical": true},":bath:":{"unicode":["1f6c0"],"isCanonical": true},":metal:":{"unicode":["1f918"],"isCanonical": true},":sign_of_the_horns:":{"unicode":["1f918"],"isCanonical": false},":grinning:":{"unicode":["1f600"],"isCanonical": true},":innocent:":{"unicode":["1f607"],"isCanonical": true},":smiling_imp:":{"unicode":["1f608"],"isCanonical": true},":sunglasses:":{"unicode":["1f60e"],"isCanonical": true},":neutral_face:":{"unicode":["1f610"],"isCanonical": true},":expressionless:":{"unicode":["1f611"],"isCanonical": true},":confused:":{"unicode":["1f615"],"isCanonical": true},":kissing:":{"unicode":["1f617"],"isCanonical": true},":kissing_smiling_eyes:":{"unicode":["1f619"],"isCanonical": true},":stuck_out_tongue:":{"unicode":["1f61b"],"isCanonical": true},":worried:":{"unicode":["1f61f"],"isCanonical": true},":frowning:":{"unicode":["1f626"],"isCanonical": true},":anguished:":{"unicode":["1f627"],"isCanonical": true},":grimacing:":{"unicode":["1f62c"],"isCanonical": true},":open_mouth:":{"unicode":["1f62e"],"isCanonical": true},":hushed:":{"unicode":["1f62f"],"isCanonical": true},":sleeping:":{"unicode":["1f634"],"isCanonical": true},":no_mouth:":{"unicode":["1f636"],"isCanonical": true},":helicopter:":{"unicode":["1f681"],"isCanonical": true},":steam_locomotive:":{"unicode":["1f682"],"isCanonical": true},":train2:":{"unicode":["1f686"],"isCanonical": true},":light_rail:":{"unicode":["1f688"],"isCanonical": true},":tram:":{"unicode":["1f68a"],"isCanonical": true},":oncoming_bus:":{"unicode":["1f68d"],"isCanonical": true},":trolleybus:":{"unicode":["1f68e"],"isCanonical": true},":minibus:":{"unicode":["1f690"],"isCanonical": true},":oncoming_police_car:":{"unicode":["1f694"],"isCanonical": true},":oncoming_taxi:":{"unicode":["1f696"],"isCanonical": true},":oncoming_automobile:":{"unicode":["1f698"],"isCanonical": true},":articulated_lorry:":{"unicode":["1f69b"],"isCanonical": true},":tractor:":{"unicode":["1f69c"],"isCanonical": true},":monorail:":{"unicode":["1f69d"],"isCanonical": true},":mountain_railway:":{"unicode":["1f69e"],"isCanonical": true},":suspension_railway:":{"unicode":["1f69f"],"isCanonical": true},":mountain_cableway:":{"unicode":["1f6a0"],"isCanonical": true},":aerial_tramway:":{"unicode":["1f6a1"],"isCanonical": true},":rowboat:":{"unicode":["1f6a3"],"isCanonical": true},":vertical_traffic_light:":{"unicode":["1f6a6"],"isCanonical": true},":put_litter_in_its_place:":{"unicode":["1f6ae"],"isCanonical": true},":do_not_litter:":{"unicode":["1f6af"],"isCanonical": true},":potable_water:":{"unicode":["1f6b0"],"isCanonical": true},":non-potable_water:":{"unicode":["1f6b1"],"isCanonical": true},":no_bicycles:":{"unicode":["1f6b3"],"isCanonical": true},":bicyclist:":{"unicode":["1f6b4"],"isCanonical": true},":mountain_bicyclist:":{"unicode":["1f6b5"],"isCanonical": true},":no_pedestrians:":{"unicode":["1f6b7"],"isCanonical": true},":children_crossing:":{"unicode":["1f6b8"],"isCanonical": true},":shower:":{"unicode":["1f6bf"],"isCanonical": true},":bathtub:":{"unicode":["1f6c1"],"isCanonical": true},":passport_control:":{"unicode":["1f6c2"],"isCanonical": true},":customs:":{"unicode":["1f6c3"],"isCanonical": true},":baggage_claim:":{"unicode":["1f6c4"],"isCanonical": true},":left_luggage:":{"unicode":["1f6c5"],"isCanonical": true},":earth_africa:":{"unicode":["1f30d"],"isCanonical": true},":earth_americas:":{"unicode":["1f30e"],"isCanonical": true},":globe_with_meridians:":{"unicode":["1f310"],"isCanonical": true},":waxing_crescent_moon:":{"unicode":["1f312"],"isCanonical": true},":waning_gibbous_moon:":{"unicode":["1f316"],"isCanonical": true},":last_quarter_moon:":{"unicode":["1f317"],"isCanonical": true},":waning_crescent_moon:":{"unicode":["1f318"],"isCanonical": true},":new_moon_with_face:":{"unicode":["1f31a"],"isCanonical": true},":last_quarter_moon_with_face:":{"unicode":["1f31c"],"isCanonical": true},":full_moon_with_face:":{"unicode":["1f31d"],"isCanonical": true},":sun_with_face:":{"unicode":["1f31e"],"isCanonical": true},":evergreen_tree:":{"unicode":["1f332"],"isCanonical": true},":deciduous_tree:":{"unicode":["1f333"],"isCanonical": true},":lemon:":{"unicode":["1f34b"],"isCanonical": true},":pear:":{"unicode":["1f350"],"isCanonical": true},":baby_bottle:":{"unicode":["1f37c"],"isCanonical": true},":horse_racing:":{"unicode":["1f3c7"],"isCanonical": true},":rugby_football:":{"unicode":["1f3c9"],"isCanonical": true},":european_post_office:":{"unicode":["1f3e4"],"isCanonical": true},":rat:":{"unicode":["1f400"],"isCanonical": true},":mouse2:":{"unicode":["1f401"],"isCanonical": true},":ox:":{"unicode":["1f402"],"isCanonical": true},":water_buffalo:":{"unicode":["1f403"],"isCanonical": true},":cow2:":{"unicode":["1f404"],"isCanonical": true},":tiger2:":{"unicode":["1f405"],"isCanonical": true},":leopard:":{"unicode":["1f406"],"isCanonical": true},":rabbit2:":{"unicode":["1f407"],"isCanonical": true},":cat2:":{"unicode":["1f408"],"isCanonical": true},":dragon:":{"unicode":["1f409"],"isCanonical": true},":crocodile:":{"unicode":["1f40a"],"isCanonical": true},":whale2:":{"unicode":["1f40b"],"isCanonical": true},":ram:":{"unicode":["1f40f"],"isCanonical": true},":goat:":{"unicode":["1f410"],"isCanonical": true},":rooster:":{"unicode":["1f413"],"isCanonical": true},":dog2:":{"unicode":["1f415"],"isCanonical": true},":pig2:":{"unicode":["1f416"],"isCanonical": true},":dromedary_camel:":{"unicode":["1f42a"],"isCanonical": true},":busts_in_silhouette:":{"unicode":["1f465"],"isCanonical": true},":two_men_holding_hands:":{"unicode":["1f46c"],"isCanonical": true},":two_women_holding_hands:":{"unicode":["1f46d"],"isCanonical": true},":thought_balloon:":{"unicode":["1f4ad"],"isCanonical": true},":euro:":{"unicode":["1f4b6"],"isCanonical": true},":pound:":{"unicode":["1f4b7"],"isCanonical": true},":mailbox_with_mail:":{"unicode":["1f4ec"],"isCanonical": true},":mailbox_with_no_mail:":{"unicode":["1f4ed"],"isCanonical": true},":postal_horn:":{"unicode":["1f4ef"],"isCanonical": true},":no_mobile_phones:":{"unicode":["1f4f5"],"isCanonical": true},":twisted_rightwards_arrows:":{"unicode":["1f500"],"isCanonical": true},":repeat:":{"unicode":["1f501"],"isCanonical": true},":repeat_one:":{"unicode":["1f502"],"isCanonical": true},":arrows_counterclockwise:":{"unicode":["1f504"],"isCanonical": true},":low_brightness:":{"unicode":["1f505"],"isCanonical": true},":high_brightness:":{"unicode":["1f506"],"isCanonical": true},":mute:":{"unicode":["1f507"],"isCanonical": true},":sound:":{"unicode":["1f509"],"isCanonical": true},":no_bell:":{"unicode":["1f515"],"isCanonical": true},":microscope:":{"unicode":["1f52c"],"isCanonical": true},":telescope:":{"unicode":["1f52d"],"isCanonical": true},":clock130:":{"unicode":["1f55c"],"isCanonical": true},":clock230:":{"unicode":["1f55d"],"isCanonical": true},":clock330:":{"unicode":["1f55e"],"isCanonical": true},":clock430:":{"unicode":["1f55f"],"isCanonical": true},":clock530:":{"unicode":["1f560"],"isCanonical": true},":clock630:":{"unicode":["1f561"],"isCanonical": true},":clock730:":{"unicode":["1f562"],"isCanonical": true},":clock830:":{"unicode":["1f563"],"isCanonical": true},":clock930:":{"unicode":["1f564"],"isCanonical": true},":clock1030:":{"unicode":["1f565"],"isCanonical": true},":clock1130:":{"unicode":["1f566"],"isCanonical": true},":clock1230:":{"unicode":["1f567"],"isCanonical": true},":speaker:":{"unicode":["1f508"],"isCanonical": true},":train:":{"unicode":["1f68b"],"isCanonical": true},":medal:":{"unicode":["1f3c5"],"isCanonical": true},":sports_medal:":{"unicode":["1f3c5"],"isCanonical": false},":flag_black:":{"unicode":["1f3f4"],"isCanonical": true},":waving_black_flag:":{"unicode":["1f3f4"],"isCanonical": false},":camera_with_flash:":{"unicode":["1f4f8"],"isCanonical": true},":sleeping_accommodation:":{"unicode":["1f6cc"],"isCanonical": true},":middle_finger:":{"unicode":["1f595"],"isCanonical": true},":reversed_hand_with_middle_finger_extended:":{"unicode":["1f595"],"isCanonical": false},":vulcan:":{"unicode":["1f596"],"isCanonical": true},":raised_hand_with_part_between_middle_and_ring_fingers:":{"unicode":["1f596"],"isCanonical": false},":slight_frown:":{"unicode":["1f641"],"isCanonical": true},":slightly_frowning_face:":{"unicode":["1f641"],"isCanonical": false},":slight_smile:":{"unicode":["1f642"],"isCanonical": true},":slightly_smiling_face:":{"unicode":["1f642"],"isCanonical": false},":airplane_departure:":{"unicode":["1f6eb"],"isCanonical": true},":airplane_arriving:":{"unicode":["1f6ec"],"isCanonical": true},":tone1:":{"unicode":["1f3fb"],"isCanonical": true},":tone2:":{"unicode":["1f3fc"],"isCanonical": true},":tone3:":{"unicode":["1f3fd"],"isCanonical": true},":tone4:":{"unicode":["1f3fe"],"isCanonical": true},":tone5:":{"unicode":["1f3ff"],"isCanonical": true},":upside_down:":{"unicode":["1f643"],"isCanonical": true},":upside_down_face:":{"unicode":["1f643"],"isCanonical": false},":money_mouth:":{"unicode":["1f911"],"isCanonical": true},":money_mouth_face:":{"unicode":["1f911"],"isCanonical": false},":nerd:":{"unicode":["1f913"],"isCanonical": true},":nerd_face:":{"unicode":["1f913"],"isCanonical": false},":hugging:":{"unicode":["1f917"],"isCanonical": true},":hugging_face:":{"unicode":["1f917"],"isCanonical": false},":rolling_eyes:":{"unicode":["1f644"],"isCanonical": true},":face_with_rolling_eyes:":{"unicode":["1f644"],"isCanonical": false},":thinking:":{"unicode":["1f914"],"isCanonical": true},":thinking_face:":{"unicode":["1f914"],"isCanonical": false},":zipper_mouth:":{"unicode":["1f910"],"isCanonical": true},":zipper_mouth_face:":{"unicode":["1f910"],"isCanonical": false},":thermometer_face:":{"unicode":["1f912"],"isCanonical": true},":face_with_thermometer:":{"unicode":["1f912"],"isCanonical": false},":head_bandage:":{"unicode":["1f915"],"isCanonical": true},":face_with_head_bandage:":{"unicode":["1f915"],"isCanonical": false},":robot:":{"unicode":["1f916"],"isCanonical": true},":robot_face:":{"unicode":["1f916"],"isCanonical": false},":lion_face:":{"unicode":["1f981"],"isCanonical": true},":lion:":{"unicode":["1f981"],"isCanonical": false},":unicorn:":{"unicode":["1f984"],"isCanonical": true},":unicorn_face:":{"unicode":["1f984"],"isCanonical": false},":scorpion:":{"unicode":["1f982"],"isCanonical": true},":crab:":{"unicode":["1f980"],"isCanonical": true},":turkey:":{"unicode":["1f983"],"isCanonical": true},":cheese:":{"unicode":["1f9c0"],"isCanonical": true},":cheese_wedge:":{"unicode":["1f9c0"],"isCanonical": false},":hotdog:":{"unicode":["1f32d"],"isCanonical": true},":hot_dog:":{"unicode":["1f32d"],"isCanonical": false},":taco:":{"unicode":["1f32e"],"isCanonical": true},":burrito:":{"unicode":["1f32f"],"isCanonical": true},":popcorn:":{"unicode":["1f37f"],"isCanonical": true},":champagne:":{"unicode":["1f37e"],"isCanonical": true},":bottle_with_popping_cork:":{"unicode":["1f37e"],"isCanonical": false},":bow_and_arrow:":{"unicode":["1f3f9"],"isCanonical": true},":archery:":{"unicode":["1f3f9"],"isCanonical": false},":amphora:":{"unicode":["1f3fa"],"isCanonical": true},":place_of_worship:":{"unicode":["1f6d0"],"isCanonical": true},":worship_symbol:":{"unicode":["1f6d0"],"isCanonical": false},":kaaba:":{"unicode":["1f54b"],"isCanonical": true},":mosque:":{"unicode":["1f54c"],"isCanonical": true},":synagogue:":{"unicode":["1f54d"],"isCanonical": true},":menorah:":{"unicode":["1f54e"],"isCanonical": true},":prayer_beads:":{"unicode":["1f4ff"],"isCanonical": true},":cricket:":{"unicode":["1f3cf"],"isCanonical": true},":cricket_bat_ball:":{"unicode":["1f3cf"],"isCanonical": false},":volleyball:":{"unicode":["1f3d0"],"isCanonical": true},":field_hockey:":{"unicode":["1f3d1"],"isCanonical": true},":hockey:":{"unicode":["1f3d2"],"isCanonical": true},":ping_pong:":{"unicode":["1f3d3"],"isCanonical": true},":table_tennis:":{"unicode":["1f3d3"],"isCanonical": false},":badminton:":{"unicode":["1f3f8"],"isCanonical": true},":drum:":{"unicode":["1f941"],"isCanonical": true},":drum_with_drumsticks:":{"unicode":["1f941"],"isCanonical": false},":shrimp:":{"unicode":["1f990"],"isCanonical": true},":squid:":{"unicode":["1f991"],"isCanonical": true},":egg:":{"unicode":["1f95a"],"isCanonical": true},":milk:":{"unicode":["1f95b"],"isCanonical": true},":glass_of_milk:":{"unicode":["1f95b"],"isCanonical": false},":peanuts:":{"unicode":["1f95c"],"isCanonical": true},":shelled_peanut:":{"unicode":["1f95c"],"isCanonical": false},":kiwi:":{"unicode":["1f95d"],"isCanonical": true},":kiwifruit:":{"unicode":["1f95d"],"isCanonical": false},":pancakes:":{"unicode":["1f95e"],"isCanonical": true},":regional_indicator_w:":{"unicode":["1f1fc"],"isCanonical": true},":regional_indicator_v:":{"unicode":["1f1fb"],"isCanonical": true},":regional_indicator_u:":{"unicode":["1f1fa"],"isCanonical": true},":regional_indicator_t:":{"unicode":["1f1f9"],"isCanonical": true},":regional_indicator_s:":{"unicode":["1f1f8"],"isCanonical": true},":regional_indicator_r:":{"unicode":["1f1f7"],"isCanonical": true},":regional_indicator_q:":{"unicode":["1f1f6"],"isCanonical": true},":regional_indicator_p:":{"unicode":["1f1f5"],"isCanonical": true},":regional_indicator_o:":{"unicode":["1f1f4"],"isCanonical": true},":regional_indicator_n:":{"unicode":["1f1f3"],"isCanonical": true},":regional_indicator_m:":{"unicode":["1f1f2"],"isCanonical": true},":regional_indicator_l:":{"unicode":["1f1f1"],"isCanonical": true},":regional_indicator_k:":{"unicode":["1f1f0"],"isCanonical": true},":regional_indicator_j:":{"unicode":["1f1ef"],"isCanonical": true},":regional_indicator_i:":{"unicode":["1f1ee"],"isCanonical": true},":regional_indicator_h:":{"unicode":["1f1ed"],"isCanonical": true},":regional_indicator_g:":{"unicode":["1f1ec"],"isCanonical": true},":regional_indicator_f:":{"unicode":["1f1eb"],"isCanonical": true},":regional_indicator_e:":{"unicode":["1f1ea"],"isCanonical": true},":regional_indicator_d:":{"unicode":["1f1e9"],"isCanonical": true},":regional_indicator_c:":{"unicode":["1f1e8"],"isCanonical": true},":regional_indicator_b:":{"unicode":["1f1e7"],"isCanonical": true},":regional_indicator_a:":{"unicode":["1f1e6"],"isCanonical": true},":fast_forward:":{"unicode":["23e9"],"isCanonical": true},":rewind:":{"unicode":["23ea"],"isCanonical": true},":arrow_double_up:":{"unicode":["23eb"],"isCanonical": true},":arrow_double_down:":{"unicode":["23ec"],"isCanonical": true},":alarm_clock:":{"unicode":["23f0"],"isCanonical": true},":hourglass_flowing_sand:":{"unicode":["23f3"],"isCanonical": true},":ophiuchus:":{"unicode":["26ce"],"isCanonical": true},":white_check_mark:":{"unicode":["2705"],"isCanonical": true},":fist:":{"unicode":["270a"],"isCanonical": true},":raised_hand:":{"unicode":["270b"],"isCanonical": true},":sparkles:":{"unicode":["2728"],"isCanonical": true},":x:":{"unicode":["274c"],"isCanonical": true},":negative_squared_cross_mark:":{"unicode":["274e"],"isCanonical": true},":question:":{"unicode":["2753"],"isCanonical": true},":grey_question:":{"unicode":["2754"],"isCanonical": true},":grey_exclamation:":{"unicode":["2755"],"isCanonical": true},":heavy_plus_sign:":{"unicode":["2795"],"isCanonical": true},":heavy_minus_sign:":{"unicode":["2796"],"isCanonical": true},":heavy_division_sign:":{"unicode":["2797"],"isCanonical": true},":curly_loop:":{"unicode":["27b0"],"isCanonical": true},":loop:":{"unicode":["27bf"],"isCanonical": true}}; + // ns.shortnames = Object.keys(ns.emojioneList).map(function(emoji) { + // return emoji.replace(/[+]/g, "\\$&"); + // }).join('|'); + var tmpShortNames = [], + emoji; + for (emoji in ns.emojioneList) { + if (!ns.emojioneList.hasOwnProperty(emoji)) continue; + tmpShortNames.push(emoji.replace(/[+]/g, "\\$&")); + } + ns.shortnames = tmpShortNames.join('|'); + ns.asciiList = { + '<3':'2764', + ':)':'1f606', + '>;)':'1f606', + '>:-)':'1f606', + '>=)':'1f606', + ';)':'1f609', + ';-)':'1f609', + '*-)':'1f609', + '*)':'1f609', + ';-]':'1f609', + ';]':'1f609', + ';D':'1f609', + ';^)':'1f609', + '\':(':'1f613', + '\':-(':'1f613', + '\'=(':'1f613', + ':*':'1f618', + ':-*':'1f618', + '=*':'1f618', + ':^*':'1f618', + '>:P':'1f61c', + 'X-P':'1f61c', + 'x-p':'1f61c', + '>:[':'1f61e', + ':-(':'1f61e', + ':(':'1f61e', + ':-[':'1f61e', + ':[':'1f61e', + '=(':'1f61e', + '>:(':'1f620', + '>:-(':'1f620', + ':@':'1f620', + ':\'(':'1f622', + ':\'-(':'1f622', + ';(':'1f622', + ';-(':'1f622', + '>.<':'1f623', + 'D:':'1f628', + ':$':'1f633', + '=$':'1f633', + '#-)':'1f635', + '#)':'1f635', + '%-)':'1f635', + '%)':'1f635', + 'X)':'1f635', + 'X-)':'1f635', + '*\\0/*':'1f646', + '\\0/':'1f646', + '*\\O/*':'1f646', + '\\O/':'1f646', + 'O:-)':'1f607', + '0:-3':'1f607', + '0:3':'1f607', + '0:-)':'1f607', + '0:)':'1f607', + '0;^)':'1f607', + 'O:)':'1f607', + 'O;-)':'1f607', + 'O=)':'1f607', + '0;-)':'1f607', + 'O:-3':'1f607', + 'O:3':'1f607', + 'B-)':'1f60e', + 'B)':'1f60e', + '8)':'1f60e', + '8-)':'1f60e', + 'B-D':'1f60e', + '8-D':'1f60e', + '-_-':'1f611', + '-__-':'1f611', + '-___-':'1f611', + '>:\\':'1f615', + '>:/':'1f615', + ':-/':'1f615', + ':-.':'1f615', + ':/':'1f615', + ':\\':'1f615', + '=/':'1f615', + '=\\':'1f615', + ':L':'1f615', + '=L':'1f615', + ':P':'1f61b', + ':-P':'1f61b', + '=P':'1f61b', + ':-p':'1f61b', + ':p':'1f61b', + '=p':'1f61b', + ':-Þ':'1f61b', + ':Þ':'1f61b', + ':þ':'1f61b', + ':-þ':'1f61b', + ':-b':'1f61b', + ':b':'1f61b', + 'd:':'1f61b', + ':-O':'1f62e', + ':O':'1f62e', + ':-o':'1f62e', + ':o':'1f62e', + 'O_O':'1f62e', + '>:O':'1f62e', + ':-X':'1f636', + ':X':'1f636', + ':-#':'1f636', + ':#':'1f636', + '=X':'1f636', + '=x':'1f636', + ':x':'1f636', + ':-x':'1f636', + '=#':'1f636' + }; + ns.asciiRegexp = '(\\<3|<3|\\<\\/3|<\\/3|\\:\'\\)|\\:\'\\-\\)|\\:D|\\:\\-D|\\=D|\\:\\)|\\:\\-\\)|\\=\\]|\\=\\)|\\:\\]|\'\\:\\)|\'\\:\\-\\)|\'\\=\\)|\'\\:D|\'\\:\\-D|\'\\=D|\\>\\:\\)|>\\:\\)|\\>;\\)|>;\\)|\\>\\:\\-\\)|>\\:\\-\\)|\\>\\=\\)|>\\=\\)|;\\)|;\\-\\)|\\*\\-\\)|\\*\\)|;\\-\\]|;\\]|;D|;\\^\\)|\'\\:\\(|\'\\:\\-\\(|\'\\=\\(|\\:\\*|\\:\\-\\*|\\=\\*|\\:\\^\\*|\\>\\:P|>\\:P|X\\-P|x\\-p|\\>\\:\\[|>\\:\\[|\\:\\-\\(|\\:\\(|\\:\\-\\[|\\:\\[|\\=\\(|\\>\\:\\(|>\\:\\(|\\>\\:\\-\\(|>\\:\\-\\(|\\:@|\\:\'\\(|\\:\'\\-\\(|;\\(|;\\-\\(|\\>\\.\\<|>\\.<|D\\:|\\:\\$|\\=\\$|#\\-\\)|#\\)|%\\-\\)|%\\)|X\\)|X\\-\\)|\\*\\\\0\\/\\*|\\\\0\\/|\\*\\\\O\\/\\*|\\\\O\\/|O\\:\\-\\)|0\\:\\-3|0\\:3|0\\:\\-\\)|0\\:\\)|0;\\^\\)|O\\:\\-\\)|O\\:\\)|O;\\-\\)|O\\=\\)|0;\\-\\)|O\\:\\-3|O\\:3|B\\-\\)|B\\)|8\\)|8\\-\\)|B\\-D|8\\-D|\\-_\\-|\\-__\\-|\\-___\\-|\\>\\:\\\\|>\\:\\\\|\\>\\:\\/|>\\:\\/|\\:\\-\\/|\\:\\-\\.|\\:\\/|\\:\\\\|\\=\\/|\\=\\\\|\\:L|\\=L|\\:P|\\:\\-P|\\=P|\\:\\-p|\\:p|\\=p|\\:\\-Þ|\\:\\-Þ|\\:Þ|\\:Þ|\\:þ|\\:þ|\\:\\-þ|\\:\\-þ|\\:\\-b|\\:b|d\\:|\\:\\-O|\\:O|\\:\\-o|\\:o|O_O|\\>\\:O|>\\:O|\\:\\-X|\\:X|\\:\\-#|\\:#|\\=X|\\=x|\\:x|\\:\\-x|\\=#)'; + // javascript escapes here must be ordered from largest length to shortest + ns.unicodeRegexp = '(\\uD83D\\uDC69\\u200D\\u2764\\uFE0F\\u200D\\uD83D\\uDC8B\\u200D\\uD83D\\uDC69|\\uD83D\\uDC68\\u200D\\u2764\\uFE0F\\u200D\\uD83D\\uDC8B\\u200D\\uD83D\\uDC68|\\uD83D\\uDC68\\u200D\\uD83D\\uDC68\\u200D\\uD83D\\uDC67\\u200D\\uD83D\\uDC66|\\uD83D\\uDC68\\u200D\\uD83D\\uDC68\\u200D\\uD83D\\uDC67\\u200D\\uD83D\\uDC67|\\uD83D\\uDC68\\u200D\\uD83D\\uDC69\\u200D\\uD83D\\uDC66\\u200D\\uD83D\\uDC66|\\uD83D\\uDC68\\u200D\\uD83D\\uDC69\\u200D\\uD83D\\uDC67\\u200D\\uD83D\\uDC66|\\uD83D\\uDC68\\u200D\\uD83D\\uDC69\\u200D\\uD83D\\uDC67\\u200D\\uD83D\\uDC67|\\uD83D\\uDC69\\u200D\\uD83D\\uDC69\\u200D\\uD83D\\uDC66\\u200D\\uD83D\\uDC66|\\uD83D\\uDC69\\u200D\\uD83D\\uDC69\\u200D\\uD83D\\uDC67\\u200D\\uD83D\\uDC66|\\uD83D\\uDC69\\u200D\\uD83D\\uDC69\\u200D\\uD83D\\uDC67\\u200D\\uD83D\\uDC67|\\uD83D\\uDC68\\u200D\\uD83D\\uDC68\\u200D\\uD83D\\uDC66\\u200D\\uD83D\\uDC66|\\uD83D\\uDC68\\u200D\\u2764\\uFE0F\\u200D\\uD83D\\uDC68|\\uD83D\\uDC68\\u200D\\uD83D\\uDC68\\u200D\\uD83D\\uDC67|\\uD83D\\uDC68\\u200D\\uD83D\\uDC69\\u200D\\uD83D\\uDC67|\\uD83D\\uDC69\\u200D\\uD83D\\uDC69\\u200D\\uD83D\\uDC66|\\uD83D\\uDC69\\u200D\\uD83D\\uDC69\\u200D\\uD83D\\uDC67|\\uD83D\\uDC69\\u200D\\u2764\\uFE0F\\u200D\\uD83D\\uDC69|\\uD83D\\uDC68\\u200D\\uD83D\\uDC68\\u200D\\uD83D\\uDC66|\\uD83D\\uDC41\\u200D\\uD83D\\uDDE8|\\uD83C\\uDDE6\\uD83C\\uDDE9|\\uD83C\\uDDE6\\uD83C\\uDDEA|\\uD83C\\uDDE6\\uD83C\\uDDEB|\\uD83C\\uDDE6\\uD83C\\uDDEC|\\uD83C\\uDDE6\\uD83C\\uDDEE|\\uD83C\\uDDE6\\uD83C\\uDDF1|\\uD83C\\uDDE6\\uD83C\\uDDF2|\\uD83C\\uDDE6\\uD83C\\uDDF4|\\uD83C\\uDDE6\\uD83C\\uDDF6|\\uD83C\\uDDE6\\uD83C\\uDDF7|\\uD83C\\uDDE6\\uD83C\\uDDF8|\\uD83E\\uDD18\\uD83C\\uDFFF|\\uD83E\\uDD18\\uD83C\\uDFFE|\\uD83E\\uDD18\\uD83C\\uDFFD|\\uD83E\\uDD18\\uD83C\\uDFFC|\\uD83E\\uDD18\\uD83C\\uDFFB|\\uD83D\\uDEC0\\uD83C\\uDFFF|\\uD83D\\uDEC0\\uD83C\\uDFFE|\\uD83D\\uDEC0\\uD83C\\uDFFD|\\uD83D\\uDEC0\\uD83C\\uDFFC|\\uD83D\\uDEC0\\uD83C\\uDFFB|\\uD83D\\uDEB6\\uD83C\\uDFFF|\\uD83D\\uDEB6\\uD83C\\uDFFE|\\uD83D\\uDEB6\\uD83C\\uDFFD|\\uD83D\\uDEB6\\uD83C\\uDFFC|\\uD83D\\uDEB6\\uD83C\\uDFFB|\\uD83D\\uDEB5\\uD83C\\uDFFF|\\uD83D\\uDEB5\\uD83C\\uDFFE|\\uD83D\\uDEB5\\uD83C\\uDFFD|\\uD83D\\uDEB5\\uD83C\\uDFFC|\\uD83D\\uDEB5\\uD83C\\uDFFB|\\uD83D\\uDEB4\\uD83C\\uDFFF|\\uD83D\\uDEB4\\uD83C\\uDFFE|\\uD83D\\uDEB4\\uD83C\\uDFFD|\\uD83D\\uDEB4\\uD83C\\uDFFC|\\uD83D\\uDEB4\\uD83C\\uDFFB|\\uD83D\\uDEA3\\uD83C\\uDFFF|\\uD83D\\uDEA3\\uD83C\\uDFFE|\\uD83D\\uDEA3\\uD83C\\uDFFD|\\uD83D\\uDEA3\\uD83C\\uDFFC|\\uD83D\\uDEA3\\uD83C\\uDFFB|\\uD83D\\uDE4F\\uD83C\\uDFFF|\\uD83D\\uDE4F\\uD83C\\uDFFE|\\uD83D\\uDE4F\\uD83C\\uDFFD|\\uD83D\\uDE4F\\uD83C\\uDFFC|\\uD83D\\uDE4F\\uD83C\\uDFFB|\\uD83D\\uDE4E\\uD83C\\uDFFF|\\uD83D\\uDE4E\\uD83C\\uDFFE|\\uD83D\\uDE4E\\uD83C\\uDFFD|\\uD83D\\uDE4E\\uD83C\\uDFFC|\\uD83D\\uDE4E\\uD83C\\uDFFB|\\uD83D\\uDE4D\\uD83C\\uDFFF|\\uD83D\\uDE4D\\uD83C\\uDFFE|\\uD83D\\uDE4D\\uD83C\\uDFFD|\\uD83D\\uDE4D\\uD83C\\uDFFC|\\uD83D\\uDE4D\\uD83C\\uDFFB|\\uD83D\\uDE4C\\uD83C\\uDFFF|\\uD83D\\uDE4C\\uD83C\\uDFFE|\\uD83D\\uDE4C\\uD83C\\uDFFD|\\uD83D\\uDE4C\\uD83C\\uDFFC|\\uD83D\\uDE4C\\uD83C\\uDFFB|\\uD83D\\uDE4B\\uD83C\\uDFFF|\\uD83D\\uDE4B\\uD83C\\uDFFE|\\uD83D\\uDE4B\\uD83C\\uDFFD|\\uD83D\\uDE4B\\uD83C\\uDFFC|\\uD83D\\uDE4B\\uD83C\\uDFFB|\\uD83D\\uDE47\\uD83C\\uDFFF|\\uD83D\\uDE47\\uD83C\\uDFFE|\\uD83D\\uDE47\\uD83C\\uDFFD|\\uD83D\\uDE47\\uD83C\\uDFFC|\\uD83D\\uDE47\\uD83C\\uDFFB|\\uD83D\\uDE46\\uD83C\\uDFFF|\\uD83D\\uDE46\\uD83C\\uDFFE|\\uD83D\\uDE46\\uD83C\\uDFFD|\\uD83D\\uDE46\\uD83C\\uDFFC|\\uD83D\\uDE46\\uD83C\\uDFFB|\\uD83D\\uDE45\\uD83C\\uDFFF|\\uD83D\\uDE45\\uD83C\\uDFFE|\\uD83D\\uDE45\\uD83C\\uDFFD|\\uD83D\\uDE45\\uD83C\\uDFFC|\\uD83D\\uDE45\\uD83C\\uDFFB|\\uD83D\\uDD96\\uD83C\\uDFFF|\\uD83D\\uDD96\\uD83C\\uDFFE|\\uD83D\\uDD96\\uD83C\\uDFFD|\\uD83D\\uDD96\\uD83C\\uDFFC|\\uD83D\\uDD96\\uD83C\\uDFFB|\\uD83D\\uDD95\\uD83C\\uDFFF|\\uD83D\\uDD95\\uD83C\\uDFFE|\\uD83D\\uDD95\\uD83C\\uDFFD|\\uD83D\\uDD95\\uD83C\\uDFFC|\\uD83D\\uDD95\\uD83C\\uDFFB|\\uD83D\\uDD90\\uD83C\\uDFFF|\\uD83D\\uDD90\\uD83C\\uDFFE|\\uD83D\\uDD90\\uD83C\\uDFFD|\\uD83D\\uDD90\\uD83C\\uDFFC|\\uD83D\\uDD90\\uD83C\\uDFFB|\\uD83D\\uDD75\\uD83C\\uDFFF|\\uD83D\\uDD75\\uD83C\\uDFFE|\\uD83D\\uDD75\\uD83C\\uDFFD|\\uD83D\\uDD75\\uD83C\\uDFFC|\\uD83D\\uDD75\\uD83C\\uDFFB|\\uD83D\\uDCAA\\uD83C\\uDFFF|\\uD83D\\uDCAA\\uD83C\\uDFFE|\\uD83D\\uDCAA\\uD83C\\uDFFD|\\uD83D\\uDCAA\\uD83C\\uDFFC|\\uD83D\\uDCAA\\uD83C\\uDFFB|\\uD83D\\uDC87\\uD83C\\uDFFF|\\uD83D\\uDC87\\uD83C\\uDFFE|\\uD83D\\uDC87\\uD83C\\uDFFD|\\uD83D\\uDC87\\uD83C\\uDFFC|\\uD83D\\uDC87\\uD83C\\uDFFB|\\uD83D\\uDC86\\uD83C\\uDFFF|\\uD83D\\uDC86\\uD83C\\uDFFE|\\uD83D\\uDC86\\uD83C\\uDFFD|\\uD83D\\uDC86\\uD83C\\uDFFC|\\uD83D\\uDC86\\uD83C\\uDFFB|\\uD83D\\uDC85\\uD83C\\uDFFF|\\uD83D\\uDC85\\uD83C\\uDFFE|\\uD83D\\uDC85\\uD83C\\uDFFD|\\uD83D\\uDC85\\uD83C\\uDFFC|\\uD83D\\uDC85\\uD83C\\uDFFB|\\uD83D\\uDC83\\uD83C\\uDFFF|\\uD83D\\uDC83\\uD83C\\uDFFE|\\uD83D\\uDC83\\uD83C\\uDFFD|\\uD83D\\uDC83\\uD83C\\uDFFC|\\uD83D\\uDC83\\uD83C\\uDFFB|\\uD83D\\uDC82\\uD83C\\uDFFF|\\uD83D\\uDC82\\uD83C\\uDFFE|\\uD83D\\uDC82\\uD83C\\uDFFD|\\uD83D\\uDC82\\uD83C\\uDFFC|\\uD83D\\uDC82\\uD83C\\uDFFB|\\uD83D\\uDC81\\uD83C\\uDFFF|\\uD83D\\uDC81\\uD83C\\uDFFE|\\uD83D\\uDC81\\uD83C\\uDFFD|\\uD83D\\uDC81\\uD83C\\uDFFC|\\uD83D\\uDC81\\uD83C\\uDFFB|\\uD83D\\uDC7C\\uD83C\\uDFFF|\\uD83D\\uDC7C\\uD83C\\uDFFE|\\uD83D\\uDC7C\\uD83C\\uDFFD|\\uD83D\\uDC7C\\uD83C\\uDFFC|\\uD83D\\uDC7C\\uD83C\\uDFFB|\\uD83D\\uDC78\\uD83C\\uDFFF|\\uD83D\\uDC78\\uD83C\\uDFFE|\\uD83D\\uDC78\\uD83C\\uDFFD|\\uD83D\\uDC78\\uD83C\\uDFFC|\\uD83D\\uDC78\\uD83C\\uDFFB|\\uD83D\\uDC77\\uD83C\\uDFFF|\\uD83D\\uDC77\\uD83C\\uDFFE|\\uD83D\\uDC77\\uD83C\\uDFFD|\\uD83D\\uDC77\\uD83C\\uDFFC|\\uD83D\\uDC77\\uD83C\\uDFFB|\\uD83D\\uDC76\\uD83C\\uDFFF|\\uD83D\\uDC76\\uD83C\\uDFFE|\\uD83D\\uDC76\\uD83C\\uDFFD|\\uD83D\\uDC76\\uD83C\\uDFFC|\\uD83D\\uDC76\\uD83C\\uDFFB|\\uD83D\\uDC75\\uD83C\\uDFFF|\\uD83D\\uDC75\\uD83C\\uDFFE|\\uD83D\\uDC75\\uD83C\\uDFFD|\\uD83D\\uDC75\\uD83C\\uDFFC|\\uD83D\\uDC75\\uD83C\\uDFFB|\\uD83D\\uDC74\\uD83C\\uDFFF|\\uD83D\\uDC74\\uD83C\\uDFFE|\\uD83D\\uDC74\\uD83C\\uDFFD|\\uD83D\\uDC74\\uD83C\\uDFFC|\\uD83D\\uDC74\\uD83C\\uDFFB|\\uD83D\\uDC73\\uD83C\\uDFFF|\\uD83D\\uDC73\\uD83C\\uDFFE|\\uD83D\\uDC73\\uD83C\\uDFFD|\\uD83D\\uDC73\\uD83C\\uDFFC|\\uD83D\\uDC73\\uD83C\\uDFFB|\\uD83D\\uDC72\\uD83C\\uDFFF|\\uD83D\\uDC72\\uD83C\\uDFFE|\\uD83D\\uDC72\\uD83C\\uDFFD|\\uD83D\\uDC72\\uD83C\\uDFFC|\\uD83D\\uDC72\\uD83C\\uDFFB|\\uD83D\\uDC71\\uD83C\\uDFFF|\\uD83D\\uDC71\\uD83C\\uDFFE|\\uD83D\\uDC71\\uD83C\\uDFFD|\\uD83D\\uDC71\\uD83C\\uDFFC|\\uD83D\\uDC71\\uD83C\\uDFFB|\\uD83D\\uDC70\\uD83C\\uDFFF|\\uD83D\\uDC70\\uD83C\\uDFFE|\\uD83D\\uDC70\\uD83C\\uDFFD|\\uD83D\\uDC70\\uD83C\\uDFFC|\\uD83D\\uDC70\\uD83C\\uDFFB|\\uD83D\\uDC6E\\uD83C\\uDFFF|\\uD83D\\uDC6E\\uD83C\\uDFFE|\\uD83D\\uDC6E\\uD83C\\uDFFD|\\uD83D\\uDC6E\\uD83C\\uDFFC|\\uD83D\\uDC6E\\uD83C\\uDFFB|\\uD83D\\uDC69\\uD83C\\uDFFF|\\uD83D\\uDC69\\uD83C\\uDFFE|\\uD83D\\uDC69\\uD83C\\uDFFD|\\uD83D\\uDC69\\uD83C\\uDFFC|\\uD83D\\uDC69\\uD83C\\uDFFB|\\uD83D\\uDC68\\uD83C\\uDFFF|\\uD83D\\uDC68\\uD83C\\uDFFE|\\uD83D\\uDC68\\uD83C\\uDFFD|\\uD83D\\uDC68\\uD83C\\uDFFC|\\uD83D\\uDC68\\uD83C\\uDFFB|\\uD83D\\uDC67\\uD83C\\uDFFF|\\uD83D\\uDC67\\uD83C\\uDFFE|\\uD83D\\uDC67\\uD83C\\uDFFD|\\uD83D\\uDC67\\uD83C\\uDFFC|\\uD83D\\uDC67\\uD83C\\uDFFB|\\uD83D\\uDC66\\uD83C\\uDFFF|\\uD83D\\uDC66\\uD83C\\uDFFE|\\uD83D\\uDC66\\uD83C\\uDFFD|\\uD83D\\uDC66\\uD83C\\uDFFC|\\uD83D\\uDC66\\uD83C\\uDFFB|\\uD83D\\uDC50\\uD83C\\uDFFF|\\uD83D\\uDC50\\uD83C\\uDFFE|\\uD83D\\uDC50\\uD83C\\uDFFD|\\uD83D\\uDC50\\uD83C\\uDFFC|\\uD83D\\uDC50\\uD83C\\uDFFB|\\uD83D\\uDC4F\\uD83C\\uDFFF|\\uD83D\\uDC4F\\uD83C\\uDFFE|\\uD83D\\uDC4F\\uD83C\\uDFFD|\\uD83D\\uDC4F\\uD83C\\uDFFC|\\uD83D\\uDC4F\\uD83C\\uDFFB|\\uD83D\\uDC4E\\uD83C\\uDFFF|\\uD83D\\uDC4E\\uD83C\\uDFFE|\\uD83D\\uDC4E\\uD83C\\uDFFD|\\uD83D\\uDC4E\\uD83C\\uDFFC|\\uD83D\\uDC4E\\uD83C\\uDFFB|\\uD83D\\uDC4D\\uD83C\\uDFFF|\\uD83D\\uDC4D\\uD83C\\uDFFE|\\uD83D\\uDC4D\\uD83C\\uDFFD|\\uD83D\\uDC4D\\uD83C\\uDFFC|\\uD83D\\uDC4D\\uD83C\\uDFFB|\\uD83D\\uDC4C\\uD83C\\uDFFF|\\uD83D\\uDC4C\\uD83C\\uDFFE|\\uD83D\\uDC4C\\uD83C\\uDFFD|\\uD83D\\uDC4C\\uD83C\\uDFFC|\\uD83D\\uDC4C\\uD83C\\uDFFB|\\uD83D\\uDC4B\\uD83C\\uDFFF|\\uD83D\\uDC4B\\uD83C\\uDFFE|\\uD83D\\uDC4B\\uD83C\\uDFFD|\\uD83D\\uDC4B\\uD83C\\uDFFC|\\uD83D\\uDC4B\\uD83C\\uDFFB|\\uD83D\\uDC4A\\uD83C\\uDFFF|\\uD83D\\uDC4A\\uD83C\\uDFFE|\\uD83D\\uDC4A\\uD83C\\uDFFD|\\uD83D\\uDC4A\\uD83C\\uDFFC|\\uD83D\\uDC4A\\uD83C\\uDFFB|\\uD83D\\uDC49\\uD83C\\uDFFF|\\uD83D\\uDC49\\uD83C\\uDFFE|\\uD83D\\uDC49\\uD83C\\uDFFD|\\uD83D\\uDC49\\uD83C\\uDFFC|\\uD83D\\uDC49\\uD83C\\uDFFB|\\uD83D\\uDC48\\uD83C\\uDFFF|\\uD83D\\uDC48\\uD83C\\uDFFE|\\uD83D\\uDC48\\uD83C\\uDFFD|\\uD83D\\uDC48\\uD83C\\uDFFC|\\uD83D\\uDC48\\uD83C\\uDFFB|\\uD83D\\uDC47\\uD83C\\uDFFF|\\uD83D\\uDC47\\uD83C\\uDFFE|\\uD83D\\uDC47\\uD83C\\uDFFD|\\uD83D\\uDC47\\uD83C\\uDFFC|\\uD83D\\uDC47\\uD83C\\uDFFB|\\uD83D\\uDC46\\uD83C\\uDFFF|\\uD83D\\uDC46\\uD83C\\uDFFE|\\uD83D\\uDC46\\uD83C\\uDFFD|\\uD83D\\uDC46\\uD83C\\uDFFC|\\uD83D\\uDC46\\uD83C\\uDFFB|\\uD83D\\uDC43\\uD83C\\uDFFF|\\uD83D\\uDC43\\uD83C\\uDFFE|\\uD83D\\uDC43\\uD83C\\uDFFD|\\uD83D\\uDC43\\uD83C\\uDFFC|\\uD83D\\uDC43\\uD83C\\uDFFB|\\uD83D\\uDC42\\uD83C\\uDFFF|\\uD83D\\uDC42\\uD83C\\uDFFE|\\uD83D\\uDC42\\uD83C\\uDFFD|\\uD83D\\uDC42\\uD83C\\uDFFC|\\uD83D\\uDC42\\uD83C\\uDFFB|\\uD83C\\uDFCB\\uD83C\\uDFFF|\\uD83C\\uDFCB\\uD83C\\uDFFE|\\uD83C\\uDFCB\\uD83C\\uDFFD|\\uD83C\\uDFCB\\uD83C\\uDFFC|\\uD83C\\uDFCB\\uD83C\\uDFFB|\\uD83C\\uDFCA\\uD83C\\uDFFF|\\uD83C\\uDFCA\\uD83C\\uDFFE|\\uD83C\\uDFCA\\uD83C\\uDFFD|\\uD83C\\uDFCA\\uD83C\\uDFFC|\\uD83C\\uDFCA\\uD83C\\uDFFB|\\uD83C\\uDFC7\\uD83C\\uDFFF|\\uD83C\\uDFC7\\uD83C\\uDFFE|\\uD83C\\uDFC7\\uD83C\\uDFFD|\\uD83C\\uDFC7\\uD83C\\uDFFC|\\uD83C\\uDFC7\\uD83C\\uDFFB|\\uD83C\\uDFC4\\uD83C\\uDFFF|\\uD83C\\uDFC4\\uD83C\\uDFFE|\\uD83C\\uDFC4\\uD83C\\uDFFD|\\uD83C\\uDFC4\\uD83C\\uDFFC|\\uD83C\\uDFC4\\uD83C\\uDFFB|\\uD83C\\uDFC3\\uD83C\\uDFFF|\\uD83C\\uDFC3\\uD83C\\uDFFE|\\uD83C\\uDFC3\\uD83C\\uDFFD|\\uD83C\\uDFC3\\uD83C\\uDFFC|\\uD83C\\uDFC3\\uD83C\\uDFFB|\\uD83C\\uDF85\\uD83C\\uDFFF|\\uD83C\\uDF85\\uD83C\\uDFFE|\\uD83C\\uDF85\\uD83C\\uDFFD|\\uD83C\\uDF85\\uD83C\\uDFFC|\\uD83C\\uDF85\\uD83C\\uDFFB|\\uD83C\\uDDFF\\uD83C\\uDDFC|\\uD83C\\uDDFF\\uD83C\\uDDF2|\\uD83C\\uDDFF\\uD83C\\uDDE6|\\uD83C\\uDDFE\\uD83C\\uDDF9|\\uD83C\\uDDFE\\uD83C\\uDDEA|\\uD83C\\uDDFD\\uD83C\\uDDF0|\\uD83C\\uDDFC\\uD83C\\uDDF8|\\uD83C\\uDDFC\\uD83C\\uDDEB|\\uD83C\\uDDFB\\uD83C\\uDDFA|\\uD83C\\uDDFB\\uD83C\\uDDF3|\\uD83C\\uDDFB\\uD83C\\uDDEE|\\uD83C\\uDDFB\\uD83C\\uDDEC|\\uD83C\\uDDFB\\uD83C\\uDDEA|\\uD83C\\uDDFB\\uD83C\\uDDE8|\\uD83C\\uDDFB\\uD83C\\uDDE6|\\uD83C\\uDDFA\\uD83C\\uDDFF|\\uD83C\\uDDFA\\uD83C\\uDDFE|\\uD83C\\uDDFA\\uD83C\\uDDF8|\\uD83C\\uDDFA\\uD83C\\uDDF2|\\uD83C\\uDDFA\\uD83C\\uDDEC|\\uD83C\\uDDFA\\uD83C\\uDDE6|\\uD83C\\uDDF9\\uD83C\\uDDFF|\\uD83C\\uDDF9\\uD83C\\uDDFC|\\uD83C\\uDDF9\\uD83C\\uDDFB|\\uD83C\\uDDF9\\uD83C\\uDDF9|\\uD83C\\uDDF9\\uD83C\\uDDF7|\\uD83C\\uDDF9\\uD83C\\uDDF4|\\uD83C\\uDDF9\\uD83C\\uDDF3|\\uD83C\\uDDF9\\uD83C\\uDDF2|\\uD83C\\uDDF9\\uD83C\\uDDF1|\\uD83C\\uDDF9\\uD83C\\uDDF0|\\uD83C\\uDDF9\\uD83C\\uDDEF|\\uD83C\\uDDF9\\uD83C\\uDDED|\\uD83C\\uDDF9\\uD83C\\uDDEC|\\uD83C\\uDDF9\\uD83C\\uDDEB|\\uD83C\\uDDE6\\uD83C\\uDDE8|\\uD83C\\uDDF9\\uD83C\\uDDE8|\\uD83C\\uDDF9\\uD83C\\uDDE6|\\uD83C\\uDDF8\\uD83C\\uDDFF|\\uD83C\\uDDF8\\uD83C\\uDDFE|\\uD83C\\uDDF8\\uD83C\\uDDFD|\\uD83C\\uDDF8\\uD83C\\uDDFB|\\uD83C\\uDDF8\\uD83C\\uDDF9|\\uD83C\\uDDF8\\uD83C\\uDDF8|\\uD83C\\uDDF8\\uD83C\\uDDF7|\\uD83C\\uDDF8\\uD83C\\uDDF4|\\uD83C\\uDDF8\\uD83C\\uDDF3|\\uD83C\\uDDF8\\uD83C\\uDDF2|\\uD83C\\uDDF8\\uD83C\\uDDF1|\\uD83C\\uDDF8\\uD83C\\uDDF0|\\uD83C\\uDDF8\\uD83C\\uDDEF|\\uD83C\\uDDF8\\uD83C\\uDDEE|\\uD83C\\uDDF8\\uD83C\\uDDED|\\uD83C\\uDDF8\\uD83C\\uDDEC|\\uD83C\\uDDF8\\uD83C\\uDDEA|\\uD83C\\uDDF8\\uD83C\\uDDE9|\\uD83C\\uDDF8\\uD83C\\uDDE8|\\uD83C\\uDDF8\\uD83C\\uDDE7|\\uD83C\\uDDF8\\uD83C\\uDDE6|\\uD83C\\uDDF7\\uD83C\\uDDFC|\\uD83C\\uDDF7\\uD83C\\uDDFA|\\uD83C\\uDDF7\\uD83C\\uDDF8|\\uD83C\\uDDF7\\uD83C\\uDDF4|\\uD83C\\uDDF7\\uD83C\\uDDEA|\\uD83C\\uDDF6\\uD83C\\uDDE6|\\uD83C\\uDDF5\\uD83C\\uDDFE|\\uD83C\\uDDF5\\uD83C\\uDDFC|\\uD83C\\uDDF5\\uD83C\\uDDF9|\\uD83C\\uDDF5\\uD83C\\uDDF8|\\uD83C\\uDDF5\\uD83C\\uDDF7|\\uD83C\\uDDF5\\uD83C\\uDDF3|\\uD83C\\uDDF5\\uD83C\\uDDF2|\\uD83C\\uDDF5\\uD83C\\uDDF1|\\uD83C\\uDDF5\\uD83C\\uDDF0|\\uD83C\\uDDF5\\uD83C\\uDDED|\\uD83C\\uDDF5\\uD83C\\uDDEC|\\uD83C\\uDDF5\\uD83C\\uDDEB|\\uD83C\\uDDF5\\uD83C\\uDDEA|\\uD83C\\uDDF5\\uD83C\\uDDE6|\\uD83C\\uDDF4\\uD83C\\uDDF2|\\uD83C\\uDDF3\\uD83C\\uDDFF|\\uD83C\\uDDF3\\uD83C\\uDDFA|\\uD83C\\uDDF3\\uD83C\\uDDF7|\\uD83C\\uDDF3\\uD83C\\uDDF5|\\uD83C\\uDDF3\\uD83C\\uDDF4|\\uD83C\\uDDF3\\uD83C\\uDDF1|\\uD83C\\uDDF3\\uD83C\\uDDEE|\\uD83C\\uDDF3\\uD83C\\uDDEC|\\uD83C\\uDDF3\\uD83C\\uDDEB|\\uD83C\\uDDF3\\uD83C\\uDDEA|\\uD83C\\uDDF3\\uD83C\\uDDE8|\\uD83C\\uDDF3\\uD83C\\uDDE6|\\uD83C\\uDDF2\\uD83C\\uDDFF|\\uD83C\\uDDF2\\uD83C\\uDDFE|\\uD83C\\uDDF2\\uD83C\\uDDFD|\\uD83C\\uDDF2\\uD83C\\uDDFC|\\uD83C\\uDDF2\\uD83C\\uDDFB|\\uD83C\\uDDF2\\uD83C\\uDDFA|\\uD83C\\uDDF2\\uD83C\\uDDF9|\\uD83C\\uDDF2\\uD83C\\uDDF8|\\uD83C\\uDDF2\\uD83C\\uDDF7|\\uD83C\\uDDF2\\uD83C\\uDDF6|\\uD83C\\uDDF2\\uD83C\\uDDF5|\\uD83C\\uDDF2\\uD83C\\uDDF4|\\uD83C\\uDDF2\\uD83C\\uDDF3|\\uD83C\\uDDF2\\uD83C\\uDDF2|\\uD83C\\uDDF2\\uD83C\\uDDF1|\\uD83C\\uDDF2\\uD83C\\uDDF0|\\uD83C\\uDDF2\\uD83C\\uDDED|\\uD83C\\uDDF2\\uD83C\\uDDEC|\\uD83C\\uDDF2\\uD83C\\uDDEB|\\uD83C\\uDDF2\\uD83C\\uDDEA|\\uD83C\\uDDF2\\uD83C\\uDDE9|\\uD83C\\uDDF2\\uD83C\\uDDE8|\\uD83C\\uDDF2\\uD83C\\uDDE6|\\uD83C\\uDDF1\\uD83C\\uDDFE|\\uD83C\\uDDF1\\uD83C\\uDDFB|\\uD83C\\uDDF1\\uD83C\\uDDFA|\\uD83C\\uDDF1\\uD83C\\uDDF9|\\uD83C\\uDDF1\\uD83C\\uDDF8|\\uD83C\\uDDF1\\uD83C\\uDDF7|\\uD83C\\uDDF1\\uD83C\\uDDF0|\\uD83C\\uDDF1\\uD83C\\uDDEE|\\uD83C\\uDDF1\\uD83C\\uDDE8|\\uD83C\\uDDF1\\uD83C\\uDDE7|\\uD83C\\uDDF1\\uD83C\\uDDE6|\\uD83C\\uDDF0\\uD83C\\uDDFF|\\uD83C\\uDDF0\\uD83C\\uDDFE|\\uD83C\\uDDF0\\uD83C\\uDDFC|\\uD83C\\uDDF0\\uD83C\\uDDF7|\\uD83C\\uDDF0\\uD83C\\uDDF5|\\uD83C\\uDDF0\\uD83C\\uDDF3|\\uD83C\\uDDF0\\uD83C\\uDDF2|\\uD83C\\uDDF0\\uD83C\\uDDEE|\\uD83C\\uDDF0\\uD83C\\uDDED|\\uD83C\\uDDF0\\uD83C\\uDDEC|\\uD83C\\uDDF0\\uD83C\\uDDEA|\\uD83C\\uDDEF\\uD83C\\uDDF5|\\uD83C\\uDDEF\\uD83C\\uDDF4|\\uD83C\\uDDEF\\uD83C\\uDDF2|\\uD83C\\uDDEF\\uD83C\\uDDEA|\\uD83C\\uDDEE\\uD83C\\uDDF9|\\uD83C\\uDDEE\\uD83C\\uDDF8|\\uD83C\\uDDEE\\uD83C\\uDDF7|\\uD83C\\uDDEE\\uD83C\\uDDF6|\\uD83C\\uDDEE\\uD83C\\uDDF4|\\uD83C\\uDDEE\\uD83C\\uDDF3|\\uD83C\\uDDEE\\uD83C\\uDDF2|\\uD83C\\uDDEE\\uD83C\\uDDF1|\\uD83C\\uDDEE\\uD83C\\uDDEA|\\uD83C\\uDDEE\\uD83C\\uDDE9|\\uD83C\\uDDEE\\uD83C\\uDDE8|\\uD83C\\uDDED\\uD83C\\uDDFA|\\uD83C\\uDDED\\uD83C\\uDDF9|\\uD83C\\uDDED\\uD83C\\uDDF7|\\uD83C\\uDDED\\uD83C\\uDDF3|\\uD83C\\uDDED\\uD83C\\uDDF2|\\uD83C\\uDDED\\uD83C\\uDDF0|\\uD83C\\uDDEC\\uD83C\\uDDFE|\\uD83C\\uDDEC\\uD83C\\uDDFC|\\uD83C\\uDDEC\\uD83C\\uDDFA|\\uD83C\\uDDEC\\uD83C\\uDDF9|\\uD83C\\uDDEC\\uD83C\\uDDF8|\\uD83C\\uDDEC\\uD83C\\uDDF7|\\uD83C\\uDDEC\\uD83C\\uDDF6|\\uD83C\\uDDEC\\uD83C\\uDDF5|\\uD83C\\uDDEC\\uD83C\\uDDF3|\\uD83C\\uDDEC\\uD83C\\uDDF2|\\uD83C\\uDDEC\\uD83C\\uDDF1|\\uD83C\\uDDEC\\uD83C\\uDDEE|\\uD83C\\uDDEC\\uD83C\\uDDED|\\uD83C\\uDDEC\\uD83C\\uDDEC|\\uD83C\\uDDEC\\uD83C\\uDDEB|\\uD83C\\uDDEC\\uD83C\\uDDEA|\\uD83C\\uDDEC\\uD83C\\uDDE9|\\uD83C\\uDDEC\\uD83C\\uDDE7|\\uD83C\\uDDEC\\uD83C\\uDDE6|\\uD83C\\uDDEB\\uD83C\\uDDF7|\\uD83C\\uDDEB\\uD83C\\uDDF4|\\uD83C\\uDDEB\\uD83C\\uDDF2|\\uD83C\\uDDEB\\uD83C\\uDDF0|\\uD83C\\uDDEB\\uD83C\\uDDEF|\\uD83C\\uDDEB\\uD83C\\uDDEE|\\uD83C\\uDDEA\\uD83C\\uDDFA|\\uD83C\\uDDEA\\uD83C\\uDDF9|\\uD83C\\uDDEA\\uD83C\\uDDF8|\\uD83C\\uDDEA\\uD83C\\uDDF7|\\uD83C\\uDDEA\\uD83C\\uDDED|\\uD83C\\uDDEA\\uD83C\\uDDEC|\\uD83C\\uDDEA\\uD83C\\uDDEA|\\uD83C\\uDDEA\\uD83C\\uDDE8|\\uD83C\\uDDEA\\uD83C\\uDDE6|\\uD83C\\uDDE9\\uD83C\\uDDFF|\\uD83C\\uDDE9\\uD83C\\uDDF4|\\uD83C\\uDDE9\\uD83C\\uDDF2|\\uD83C\\uDDE9\\uD83C\\uDDF0|\\uD83C\\uDDE9\\uD83C\\uDDEF|\\uD83C\\uDDE9\\uD83C\\uDDEC|\\uD83C\\uDDE9\\uD83C\\uDDEA|\\uD83C\\uDDE8\\uD83C\\uDDFF|\\uD83C\\uDDE8\\uD83C\\uDDFE|\\uD83C\\uDDE8\\uD83C\\uDDFD|\\uD83C\\uDDE8\\uD83C\\uDDFC|\\uD83C\\uDDE8\\uD83C\\uDDFB|\\uD83C\\uDDE8\\uD83C\\uDDFA|\\uD83C\\uDDE8\\uD83C\\uDDF7|\\uD83C\\uDDE8\\uD83C\\uDDF5|\\uD83C\\uDDE8\\uD83C\\uDDF4|\\uD83C\\uDDE8\\uD83C\\uDDF3|\\uD83C\\uDDE8\\uD83C\\uDDF2|\\uD83C\\uDDE8\\uD83C\\uDDF1|\\uD83C\\uDDE8\\uD83C\\uDDF0|\\uD83C\\uDDE8\\uD83C\\uDDEE|\\uD83C\\uDDE8\\uD83C\\uDDED|\\uD83C\\uDDE8\\uD83C\\uDDEC|\\uD83C\\uDDE8\\uD83C\\uDDEB|\\uD83C\\uDDE8\\uD83C\\uDDE9|\\uD83C\\uDDE8\\uD83C\\uDDE8|\\uD83C\\uDDE8\\uD83C\\uDDE6|\\uD83C\\uDDE7\\uD83C\\uDDFF|\\uD83C\\uDDE7\\uD83C\\uDDFE|\\uD83C\\uDDE7\\uD83C\\uDDFC|\\uD83C\\uDDE7\\uD83C\\uDDFB|\\uD83C\\uDDE7\\uD83C\\uDDF9|\\uD83C\\uDDE7\\uD83C\\uDDF8|\\uD83C\\uDDE7\\uD83C\\uDDF7|\\uD83C\\uDDE7\\uD83C\\uDDF6|\\uD83C\\uDDE7\\uD83C\\uDDF4|\\uD83C\\uDDE7\\uD83C\\uDDF3|\\uD83C\\uDDE7\\uD83C\\uDDF2|\\uD83C\\uDDE7\\uD83C\\uDDF1|\\uD83C\\uDDE7\\uD83C\\uDDEF|\\uD83C\\uDDE7\\uD83C\\uDDEE|\\uD83C\\uDDE7\\uD83C\\uDDED|\\uD83C\\uDDE7\\uD83C\\uDDEC|\\uD83C\\uDDE7\\uD83C\\uDDEB|\\uD83C\\uDDE7\\uD83C\\uDDEA|\\uD83C\\uDDE7\\uD83C\\uDDE9|\\uD83C\\uDDE7\\uD83C\\uDDE7|\\uD83C\\uDDE7\\uD83C\\uDDE6|\\uD83C\\uDDE6\\uD83C\\uDDFF|\\uD83C\\uDDE6\\uD83C\\uDDFD|\\uD83C\\uDDE6\\uD83C\\uDDFC|\\uD83C\\uDDE6\\uD83C\\uDDFA|\\uD83C\\uDDE6\\uD83C\\uDDF9|\\uD83C\\uDDF9\\uD83C\\uDDE9|\\uD83D\\uDDE1\\uFE0F|\\u26F9\\uD83C\\uDFFF|\\u26F9\\uD83C\\uDFFE|\\u26F9\\uD83C\\uDFFD|\\u26F9\\uD83C\\uDFFC|\\u26F9\\uD83C\\uDFFB|\\u270D\\uD83C\\uDFFF|\\u270D\\uD83C\\uDFFE|\\u270D\\uD83C\\uDFFD|\\u270D\\uD83C\\uDFFC|\\u270D\\uD83C\\uDFFB|\\uD83C\\uDC04\\uFE0F|\\uD83C\\uDD7F\\uFE0F|\\uD83C\\uDE02\\uFE0F|\\uD83C\\uDE1A\\uFE0F|\\uD83C\\uDE2F\\uFE0F|\\uD83C\\uDE37\\uFE0F|\\uD83C\\uDF9E\\uFE0F|\\uD83C\\uDF9F\\uFE0F|\\uD83C\\uDFCB\\uFE0F|\\uD83C\\uDFCC\\uFE0F|\\uD83C\\uDFCD\\uFE0F|\\uD83C\\uDFCE\\uFE0F|\\uD83C\\uDF96\\uFE0F|\\uD83C\\uDF97\\uFE0F|\\uD83C\\uDF36\\uFE0F|\\uD83C\\uDF27\\uFE0F|\\uD83C\\uDF28\\uFE0F|\\uD83C\\uDF29\\uFE0F|\\uD83C\\uDF2A\\uFE0F|\\uD83C\\uDF2B\\uFE0F|\\uD83C\\uDF2C\\uFE0F|\\uD83D\\uDC3F\\uFE0F|\\uD83D\\uDD77\\uFE0F|\\uD83D\\uDD78\\uFE0F|\\uD83C\\uDF21\\uFE0F|\\uD83C\\uDF99\\uFE0F|\\uD83C\\uDF9A\\uFE0F|\\uD83C\\uDF9B\\uFE0F|\\uD83C\\uDFF3\\uFE0F|\\uD83C\\uDFF5\\uFE0F|\\uD83C\\uDFF7\\uFE0F|\\uD83D\\uDCFD\\uFE0F|\\uD83D\\uDD49\\uFE0F|\\uD83D\\uDD4A\\uFE0F|\\uD83D\\uDD6F\\uFE0F|\\uD83D\\uDD70\\uFE0F|\\uD83D\\uDD73\\uFE0F|\\uD83D\\uDD76\\uFE0F|\\uD83D\\uDD79\\uFE0F|\\uD83D\\uDD87\\uFE0F|\\uD83D\\uDD8A\\uFE0F|\\uD83D\\uDD8B\\uFE0F|\\uD83D\\uDD8C\\uFE0F|\\uD83D\\uDD8D\\uFE0F|\\uD83D\\uDDA5\\uFE0F|\\uD83D\\uDDA8\\uFE0F|\\uD83D\\uDDB2\\uFE0F|\\uD83D\\uDDBC\\uFE0F|\\uD83D\\uDDC2\\uFE0F|\\uD83D\\uDDC3\\uFE0F|\\uD83D\\uDDC4\\uFE0F|\\uD83D\\uDDD1\\uFE0F|\\uD83D\\uDDD2\\uFE0F|\\uD83D\\uDDD3\\uFE0F|\\uD83D\\uDDDC\\uFE0F|\\uD83D\\uDDDD\\uFE0F|\\uD83D\\uDDDE\\uFE0F|\\u270B\\uD83C\\uDFFF|\\uD83D\\uDDE3\\uFE0F|\\uD83D\\uDDEF\\uFE0F|\\uD83D\\uDDF3\\uFE0F|\\uD83D\\uDDFA\\uFE0F|\\uD83D\\uDEE0\\uFE0F|\\uD83D\\uDEE1\\uFE0F|\\uD83D\\uDEE2\\uFE0F|\\uD83D\\uDEF0\\uFE0F|\\uD83C\\uDF7D\\uFE0F|\\uD83D\\uDC41\\uFE0F|\\uD83D\\uDD74\\uFE0F|\\uD83D\\uDD75\\uFE0F|\\uD83D\\uDD90\\uFE0F|\\uD83C\\uDFD4\\uFE0F|\\uD83C\\uDFD5\\uFE0F|\\uD83C\\uDFD6\\uFE0F|\\uD83C\\uDFD7\\uFE0F|\\uD83C\\uDFD8\\uFE0F|\\uD83C\\uDFD9\\uFE0F|\\uD83C\\uDFDA\\uFE0F|\\uD83C\\uDFDB\\uFE0F|\\uD83C\\uDFDC\\uFE0F|\\uD83C\\uDFDD\\uFE0F|\\uD83C\\uDFDE\\uFE0F|\\uD83C\\uDFDF\\uFE0F|\\uD83D\\uDECB\\uFE0F|\\uD83D\\uDECD\\uFE0F|\\uD83D\\uDECE\\uFE0F|\\uD83D\\uDECF\\uFE0F|\\uD83D\\uDEE3\\uFE0F|\\uD83D\\uDEE4\\uFE0F|\\uD83D\\uDEE5\\uFE0F|\\uD83D\\uDEE9\\uFE0F|\\uD83D\\uDEF3\\uFE0F|\\uD83C\\uDF24\\uFE0F|\\uD83C\\uDF25\\uFE0F|\\uD83C\\uDF26\\uFE0F|\\uD83D\\uDDB1\\uFE0F|\\u261D\\uD83C\\uDFFB|\\u261D\\uD83C\\uDFFC|\\u261D\\uD83C\\uDFFD|\\u261D\\uD83C\\uDFFE|\\u261D\\uD83C\\uDFFF|\\u270C\\uD83C\\uDFFB|\\u270C\\uD83C\\uDFFC|\\u270C\\uD83C\\uDFFD|\\u270C\\uD83C\\uDFFE|\\u270C\\uD83C\\uDFFF|\\u270A\\uD83C\\uDFFB|\\u270A\\uD83C\\uDFFC|\\u270A\\uD83C\\uDFFD|\\u270A\\uD83C\\uDFFE|\\u270A\\uD83C\\uDFFF|\\u270B\\uD83C\\uDFFB|\\u270B\\uD83C\\uDFFC|\\u270B\\uD83C\\uDFFD|\\u270B\\uD83C\\uDFFE|4\\uFE0F\\u20E3|9\\uFE0F\\u20E3|0\\uFE0F\\u20E3|1\\uFE0F\\u20E3|2\\uFE0F\\u20E3|3\\uFE0F\\u20E3|#\\uFE0F\\u20E3|5\\uFE0F\\u20E3|6\\uFE0F\\u20E3|7\\uFE0F\\u20E3|8\\uFE0F\\u20E3|\\*\\uFE0F\\u20E3|\\u00A9\\uFE0F|\\u00AE\\uFE0F|\\u203C\\uFE0F|\\u2049\\uFE0F|\\u2122\\uFE0F|\\u2139\\uFE0F|\\u2194\\uFE0F|\\u2195\\uFE0F|\\u2196\\uFE0F|\\u2197\\uFE0F|\\u2198\\uFE0F|\\u2199\\uFE0F|\\u21A9\\uFE0F|\\u21AA\\uFE0F|\\u231A\\uFE0F|\\u231B\\uFE0F|\\u24C2\\uFE0F|\\u25AA\\uFE0F|\\u25AB\\uFE0F|\\u25B6\\uFE0F|\\u25C0\\uFE0F|\\u25FB\\uFE0F|\\u25FC\\uFE0F|\\u25FD\\uFE0F|\\u25FE\\uFE0F|\\u2600\\uFE0F|\\u2601\\uFE0F|\\u260E\\uFE0F|\\u2611\\uFE0F|\\u2614\\uFE0F|\\u2615\\uFE0F|\\u261D\\uFE0F|\\u263A\\uFE0F|\\u2648\\uFE0F|\\u2649\\uFE0F|\\u264A\\uFE0F|\\u264B\\uFE0F|\\u264C\\uFE0F|\\u264D\\uFE0F|\\u264E\\uFE0F|\\u264F\\uFE0F|\\u2650\\uFE0F|\\u2651\\uFE0F|\\u2652\\uFE0F|\\u2653\\uFE0F|\\u2660\\uFE0F|\\u2663\\uFE0F|\\u2665\\uFE0F|\\u2666\\uFE0F|\\u2668\\uFE0F|\\u267B\\uFE0F|\\u267F\\uFE0F|\\u2693\\uFE0F|\\u26A0\\uFE0F|\\u26A1\\uFE0F|\\u26AA\\uFE0F|\\u26AB\\uFE0F|\\u26BD\\uFE0F|\\u26BE\\uFE0F|\\u26C4\\uFE0F|\\u26C5\\uFE0F|\\u26D4\\uFE0F|\\u26EA\\uFE0F|\\u26F2\\uFE0F|\\u26F3\\uFE0F|\\u26F5\\uFE0F|\\u26FA\\uFE0F|\\u26FD\\uFE0F|\\u2702\\uFE0F|\\u2708\\uFE0F|\\u2709\\uFE0F|\\u270C\\uFE0F|\\u270F\\uFE0F|\\u2712\\uFE0F|\\u2714\\uFE0F|\\u2716\\uFE0F|\\u2733\\uFE0F|\\u2734\\uFE0F|\\u2744\\uFE0F|\\u2747\\uFE0F|\\u2757\\uFE0F|\\u2764\\uFE0F|\\u27A1\\uFE0F|\\u2934\\uFE0F|\\u2935\\uFE0F|\\u2B05\\uFE0F|\\u2B06\\uFE0F|\\u2B07\\uFE0F|\\u2B1B\\uFE0F|\\u2B1C\\uFE0F|\\u2B50\\uFE0F|\\u2B55\\uFE0F|\\u3030\\uFE0F|\\u303D\\uFE0F|\\u3297\\uFE0F|\\u3299\\uFE0F|\\u271D\\uFE0F|\\u2328\\uFE0F|\\u270D\\uFE0F|\\u23ED\\uFE0F|\\u23EE\\uFE0F|\\u23EF\\uFE0F|\\u23F1\\uFE0F|\\u23F2\\uFE0F|\\u23F8\\uFE0F|\\u23F9\\uFE0F|\\u23FA\\uFE0F|\\u2602\\uFE0F|\\u2603\\uFE0F|\\u2604\\uFE0F|\\u2618\\uFE0F|\\u2620\\uFE0F|\\u2622\\uFE0F|\\u2623\\uFE0F|\\u2626\\uFE0F|\\u262A\\uFE0F|\\u262E\\uFE0F|\\u262F\\uFE0F|\\u2638\\uFE0F|\\u2639\\uFE0F|\\u2692\\uFE0F|\\u2694\\uFE0F|\\u2696\\uFE0F|\\u2697\\uFE0F|\\u2699\\uFE0F|\\u269B\\uFE0F|\\u269C\\uFE0F|\\u26B0\\uFE0F|\\u26B1\\uFE0F|\\u26C8\\uFE0F|\\u26CF\\uFE0F|\\u26D1\\uFE0F|\\u26D3\\uFE0F|\\u26E9\\uFE0F|\\u26F0\\uFE0F|\\u26F1\\uFE0F|\\u26F4\\uFE0F|\\u26F7\\uFE0F|\\u26F8\\uFE0F|\\u26F9\\uFE0F|\\u2721\\uFE0F|\\u2763\\uFE0F|\\uD83C\\uDCCF|\\uD83C\\uDD70|\\uD83C\\uDD71|\\uD83C\\uDD7E|\\uD83C\\uDD8E|\\uD83C\\uDD91|\\uD83C\\uDD92|\\uD83C\\uDD93|\\uD83C\\uDD94|\\uD83C\\uDD95|\\uD83C\\uDD96|\\uD83C\\uDD97|\\uD83C\\uDD98|\\uD83C\\uDD99|\\uD83C\\uDD9A|\\uD83C\\uDE01|\\uD83C\\uDE32|\\uD83C\\uDE33|\\uD83C\\uDE34|\\uD83C\\uDE35|\\uD83C\\uDE36|\\uD83C\\uDE38|\\uD83C\\uDE39|\\uD83C\\uDE3A|\\uD83C\\uDE50|\\uD83C\\uDE51|\\uD83C\\uDF00|\\uD83C\\uDF01|\\uD83C\\uDF02|\\uD83C\\uDF03|\\uD83C\\uDF04|\\uD83C\\uDF05|\\uD83C\\uDF06|\\uD83C\\uDF07|\\uD83C\\uDF08|\\uD83C\\uDF09|\\uD83C\\uDF0A|\\uD83C\\uDF0B|\\uD83C\\uDF0C|\\uD83C\\uDF0F|\\uD83C\\uDF11|\\uD83C\\uDF13|\\uD83C\\uDF14|\\uD83C\\uDF15|\\uD83C\\uDF19|\\uD83C\\uDF1B|\\uD83C\\uDF1F|\\uD83C\\uDF20|\\uD83C\\uDF30|\\uD83C\\uDF31|\\uD83C\\uDF34|\\uD83C\\uDF35|\\uD83C\\uDF37|\\uD83C\\uDF38|\\uD83C\\uDF39|\\uD83C\\uDF3A|\\uD83C\\uDF3B|\\uD83C\\uDF3C|\\uD83C\\uDF3D|\\uD83C\\uDF3E|\\uD83C\\uDF3F|\\uD83C\\uDF40|\\uD83C\\uDF41|\\uD83C\\uDF42|\\uD83C\\uDF43|\\uD83C\\uDF44|\\uD83C\\uDF45|\\uD83C\\uDF46|\\uD83C\\uDF47|\\uD83C\\uDF48|\\uD83C\\uDF49|\\uD83C\\uDF4A|\\uD83C\\uDF4C|\\uD83C\\uDF4D|\\uD83C\\uDF4E|\\uD83C\\uDF4F|\\uD83C\\uDF51|\\uD83C\\uDF52|\\uD83C\\uDF53|\\uD83C\\uDF54|\\uD83C\\uDF55|\\uD83C\\uDF56|\\uD83C\\uDF57|\\uD83C\\uDF58|\\uD83C\\uDF59|\\uD83C\\uDF5A|\\uD83C\\uDF5B|\\uD83C\\uDF5C|\\uD83C\\uDF5D|\\uD83C\\uDF5E|\\uD83C\\uDF5F|\\uD83C\\uDF60|\\uD83C\\uDF61|\\uD83C\\uDF62|\\uD83C\\uDF63|\\uD83C\\uDF64|\\uD83C\\uDF65|\\uD83C\\uDF66|\\uD83C\\uDF67|\\uD83C\\uDF68|\\uD83C\\uDF69|\\uD83C\\uDF6A|\\uD83C\\uDF6B|\\uD83C\\uDF6C|\\uD83C\\uDF6D|\\uD83C\\uDF6E|\\uD83C\\uDF6F|\\uD83C\\uDF70|\\uD83C\\uDF71|\\uD83C\\uDF72|\\uD83C\\uDF73|\\uD83C\\uDF74|\\uD83C\\uDF75|\\uD83C\\uDF76|\\uD83C\\uDF77|\\uD83C\\uDF78|\\uD83C\\uDF79|\\uD83C\\uDF7A|\\uD83C\\uDF7B|\\uD83C\\uDF80|\\uD83C\\uDF81|\\uD83C\\uDF82|\\uD83C\\uDF83|\\uD83C\\uDF84|\\uD83C\\uDF85|\\uD83C\\uDF86|\\uD83C\\uDF87|\\uD83C\\uDF88|\\uD83C\\uDF89|\\uD83C\\uDF8A|\\uD83C\\uDF8B|\\uD83C\\uDF8C|\\uD83C\\uDF8D|\\uD83C\\uDF8E|\\uD83C\\uDF8F|\\uD83C\\uDF90|\\uD83C\\uDF91|\\uD83C\\uDF92|\\uD83C\\uDF93|\\uD83C\\uDFA0|\\uD83C\\uDFA1|\\uD83C\\uDFA2|\\uD83C\\uDFA3|\\uD83C\\uDFA4|\\uD83C\\uDFA5|\\uD83C\\uDFA6|\\uD83C\\uDFA7|\\uD83C\\uDFA8|\\uD83C\\uDFA9|\\uD83C\\uDFAA|\\uD83C\\uDFAB|\\uD83C\\uDFAC|\\uD83C\\uDFAD|\\uD83C\\uDFAE|\\uD83C\\uDFAF|\\uD83C\\uDFB0|\\uD83C\\uDFB1|\\uD83C\\uDFB2|\\uD83C\\uDFB3|\\uD83C\\uDFB4|\\uD83C\\uDFB5|\\uD83C\\uDFB6|\\uD83C\\uDFB7|\\uD83C\\uDFB8|\\uD83C\\uDFB9|\\uD83C\\uDFBA|\\uD83C\\uDFBB|\\uD83C\\uDFBC|\\uD83C\\uDFBD|\\uD83C\\uDFBE|\\uD83C\\uDFBF|\\uD83C\\uDFC0|\\uD83C\\uDFC1|\\uD83C\\uDFC2|\\uD83C\\uDFC3|\\uD83C\\uDFC4|\\uD83C\\uDFC6|\\uD83C\\uDFC8|\\uD83C\\uDFCA|\\uD83C\\uDFE0|\\uD83D\\uDDB1|\\uD83C\\uDFE2|\\uD83C\\uDFE3|\\uD83C\\uDFE5|\\uD83C\\uDFE6|\\uD83C\\uDFE7|\\uD83C\\uDFE8|\\uD83C\\uDFE9|\\uD83C\\uDFEA|\\uD83C\\uDFEB|\\uD83C\\uDFEC|\\uD83C\\uDFED|\\uD83C\\uDFEE|\\uD83C\\uDFEF|\\uD83C\\uDFF0|\\uD83D\\uDC0C|\\uD83D\\uDC0D|\\uD83D\\uDC0E|\\uD83D\\uDC11|\\uD83D\\uDC12|\\uD83D\\uDC14|\\uD83D\\uDC17|\\uD83D\\uDC18|\\uD83D\\uDC19|\\uD83D\\uDC1A|\\uD83D\\uDC1B|\\uD83D\\uDC1C|\\uD83D\\uDC1D|\\uD83D\\uDC1E|\\uD83D\\uDC1F|\\uD83D\\uDC20|\\uD83D\\uDC21|\\uD83D\\uDC22|\\uD83D\\uDC23|\\uD83D\\uDC24|\\uD83D\\uDC25|\\uD83D\\uDC26|\\uD83D\\uDC27|\\uD83D\\uDC28|\\uD83D\\uDC29|\\uD83D\\uDC2B|\\uD83D\\uDC2C|\\uD83D\\uDC2D|\\uD83D\\uDC2E|\\uD83D\\uDC2F|\\uD83D\\uDC30|\\uD83D\\uDC31|\\uD83D\\uDC32|\\uD83D\\uDC33|\\uD83D\\uDC34|\\uD83D\\uDC35|\\uD83D\\uDC36|\\uD83D\\uDC37|\\uD83D\\uDC38|\\uD83D\\uDC39|\\uD83D\\uDC3A|\\uD83D\\uDC3B|\\uD83D\\uDC3C|\\uD83D\\uDC3D|\\uD83D\\uDC3E|\\uD83D\\uDC40|\\uD83D\\uDC42|\\uD83D\\uDC43|\\uD83D\\uDC44|\\uD83D\\uDC45|\\uD83D\\uDC46|\\uD83D\\uDC47|\\uD83D\\uDC48|\\uD83D\\uDC49|\\uD83D\\uDC4A|\\uD83D\\uDC4B|\\uD83D\\uDC4C|\\uD83D\\uDC4D|\\uD83D\\uDC4E|\\uD83D\\uDC4F|\\uD83D\\uDC50|\\uD83D\\uDC51|\\uD83D\\uDC52|\\uD83D\\uDC53|\\uD83D\\uDC54|\\uD83D\\uDC55|\\uD83D\\uDC56|\\uD83D\\uDC57|\\uD83D\\uDC58|\\uD83D\\uDC59|\\uD83D\\uDC5A|\\uD83D\\uDC5B|\\uD83D\\uDC5C|\\uD83D\\uDC5D|\\uD83D\\uDC5E|\\uD83D\\uDC5F|\\uD83D\\uDC60|\\uD83D\\uDC61|\\uD83D\\uDC62|\\uD83D\\uDC63|\\uD83D\\uDC64|\\uD83D\\uDC66|\\uD83D\\uDC67|\\uD83D\\uDC68|\\uD83D\\uDC69|\\uD83D\\uDC6A|\\uD83D\\uDC6B|\\uD83D\\uDC6E|\\uD83D\\uDC6F|\\uD83D\\uDC70|\\uD83D\\uDC71|\\uD83D\\uDC72|\\uD83D\\uDC73|\\uD83D\\uDC74|\\uD83D\\uDC75|\\uD83D\\uDC76|\\uD83D\\uDC77|\\uD83D\\uDC78|\\uD83D\\uDC79|\\uD83D\\uDC7A|\\uD83D\\uDC7B|\\uD83D\\uDC7C|\\uD83D\\uDC7D|\\uD83D\\uDC7E|\\uD83D\\uDC7F|\\uD83D\\uDC80|\\uD83D\\uDCC7|\\uD83D\\uDC81|\\uD83D\\uDC82|\\uD83D\\uDC83|\\uD83D\\uDC84|\\uD83D\\uDC85|\\uD83D\\uDCD2|\\uD83D\\uDC86|\\uD83D\\uDCD3|\\uD83D\\uDC87|\\uD83D\\uDCD4|\\uD83D\\uDC88|\\uD83D\\uDCD5|\\uD83D\\uDC89|\\uD83D\\uDCD6|\\uD83D\\uDC8A|\\uD83D\\uDCD7|\\uD83D\\uDC8B|\\uD83D\\uDCD8|\\uD83D\\uDC8C|\\uD83D\\uDCD9|\\uD83D\\uDC8D|\\uD83D\\uDCDA|\\uD83D\\uDC8E|\\uD83D\\uDCDB|\\uD83D\\uDC8F|\\uD83D\\uDCDC|\\uD83D\\uDC90|\\uD83D\\uDCDD|\\uD83D\\uDC91|\\uD83D\\uDCDE|\\uD83D\\uDC92|\\uD83D\\uDCDF|\\uD83D\\uDCE0|\\uD83D\\uDC93|\\uD83D\\uDCE1|\\uD83D\\uDCE2|\\uD83D\\uDC94|\\uD83D\\uDCE3|\\uD83D\\uDCE4|\\uD83D\\uDC95|\\uD83D\\uDCE5|\\uD83D\\uDCE6|\\uD83D\\uDC96|\\uD83D\\uDCE7|\\uD83D\\uDCE8|\\uD83D\\uDC97|\\uD83D\\uDCE9|\\uD83D\\uDCEA|\\uD83D\\uDC98|\\uD83D\\uDCEB|\\uD83D\\uDCEE|\\uD83D\\uDC99|\\uD83D\\uDCF0|\\uD83D\\uDCF1|\\uD83D\\uDC9A|\\uD83D\\uDCF2|\\uD83D\\uDCF3|\\uD83D\\uDC9B|\\uD83D\\uDCF4|\\uD83D\\uDCF6|\\uD83D\\uDC9C|\\uD83D\\uDCF7|\\uD83D\\uDCF9|\\uD83D\\uDC9D|\\uD83D\\uDCFA|\\uD83D\\uDCFB|\\uD83D\\uDC9E|\\uD83D\\uDCFC|\\uD83D\\uDD03|\\uD83D\\uDC9F|\\uD83D\\uDD0A|\\uD83D\\uDD0B|\\uD83D\\uDCA0|\\uD83D\\uDD0C|\\uD83D\\uDD0D|\\uD83D\\uDCA1|\\uD83D\\uDD0E|\\uD83D\\uDD0F|\\uD83D\\uDCA2|\\uD83D\\uDD10|\\uD83D\\uDD11|\\uD83D\\uDCA3|\\uD83D\\uDD12|\\uD83D\\uDD13|\\uD83D\\uDCA4|\\uD83D\\uDD14|\\uD83D\\uDD16|\\uD83D\\uDCA5|\\uD83D\\uDD17|\\uD83D\\uDD18|\\uD83D\\uDCA6|\\uD83D\\uDD19|\\uD83D\\uDD1A|\\uD83D\\uDCA7|\\uD83D\\uDD1B|\\uD83D\\uDD1C|\\uD83D\\uDCA8|\\uD83D\\uDD1D|\\uD83D\\uDD1E|\\uD83D\\uDCA9|\\uD83D\\uDD1F|\\uD83D\\uDCAA|\\uD83D\\uDD20|\\uD83D\\uDD21|\\uD83D\\uDCAB|\\uD83D\\uDD22|\\uD83D\\uDD23|\\uD83D\\uDCAC|\\uD83D\\uDD24|\\uD83D\\uDD25|\\uD83D\\uDCAE|\\uD83D\\uDD26|\\uD83D\\uDD27|\\uD83D\\uDCAF|\\uD83D\\uDD28|\\uD83D\\uDD29|\\uD83D\\uDCB0|\\uD83D\\uDD2A|\\uD83D\\uDD2B|\\uD83D\\uDCB1|\\uD83D\\uDD2E|\\uD83D\\uDCB2|\\uD83D\\uDD2F|\\uD83D\\uDCB3|\\uD83D\\uDD30|\\uD83D\\uDD31|\\uD83D\\uDCB4|\\uD83D\\uDD32|\\uD83D\\uDD33|\\uD83D\\uDCB5|\\uD83D\\uDD34|\\uD83D\\uDD35|\\uD83D\\uDCB8|\\uD83D\\uDD36|\\uD83D\\uDD37|\\uD83D\\uDCB9|\\uD83D\\uDD38|\\uD83D\\uDD39|\\uD83D\\uDCBA|\\uD83D\\uDD3A|\\uD83D\\uDD3B|\\uD83D\\uDCBB|\\uD83D\\uDD3C|\\uD83D\\uDCBC|\\uD83D\\uDD3D|\\uD83D\\uDD50|\\uD83D\\uDCBD|\\uD83D\\uDD51|\\uD83D\\uDCBE|\\uD83D\\uDD52|\\uD83D\\uDCBF|\\uD83D\\uDD53|\\uD83D\\uDCC0|\\uD83D\\uDD54|\\uD83D\\uDD55|\\uD83D\\uDCC1|\\uD83D\\uDD56|\\uD83D\\uDD57|\\uD83D\\uDCC2|\\uD83D\\uDD58|\\uD83D\\uDD59|\\uD83D\\uDCC3|\\uD83D\\uDD5A|\\uD83D\\uDD5B|\\uD83D\\uDCC4|\\uD83D\\uDDFB|\\uD83D\\uDDFC|\\uD83D\\uDCC5|\\uD83D\\uDDFD|\\uD83D\\uDDFE|\\uD83D\\uDCC6|\\uD83D\\uDDFF|\\uD83D\\uDE01|\\uD83D\\uDE02|\\uD83D\\uDE03|\\uD83D\\uDCC8|\\uD83D\\uDE04|\\uD83D\\uDE05|\\uD83D\\uDCC9|\\uD83D\\uDE06|\\uD83D\\uDE09|\\uD83D\\uDCCA|\\uD83D\\uDE0A|\\uD83D\\uDE0B|\\uD83D\\uDCCB|\\uD83D\\uDE0C|\\uD83D\\uDE0D|\\uD83D\\uDCCC|\\uD83D\\uDE0F|\\uD83D\\uDE12|\\uD83D\\uDCCD|\\uD83D\\uDE13|\\uD83D\\uDE14|\\uD83D\\uDCCE|\\uD83D\\uDE16|\\uD83D\\uDE18|\\uD83D\\uDCCF|\\uD83D\\uDE1A|\\uD83D\\uDE1C|\\uD83D\\uDCD0|\\uD83D\\uDE1D|\\uD83D\\uDE1E|\\uD83D\\uDCD1|\\uD83D\\uDE20|\\uD83D\\uDE21|\\uD83D\\uDE22|\\uD83D\\uDE23|\\uD83D\\uDE24|\\uD83D\\uDE25|\\uD83D\\uDE28|\\uD83D\\uDE29|\\uD83D\\uDE2A|\\uD83D\\uDE2B|\\uD83D\\uDE2D|\\uD83D\\uDE30|\\uD83D\\uDE31|\\uD83D\\uDE32|\\uD83D\\uDE33|\\uD83D\\uDE35|\\uD83D\\uDE37|\\uD83D\\uDE38|\\uD83D\\uDE39|\\uD83D\\uDE3A|\\uD83D\\uDE3B|\\uD83D\\uDE3C|\\uD83D\\uDE3D|\\uD83D\\uDE3E|\\uD83D\\uDE3F|\\uD83D\\uDE40|\\uD83D\\uDE45|\\uD83D\\uDE46|\\uD83D\\uDE47|\\uD83D\\uDE48|\\uD83D\\uDE49|\\uD83D\\uDE4A|\\uD83D\\uDE4B|\\uD83D\\uDE4C|\\uD83D\\uDE4D|\\uD83D\\uDE4E|\\uD83D\\uDE4F|\\uD83D\\uDE80|\\uD83D\\uDE83|\\uD83D\\uDE84|\\uD83D\\uDE85|\\uD83D\\uDE87|\\uD83D\\uDE89|\\uD83D\\uDE8C|\\uD83D\\uDE8F|\\uD83D\\uDE91|\\uD83D\\uDE92|\\uD83D\\uDE93|\\uD83D\\uDE95|\\uD83D\\uDE97|\\uD83D\\uDE99|\\uD83D\\uDE9A|\\uD83D\\uDEA2|\\uD83D\\uDEA4|\\uD83D\\uDEA5|\\uD83D\\uDEA7|\\uD83D\\uDEA8|\\uD83D\\uDEA9|\\uD83D\\uDEAA|\\uD83D\\uDEAB|\\uD83D\\uDEAC|\\uD83D\\uDEAD|\\uD83D\\uDEB2|\\uD83D\\uDEB6|\\uD83D\\uDEB9|\\uD83D\\uDEBA|\\uD83D\\uDEBB|\\uD83D\\uDEBC|\\uD83D\\uDEBD|\\uD83D\\uDEBE|\\uD83D\\uDEC0|\\uD83E\\uDD18|\\uD83D\\uDE00|\\uD83D\\uDE07|\\uD83D\\uDE08|\\uD83D\\uDE0E|\\uD83D\\uDE10|\\uD83D\\uDE11|\\uD83D\\uDE15|\\uD83D\\uDE17|\\uD83D\\uDE19|\\uD83D\\uDE1B|\\uD83D\\uDE1F|\\uD83D\\uDE26|\\uD83D\\uDE27|\\uD83D\\uDE2C|\\uD83D\\uDE2E|\\uD83D\\uDE2F|\\uD83D\\uDE34|\\uD83D\\uDE36|\\uD83D\\uDE81|\\uD83D\\uDE82|\\uD83D\\uDE86|\\uD83D\\uDE88|\\uD83D\\uDE8A|\\uD83D\\uDE8D|\\uD83D\\uDE8E|\\uD83D\\uDE90|\\uD83D\\uDE94|\\uD83D\\uDE96|\\uD83D\\uDE98|\\uD83D\\uDE9B|\\uD83D\\uDE9C|\\uD83D\\uDE9D|\\uD83D\\uDE9E|\\uD83D\\uDE9F|\\uD83D\\uDEA0|\\uD83D\\uDEA1|\\uD83D\\uDEA3|\\uD83D\\uDEA6|\\uD83D\\uDEAE|\\uD83D\\uDEAF|\\uD83D\\uDEB0|\\uD83D\\uDEB1|\\uD83D\\uDEB3|\\uD83D\\uDEB4|\\uD83D\\uDEB5|\\uD83D\\uDEB7|\\uD83D\\uDEB8|\\uD83D\\uDEBF|\\uD83D\\uDEC1|\\uD83D\\uDEC2|\\uD83D\\uDEC3|\\uD83D\\uDEC4|\\uD83D\\uDEC5|\\uD83C\\uDF0D|\\uD83C\\uDF0E|\\uD83C\\uDF10|\\uD83C\\uDF12|\\uD83C\\uDF16|\\uD83C\\uDF17|\\uD83C\\uDF18|\\uD83C\\uDF1A|\\uD83C\\uDF1C|\\uD83C\\uDF1D|\\uD83C\\uDF1E|\\uD83C\\uDF32|\\uD83C\\uDF33|\\uD83C\\uDF4B|\\uD83C\\uDF50|\\uD83C\\uDF7C|\\uD83C\\uDFC7|\\uD83C\\uDFC9|\\uD83C\\uDFE4|\\uD83D\\uDC00|\\uD83D\\uDC01|\\uD83D\\uDC02|\\uD83D\\uDC03|\\uD83D\\uDC04|\\uD83D\\uDC05|\\uD83D\\uDC06|\\uD83D\\uDC07|\\uD83D\\uDC08|\\uD83D\\uDC09|\\uD83D\\uDC0A|\\uD83D\\uDC0B|\\uD83D\\uDC0F|\\uD83D\\uDC10|\\uD83D\\uDC13|\\uD83D\\uDC15|\\uD83D\\uDC16|\\uD83D\\uDC2A|\\uD83D\\uDC65|\\uD83D\\uDC6C|\\uD83D\\uDC6D|\\uD83D\\uDCAD|\\uD83D\\uDCB6|\\uD83D\\uDCB7|\\uD83D\\uDCEC|\\uD83D\\uDCED|\\uD83D\\uDCEF|\\uD83D\\uDCF5|\\uD83D\\uDD00|\\uD83D\\uDD01|\\uD83D\\uDD02|\\uD83D\\uDD04|\\uD83D\\uDD05|\\uD83D\\uDD06|\\uD83D\\uDD07|\\uD83D\\uDD09|\\uD83D\\uDD15|\\uD83D\\uDD2C|\\uD83D\\uDD2D|\\uD83D\\uDD5C|\\uD83D\\uDD5D|\\uD83D\\uDD5E|\\uD83D\\uDD5F|\\uD83D\\uDD60|\\uD83D\\uDD61|\\uD83D\\uDD62|\\uD83D\\uDD63|\\uD83D\\uDD64|\\uD83D\\uDD65|\\uD83D\\uDD66|\\uD83D\\uDD67|\\uD83D\\uDD08|\\uD83D\\uDE8B|\\uD83C\\uDFC5|\\uD83C\\uDFF4|\\uD83D\\uDCF8|\\uD83D\\uDECC|\\uD83D\\uDD95|\\uD83D\\uDD96|\\uD83D\\uDE41|\\uD83D\\uDE42|\\uD83D\\uDEEB|\\uD83D\\uDEEC|\\uD83C\\uDFFB|\\uD83C\\uDFFC|\\uD83C\\uDFFD|\\uD83C\\uDFFE|\\uD83C\\uDFFF|\\uD83D\\uDE43|\\uD83E\\uDD11|\\uD83E\\uDD13|\\uD83E\\uDD17|\\uD83D\\uDE44|\\uD83E\\uDD14|\\uD83E\\uDD10|\\uD83E\\uDD12|\\uD83E\\uDD15|\\uD83E\\uDD16|\\uD83E\\uDD81|\\uD83E\\uDD84|\\uD83E\\uDD82|\\uD83E\\uDD80|\\uD83E\\uDD83|\\uD83E\\uDDC0|\\uD83C\\uDF2D|\\uD83C\\uDF2E|\\uD83C\\uDF2F|\\uD83C\\uDF7F|\\uD83C\\uDF7E|\\uD83C\\uDFF9|\\uD83C\\uDFFA|\\uD83D\\uDED0|\\uD83D\\uDD4B|\\uD83D\\uDD4C|\\uD83D\\uDD4D|\\uD83D\\uDD4E|\\uD83D\\uDCFF|\\uD83C\\uDFCF|\\uD83C\\uDFD0|\\uD83C\\uDFD1|\\uD83C\\uDFD2|\\uD83C\\uDFD3|\\uD83C\\uDFF8|\\uD83C\\uDF26|\\uD83C\\uDF25|\\uD83C\\uDF24|\\uD83D\\uDEF3|\\uD83D\\uDEE9|\\uD83D\\uDEE5|\\uD83D\\uDEE4|\\uD83D\\uDEE3|\\uD83D\\uDECF|\\uD83D\\uDECE|\\uD83D\\uDECD|\\uD83D\\uDECB|\\uD83C\\uDFDF|\\uD83C\\uDFDE|\\uD83C\\uDFDD|\\uD83C\\uDFDC|\\uD83C\\uDFDB|\\uD83C\\uDFDA|\\uD83C\\uDFD9|\\uD83C\\uDFD8|\\uD83C\\uDFD7|\\uD83C\\uDFD6|\\uD83C\\uDFD5|\\uD83C\\uDFD4|\\uD83D\\uDD90|\\uD83D\\uDD75|\\uD83D\\uDD74|\\uD83D\\uDC41|\\uD83C\\uDF7D|\\uD83D\\uDEF0|\\uD83D\\uDEE2|\\uD83D\\uDEE1|\\uD83D\\uDEE0|\\uD83D\\uDDFA|\\uD83D\\uDDF3|\\uD83D\\uDDEF|\\uD83D\\uDDE3|\\uD83D\\uDDE1|\\uD83D\\uDDDE|\\uD83D\\uDDDD|\\uD83D\\uDDDC|\\uD83D\\uDDD3|\\uD83D\\uDDD2|\\uD83D\\uDDD1|\\uD83D\\uDDC4|\\uD83D\\uDDC3|\\uD83D\\uDDC2|\\uD83D\\uDDBC|\\uD83D\\uDDB2|\\uD83D\\uDDA8|\\uD83D\\uDDA5|\\uD83D\\uDD8D|\\uD83D\\uDD8C|\\uD83D\\uDD8B|\\uD83D\\uDD8A|\\uD83D\\uDD87|\\uD83D\\uDD79|\\uD83D\\uDD76|\\uD83D\\uDD73|\\uD83D\\uDD70|\\uD83D\\uDD6F|\\uD83D\\uDD4A|\\uD83D\\uDD49|\\uD83D\\uDCFD|\\uD83C\\uDFF7|\\uD83C\\uDFF5|\\uD83C\\uDFF3|\\uD83C\\uDF9B|\\uD83C\\uDF9A|\\uD83C\\uDF99|\\uD83C\\uDF21|\\uD83D\\uDD78|\\uD83D\\uDD77|\\uD83D\\uDC3F|\\uD83C\\uDF2C|\\uD83C\\uDF2B|\\uD83C\\uDF2A|\\uD83C\\uDF29|\\uD83C\\uDF28|\\uD83C\\uDF27|\\uD83C\\uDF36|\\uD83C\\uDF97|\\uD83C\\uDF96|\\uD83C\\uDFCE|\\uD83C\\uDFCD|\\uD83C\\uDFCC|\\uD83C\\uDFCB|\\uD83C\\uDF9F|\\uD83C\\uDF9E|\\uD83C\\uDE37|\\uD83C\\uDE2F|\\uD83C\\uDE1A|\\uD83C\\uDE02|\\uD83C\\uDD7F|\\uD83C\\uDC04|\\uD83C\\uDFE1|\\u2714|\\u2733|\\u2734|\\u2744|\\u2747|\\u2757|\\u2764|\\u27A1|\\u2934|\\u2935|\\u2B05|\\u2B06|\\u2B07|\\u2B1B|\\u2B1C|\\u2B50|\\u2B55|\\u3030|\\u303D|\\u3297|\\u3299|\\u2712|\\u270F|\\u270C|\\u2709|\\u2708|\\u2702|\\u26FD|\\u26FA|\\u26F5|\\u26F3|\\u26F2|\\u26EA|\\u26D4|\\u26C5|\\u26C4|\\u26BE|\\u26BD|\\u26AB|\\u26AA|\\u26A1|\\u26A0|\\u2693|\\u267F|\\u267B|\\u2668|\\u2666|\\u2665|\\u2663|\\u2660|\\u2653|\\u2652|\\u2651|\\u271D|\\u2650|\\u264F|\\u264E|\\u264D|\\u264C|\\u264B|\\u264A|\\u2649|\\u2648|\\u263A|\\u261D|\\u2615|\\u2614|\\u2611|\\u2328|\\u260E|\\u2601|\\u2600|\\u25FE|\\u25FD|\\u25FC|\\u25FB|\\u25C0|\\u25B6|\\u25AB|\\u25AA|\\u24C2|\\u2716|\\u231A|\\u21AA|\\u21A9|\\u2199|\\u2198|\\u2197|\\u2196|\\u2195|\\u2194|\\u2139|\\u2122|\\u270D|\\u2049|\\u203C|\\u00AE|\\u00A9|\\u27BF|\\u27B0|\\u2797|\\u2796|\\u2795|\\u2755|\\u2754|\\u2753|\\u274E|\\u274C|\\u2728|\\u270B|\\u270A|\\u2705|\\u26CE|\\u23F3|\\u23F0|\\u23EC|\\u23ED|\\u23EE|\\u23EF|\\u23F1|\\u23F2|\\u23F8|\\u23F9|\\u23FA|\\u2602|\\u2603|\\u2604|\\u2618|\\u2620|\\u2622|\\u2623|\\u2626|\\u262A|\\u262E|\\u262F|\\u2638|\\u2639|\\u2692|\\u2694|\\u2696|\\u2697|\\u2699|\\u269B|\\u269C|\\u26B0|\\u26B1|\\u26C8|\\u26CF|\\u26D1|\\u26D3|\\u26E9|\\u26F0|\\u26F1|\\u26F4|\\u26F7|\\u26F8|\\u26F9|\\u2721|\\u2763|\\u23EB|\\u23EA|\\u23E9|\\u231B|\\uD83E\\uDD19\\uD83C\\uDFFE|\\uD83E\\uDD34\\uD83C\\uDFFB|\\uD83E\\uDD34\\uD83C\\uDFFE|\\uD83E\\uDD34\\uD83C\\uDFFF|\\uD83E\\uDD36\\uD83C\\uDFFB|\\uD83E\\uDD36\\uD83C\\uDFFC|\\uD83E\\uDD36\\uD83C\\uDFFD|\\uD83E\\uDD36\\uD83C\\uDFFE|\\uD83E\\uDD36\\uD83C\\uDFFF|\\uD83E\\uDD35\\uD83C\\uDFFB|\\uD83E\\uDD35\\uD83C\\uDFFC|\\uD83E\\uDD35\\uD83C\\uDFFD|\\uD83E\\uDD35\\uD83C\\uDFFE|\\uD83E\\uDD35\\uD83C\\uDFFF|\\uD83E\\uDD37\\uD83C\\uDFFB|\\uD83E\\uDD37\\uD83C\\uDFFC|\\uD83E\\uDD37\\uD83C\\uDFFD|\\uD83E\\uDD37\\uD83C\\uDFFE|\\uD83E\\uDD37\\uD83C\\uDFFF|\\uD83E\\uDD26\\uD83C\\uDFFB|\\uD83E\\uDD26\\uD83C\\uDFFC|\\uD83E\\uDD26\\uD83C\\uDFFD|\\uD83E\\uDD26\\uD83C\\uDFFE|\\uD83E\\uDD26\\uD83C\\uDFFF|\\uD83E\\uDD30\\uD83C\\uDFFB|\\uD83E\\uDD30\\uD83C\\uDFFC|\\uD83E\\uDD30\\uD83C\\uDFFD|\\uD83E\\uDD30\\uD83C\\uDFFE|\\uD83E\\uDD30\\uD83C\\uDFFF|\\uD83D\\uDD7A\\uD83C\\uDFFB|\\uD83D\\uDD7A\\uD83C\\uDFFC|\\uD83D\\uDD7A\\uD83C\\uDFFD|\\uD83D\\uDD7A\\uD83C\\uDFFE|\\uD83D\\uDD7A\\uD83C\\uDFFF|\\uD83E\\uDD33\\uD83C\\uDFFB|\\uD83E\\uDD33\\uD83C\\uDFFC|\\uD83E\\uDD33\\uD83C\\uDFFD|\\uD83E\\uDD33\\uD83C\\uDFFE|\\uD83E\\uDD33\\uD83C\\uDFFF|\\uD83E\\uDD1E\\uD83C\\uDFFB|\\uD83E\\uDD1E\\uD83C\\uDFFC|\\uD83E\\uDD1E\\uD83C\\uDFFD|\\uD83E\\uDD1E\\uD83C\\uDFFE|\\uD83E\\uDD1E\\uD83C\\uDFFF|\\uD83E\\uDD19\\uD83C\\uDFFB|\\uD83E\\uDD19\\uD83C\\uDFFC|\\uD83E\\uDD19\\uD83C\\uDFFD|\\uD83E\\uDD34\\uD83C\\uDFFD|\\uD83E\\uDD19\\uD83C\\uDFFF|\\uD83E\\uDD1B\\uD83C\\uDFFB|\\uD83E\\uDD1B\\uD83C\\uDFFC|\\uD83E\\uDD1B\\uD83C\\uDFFD|\\uD83E\\uDD1B\\uD83C\\uDFFE|\\uD83E\\uDD1B\\uD83C\\uDFFF|\\uD83E\\uDD1C\\uD83C\\uDFFB|\\uD83E\\uDD1C\\uD83C\\uDFFC|\\uD83E\\uDD1C\\uD83C\\uDFFD|\\uD83E\\uDD1C\\uD83C\\uDFFE|\\uD83E\\uDD1C\\uD83C\\uDFFF|\\uD83E\\uDD1A\\uD83C\\uDFFB|\\uD83E\\uDD1A\\uD83C\\uDFFC|\\uD83E\\uDD1A\\uD83C\\uDFFD|\\uD83E\\uDD1A\\uD83C\\uDFFE|\\uD83E\\uDD1A\\uD83C\\uDFFF|\\uD83E\\uDD1D\\uD83C\\uDFFB|\\uD83E\\uDD1D\\uD83C\\uDFFC|\\uD83E\\uDD1D\\uD83C\\uDFFD|\\uD83E\\uDD1D\\uD83C\\uDFFE|\\uD83E\\uDD1D\\uD83C\\uDFFF|\\uD83E\\uDD38\\uD83C\\uDFFB|\\uD83E\\uDD38\\uD83C\\uDFFC|\\uD83E\\uDD38\\uD83C\\uDFFD|\\uD83E\\uDD38\\uD83C\\uDFFE|\\uD83E\\uDD38\\uD83C\\uDFFF|\\uD83E\\uDD3C\\uD83C\\uDFFC|\\uD83E\\uDD3C\\uD83C\\uDFFB|\\uD83E\\uDD3C\\uD83C\\uDFFD|\\uD83E\\uDD3C\\uD83C\\uDFFE|\\uD83E\\uDD3C\\uD83C\\uDFFF|\\uD83E\\uDD3D\\uD83C\\uDFFB|\\uD83E\\uDD3D\\uD83C\\uDFFC|\\uD83E\\uDD3D\\uD83C\\uDFFD|\\uD83E\\uDD3D\\uD83C\\uDFFE|\\uD83E\\uDD3D\\uD83C\\uDFFF|\\uD83E\\uDD3E\\uD83C\\uDFFB|\\uD83E\\uDD3E\\uD83C\\uDFFC|\\uD83E\\uDD3E\\uD83C\\uDFFD|\\uD83E\\uDD3E\\uD83C\\uDFFE|\\uD83E\\uDD3E\\uD83C\\uDFFF|\\uD83E\\uDD39\\uD83C\\uDFFB|\\uD83E\\uDD39\\uD83C\\uDFFC|\\uD83E\\uDD39\\uD83C\\uDFFD|\\uD83E\\uDD39\\uD83C\\uDFFE|\\uD83E\\uDD39\\uD83C\\uDFFF|\\uD83E\\uDD34\\uD83C\\uDFFC|\\uD83E\\uDD49|\\uD83E\\uDD48|\\uD83E\\uDD47|\\uD83E\\uDD3A|\\uD83E\\uDD45|\\uD83E\\uDD3E|\\uD83C\\uDDFF|\\uD83E\\uDD3D|\\uD83E\\uDD4B|\\uD83E\\uDD4A|\\uD83E\\uDD3C|\\uD83E\\uDD39|\\uD83E\\uDD38|\\uD83D\\uDEF6|\\uD83D\\uDEF5|\\uD83D\\uDEF4|\\uD83D\\uDED2|\\uD83D\\uDED1|\\uD83C\\uDDFE|\\uD83E\\uDD44|\\uD83E\\uDD42|\\uD83E\\uDD43|\\uD83E\\uDD59|\\uD83E\\uDD58|\\uD83E\\uDD57|\\uD83E\\uDD56|\\uD83E\\uDD55|\\uD83E\\uDD54|\\uD83E\\uDD53|\\uD83E\\uDD52|\\uD83E\\uDD51|\\uD83E\\uDD50|\\uD83E\\uDD40|\\uD83E\\uDD8F|\\uD83E\\uDD8E|\\uD83E\\uDD8D|\\uD83E\\uDD8C|\\uD83E\\uDD8B|\\uD83E\\uDD8A|\\uD83E\\uDD89|\\uD83E\\uDD88|\\uD83E\\uDD87|\\uD83C\\uDDFD|\\uD83E\\uDD86|\\uD83E\\uDD85|\\uD83D\\uDDA4|\\uD83E\\uDD1E|\\uD83E\\uDD1D|\\uD83E\\uDD1B|\\uD83E\\uDD1C|\\uD83E\\uDD1A|\\uD83E\\uDD19|\\uD83D\\uDD7A|\\uD83E\\uDD33|\\uD83E\\uDD30|\\uD83E\\uDD26|\\uD83E\\uDD37|\\uD83E\\uDD36|\\uD83E\\uDD35|\\uD83E\\uDD34|\\uD83E\\uDD27|\\uD83E\\uDD25|\\uD83E\\uDD24|\\uD83E\\uDD23|\\uD83E\\uDD22|\\uD83E\\uDD21|\\uD83E\\uDD20|\\uD83E\\uDD41|\\uD83E\\uDD90|\\uD83E\\uDD91|\\uD83E\\uDD5A|\\uD83E\\uDD5B|\\uD83E\\uDD5C|\\uD83E\\uDD5D|\\uD83E\\uDD5E|\\uD83C\\uDDFC|\\uD83C\\uDDFB|\\uD83C\\uDDFA|\\uD83C\\uDDF9|\\uD83C\\uDDF8|\\uD83C\\uDDF7|\\uD83C\\uDDF6|\\uD83C\\uDDF5|\\uD83C\\uDDF4|\\uD83C\\uDDF3|\\uD83C\\uDDF2|\\uD83C\\uDDF1|\\uD83C\\uDDF0|\\uD83C\\uDDEF|\\uD83C\\uDDEE|\\uD83C\\uDDED|\\uD83C\\uDDEC|\\uD83C\\uDDEB|\\uD83C\\uDDEA|\\uD83C\\uDDE9|\\uD83C\\uDDE8|\\uD83C\\uDDE7|\\uD83C\\uDDE6|\\uD83C\\uDF26|\\uD83C\\uDF25|\\uD83C\\uDF24|\\uD83D\\uDEF3|\\uD83D\\uDEE9|\\uD83D\\uDEE5|\\uD83D\\uDEE4|\\uD83D\\uDEE3|\\uD83D\\uDECF|\\uD83D\\uDECE|\\uD83D\\uDECD|\\uD83D\\uDECB|\\uD83C\\uDFDF|\\uD83C\\uDFDE|\\uD83C\\uDFDD|\\uD83C\\uDFDC|\\uD83C\\uDFDB|\\uD83C\\uDFDA|\\uD83C\\uDFD9|\\uD83C\\uDFD8|\\uD83C\\uDFD7|\\uD83C\\uDFD6|\\uD83C\\uDFD5|\\uD83C\\uDFD4|\\uD83D\\uDD90|\\uD83D\\uDD75|\\uD83D\\uDD74|\\uD83D\\uDC41|\\uD83C\\uDF7D|\\uD83D\\uDDB1|\\uD83D\\uDEF0|\\uD83D\\uDEE2|\\uD83D\\uDEE1|\\uD83D\\uDEE0|\\uD83D\\uDDFA|\\uD83D\\uDDF3|\\uD83D\\uDDEF|\\uD83D\\uDDE8|\\uD83D\\uDDE3|\\uD83D\\uDDE1|\\uD83D\\uDDDE|\\uD83D\\uDDDD|\\uD83D\\uDDDC|\\uD83D\\uDDD3|\\uD83D\\uDDD2|\\uD83D\\uDDD1|\\uD83D\\uDDC4|\\uD83D\\uDDC3|\\uD83D\\uDDC2|\\uD83D\\uDDBC|\\uD83D\\uDDB2|\\uD83D\\uDDA8|\\uD83D\\uDDA5|\\uD83D\\uDD8D|\\uD83D\\uDD8C|\\uD83D\\uDD8B|\\uD83D\\uDD8A|\\uD83D\\uDD87|\\uD83D\\uDD79|\\uD83D\\uDD76|\\uD83D\\uDD73|\\uD83D\\uDD70|\\uD83D\\uDD6F|\\uD83D\\uDD4A|\\uD83D\\uDD49|\\uD83D\\uDCFD|\\uD83C\\uDFF7|\\uD83C\\uDFF5|\\uD83C\\uDFF3|\\uD83C\\uDF9B|\\uD83C\\uDF9A|\\uD83C\\uDF99|\\uD83C\\uDF21|\\uD83D\\uDD78|\\uD83D\\uDD77|\\uD83D\\uDC3F|\\uD83C\\uDF2C|\\uD83C\\uDF2B|\\uD83C\\uDF2A|\\uD83C\\uDF29|\\uD83C\\uDF28|\\uD83C\\uDF27|\\uD83C\\uDF36|\\uD83C\\uDF97|\\uD83C\\uDF96|\\uD83C\\uDFCE|\\uD83C\\uDFCD|\\uD83C\\uDFCC|\\uD83C\\uDFCB|\\uD83C\\uDF9F|\\uD83C\\uDF9E|\\uD83C\\uDE37|\\uD83C\\uDE2F|\\uD83C\\uDE1A|\\uD83C\\uDE02|\\uD83C\\uDD7F|\\uD83C\\uDC04|\\u25C0|\\u2B05|\\u2B07|\\u2B1B|\\u2B1C|\\u2B50|\\u2B55|\\u3030|\\u303D|\\u3297|\\u3299|\\u2935|\\u2934|\\u27A1|\\u2764|\\u2757|\\u2747|\\u2744|\\u2734|\\u2733|\\u2716|\\u2714|\\u2712|\\u270F|\\u270C|\\u2709|\\u2708|\\u2702|\\u26FD|\\u26FA|\\u26F5|\\u26F3|\\u26F2|\\u26EA|\\u26D4|\\u26C5|\\u26C4|\\u26BE|\\u26BD|\\u26AB|\\u26AA|\\u26A1|\\u26A0|\\u271D|\\u2693|\\u267F|\\u267B|\\u2668|\\u2666|\\u2665|\\u2663|\\u2660|\\u2653|\\u2652|\\u2651|\\u2650|\\u264F|\\u264E|\\u2328|\\u264D|\\u264C|\\u264B|\\u264A|\\u2649|\\u2648|\\u263A|\\u261D|\\u2615|\\u2614|\\u2611|\\u260E|\\u2601|\\u2600|\\u25FE|\\u25FD|\\u25FC|\\u25FB|\\u2B06|\\u25B6|\\u25AB|\\u24C2|\\u231B|\\u231A|\\u21AA|\\u270D|\\u21A9|\\u2199|\\u2198|\\u2197|\\u2196|\\u2195|\\u2194|\\u2139|\\u2122|\\u2049|\\u203C|\\u00AE|\\u00A9|\\u2763|\\u2721|\\u26F9|\\u26F8|\\u26F7|\\u26F4|\\u26F1|\\u26F0|\\u26E9|\\u23CF|\\u23ED|\\u23EE|\\u23EF|\\u23F1|\\u23F2|\\u23F8|\\u23F9|\\u23FA|\\u2602|\\u2603|\\u2604|\\u2618|\\u2620|\\u2622|\\u2623|\\u2626|\\u262A|\\u262E|\\u262F|\\u2638|\\u2639|\\u2692|\\u2694|\\u2696|\\u2697|\\u2699|\\u269B|\\u269C|\\u26B0|\\u26B1|\\u26C8|\\u26CF|\\u26D1|\\u26D3|\\u25AA)'; + ns.jsEscapeMap = {"\uD83D\uDC69\u2764\uD83D\uDC8B\uD83D\uDC69":"1f469-2764-1f48b-1f469","\uD83D\uDC68\u2764\uD83D\uDC8B\uD83D\uDC68":"1f468-2764-1f48b-1f468","\uD83D\uDC68\uD83D\uDC68\uD83D\uDC66\uD83D\uDC66":"1f468-1f468-1f466-1f466","\uD83D\uDC68\uD83D\uDC68\uD83D\uDC67\uD83D\uDC66":"1f468-1f468-1f467-1f466","\uD83D\uDC68\uD83D\uDC68\uD83D\uDC67\uD83D\uDC67":"1f468-1f468-1f467-1f467","\uD83D\uDC68\uD83D\uDC69\uD83D\uDC66\uD83D\uDC66":"1f468-1f469-1f466-1f466","\uD83D\uDC68\uD83D\uDC69\uD83D\uDC67\uD83D\uDC66":"1f468-1f469-1f467-1f466","\uD83D\uDC68\uD83D\uDC69\uD83D\uDC67\uD83D\uDC67":"1f468-1f469-1f467-1f467","\uD83D\uDC69\uD83D\uDC69\uD83D\uDC66\uD83D\uDC66":"1f469-1f469-1f466-1f466","\uD83D\uDC69\uD83D\uDC69\uD83D\uDC67\uD83D\uDC66":"1f469-1f469-1f467-1f466","\uD83D\uDC69\uD83D\uDC69\uD83D\uDC67\uD83D\uDC67":"1f469-1f469-1f467-1f467","\uD83D\uDC69\u2764\uD83D\uDC69":"1f469-2764-1f469","\uD83D\uDC68\u2764\uD83D\uDC68":"1f468-2764-1f468","\uD83D\uDC68\uD83D\uDC68\uD83D\uDC66":"1f468-1f468-1f466","\uD83D\uDC68\uD83D\uDC68\uD83D\uDC67":"1f468-1f468-1f467","\uD83D\uDC68\uD83D\uDC69\uD83D\uDC67":"1f468-1f469-1f467","\uD83D\uDC69\uD83D\uDC69\uD83D\uDC66":"1f469-1f469-1f466","\uD83D\uDC69\uD83D\uDC69\uD83D\uDC67":"1f469-1f469-1f467","\uD83D\uDC41\uD83D\uDDE8":"1f441-1f5e8","#\u20E3":"0023-20e3","0\u20E3":"0030-20e3","1\u20E3":"0031-20e3","2\u20E3":"0032-20e3","3\u20E3":"0033-20e3","4\u20E3":"0034-20e3","5\u20E3":"0035-20e3","6\u20E3":"0036-20e3","7\u20E3":"0037-20e3","8\u20E3":"0038-20e3","9\u20E3":"0039-20e3","*\u20E3":"002a-20e3","\uD83E\uDD3E\uD83C\uDFFF":"1f93e-1f3ff","\uD83E\uDD3E\uD83C\uDFFE":"1f93e-1f3fe","\uD83E\uDD3E\uD83C\uDFFD":"1f93e-1f3fd","\uD83E\uDD3E\uD83C\uDFFC":"1f93e-1f3fc","\uD83E\uDD3E\uD83C\uDFFB":"1f93e-1f3fb","\uD83E\uDD3D\uD83C\uDFFF":"1f93d-1f3ff","\uD83E\uDD3D\uD83C\uDFFE":"1f93d-1f3fe","\uD83E\uDD3D\uD83C\uDFFD":"1f93d-1f3fd","\uD83E\uDD3D\uD83C\uDFFC":"1f93d-1f3fc","\uD83E\uDD3D\uD83C\uDFFB":"1f93d-1f3fb","\uD83E\uDD3C\uD83C\uDFFF":"1f93c-1f3ff","\uD83E\uDD3C\uD83C\uDFFE":"1f93c-1f3fe","\uD83E\uDD3C\uD83C\uDFFD":"1f93c-1f3fd","\uD83E\uDD3C\uD83C\uDFFC":"1f93c-1f3fc","\uD83E\uDD3C\uD83C\uDFFB":"1f93c-1f3fb","\uD83E\uDD39\uD83C\uDFFF":"1f939-1f3ff","\uD83E\uDD39\uD83C\uDFFE":"1f939-1f3fe","\uD83E\uDD39\uD83C\uDFFD":"1f939-1f3fd","\uD83E\uDD39\uD83C\uDFFC":"1f939-1f3fc","\uD83E\uDD39\uD83C\uDFFB":"1f939-1f3fb","\uD83E\uDD38\uD83C\uDFFF":"1f938-1f3ff","\uD83E\uDD38\uD83C\uDFFE":"1f938-1f3fe","\uD83E\uDD38\uD83C\uDFFD":"1f938-1f3fd","\uD83E\uDD38\uD83C\uDFFC":"1f938-1f3fc","\uD83E\uDD38\uD83C\uDFFB":"1f938-1f3fb","\uD83E\uDD37\uD83C\uDFFF":"1f937-1f3ff","\uD83E\uDD37\uD83C\uDFFE":"1f937-1f3fe","\uD83E\uDD37\uD83C\uDFFD":"1f937-1f3fd","\uD83E\uDD37\uD83C\uDFFC":"1f937-1f3fc","\uD83E\uDD37\uD83C\uDFFB":"1f937-1f3fb","\uD83E\uDD36\uD83C\uDFFF":"1f936-1f3ff","\uD83E\uDD36\uD83C\uDFFE":"1f936-1f3fe","\uD83E\uDD36\uD83C\uDFFD":"1f936-1f3fd","\uD83E\uDD36\uD83C\uDFFC":"1f936-1f3fc","\uD83E\uDD36\uD83C\uDFFB":"1f936-1f3fb","\uD83E\uDD35\uD83C\uDFFF":"1f935-1f3ff","\uD83E\uDD35\uD83C\uDFFE":"1f935-1f3fe","\uD83E\uDD35\uD83C\uDFFD":"1f935-1f3fd","\uD83E\uDD35\uD83C\uDFFC":"1f935-1f3fc","\uD83E\uDD35\uD83C\uDFFB":"1f935-1f3fb","\uD83E\uDD34\uD83C\uDFFF":"1f934-1f3ff","\uD83E\uDD34\uD83C\uDFFE":"1f934-1f3fe","\uD83E\uDD34\uD83C\uDFFD":"1f934-1f3fd","\uD83E\uDD34\uD83C\uDFFC":"1f934-1f3fc","\uD83E\uDD34\uD83C\uDFFB":"1f934-1f3fb","\uD83E\uDD33\uD83C\uDFFF":"1f933-1f3ff","\uD83E\uDD33\uD83C\uDFFE":"1f933-1f3fe","\uD83E\uDD33\uD83C\uDFFD":"1f933-1f3fd","\uD83E\uDD33\uD83C\uDFFC":"1f933-1f3fc","\uD83E\uDD33\uD83C\uDFFB":"1f933-1f3fb","\uD83E\uDD30\uD83C\uDFFF":"1f930-1f3ff","\uD83E\uDD30\uD83C\uDFFE":"1f930-1f3fe","\uD83E\uDD30\uD83C\uDFFD":"1f930-1f3fd","\uD83E\uDD30\uD83C\uDFFC":"1f930-1f3fc","\uD83E\uDD30\uD83C\uDFFB":"1f930-1f3fb","\uD83E\uDD26\uD83C\uDFFF":"1f926-1f3ff","\uD83E\uDD26\uD83C\uDFFE":"1f926-1f3fe","\uD83E\uDD26\uD83C\uDFFD":"1f926-1f3fd","\uD83E\uDD26\uD83C\uDFFC":"1f926-1f3fc","\uD83E\uDD26\uD83C\uDFFB":"1f926-1f3fb","\uD83E\uDD1E\uD83C\uDFFF":"1f91e-1f3ff","\uD83E\uDD1E\uD83C\uDFFE":"1f91e-1f3fe","\uD83E\uDD1E\uD83C\uDFFD":"1f91e-1f3fd","\uD83E\uDD1E\uD83C\uDFFC":"1f91e-1f3fc","\uD83E\uDD1E\uD83C\uDFFB":"1f91e-1f3fb","\uD83E\uDD1D\uD83C\uDFFF":"1f91d-1f3ff","\uD83E\uDD1D\uD83C\uDFFE":"1f91d-1f3fe","\uD83E\uDD1D\uD83C\uDFFD":"1f91d-1f3fd","\uD83E\uDD1D\uD83C\uDFFC":"1f91d-1f3fc","\uD83E\uDD1D\uD83C\uDFFB":"1f91d-1f3fb","\uD83E\uDD1C\uD83C\uDFFF":"1f91c-1f3ff","\uD83E\uDD1C\uD83C\uDFFE":"1f91c-1f3fe","\uD83E\uDD1C\uD83C\uDFFD":"1f91c-1f3fd","\uD83E\uDD1C\uD83C\uDFFC":"1f91c-1f3fc","\uD83E\uDD1C\uD83C\uDFFB":"1f91c-1f3fb","\uD83E\uDD1B\uD83C\uDFFF":"1f91b-1f3ff","\uD83E\uDD1B\uD83C\uDFFE":"1f91b-1f3fe","\uD83E\uDD1B\uD83C\uDFFD":"1f91b-1f3fd","\uD83E\uDD1B\uD83C\uDFFC":"1f91b-1f3fc","\uD83E\uDD1B\uD83C\uDFFB":"1f91b-1f3fb","\uD83E\uDD1A\uD83C\uDFFF":"1f91a-1f3ff","\uD83E\uDD1A\uD83C\uDFFE":"1f91a-1f3fe","\uD83E\uDD1A\uD83C\uDFFD":"1f91a-1f3fd","\uD83E\uDD1A\uD83C\uDFFC":"1f91a-1f3fc","\uD83E\uDD1A\uD83C\uDFFB":"1f91a-1f3fb","\uD83E\uDD19\uD83C\uDFFF":"1f919-1f3ff","\uD83E\uDD19\uD83C\uDFFE":"1f919-1f3fe","\uD83E\uDD19\uD83C\uDFFD":"1f919-1f3fd","\uD83E\uDD19\uD83C\uDFFC":"1f919-1f3fc","\uD83E\uDD19\uD83C\uDFFB":"1f919-1f3fb","\uD83E\uDD18\uD83C\uDFFF":"1f918-1f3ff","\uD83E\uDD18\uD83C\uDFFE":"1f918-1f3fe","\uD83E\uDD18\uD83C\uDFFD":"1f918-1f3fd","\uD83E\uDD18\uD83C\uDFFC":"1f918-1f3fc","\uD83E\uDD18\uD83C\uDFFB":"1f918-1f3fb","\uD83D\uDEC0\uD83C\uDFFF":"1f6c0-1f3ff","\uD83D\uDEC0\uD83C\uDFFE":"1f6c0-1f3fe","\uD83D\uDEC0\uD83C\uDFFD":"1f6c0-1f3fd","\uD83D\uDEC0\uD83C\uDFFC":"1f6c0-1f3fc","\uD83D\uDEC0\uD83C\uDFFB":"1f6c0-1f3fb","\uD83D\uDEB6\uD83C\uDFFF":"1f6b6-1f3ff","\uD83D\uDEB6\uD83C\uDFFE":"1f6b6-1f3fe","\uD83D\uDEB6\uD83C\uDFFD":"1f6b6-1f3fd","\uD83D\uDEB6\uD83C\uDFFC":"1f6b6-1f3fc","\uD83D\uDEB6\uD83C\uDFFB":"1f6b6-1f3fb","\uD83D\uDEB5\uD83C\uDFFF":"1f6b5-1f3ff","\uD83D\uDEB5\uD83C\uDFFE":"1f6b5-1f3fe","\uD83D\uDEB5\uD83C\uDFFD":"1f6b5-1f3fd","\uD83D\uDEB5\uD83C\uDFFC":"1f6b5-1f3fc","\uD83D\uDEB5\uD83C\uDFFB":"1f6b5-1f3fb","\uD83D\uDEB4\uD83C\uDFFF":"1f6b4-1f3ff","\uD83D\uDEB4\uD83C\uDFFE":"1f6b4-1f3fe","\uD83D\uDEB4\uD83C\uDFFD":"1f6b4-1f3fd","\uD83D\uDEB4\uD83C\uDFFC":"1f6b4-1f3fc","\uD83D\uDEB4\uD83C\uDFFB":"1f6b4-1f3fb","\uD83D\uDEA3\uD83C\uDFFF":"1f6a3-1f3ff","\uD83D\uDEA3\uD83C\uDFFE":"1f6a3-1f3fe","\uD83D\uDEA3\uD83C\uDFFD":"1f6a3-1f3fd","\uD83D\uDEA3\uD83C\uDFFC":"1f6a3-1f3fc","\uD83D\uDEA3\uD83C\uDFFB":"1f6a3-1f3fb","\uD83D\uDE4F\uD83C\uDFFF":"1f64f-1f3ff","\uD83D\uDE4F\uD83C\uDFFE":"1f64f-1f3fe","\uD83D\uDE4F\uD83C\uDFFD":"1f64f-1f3fd","\uD83D\uDE4F\uD83C\uDFFC":"1f64f-1f3fc","\uD83D\uDE4F\uD83C\uDFFB":"1f64f-1f3fb","\uD83D\uDE4E\uD83C\uDFFF":"1f64e-1f3ff","\uD83D\uDE4E\uD83C\uDFFE":"1f64e-1f3fe","\uD83D\uDE4E\uD83C\uDFFD":"1f64e-1f3fd","\uD83D\uDE4E\uD83C\uDFFC":"1f64e-1f3fc","\uD83D\uDE4E\uD83C\uDFFB":"1f64e-1f3fb","\uD83D\uDE4D\uD83C\uDFFF":"1f64d-1f3ff","\uD83D\uDE4D\uD83C\uDFFE":"1f64d-1f3fe","\uD83D\uDE4D\uD83C\uDFFD":"1f64d-1f3fd","\uD83D\uDE4D\uD83C\uDFFC":"1f64d-1f3fc","\uD83D\uDE4D\uD83C\uDFFB":"1f64d-1f3fb","\uD83D\uDE4C\uD83C\uDFFF":"1f64c-1f3ff","\uD83D\uDE4C\uD83C\uDFFE":"1f64c-1f3fe","\uD83D\uDE4C\uD83C\uDFFD":"1f64c-1f3fd","\uD83D\uDE4C\uD83C\uDFFC":"1f64c-1f3fc","\uD83D\uDE4C\uD83C\uDFFB":"1f64c-1f3fb","\uD83D\uDE4B\uD83C\uDFFF":"1f64b-1f3ff","\uD83D\uDE4B\uD83C\uDFFE":"1f64b-1f3fe","\uD83D\uDE4B\uD83C\uDFFD":"1f64b-1f3fd","\uD83D\uDE4B\uD83C\uDFFC":"1f64b-1f3fc","\uD83D\uDE4B\uD83C\uDFFB":"1f64b-1f3fb","\uD83D\uDE47\uD83C\uDFFF":"1f647-1f3ff","\uD83D\uDE47\uD83C\uDFFE":"1f647-1f3fe","\uD83D\uDE47\uD83C\uDFFD":"1f647-1f3fd","\uD83D\uDE47\uD83C\uDFFC":"1f647-1f3fc","\uD83D\uDE47\uD83C\uDFFB":"1f647-1f3fb","\uD83D\uDE46\uD83C\uDFFF":"1f646-1f3ff","\uD83D\uDE46\uD83C\uDFFE":"1f646-1f3fe","\uD83D\uDE46\uD83C\uDFFD":"1f646-1f3fd","\uD83D\uDE46\uD83C\uDFFC":"1f646-1f3fc","\uD83D\uDE46\uD83C\uDFFB":"1f646-1f3fb","\uD83D\uDE45\uD83C\uDFFF":"1f645-1f3ff","\uD83D\uDE45\uD83C\uDFFE":"1f645-1f3fe","\uD83D\uDE45\uD83C\uDFFD":"1f645-1f3fd","\uD83D\uDE45\uD83C\uDFFC":"1f645-1f3fc","\uD83D\uDE45\uD83C\uDFFB":"1f645-1f3fb","\uD83D\uDD96\uD83C\uDFFF":"1f596-1f3ff","\uD83D\uDD96\uD83C\uDFFE":"1f596-1f3fe","\uD83D\uDD96\uD83C\uDFFD":"1f596-1f3fd","\uD83D\uDD96\uD83C\uDFFC":"1f596-1f3fc","\uD83D\uDD96\uD83C\uDFFB":"1f596-1f3fb","\uD83D\uDD95\uD83C\uDFFF":"1f595-1f3ff","\uD83D\uDD95\uD83C\uDFFE":"1f595-1f3fe","\uD83D\uDD95\uD83C\uDFFD":"1f595-1f3fd","\uD83D\uDD95\uD83C\uDFFC":"1f595-1f3fc","\uD83D\uDD95\uD83C\uDFFB":"1f595-1f3fb","\uD83D\uDD90\uD83C\uDFFF":"1f590-1f3ff","\uD83D\uDD90\uD83C\uDFFE":"1f590-1f3fe","\uD83D\uDD90\uD83C\uDFFD":"1f590-1f3fd","\uD83D\uDD90\uD83C\uDFFC":"1f590-1f3fc","\uD83D\uDD90\uD83C\uDFFB":"1f590-1f3fb","\uD83D\uDD7A\uD83C\uDFFF":"1f57a-1f3ff","\uD83D\uDD7A\uD83C\uDFFE":"1f57a-1f3fe","\uD83D\uDD7A\uD83C\uDFFD":"1f57a-1f3fd","\uD83D\uDD7A\uD83C\uDFFC":"1f57a-1f3fc","\uD83D\uDD7A\uD83C\uDFFB":"1f57a-1f3fb","\uD83D\uDD75\uD83C\uDFFF":"1f575-1f3ff","\uD83D\uDD75\uD83C\uDFFE":"1f575-1f3fe","\uD83D\uDD75\uD83C\uDFFD":"1f575-1f3fd","\uD83D\uDD75\uD83C\uDFFC":"1f575-1f3fc","\uD83D\uDD75\uD83C\uDFFB":"1f575-1f3fb","\uD83D\uDCAA\uD83C\uDFFF":"1f4aa-1f3ff","\uD83D\uDCAA\uD83C\uDFFE":"1f4aa-1f3fe","\uD83D\uDCAA\uD83C\uDFFD":"1f4aa-1f3fd","\uD83D\uDCAA\uD83C\uDFFC":"1f4aa-1f3fc","\uD83D\uDCAA\uD83C\uDFFB":"1f4aa-1f3fb","\uD83D\uDC87\uD83C\uDFFF":"1f487-1f3ff","\uD83D\uDC87\uD83C\uDFFE":"1f487-1f3fe","\uD83D\uDC87\uD83C\uDFFD":"1f487-1f3fd","\uD83D\uDC87\uD83C\uDFFC":"1f487-1f3fc","\uD83D\uDC87\uD83C\uDFFB":"1f487-1f3fb","\uD83D\uDC86\uD83C\uDFFF":"1f486-1f3ff","\uD83D\uDC86\uD83C\uDFFE":"1f486-1f3fe","\uD83D\uDC86\uD83C\uDFFD":"1f486-1f3fd","\uD83D\uDC86\uD83C\uDFFC":"1f486-1f3fc","\uD83D\uDC86\uD83C\uDFFB":"1f486-1f3fb","\uD83D\uDC85\uD83C\uDFFF":"1f485-1f3ff","\uD83D\uDC85\uD83C\uDFFE":"1f485-1f3fe","\uD83D\uDC85\uD83C\uDFFD":"1f485-1f3fd","\uD83D\uDC85\uD83C\uDFFC":"1f485-1f3fc","\uD83D\uDC85\uD83C\uDFFB":"1f485-1f3fb","\uD83D\uDC83\uD83C\uDFFF":"1f483-1f3ff","\uD83D\uDC83\uD83C\uDFFE":"1f483-1f3fe","\uD83D\uDC83\uD83C\uDFFD":"1f483-1f3fd","\uD83D\uDC83\uD83C\uDFFC":"1f483-1f3fc","\uD83D\uDC83\uD83C\uDFFB":"1f483-1f3fb","\uD83D\uDC82\uD83C\uDFFF":"1f482-1f3ff","\uD83D\uDC82\uD83C\uDFFE":"1f482-1f3fe","\uD83D\uDC82\uD83C\uDFFD":"1f482-1f3fd","\uD83D\uDC82\uD83C\uDFFC":"1f482-1f3fc","\uD83D\uDC82\uD83C\uDFFB":"1f482-1f3fb","\uD83D\uDC81\uD83C\uDFFF":"1f481-1f3ff","\uD83D\uDC81\uD83C\uDFFE":"1f481-1f3fe","\uD83D\uDC81\uD83C\uDFFD":"1f481-1f3fd","\uD83D\uDC81\uD83C\uDFFC":"1f481-1f3fc","\uD83D\uDC81\uD83C\uDFFB":"1f481-1f3fb","\uD83D\uDC7C\uD83C\uDFFF":"1f47c-1f3ff","\uD83D\uDC7C\uD83C\uDFFE":"1f47c-1f3fe","\uD83D\uDC7C\uD83C\uDFFD":"1f47c-1f3fd","\uD83D\uDC7C\uD83C\uDFFC":"1f47c-1f3fc","\uD83D\uDC7C\uD83C\uDFFB":"1f47c-1f3fb","\uD83D\uDC78\uD83C\uDFFF":"1f478-1f3ff","\uD83D\uDC78\uD83C\uDFFE":"1f478-1f3fe","\uD83D\uDC78\uD83C\uDFFD":"1f478-1f3fd","\uD83D\uDC78\uD83C\uDFFC":"1f478-1f3fc","\uD83D\uDC78\uD83C\uDFFB":"1f478-1f3fb","\uD83D\uDC77\uD83C\uDFFF":"1f477-1f3ff","\uD83D\uDC77\uD83C\uDFFE":"1f477-1f3fe","\uD83D\uDC77\uD83C\uDFFD":"1f477-1f3fd","\uD83D\uDC77\uD83C\uDFFC":"1f477-1f3fc","\uD83D\uDC77\uD83C\uDFFB":"1f477-1f3fb","\uD83D\uDC76\uD83C\uDFFF":"1f476-1f3ff","\uD83D\uDC76\uD83C\uDFFE":"1f476-1f3fe","\uD83D\uDC76\uD83C\uDFFD":"1f476-1f3fd","\uD83D\uDC76\uD83C\uDFFC":"1f476-1f3fc","\uD83D\uDC76\uD83C\uDFFB":"1f476-1f3fb","\uD83D\uDC75\uD83C\uDFFF":"1f475-1f3ff","\uD83D\uDC75\uD83C\uDFFE":"1f475-1f3fe","\uD83D\uDC75\uD83C\uDFFD":"1f475-1f3fd","\uD83D\uDC75\uD83C\uDFFC":"1f475-1f3fc","\uD83D\uDC75\uD83C\uDFFB":"1f475-1f3fb","\uD83D\uDC74\uD83C\uDFFF":"1f474-1f3ff","\uD83D\uDC74\uD83C\uDFFE":"1f474-1f3fe","\uD83D\uDC74\uD83C\uDFFD":"1f474-1f3fd","\uD83D\uDC74\uD83C\uDFFC":"1f474-1f3fc","\uD83D\uDC74\uD83C\uDFFB":"1f474-1f3fb","\uD83D\uDC73\uD83C\uDFFF":"1f473-1f3ff","\uD83D\uDC73\uD83C\uDFFE":"1f473-1f3fe","\uD83D\uDC73\uD83C\uDFFD":"1f473-1f3fd","\uD83D\uDC73\uD83C\uDFFC":"1f473-1f3fc","\uD83D\uDC73\uD83C\uDFFB":"1f473-1f3fb","\uD83D\uDC72\uD83C\uDFFF":"1f472-1f3ff","\uD83D\uDC72\uD83C\uDFFE":"1f472-1f3fe","\uD83D\uDC72\uD83C\uDFFD":"1f472-1f3fd","\uD83D\uDC72\uD83C\uDFFC":"1f472-1f3fc","\uD83D\uDC72\uD83C\uDFFB":"1f472-1f3fb","\uD83D\uDC71\uD83C\uDFFF":"1f471-1f3ff","\uD83D\uDC71\uD83C\uDFFE":"1f471-1f3fe","\uD83D\uDC71\uD83C\uDFFD":"1f471-1f3fd","\uD83D\uDC71\uD83C\uDFFC":"1f471-1f3fc","\uD83D\uDC71\uD83C\uDFFB":"1f471-1f3fb","\uD83D\uDC70\uD83C\uDFFF":"1f470-1f3ff","\uD83D\uDC70\uD83C\uDFFE":"1f470-1f3fe","\uD83D\uDC70\uD83C\uDFFD":"1f470-1f3fd","\uD83D\uDC70\uD83C\uDFFC":"1f470-1f3fc","\uD83D\uDC70\uD83C\uDFFB":"1f470-1f3fb","\uD83D\uDC6E\uD83C\uDFFF":"1f46e-1f3ff","\uD83D\uDC6E\uD83C\uDFFE":"1f46e-1f3fe","\uD83D\uDC6E\uD83C\uDFFD":"1f46e-1f3fd","\uD83D\uDC6E\uD83C\uDFFC":"1f46e-1f3fc","\uD83D\uDC6E\uD83C\uDFFB":"1f46e-1f3fb","\uD83D\uDC69\uD83C\uDFFF":"1f469-1f3ff","\uD83D\uDC69\uD83C\uDFFE":"1f469-1f3fe","\uD83D\uDC69\uD83C\uDFFD":"1f469-1f3fd","\uD83D\uDC69\uD83C\uDFFC":"1f469-1f3fc","\uD83D\uDC69\uD83C\uDFFB":"1f469-1f3fb","\uD83D\uDC68\uD83C\uDFFF":"1f468-1f3ff","\uD83D\uDC68\uD83C\uDFFE":"1f468-1f3fe","\uD83D\uDC68\uD83C\uDFFD":"1f468-1f3fd","\uD83D\uDC68\uD83C\uDFFC":"1f468-1f3fc","\uD83D\uDC68\uD83C\uDFFB":"1f468-1f3fb","\uD83D\uDC67\uD83C\uDFFF":"1f467-1f3ff","\uD83D\uDC67\uD83C\uDFFE":"1f467-1f3fe","\uD83D\uDC67\uD83C\uDFFD":"1f467-1f3fd","\uD83D\uDC67\uD83C\uDFFC":"1f467-1f3fc","\uD83D\uDC67\uD83C\uDFFB":"1f467-1f3fb","\uD83D\uDC66\uD83C\uDFFF":"1f466-1f3ff","\uD83D\uDC66\uD83C\uDFFE":"1f466-1f3fe","\uD83D\uDC66\uD83C\uDFFD":"1f466-1f3fd","\uD83D\uDC66\uD83C\uDFFC":"1f466-1f3fc","\uD83D\uDC66\uD83C\uDFFB":"1f466-1f3fb","\uD83D\uDC50\uD83C\uDFFF":"1f450-1f3ff","\uD83D\uDC50\uD83C\uDFFE":"1f450-1f3fe","\uD83D\uDC50\uD83C\uDFFD":"1f450-1f3fd","\uD83D\uDC50\uD83C\uDFFC":"1f450-1f3fc","\uD83D\uDC50\uD83C\uDFFB":"1f450-1f3fb","\uD83D\uDC4F\uD83C\uDFFF":"1f44f-1f3ff","\uD83D\uDC4F\uD83C\uDFFE":"1f44f-1f3fe","\uD83D\uDC4F\uD83C\uDFFD":"1f44f-1f3fd","\uD83D\uDC4F\uD83C\uDFFC":"1f44f-1f3fc","\uD83D\uDC4F\uD83C\uDFFB":"1f44f-1f3fb","\uD83D\uDC4E\uD83C\uDFFF":"1f44e-1f3ff","\uD83D\uDC4E\uD83C\uDFFE":"1f44e-1f3fe","\uD83D\uDC4E\uD83C\uDFFD":"1f44e-1f3fd","\uD83D\uDC4E\uD83C\uDFFC":"1f44e-1f3fc","\uD83D\uDC4E\uD83C\uDFFB":"1f44e-1f3fb","\uD83D\uDC4D\uD83C\uDFFF":"1f44d-1f3ff","\uD83D\uDC4D\uD83C\uDFFE":"1f44d-1f3fe","\uD83D\uDC4D\uD83C\uDFFD":"1f44d-1f3fd","\uD83D\uDC4D\uD83C\uDFFC":"1f44d-1f3fc","\uD83D\uDC4D\uD83C\uDFFB":"1f44d-1f3fb","\uD83D\uDC4C\uD83C\uDFFF":"1f44c-1f3ff","\uD83D\uDC4C\uD83C\uDFFE":"1f44c-1f3fe","\uD83D\uDC4C\uD83C\uDFFD":"1f44c-1f3fd","\uD83D\uDC4C\uD83C\uDFFC":"1f44c-1f3fc","\uD83D\uDC4C\uD83C\uDFFB":"1f44c-1f3fb","\uD83D\uDC4B\uD83C\uDFFF":"1f44b-1f3ff","\uD83D\uDC4B\uD83C\uDFFE":"1f44b-1f3fe","\uD83D\uDC4B\uD83C\uDFFD":"1f44b-1f3fd","\uD83D\uDC4B\uD83C\uDFFC":"1f44b-1f3fc","\uD83D\uDC4B\uD83C\uDFFB":"1f44b-1f3fb","\uD83D\uDC4A\uD83C\uDFFF":"1f44a-1f3ff","\uD83D\uDC4A\uD83C\uDFFE":"1f44a-1f3fe","\uD83D\uDC4A\uD83C\uDFFD":"1f44a-1f3fd","\uD83D\uDC4A\uD83C\uDFFC":"1f44a-1f3fc","\uD83D\uDC4A\uD83C\uDFFB":"1f44a-1f3fb","\uD83D\uDC49\uD83C\uDFFF":"1f449-1f3ff","\uD83D\uDC49\uD83C\uDFFE":"1f449-1f3fe","\uD83D\uDC49\uD83C\uDFFD":"1f449-1f3fd","\uD83D\uDC49\uD83C\uDFFC":"1f449-1f3fc","\uD83D\uDC49\uD83C\uDFFB":"1f449-1f3fb","\uD83D\uDC48\uD83C\uDFFF":"1f448-1f3ff","\uD83D\uDC48\uD83C\uDFFE":"1f448-1f3fe","\uD83D\uDC48\uD83C\uDFFD":"1f448-1f3fd","\uD83D\uDC48\uD83C\uDFFC":"1f448-1f3fc","\uD83D\uDC48\uD83C\uDFFB":"1f448-1f3fb","\uD83D\uDC47\uD83C\uDFFF":"1f447-1f3ff","\uD83D\uDC47\uD83C\uDFFE":"1f447-1f3fe","\uD83D\uDC47\uD83C\uDFFD":"1f447-1f3fd","\uD83D\uDC47\uD83C\uDFFC":"1f447-1f3fc","\uD83D\uDC47\uD83C\uDFFB":"1f447-1f3fb","\uD83D\uDC46\uD83C\uDFFF":"1f446-1f3ff","\uD83D\uDC46\uD83C\uDFFE":"1f446-1f3fe","\uD83D\uDC46\uD83C\uDFFD":"1f446-1f3fd","\uD83D\uDC46\uD83C\uDFFC":"1f446-1f3fc","\uD83D\uDC46\uD83C\uDFFB":"1f446-1f3fb","\uD83D\uDC43\uD83C\uDFFF":"1f443-1f3ff","\uD83D\uDC43\uD83C\uDFFE":"1f443-1f3fe","\uD83D\uDC43\uD83C\uDFFD":"1f443-1f3fd","\uD83D\uDC43\uD83C\uDFFC":"1f443-1f3fc","\uD83D\uDC43\uD83C\uDFFB":"1f443-1f3fb","\uD83D\uDC42\uD83C\uDFFF":"1f442-1f3ff","\uD83D\uDC42\uD83C\uDFFE":"1f442-1f3fe","\uD83D\uDC42\uD83C\uDFFD":"1f442-1f3fd","\uD83D\uDC42\uD83C\uDFFC":"1f442-1f3fc","\uD83D\uDC42\uD83C\uDFFB":"1f442-1f3fb","\uD83C\uDFF3\uD83C\uDF08":"1f3f3-1f308","\uD83C\uDFCB\uD83C\uDFFF":"1f3cb-1f3ff","\uD83C\uDFCB\uD83C\uDFFE":"1f3cb-1f3fe","\uD83C\uDFCB\uD83C\uDFFD":"1f3cb-1f3fd","\uD83C\uDFCB\uD83C\uDFFC":"1f3cb-1f3fc","\uD83C\uDFCB\uD83C\uDFFB":"1f3cb-1f3fb","\uD83C\uDFCA\uD83C\uDFFF":"1f3ca-1f3ff","\uD83C\uDFCA\uD83C\uDFFE":"1f3ca-1f3fe","\uD83C\uDFCA\uD83C\uDFFD":"1f3ca-1f3fd","\uD83C\uDFCA\uD83C\uDFFC":"1f3ca-1f3fc","\uD83C\uDFCA\uD83C\uDFFB":"1f3ca-1f3fb","\uD83C\uDFC7\uD83C\uDFFF":"1f3c7-1f3ff","\uD83C\uDFC7\uD83C\uDFFE":"1f3c7-1f3fe","\uD83C\uDFC7\uD83C\uDFFD":"1f3c7-1f3fd","\uD83C\uDFC7\uD83C\uDFFC":"1f3c7-1f3fc","\uD83C\uDFC7\uD83C\uDFFB":"1f3c7-1f3fb","\uD83C\uDFC4\uD83C\uDFFF":"1f3c4-1f3ff","\uD83C\uDFC4\uD83C\uDFFE":"1f3c4-1f3fe","\uD83C\uDFC4\uD83C\uDFFD":"1f3c4-1f3fd","\uD83C\uDFC4\uD83C\uDFFC":"1f3c4-1f3fc","\uD83C\uDFC4\uD83C\uDFFB":"1f3c4-1f3fb","\uD83C\uDFC3\uD83C\uDFFF":"1f3c3-1f3ff","\uD83C\uDFC3\uD83C\uDFFE":"1f3c3-1f3fe","\uD83C\uDFC3\uD83C\uDFFD":"1f3c3-1f3fd","\uD83C\uDFC3\uD83C\uDFFC":"1f3c3-1f3fc","\uD83C\uDFC3\uD83C\uDFFB":"1f3c3-1f3fb","\uD83C\uDF85\uD83C\uDFFF":"1f385-1f3ff","\uD83C\uDF85\uD83C\uDFFE":"1f385-1f3fe","\uD83C\uDF85\uD83C\uDFFD":"1f385-1f3fd","\uD83C\uDF85\uD83C\uDFFC":"1f385-1f3fc","\uD83C\uDF85\uD83C\uDFFB":"1f385-1f3fb","\uD83C\uDDFF\uD83C\uDDFC":"1f1ff-1f1fc","\uD83C\uDDFF\uD83C\uDDF2":"1f1ff-1f1f2","\uD83C\uDDFF\uD83C\uDDE6":"1f1ff-1f1e6","\uD83C\uDDFE\uD83C\uDDF9":"1f1fe-1f1f9","\uD83C\uDDFE\uD83C\uDDEA":"1f1fe-1f1ea","\uD83C\uDDFD\uD83C\uDDF0":"1f1fd-1f1f0","\uD83C\uDDFC\uD83C\uDDF8":"1f1fc-1f1f8","\uD83C\uDDFC\uD83C\uDDEB":"1f1fc-1f1eb","\uD83C\uDDFB\uD83C\uDDFA":"1f1fb-1f1fa","\uD83C\uDDFB\uD83C\uDDF3":"1f1fb-1f1f3","\uD83C\uDDFB\uD83C\uDDEE":"1f1fb-1f1ee","\uD83C\uDDFB\uD83C\uDDEC":"1f1fb-1f1ec","\uD83C\uDDFB\uD83C\uDDEA":"1f1fb-1f1ea","\uD83C\uDDFB\uD83C\uDDE8":"1f1fb-1f1e8","\uD83C\uDDFB\uD83C\uDDE6":"1f1fb-1f1e6","\uD83C\uDDFA\uD83C\uDDFF":"1f1fa-1f1ff","\uD83C\uDDFA\uD83C\uDDFE":"1f1fa-1f1fe","\uD83C\uDDFA\uD83C\uDDF8":"1f1fa-1f1f8","\uD83C\uDDFA\uD83C\uDDF2":"1f1fa-1f1f2","\uD83C\uDDFA\uD83C\uDDEC":"1f1fa-1f1ec","\uD83C\uDDFA\uD83C\uDDE6":"1f1fa-1f1e6","\uD83C\uDDF9\uD83C\uDDFF":"1f1f9-1f1ff","\uD83C\uDDF9\uD83C\uDDFC":"1f1f9-1f1fc","\uD83C\uDDF9\uD83C\uDDFB":"1f1f9-1f1fb","\uD83C\uDDF9\uD83C\uDDF9":"1f1f9-1f1f9","\uD83C\uDDF9\uD83C\uDDF7":"1f1f9-1f1f7","\uD83C\uDDF9\uD83C\uDDF4":"1f1f9-1f1f4","\uD83C\uDDF9\uD83C\uDDF3":"1f1f9-1f1f3","\uD83C\uDDF9\uD83C\uDDF2":"1f1f9-1f1f2","\uD83C\uDDF9\uD83C\uDDF1":"1f1f9-1f1f1","\uD83C\uDDF9\uD83C\uDDF0":"1f1f9-1f1f0","\uD83C\uDDF9\uD83C\uDDEF":"1f1f9-1f1ef","\uD83C\uDDF9\uD83C\uDDED":"1f1f9-1f1ed","\uD83C\uDDF9\uD83C\uDDEC":"1f1f9-1f1ec","\uD83C\uDDF9\uD83C\uDDEB":"1f1f9-1f1eb","\uD83C\uDDF9\uD83C\uDDE9":"1f1f9-1f1e9","\uD83C\uDDF9\uD83C\uDDE8":"1f1f9-1f1e8","\uD83C\uDDF9\uD83C\uDDE6":"1f1f9-1f1e6","\uD83C\uDDF8\uD83C\uDDFF":"1f1f8-1f1ff","\uD83C\uDDF8\uD83C\uDDFE":"1f1f8-1f1fe","\uD83C\uDDF8\uD83C\uDDFD":"1f1f8-1f1fd","\uD83C\uDDF8\uD83C\uDDFB":"1f1f8-1f1fb","\uD83C\uDDF8\uD83C\uDDF9":"1f1f8-1f1f9","\uD83C\uDDF8\uD83C\uDDF8":"1f1f8-1f1f8","\uD83C\uDDF8\uD83C\uDDF7":"1f1f8-1f1f7","\uD83C\uDDF8\uD83C\uDDF4":"1f1f8-1f1f4","\uD83C\uDDF8\uD83C\uDDF3":"1f1f8-1f1f3","\uD83C\uDDF8\uD83C\uDDF2":"1f1f8-1f1f2","\uD83C\uDDF8\uD83C\uDDF1":"1f1f8-1f1f1","\uD83C\uDDF8\uD83C\uDDF0":"1f1f8-1f1f0","\uD83C\uDDF8\uD83C\uDDEF":"1f1f8-1f1ef","\uD83C\uDDF8\uD83C\uDDEE":"1f1f8-1f1ee","\uD83C\uDDF8\uD83C\uDDED":"1f1f8-1f1ed","\uD83C\uDDF8\uD83C\uDDEC":"1f1f8-1f1ec","\uD83C\uDDF8\uD83C\uDDEA":"1f1f8-1f1ea","\uD83C\uDDF8\uD83C\uDDE9":"1f1f8-1f1e9","\uD83C\uDDF8\uD83C\uDDE8":"1f1f8-1f1e8","\uD83C\uDDF8\uD83C\uDDE7":"1f1f8-1f1e7","\uD83C\uDDF8\uD83C\uDDE6":"1f1f8-1f1e6","\uD83C\uDDF7\uD83C\uDDFC":"1f1f7-1f1fc","\uD83C\uDDF7\uD83C\uDDFA":"1f1f7-1f1fa","\uD83C\uDDF7\uD83C\uDDF8":"1f1f7-1f1f8","\uD83C\uDDF7\uD83C\uDDF4":"1f1f7-1f1f4","\uD83C\uDDF7\uD83C\uDDEA":"1f1f7-1f1ea","\uD83C\uDDF6\uD83C\uDDE6":"1f1f6-1f1e6","\uD83C\uDDF5\uD83C\uDDFE":"1f1f5-1f1fe","\uD83C\uDDF5\uD83C\uDDFC":"1f1f5-1f1fc","\uD83C\uDDF5\uD83C\uDDF9":"1f1f5-1f1f9","\uD83C\uDDF5\uD83C\uDDF8":"1f1f5-1f1f8","\uD83C\uDDF5\uD83C\uDDF7":"1f1f5-1f1f7","\uD83C\uDDF5\uD83C\uDDF3":"1f1f5-1f1f3","\uD83C\uDDF5\uD83C\uDDF2":"1f1f5-1f1f2","\uD83C\uDDF5\uD83C\uDDF1":"1f1f5-1f1f1","\uD83C\uDDF5\uD83C\uDDF0":"1f1f5-1f1f0","\uD83C\uDDF5\uD83C\uDDED":"1f1f5-1f1ed","\uD83C\uDDF5\uD83C\uDDEC":"1f1f5-1f1ec","\uD83C\uDDF5\uD83C\uDDEB":"1f1f5-1f1eb","\uD83C\uDDF5\uD83C\uDDEA":"1f1f5-1f1ea","\uD83C\uDDF5\uD83C\uDDE6":"1f1f5-1f1e6","\uD83C\uDDF4\uD83C\uDDF2":"1f1f4-1f1f2","\uD83C\uDDF3\uD83C\uDDFF":"1f1f3-1f1ff","\uD83C\uDDF3\uD83C\uDDFA":"1f1f3-1f1fa","\uD83C\uDDF3\uD83C\uDDF7":"1f1f3-1f1f7","\uD83C\uDDF3\uD83C\uDDF5":"1f1f3-1f1f5","\uD83C\uDDF3\uD83C\uDDF4":"1f1f3-1f1f4","\uD83C\uDDF3\uD83C\uDDF1":"1f1f3-1f1f1","\uD83C\uDDF3\uD83C\uDDEE":"1f1f3-1f1ee","\uD83C\uDDF3\uD83C\uDDEC":"1f1f3-1f1ec","\uD83C\uDDF3\uD83C\uDDEB":"1f1f3-1f1eb","\uD83C\uDDF3\uD83C\uDDEA":"1f1f3-1f1ea","\uD83C\uDDF3\uD83C\uDDE8":"1f1f3-1f1e8","\uD83C\uDDF3\uD83C\uDDE6":"1f1f3-1f1e6","\uD83C\uDDF2\uD83C\uDDFF":"1f1f2-1f1ff","\uD83C\uDDF2\uD83C\uDDFE":"1f1f2-1f1fe","\uD83C\uDDF2\uD83C\uDDFD":"1f1f2-1f1fd","\uD83C\uDDF2\uD83C\uDDFC":"1f1f2-1f1fc","\uD83C\uDDF2\uD83C\uDDFB":"1f1f2-1f1fb","\uD83C\uDDF2\uD83C\uDDFA":"1f1f2-1f1fa","\uD83C\uDDF2\uD83C\uDDF9":"1f1f2-1f1f9","\uD83C\uDDF2\uD83C\uDDF8":"1f1f2-1f1f8","\uD83C\uDDF2\uD83C\uDDF7":"1f1f2-1f1f7","\uD83C\uDDF2\uD83C\uDDF6":"1f1f2-1f1f6","\uD83C\uDDF2\uD83C\uDDF5":"1f1f2-1f1f5","\uD83C\uDDF2\uD83C\uDDF4":"1f1f2-1f1f4","\uD83C\uDDF2\uD83C\uDDF3":"1f1f2-1f1f3","\uD83C\uDDF2\uD83C\uDDF2":"1f1f2-1f1f2","\uD83C\uDDF2\uD83C\uDDF1":"1f1f2-1f1f1","\uD83C\uDDF2\uD83C\uDDF0":"1f1f2-1f1f0","\uD83C\uDDF2\uD83C\uDDED":"1f1f2-1f1ed","\uD83C\uDDF2\uD83C\uDDEC":"1f1f2-1f1ec","\uD83C\uDDF2\uD83C\uDDEB":"1f1f2-1f1eb","\uD83C\uDDF2\uD83C\uDDEA":"1f1f2-1f1ea","\uD83C\uDDF2\uD83C\uDDE9":"1f1f2-1f1e9","\uD83C\uDDF2\uD83C\uDDE8":"1f1f2-1f1e8","\uD83C\uDDF2\uD83C\uDDE6":"1f1f2-1f1e6","\uD83C\uDDF1\uD83C\uDDFE":"1f1f1-1f1fe","\uD83C\uDDF1\uD83C\uDDFB":"1f1f1-1f1fb","\uD83C\uDDF1\uD83C\uDDFA":"1f1f1-1f1fa","\uD83C\uDDF1\uD83C\uDDF9":"1f1f1-1f1f9","\uD83C\uDDF1\uD83C\uDDF8":"1f1f1-1f1f8","\uD83C\uDDF1\uD83C\uDDF7":"1f1f1-1f1f7","\uD83C\uDDF1\uD83C\uDDF0":"1f1f1-1f1f0","\uD83C\uDDF1\uD83C\uDDEE":"1f1f1-1f1ee","\uD83C\uDDF1\uD83C\uDDE8":"1f1f1-1f1e8","\uD83C\uDDF1\uD83C\uDDE7":"1f1f1-1f1e7","\uD83C\uDDF1\uD83C\uDDE6":"1f1f1-1f1e6","\uD83C\uDDF0\uD83C\uDDFF":"1f1f0-1f1ff","\uD83C\uDDF0\uD83C\uDDFE":"1f1f0-1f1fe","\uD83C\uDDF0\uD83C\uDDFC":"1f1f0-1f1fc","\uD83C\uDDF0\uD83C\uDDF7":"1f1f0-1f1f7","\uD83C\uDDF0\uD83C\uDDF5":"1f1f0-1f1f5","\uD83C\uDDF0\uD83C\uDDF3":"1f1f0-1f1f3","\uD83C\uDDF0\uD83C\uDDF2":"1f1f0-1f1f2","\uD83C\uDDF0\uD83C\uDDEE":"1f1f0-1f1ee","\uD83C\uDDF0\uD83C\uDDED":"1f1f0-1f1ed","\uD83C\uDDF0\uD83C\uDDEC":"1f1f0-1f1ec","\uD83C\uDDF0\uD83C\uDDEA":"1f1f0-1f1ea","\uD83C\uDDEF\uD83C\uDDF5":"1f1ef-1f1f5","\uD83C\uDDEF\uD83C\uDDF4":"1f1ef-1f1f4","\uD83C\uDDEF\uD83C\uDDF2":"1f1ef-1f1f2","\uD83C\uDDEF\uD83C\uDDEA":"1f1ef-1f1ea","\uD83C\uDDEE\uD83C\uDDF9":"1f1ee-1f1f9","\uD83C\uDDEE\uD83C\uDDF8":"1f1ee-1f1f8","\uD83C\uDDEE\uD83C\uDDF7":"1f1ee-1f1f7","\uD83C\uDDEE\uD83C\uDDF6":"1f1ee-1f1f6","\uD83C\uDDEE\uD83C\uDDF4":"1f1ee-1f1f4","\uD83C\uDDEE\uD83C\uDDF3":"1f1ee-1f1f3","\uD83C\uDDEE\uD83C\uDDF2":"1f1ee-1f1f2","\uD83C\uDDEE\uD83C\uDDF1":"1f1ee-1f1f1","\uD83C\uDDEE\uD83C\uDDEA":"1f1ee-1f1ea","\uD83C\uDDEE\uD83C\uDDE9":"1f1ee-1f1e9","\uD83C\uDDEE\uD83C\uDDE8":"1f1ee-1f1e8","\uD83C\uDDED\uD83C\uDDFA":"1f1ed-1f1fa","\uD83C\uDDED\uD83C\uDDF9":"1f1ed-1f1f9","\uD83C\uDDED\uD83C\uDDF7":"1f1ed-1f1f7","\uD83C\uDDED\uD83C\uDDF3":"1f1ed-1f1f3","\uD83C\uDDED\uD83C\uDDF2":"1f1ed-1f1f2","\uD83C\uDDED\uD83C\uDDF0":"1f1ed-1f1f0","\uD83C\uDDEC\uD83C\uDDFE":"1f1ec-1f1fe","\uD83C\uDDEC\uD83C\uDDFC":"1f1ec-1f1fc","\uD83C\uDDEC\uD83C\uDDFA":"1f1ec-1f1fa","\uD83C\uDDEC\uD83C\uDDF9":"1f1ec-1f1f9","\uD83C\uDDEC\uD83C\uDDF8":"1f1ec-1f1f8","\uD83C\uDDEC\uD83C\uDDF7":"1f1ec-1f1f7","\uD83C\uDDEC\uD83C\uDDF6":"1f1ec-1f1f6","\uD83C\uDDEC\uD83C\uDDF5":"1f1ec-1f1f5","\uD83C\uDDEC\uD83C\uDDF3":"1f1ec-1f1f3","\uD83C\uDDEC\uD83C\uDDF2":"1f1ec-1f1f2","\uD83C\uDDEC\uD83C\uDDF1":"1f1ec-1f1f1","\uD83C\uDDEC\uD83C\uDDEE":"1f1ec-1f1ee","\uD83C\uDDEC\uD83C\uDDED":"1f1ec-1f1ed","\uD83C\uDDEC\uD83C\uDDEC":"1f1ec-1f1ec","\uD83C\uDDEC\uD83C\uDDEB":"1f1ec-1f1eb","\uD83C\uDDEC\uD83C\uDDEA":"1f1ec-1f1ea","\uD83C\uDDEC\uD83C\uDDE9":"1f1ec-1f1e9","\uD83C\uDDEC\uD83C\uDDE7":"1f1ec-1f1e7","\uD83C\uDDEC\uD83C\uDDE6":"1f1ec-1f1e6","\uD83C\uDDEB\uD83C\uDDF7":"1f1eb-1f1f7","\uD83C\uDDEB\uD83C\uDDF4":"1f1eb-1f1f4","\uD83C\uDDEB\uD83C\uDDF2":"1f1eb-1f1f2","\uD83C\uDDEB\uD83C\uDDF0":"1f1eb-1f1f0","\uD83C\uDDEB\uD83C\uDDEF":"1f1eb-1f1ef","\uD83C\uDDEB\uD83C\uDDEE":"1f1eb-1f1ee","\uD83C\uDDEA\uD83C\uDDFA":"1f1ea-1f1fa","\uD83C\uDDEA\uD83C\uDDF9":"1f1ea-1f1f9","\uD83C\uDDEA\uD83C\uDDF8":"1f1ea-1f1f8","\uD83C\uDDEA\uD83C\uDDF7":"1f1ea-1f1f7","\uD83C\uDDEA\uD83C\uDDED":"1f1ea-1f1ed","\uD83C\uDDEA\uD83C\uDDEC":"1f1ea-1f1ec","\uD83C\uDDEA\uD83C\uDDEA":"1f1ea-1f1ea","\uD83C\uDDEA\uD83C\uDDE8":"1f1ea-1f1e8","\uD83C\uDDEA\uD83C\uDDE6":"1f1ea-1f1e6","\uD83C\uDDE9\uD83C\uDDFF":"1f1e9-1f1ff","\uD83C\uDDE9\uD83C\uDDF4":"1f1e9-1f1f4","\uD83C\uDDE9\uD83C\uDDF2":"1f1e9-1f1f2","\uD83C\uDDE9\uD83C\uDDF0":"1f1e9-1f1f0","\uD83C\uDDE9\uD83C\uDDEF":"1f1e9-1f1ef","\uD83C\uDDE9\uD83C\uDDEC":"1f1e9-1f1ec","\uD83C\uDDE9\uD83C\uDDEA":"1f1e9-1f1ea","\uD83C\uDDE8\uD83C\uDDFF":"1f1e8-1f1ff","\uD83C\uDDE8\uD83C\uDDFE":"1f1e8-1f1fe","\uD83C\uDDE8\uD83C\uDDFD":"1f1e8-1f1fd","\uD83C\uDDE8\uD83C\uDDFC":"1f1e8-1f1fc","\uD83C\uDDE8\uD83C\uDDFB":"1f1e8-1f1fb","\uD83C\uDDE8\uD83C\uDDFA":"1f1e8-1f1fa","\uD83C\uDDE8\uD83C\uDDF7":"1f1e8-1f1f7","\uD83C\uDDE8\uD83C\uDDF5":"1f1e8-1f1f5","\uD83C\uDDE8\uD83C\uDDF4":"1f1e8-1f1f4","\uD83C\uDDE8\uD83C\uDDF3":"1f1e8-1f1f3","\uD83C\uDDE8\uD83C\uDDF2":"1f1e8-1f1f2","\uD83C\uDDE8\uD83C\uDDF1":"1f1e8-1f1f1","\uD83C\uDDE8\uD83C\uDDF0":"1f1e8-1f1f0","\uD83C\uDDE8\uD83C\uDDEE":"1f1e8-1f1ee","\uD83C\uDDE8\uD83C\uDDED":"1f1e8-1f1ed","\uD83C\uDDE8\uD83C\uDDEC":"1f1e8-1f1ec","\uD83C\uDDE8\uD83C\uDDEB":"1f1e8-1f1eb","\uD83C\uDDE8\uD83C\uDDE9":"1f1e8-1f1e9","\uD83C\uDDE8\uD83C\uDDE8":"1f1e8-1f1e8","\uD83C\uDDE8\uD83C\uDDE6":"1f1e8-1f1e6","\uD83C\uDDE7\uD83C\uDDFF":"1f1e7-1f1ff","\uD83C\uDDE7\uD83C\uDDFE":"1f1e7-1f1fe","\uD83C\uDDE7\uD83C\uDDFC":"1f1e7-1f1fc","\uD83C\uDDE7\uD83C\uDDFB":"1f1e7-1f1fb","\uD83C\uDDE7\uD83C\uDDF9":"1f1e7-1f1f9","\uD83C\uDDE7\uD83C\uDDF8":"1f1e7-1f1f8","\uD83C\uDDE7\uD83C\uDDF7":"1f1e7-1f1f7","\uD83C\uDDE7\uD83C\uDDF6":"1f1e7-1f1f6","\uD83C\uDDE7\uD83C\uDDF4":"1f1e7-1f1f4","\uD83C\uDDE7\uD83C\uDDF3":"1f1e7-1f1f3","\uD83C\uDDE7\uD83C\uDDF2":"1f1e7-1f1f2","\uD83C\uDDE7\uD83C\uDDF1":"1f1e7-1f1f1","\uD83C\uDDE7\uD83C\uDDEF":"1f1e7-1f1ef","\uD83C\uDDE7\uD83C\uDDEE":"1f1e7-1f1ee","\uD83C\uDDE7\uD83C\uDDED":"1f1e7-1f1ed","\uD83C\uDDE7\uD83C\uDDEC":"1f1e7-1f1ec","\uD83C\uDDE7\uD83C\uDDEB":"1f1e7-1f1eb","\uD83C\uDDE7\uD83C\uDDEA":"1f1e7-1f1ea","\uD83C\uDDE7\uD83C\uDDE9":"1f1e7-1f1e9","\uD83C\uDDE7\uD83C\uDDE7":"1f1e7-1f1e7","\uD83C\uDDE7\uD83C\uDDE6":"1f1e7-1f1e6","\uD83C\uDDE6\uD83C\uDDFF":"1f1e6-1f1ff","\uD83C\uDDE6\uD83C\uDDFD":"1f1e6-1f1fd","\uD83C\uDDE6\uD83C\uDDFC":"1f1e6-1f1fc","\uD83C\uDDE6\uD83C\uDDFA":"1f1e6-1f1fa","\uD83C\uDDE6\uD83C\uDDF9":"1f1e6-1f1f9","\uD83C\uDDE6\uD83C\uDDF8":"1f1e6-1f1f8","\uD83C\uDDE6\uD83C\uDDF7":"1f1e6-1f1f7","\uD83C\uDDE6\uD83C\uDDF6":"1f1e6-1f1f6","\uD83C\uDDE6\uD83C\uDDF4":"1f1e6-1f1f4","\uD83C\uDDE6\uD83C\uDDF2":"1f1e6-1f1f2","\uD83C\uDDE6\uD83C\uDDF1":"1f1e6-1f1f1","\uD83C\uDDE6\uD83C\uDDEE":"1f1e6-1f1ee","\uD83C\uDDE6\uD83C\uDDEC":"1f1e6-1f1ec","\uD83C\uDDE6\uD83C\uDDEB":"1f1e6-1f1eb","\uD83C\uDDE6\uD83C\uDDEA":"1f1e6-1f1ea","\uD83C\uDDE6\uD83C\uDDE9":"1f1e6-1f1e9","\uD83C\uDDE6\uD83C\uDDE8":"1f1e6-1f1e8","\uD83C\uDC04":"1f004","\uD83C\uDD7F":"1f17f","\uD83C\uDE02":"1f202","\uD83C\uDE1A":"1f21a","\uD83C\uDE2F":"1f22f","\uD83C\uDE37":"1f237","\uD83C\uDF9E":"1f39e","\uD83C\uDF9F":"1f39f","\uD83C\uDFCB":"1f3cb","\uD83C\uDFCC":"1f3cc","\uD83C\uDFCD":"1f3cd","\uD83C\uDFCE":"1f3ce","\uD83C\uDF96":"1f396","\uD83C\uDF97":"1f397","\uD83C\uDF36":"1f336","\uD83C\uDF27":"1f327","\uD83C\uDF28":"1f328","\uD83C\uDF29":"1f329","\uD83C\uDF2A":"1f32a","\uD83C\uDF2B":"1f32b","\uD83C\uDF2C":"1f32c","\uD83D\uDC3F":"1f43f","\uD83D\uDD77":"1f577","\uD83D\uDD78":"1f578","\uD83C\uDF21":"1f321","\uD83C\uDF99":"1f399","\uD83C\uDF9A":"1f39a","\uD83C\uDF9B":"1f39b","\uD83C\uDFF3":"1f3f3","\uD83C\uDFF5":"1f3f5","\uD83C\uDFF7":"1f3f7","\uD83D\uDCFD":"1f4fd","\uD83D\uDD49":"1f549","\uD83D\uDD4A":"1f54a","\uD83D\uDD6F":"1f56f","\uD83D\uDD70":"1f570","\uD83D\uDD73":"1f573","\uD83D\uDD76":"1f576","\uD83D\uDD79":"1f579","\uD83D\uDD87":"1f587","\uD83D\uDD8A":"1f58a","\uD83D\uDD8B":"1f58b","\uD83D\uDD8C":"1f58c","\uD83D\uDD8D":"1f58d","\uD83D\uDDA5":"1f5a5","\uD83D\uDDA8":"1f5a8","\uD83D\uDDB2":"1f5b2","\uD83D\uDDBC":"1f5bc","\uD83D\uDDC2":"1f5c2","\uD83D\uDDC3":"1f5c3","\uD83D\uDDC4":"1f5c4","\uD83D\uDDD1":"1f5d1","\uD83D\uDDD2":"1f5d2","\uD83D\uDDD3":"1f5d3","\uD83D\uDDDC":"1f5dc","\uD83D\uDDDD":"1f5dd","\uD83D\uDDDE":"1f5de","\uD83D\uDDE1":"1f5e1","\uD83D\uDDE3":"1f5e3","\uD83D\uDDE8":"1f5e8","\uD83D\uDDEF":"1f5ef","\uD83D\uDDF3":"1f5f3","\uD83D\uDDFA":"1f5fa","\uD83D\uDEE0":"1f6e0","\uD83D\uDEE1":"1f6e1","\uD83D\uDEE2":"1f6e2","\uD83D\uDEF0":"1f6f0","\uD83C\uDF7D":"1f37d","\uD83D\uDC41":"1f441","\uD83D\uDD74":"1f574","\uD83D\uDD75":"1f575","\uD83D\uDD90":"1f590","\uD83C\uDFD4":"1f3d4","\uD83C\uDFD5":"1f3d5","\uD83C\uDFD6":"1f3d6","\uD83C\uDFD7":"1f3d7","\uD83C\uDFD8":"1f3d8","\uD83C\uDFD9":"1f3d9","\uD83C\uDFDA":"1f3da","\uD83C\uDFDB":"1f3db","\uD83C\uDFDC":"1f3dc","\uD83C\uDFDD":"1f3dd","\uD83C\uDFDE":"1f3de","\uD83C\uDFDF":"1f3df","\uD83D\uDECB":"1f6cb","\uD83D\uDECD":"1f6cd","\uD83D\uDECE":"1f6ce","\uD83D\uDECF":"1f6cf","\uD83D\uDEE3":"1f6e3","\uD83D\uDEE4":"1f6e4","\uD83D\uDEE5":"1f6e5","\uD83D\uDEE9":"1f6e9","\uD83D\uDEF3":"1f6f3","\uD83C\uDF24":"1f324","\uD83C\uDF25":"1f325","\uD83C\uDF26":"1f326","\uD83D\uDDB1":"1f5b1","\u261D\uD83C\uDFFB":"261d-1f3fb","\u261D\uD83C\uDFFC":"261d-1f3fc","\u261D\uD83C\uDFFD":"261d-1f3fd","\u261D\uD83C\uDFFE":"261d-1f3fe","\u261D\uD83C\uDFFF":"261d-1f3ff","\u270C\uD83C\uDFFB":"270c-1f3fb","\u270C\uD83C\uDFFC":"270c-1f3fc","\u270C\uD83C\uDFFD":"270c-1f3fd","\u270C\uD83C\uDFFE":"270c-1f3fe","\u270C\uD83C\uDFFF":"270c-1f3ff","\u270A\uD83C\uDFFB":"270a-1f3fb","\u270A\uD83C\uDFFC":"270a-1f3fc","\u270A\uD83C\uDFFD":"270a-1f3fd","\u270A\uD83C\uDFFE":"270a-1f3fe","\u270A\uD83C\uDFFF":"270a-1f3ff","\u270B\uD83C\uDFFB":"270b-1f3fb","\u270B\uD83C\uDFFC":"270b-1f3fc","\u270B\uD83C\uDFFD":"270b-1f3fd","\u270B\uD83C\uDFFE":"270b-1f3fe","\u270B\uD83C\uDFFF":"270b-1f3ff","\u270D\uD83C\uDFFB":"270d-1f3fb","\u270D\uD83C\uDFFC":"270d-1f3fc","\u270D\uD83C\uDFFD":"270d-1f3fd","\u270D\uD83C\uDFFE":"270d-1f3fe","\u270D\uD83C\uDFFF":"270d-1f3ff","\u26F9\uD83C\uDFFB":"26f9-1f3fb","\u26F9\uD83C\uDFFC":"26f9-1f3fc","\u26F9\uD83C\uDFFD":"26f9-1f3fd","\u26F9\uD83C\uDFFE":"26f9-1f3fe","\u26F9\uD83C\uDFFF":"26f9-1f3ff","\u00A9":"00a9","\u00AE":"00ae","\u203C":"203c","\u2049":"2049","\u2122":"2122","\u2139":"2139","\u2194":"2194","\u2195":"2195","\u2196":"2196","\u2197":"2197","\u2198":"2198","\u2199":"2199","\u21A9":"21a9","\u21AA":"21aa","\u231A":"231a","\u231B":"231b","\u24C2":"24c2","\u25AA":"25aa","\u25AB":"25ab","\u25B6":"25b6","\u25C0":"25c0","\u25FB":"25fb","\u25FC":"25fc","\u25FD":"25fd","\u25FE":"25fe","\u2600":"2600","\u2601":"2601","\u260E":"260e","\u2611":"2611","\u2614":"2614","\u2615":"2615","\u261D":"261d","\u263A":"263a","\u2648":"2648","\u2649":"2649","\u264A":"264a","\u264B":"264b","\u264C":"264c","\u264D":"264d","\u264E":"264e","\u264F":"264f","\u2650":"2650","\u2651":"2651","\u2652":"2652","\u2653":"2653","\u2660":"2660","\u2663":"2663","\u2665":"2665","\u2666":"2666","\u2668":"2668","\u267B":"267b","\u267F":"267f","\u2693":"2693","\u26A0":"26a0","\u26A1":"26a1","\u26AA":"26aa","\u26AB":"26ab","\u26BD":"26bd","\u26BE":"26be","\u26C4":"26c4","\u26C5":"26c5","\u26D4":"26d4","\u26EA":"26ea","\u26F2":"26f2","\u26F3":"26f3","\u26F5":"26f5","\u26FA":"26fa","\u26FD":"26fd","\u2702":"2702","\u2708":"2708","\u2709":"2709","\u270C":"270c","\u270F":"270f","\u2712":"2712","\u2714":"2714","\u2716":"2716","\u2733":"2733","\u2734":"2734","\u2744":"2744","\u2747":"2747","\u2757":"2757","\u2764":"2764","\u27A1":"27a1","\u2934":"2934","\u2935":"2935","\u2B05":"2b05","\u2B06":"2b06","\u2B07":"2b07","\u2B1B":"2b1b","\u2B1C":"2b1c","\u2B50":"2b50","\u2B55":"2b55","\u3030":"3030","\u303D":"303d","\u3297":"3297","\u3299":"3299","\u271D":"271d","\u2328":"2328","\u270D":"270d","\u23CF":"23cf","\u23ED":"23ed","\u23EE":"23ee","\u23EF":"23ef","\u23F1":"23f1","\u23F2":"23f2","\u23F8":"23f8","\u23F9":"23f9","\u23FA":"23fa","\u2602":"2602","\u2603":"2603","\u2604":"2604","\u2618":"2618","\u2620":"2620","\u2622":"2622","\u2623":"2623","\u2626":"2626","\u262A":"262a","\u262E":"262e","\u262F":"262f","\u2638":"2638","\u2639":"2639","\u2692":"2692","\u2694":"2694","\u2696":"2696","\u2697":"2697","\u2699":"2699","\u269B":"269b","\u269C":"269c","\u26B0":"26b0","\u26B1":"26b1","\u26C8":"26c8","\u26CF":"26cf","\u26D1":"26d1","\u26D3":"26d3","\u26E9":"26e9","\u26F0":"26f0","\u26F1":"26f1","\u26F4":"26f4","\u26F7":"26f7","\u26F8":"26f8","\u26F9":"26f9","\u2721":"2721","\u2763":"2763","\uD83E\uDD49":"1f949","\uD83E\uDD48":"1f948","\uD83E\uDD47":"1f947","\uD83E\uDD3A":"1f93a","\uD83E\uDD45":"1f945","\uD83E\uDD3E":"1f93e","\uD83C\uDDFF":"1f1ff","\uD83E\uDD3D":"1f93d","\uD83E\uDD4B":"1f94b","\uD83E\uDD4A":"1f94a","\uD83E\uDD3C":"1f93c","\uD83E\uDD39":"1f939","\uD83E\uDD38":"1f938","\uD83D\uDEF6":"1f6f6","\uD83D\uDEF5":"1f6f5","\uD83D\uDEF4":"1f6f4","\uD83D\uDED2":"1f6d2","\uD83C\uDCCF":"1f0cf","\uD83C\uDD70":"1f170","\uD83C\uDD71":"1f171","\uD83C\uDD7E":"1f17e","\uD83D\uDED1":"1f6d1","\uD83C\uDD8E":"1f18e","\uD83C\uDD91":"1f191","\uD83C\uDDFE":"1f1fe","\uD83C\uDD92":"1f192","\uD83C\uDD93":"1f193","\uD83C\uDD94":"1f194","\uD83C\uDD95":"1f195","\uD83C\uDD96":"1f196","\uD83C\uDD97":"1f197","\uD83C\uDD98":"1f198","\uD83E\uDD44":"1f944","\uD83C\uDD99":"1f199","\uD83C\uDD9A":"1f19a","\uD83E\uDD42":"1f942","\uD83E\uDD43":"1f943","\uD83C\uDE01":"1f201","\uD83E\uDD59":"1f959","\uD83C\uDE32":"1f232","\uD83C\uDE33":"1f233","\uD83C\uDE34":"1f234","\uD83C\uDE35":"1f235","\uD83C\uDE36":"1f236","\uD83E\uDD58":"1f958","\uD83C\uDE38":"1f238","\uD83C\uDE39":"1f239","\uD83E\uDD57":"1f957","\uD83C\uDE3A":"1f23a","\uD83C\uDE50":"1f250","\uD83C\uDE51":"1f251","\uD83C\uDF00":"1f300","\uD83E\uDD56":"1f956","\uD83C\uDF01":"1f301","\uD83C\uDF02":"1f302","\uD83C\uDF03":"1f303","\uD83C\uDF04":"1f304","\uD83C\uDF05":"1f305","\uD83C\uDF06":"1f306","\uD83E\uDD55":"1f955","\uD83C\uDF07":"1f307","\uD83C\uDF08":"1f308","\uD83E\uDD54":"1f954","\uD83C\uDF09":"1f309","\uD83C\uDF0A":"1f30a","\uD83C\uDF0B":"1f30b","\uD83C\uDF0C":"1f30c","\uD83C\uDF0F":"1f30f","\uD83C\uDF11":"1f311","\uD83E\uDD53":"1f953","\uD83C\uDF13":"1f313","\uD83C\uDF14":"1f314","\uD83C\uDF15":"1f315","\uD83C\uDF19":"1f319","\uD83C\uDF1B":"1f31b","\uD83C\uDF1F":"1f31f","\uD83E\uDD52":"1f952","\uD83C\uDF20":"1f320","\uD83C\uDF30":"1f330","\uD83E\uDD51":"1f951","\uD83C\uDF31":"1f331","\uD83C\uDF34":"1f334","\uD83C\uDF35":"1f335","\uD83C\uDF37":"1f337","\uD83C\uDF38":"1f338","\uD83C\uDF39":"1f339","\uD83C\uDF3A":"1f33a","\uD83C\uDF3B":"1f33b","\uD83C\uDF3C":"1f33c","\uD83C\uDF3D":"1f33d","\uD83E\uDD50":"1f950","\uD83C\uDF3E":"1f33e","\uD83C\uDF3F":"1f33f","\uD83C\uDF40":"1f340","\uD83C\uDF41":"1f341","\uD83C\uDF42":"1f342","\uD83C\uDF43":"1f343","\uD83C\uDF44":"1f344","\uD83C\uDF45":"1f345","\uD83C\uDF46":"1f346","\uD83C\uDF47":"1f347","\uD83C\uDF48":"1f348","\uD83C\uDF49":"1f349","\uD83C\uDF4A":"1f34a","\uD83E\uDD40":"1f940","\uD83C\uDF4C":"1f34c","\uD83C\uDF4D":"1f34d","\uD83C\uDF4E":"1f34e","\uD83C\uDF4F":"1f34f","\uD83C\uDF51":"1f351","\uD83C\uDF52":"1f352","\uD83C\uDF53":"1f353","\uD83E\uDD8F":"1f98f","\uD83C\uDF54":"1f354","\uD83C\uDF55":"1f355","\uD83C\uDF56":"1f356","\uD83E\uDD8E":"1f98e","\uD83C\uDF57":"1f357","\uD83C\uDF58":"1f358","\uD83C\uDF59":"1f359","\uD83E\uDD8D":"1f98d","\uD83C\uDF5A":"1f35a","\uD83C\uDF5B":"1f35b","\uD83E\uDD8C":"1f98c","\uD83C\uDF5C":"1f35c","\uD83C\uDF5D":"1f35d","\uD83C\uDF5E":"1f35e","\uD83C\uDF5F":"1f35f","\uD83E\uDD8B":"1f98b","\uD83C\uDF60":"1f360","\uD83C\uDF61":"1f361","\uD83E\uDD8A":"1f98a","\uD83C\uDF62":"1f362","\uD83C\uDF63":"1f363","\uD83E\uDD89":"1f989","\uD83C\uDF64":"1f364","\uD83C\uDF65":"1f365","\uD83E\uDD88":"1f988","\uD83C\uDF66":"1f366","\uD83E\uDD87":"1f987","\uD83C\uDF67":"1f367","\uD83C\uDDFD":"1f1fd","\uD83C\uDF68":"1f368","\uD83E\uDD86":"1f986","\uD83C\uDF69":"1f369","\uD83E\uDD85":"1f985","\uD83C\uDF6A":"1f36a","\uD83D\uDDA4":"1f5a4","\uD83C\uDF6B":"1f36b","\uD83C\uDF6C":"1f36c","\uD83C\uDF6D":"1f36d","\uD83C\uDF6E":"1f36e","\uD83C\uDF6F":"1f36f","\uD83E\uDD1E":"1f91e","\uD83C\uDF70":"1f370","\uD83C\uDF71":"1f371","\uD83C\uDF72":"1f372","\uD83E\uDD1D":"1f91d","\uD83C\uDF73":"1f373","\uD83C\uDF74":"1f374","\uD83C\uDF75":"1f375","\uD83C\uDF76":"1f376","\uD83C\uDF77":"1f377","\uD83C\uDF78":"1f378","\uD83C\uDF79":"1f379","\uD83C\uDF7A":"1f37a","\uD83C\uDF7B":"1f37b","\uD83C\uDF80":"1f380","\uD83C\uDF81":"1f381","\uD83C\uDF82":"1f382","\uD83C\uDF83":"1f383","\uD83E\uDD1B":"1f91b","\uD83E\uDD1C":"1f91c","\uD83C\uDF84":"1f384","\uD83C\uDF85":"1f385","\uD83C\uDF86":"1f386","\uD83E\uDD1A":"1f91a","\uD83C\uDF87":"1f387","\uD83C\uDF88":"1f388","\uD83C\uDF89":"1f389","\uD83C\uDF8A":"1f38a","\uD83C\uDF8B":"1f38b","\uD83C\uDF8C":"1f38c","\uD83E\uDD19":"1f919","\uD83C\uDF8D":"1f38d","\uD83D\uDD7A":"1f57a","\uD83C\uDF8E":"1f38e","\uD83E\uDD33":"1f933","\uD83C\uDF8F":"1f38f","\uD83E\uDD30":"1f930","\uD83C\uDF90":"1f390","\uD83E\uDD26":"1f926","\uD83E\uDD37":"1f937","\uD83C\uDF91":"1f391","\uD83C\uDF92":"1f392","\uD83C\uDF93":"1f393","\uD83C\uDFA0":"1f3a0","\uD83C\uDFA1":"1f3a1","\uD83C\uDFA2":"1f3a2","\uD83C\uDFA3":"1f3a3","\uD83C\uDFA4":"1f3a4","\uD83C\uDFA5":"1f3a5","\uD83C\uDFA6":"1f3a6","\uD83C\uDFA7":"1f3a7","\uD83E\uDD36":"1f936","\uD83C\uDFA8":"1f3a8","\uD83E\uDD35":"1f935","\uD83C\uDFA9":"1f3a9","\uD83C\uDFAA":"1f3aa","\uD83E\uDD34":"1f934","\uD83C\uDFAB":"1f3ab","\uD83C\uDFAC":"1f3ac","\uD83C\uDFAD":"1f3ad","\uD83E\uDD27":"1f927","\uD83C\uDFAE":"1f3ae","\uD83C\uDFAF":"1f3af","\uD83C\uDFB0":"1f3b0","\uD83C\uDFB1":"1f3b1","\uD83C\uDFB2":"1f3b2","\uD83C\uDFB3":"1f3b3","\uD83C\uDFB4":"1f3b4","\uD83E\uDD25":"1f925","\uD83C\uDFB5":"1f3b5","\uD83C\uDFB6":"1f3b6","\uD83C\uDFB7":"1f3b7","\uD83E\uDD24":"1f924","\uD83C\uDFB8":"1f3b8","\uD83C\uDFB9":"1f3b9","\uD83C\uDFBA":"1f3ba","\uD83E\uDD23":"1f923","\uD83C\uDFBB":"1f3bb","\uD83C\uDFBC":"1f3bc","\uD83C\uDFBD":"1f3bd","\uD83E\uDD22":"1f922","\uD83C\uDFBE":"1f3be","\uD83C\uDFBF":"1f3bf","\uD83C\uDFC0":"1f3c0","\uD83C\uDFC1":"1f3c1","\uD83E\uDD21":"1f921","\uD83C\uDFC2":"1f3c2","\uD83C\uDFC3":"1f3c3","\uD83C\uDFC4":"1f3c4","\uD83C\uDFC6":"1f3c6","\uD83C\uDFC8":"1f3c8","\uD83C\uDFCA":"1f3ca","\uD83C\uDFE0":"1f3e0","\uD83C\uDFE1":"1f3e1","\uD83C\uDFE2":"1f3e2","\uD83C\uDFE3":"1f3e3","\uD83C\uDFE5":"1f3e5","\uD83C\uDFE6":"1f3e6","\uD83C\uDFE7":"1f3e7","\uD83C\uDFE8":"1f3e8","\uD83C\uDFE9":"1f3e9","\uD83C\uDFEA":"1f3ea","\uD83C\uDFEB":"1f3eb","\uD83C\uDFEC":"1f3ec","\uD83E\uDD20":"1f920","\uD83C\uDFED":"1f3ed","\uD83C\uDFEE":"1f3ee","\uD83C\uDFEF":"1f3ef","\uD83C\uDFF0":"1f3f0","\uD83D\uDC0C":"1f40c","\uD83D\uDC0D":"1f40d","\uD83D\uDC0E":"1f40e","\uD83D\uDC11":"1f411","\uD83D\uDC12":"1f412","\uD83D\uDC14":"1f414","\uD83D\uDC17":"1f417","\uD83D\uDC18":"1f418","\uD83D\uDC19":"1f419","\uD83D\uDC1A":"1f41a","\uD83D\uDC1B":"1f41b","\uD83D\uDC1C":"1f41c","\uD83D\uDC1D":"1f41d","\uD83D\uDC1E":"1f41e","\uD83D\uDC1F":"1f41f","\uD83D\uDC20":"1f420","\uD83D\uDC21":"1f421","\uD83D\uDC22":"1f422","\uD83D\uDC23":"1f423","\uD83D\uDC24":"1f424","\uD83D\uDC25":"1f425","\uD83D\uDC26":"1f426","\uD83D\uDC27":"1f427","\uD83D\uDC28":"1f428","\uD83D\uDC29":"1f429","\uD83D\uDC2B":"1f42b","\uD83D\uDC2C":"1f42c","\uD83D\uDC2D":"1f42d","\uD83D\uDC2E":"1f42e","\uD83D\uDC2F":"1f42f","\uD83D\uDC30":"1f430","\uD83D\uDC31":"1f431","\uD83D\uDC32":"1f432","\uD83D\uDC33":"1f433","\uD83D\uDC34":"1f434","\uD83D\uDC35":"1f435","\uD83D\uDC36":"1f436","\uD83D\uDC37":"1f437","\uD83D\uDC38":"1f438","\uD83D\uDC39":"1f439","\uD83D\uDC3A":"1f43a","\uD83D\uDC3B":"1f43b","\uD83D\uDC3C":"1f43c","\uD83D\uDC3D":"1f43d","\uD83D\uDC3E":"1f43e","\uD83D\uDC40":"1f440","\uD83D\uDC42":"1f442","\uD83D\uDC43":"1f443","\uD83D\uDC44":"1f444","\uD83D\uDC45":"1f445","\uD83D\uDC46":"1f446","\uD83D\uDC47":"1f447","\uD83D\uDC48":"1f448","\uD83D\uDC49":"1f449","\uD83D\uDC4A":"1f44a","\uD83D\uDC4B":"1f44b","\uD83D\uDC4C":"1f44c","\uD83D\uDC4D":"1f44d","\uD83D\uDC4E":"1f44e","\uD83D\uDC4F":"1f44f","\uD83D\uDC50":"1f450","\uD83D\uDC51":"1f451","\uD83D\uDC52":"1f452","\uD83D\uDC53":"1f453","\uD83D\uDC54":"1f454","\uD83D\uDC55":"1f455","\uD83D\uDC56":"1f456","\uD83D\uDC57":"1f457","\uD83D\uDC58":"1f458","\uD83D\uDC59":"1f459","\uD83D\uDC5A":"1f45a","\uD83D\uDC5B":"1f45b","\uD83D\uDC5C":"1f45c","\uD83D\uDC5D":"1f45d","\uD83D\uDC5E":"1f45e","\uD83D\uDC5F":"1f45f","\uD83D\uDC60":"1f460","\uD83D\uDC61":"1f461","\uD83D\uDC62":"1f462","\uD83D\uDC63":"1f463","\uD83D\uDC64":"1f464","\uD83D\uDC66":"1f466","\uD83D\uDC67":"1f467","\uD83D\uDC68":"1f468","\uD83D\uDC69":"1f469","\uD83D\uDC6A":"1f46a","\uD83D\uDC6B":"1f46b","\uD83D\uDC6E":"1f46e","\uD83D\uDC6F":"1f46f","\uD83D\uDC70":"1f470","\uD83D\uDC71":"1f471","\uD83D\uDC72":"1f472","\uD83D\uDC73":"1f473","\uD83D\uDC74":"1f474","\uD83D\uDC75":"1f475","\uD83D\uDC76":"1f476","\uD83D\uDC77":"1f477","\uD83D\uDC78":"1f478","\uD83D\uDC79":"1f479","\uD83D\uDC7A":"1f47a","\uD83D\uDC7B":"1f47b","\uD83D\uDC7C":"1f47c","\uD83D\uDC7D":"1f47d","\uD83D\uDC7E":"1f47e","\uD83D\uDC7F":"1f47f","\uD83D\uDC80":"1f480","\uD83D\uDCC7":"1f4c7","\uD83D\uDC81":"1f481","\uD83D\uDC82":"1f482","\uD83D\uDC83":"1f483","\uD83D\uDC84":"1f484","\uD83D\uDC85":"1f485","\uD83D\uDCD2":"1f4d2","\uD83D\uDC86":"1f486","\uD83D\uDCD3":"1f4d3","\uD83D\uDC87":"1f487","\uD83D\uDCD4":"1f4d4","\uD83D\uDC88":"1f488","\uD83D\uDCD5":"1f4d5","\uD83D\uDC89":"1f489","\uD83D\uDCD6":"1f4d6","\uD83D\uDC8A":"1f48a","\uD83D\uDCD7":"1f4d7","\uD83D\uDC8B":"1f48b","\uD83D\uDCD8":"1f4d8","\uD83D\uDC8C":"1f48c","\uD83D\uDCD9":"1f4d9","\uD83D\uDC8D":"1f48d","\uD83D\uDCDA":"1f4da","\uD83D\uDC8E":"1f48e","\uD83D\uDCDB":"1f4db","\uD83D\uDC8F":"1f48f","\uD83D\uDCDC":"1f4dc","\uD83D\uDC90":"1f490","\uD83D\uDCDD":"1f4dd","\uD83D\uDC91":"1f491","\uD83D\uDCDE":"1f4de","\uD83D\uDC92":"1f492","\uD83D\uDCDF":"1f4df","\uD83D\uDCE0":"1f4e0","\uD83D\uDC93":"1f493","\uD83D\uDCE1":"1f4e1","\uD83D\uDCE2":"1f4e2","\uD83D\uDC94":"1f494","\uD83D\uDCE3":"1f4e3","\uD83D\uDCE4":"1f4e4","\uD83D\uDC95":"1f495","\uD83D\uDCE5":"1f4e5","\uD83D\uDCE6":"1f4e6","\uD83D\uDC96":"1f496","\uD83D\uDCE7":"1f4e7","\uD83D\uDCE8":"1f4e8","\uD83D\uDC97":"1f497","\uD83D\uDCE9":"1f4e9","\uD83D\uDCEA":"1f4ea","\uD83D\uDC98":"1f498","\uD83D\uDCEB":"1f4eb","\uD83D\uDCEE":"1f4ee","\uD83D\uDC99":"1f499","\uD83D\uDCF0":"1f4f0","\uD83D\uDCF1":"1f4f1","\uD83D\uDC9A":"1f49a","\uD83D\uDCF2":"1f4f2","\uD83D\uDCF3":"1f4f3","\uD83D\uDC9B":"1f49b","\uD83D\uDCF4":"1f4f4","\uD83D\uDCF6":"1f4f6","\uD83D\uDC9C":"1f49c","\uD83D\uDCF7":"1f4f7","\uD83D\uDCF9":"1f4f9","\uD83D\uDC9D":"1f49d","\uD83D\uDCFA":"1f4fa","\uD83D\uDCFB":"1f4fb","\uD83D\uDC9E":"1f49e","\uD83D\uDCFC":"1f4fc","\uD83D\uDD03":"1f503","\uD83D\uDC9F":"1f49f","\uD83D\uDD0A":"1f50a","\uD83D\uDD0B":"1f50b","\uD83D\uDCA0":"1f4a0","\uD83D\uDD0C":"1f50c","\uD83D\uDD0D":"1f50d","\uD83D\uDCA1":"1f4a1","\uD83D\uDD0E":"1f50e","\uD83D\uDD0F":"1f50f","\uD83D\uDCA2":"1f4a2","\uD83D\uDD10":"1f510","\uD83D\uDD11":"1f511","\uD83D\uDCA3":"1f4a3","\uD83D\uDD12":"1f512","\uD83D\uDD13":"1f513","\uD83D\uDCA4":"1f4a4","\uD83D\uDD14":"1f514","\uD83D\uDD16":"1f516","\uD83D\uDCA5":"1f4a5","\uD83D\uDD17":"1f517","\uD83D\uDD18":"1f518","\uD83D\uDCA6":"1f4a6","\uD83D\uDD19":"1f519","\uD83D\uDD1A":"1f51a","\uD83D\uDCA7":"1f4a7","\uD83D\uDD1B":"1f51b","\uD83D\uDD1C":"1f51c","\uD83D\uDCA8":"1f4a8","\uD83D\uDD1D":"1f51d","\uD83D\uDD1E":"1f51e","\uD83D\uDCA9":"1f4a9","\uD83D\uDD1F":"1f51f","\uD83D\uDCAA":"1f4aa","\uD83D\uDD20":"1f520","\uD83D\uDD21":"1f521","\uD83D\uDCAB":"1f4ab","\uD83D\uDD22":"1f522","\uD83D\uDD23":"1f523","\uD83D\uDCAC":"1f4ac","\uD83D\uDD24":"1f524","\uD83D\uDD25":"1f525","\uD83D\uDCAE":"1f4ae","\uD83D\uDD26":"1f526","\uD83D\uDD27":"1f527","\uD83D\uDCAF":"1f4af","\uD83D\uDD28":"1f528","\uD83D\uDD29":"1f529","\uD83D\uDCB0":"1f4b0","\uD83D\uDD2A":"1f52a","\uD83D\uDD2B":"1f52b","\uD83D\uDCB1":"1f4b1","\uD83D\uDD2E":"1f52e","\uD83D\uDCB2":"1f4b2","\uD83D\uDD2F":"1f52f","\uD83D\uDCB3":"1f4b3","\uD83D\uDD30":"1f530","\uD83D\uDD31":"1f531","\uD83D\uDCB4":"1f4b4","\uD83D\uDD32":"1f532","\uD83D\uDD33":"1f533","\uD83D\uDCB5":"1f4b5","\uD83D\uDD34":"1f534","\uD83D\uDD35":"1f535","\uD83D\uDCB8":"1f4b8","\uD83D\uDD36":"1f536","\uD83D\uDD37":"1f537","\uD83D\uDCB9":"1f4b9","\uD83D\uDD38":"1f538","\uD83D\uDD39":"1f539","\uD83D\uDCBA":"1f4ba","\uD83D\uDD3A":"1f53a","\uD83D\uDD3B":"1f53b","\uD83D\uDCBB":"1f4bb","\uD83D\uDD3C":"1f53c","\uD83D\uDCBC":"1f4bc","\uD83D\uDD3D":"1f53d","\uD83D\uDD50":"1f550","\uD83D\uDCBD":"1f4bd","\uD83D\uDD51":"1f551","\uD83D\uDCBE":"1f4be","\uD83D\uDD52":"1f552","\uD83D\uDCBF":"1f4bf","\uD83D\uDD53":"1f553","\uD83D\uDCC0":"1f4c0","\uD83D\uDD54":"1f554","\uD83D\uDD55":"1f555","\uD83D\uDCC1":"1f4c1","\uD83D\uDD56":"1f556","\uD83D\uDD57":"1f557","\uD83D\uDCC2":"1f4c2","\uD83D\uDD58":"1f558","\uD83D\uDD59":"1f559","\uD83D\uDCC3":"1f4c3","\uD83D\uDD5A":"1f55a","\uD83D\uDD5B":"1f55b","\uD83D\uDCC4":"1f4c4","\uD83D\uDDFB":"1f5fb","\uD83D\uDDFC":"1f5fc","\uD83D\uDCC5":"1f4c5","\uD83D\uDDFD":"1f5fd","\uD83D\uDDFE":"1f5fe","\uD83D\uDCC6":"1f4c6","\uD83D\uDDFF":"1f5ff","\uD83D\uDE01":"1f601","\uD83D\uDE02":"1f602","\uD83D\uDE03":"1f603","\uD83D\uDCC8":"1f4c8","\uD83D\uDE04":"1f604","\uD83D\uDE05":"1f605","\uD83D\uDCC9":"1f4c9","\uD83D\uDE06":"1f606","\uD83D\uDE09":"1f609","\uD83D\uDCCA":"1f4ca","\uD83D\uDE0A":"1f60a","\uD83D\uDE0B":"1f60b","\uD83D\uDCCB":"1f4cb","\uD83D\uDE0C":"1f60c","\uD83D\uDE0D":"1f60d","\uD83D\uDCCC":"1f4cc","\uD83D\uDE0F":"1f60f","\uD83D\uDE12":"1f612","\uD83D\uDCCD":"1f4cd","\uD83D\uDE13":"1f613","\uD83D\uDE14":"1f614","\uD83D\uDCCE":"1f4ce","\uD83D\uDE16":"1f616","\uD83D\uDE18":"1f618","\uD83D\uDCCF":"1f4cf","\uD83D\uDE1A":"1f61a","\uD83D\uDE1C":"1f61c","\uD83D\uDCD0":"1f4d0","\uD83D\uDE1D":"1f61d","\uD83D\uDE1E":"1f61e","\uD83D\uDCD1":"1f4d1","\uD83D\uDE20":"1f620","\uD83D\uDE21":"1f621","\uD83D\uDE22":"1f622","\uD83D\uDE23":"1f623","\uD83D\uDE24":"1f624","\uD83D\uDE25":"1f625","\uD83D\uDE28":"1f628","\uD83D\uDE29":"1f629","\uD83D\uDE2A":"1f62a","\uD83D\uDE2B":"1f62b","\uD83D\uDE2D":"1f62d","\uD83D\uDE30":"1f630","\uD83D\uDE31":"1f631","\uD83D\uDE32":"1f632","\uD83D\uDE33":"1f633","\uD83D\uDE35":"1f635","\uD83D\uDE37":"1f637","\uD83D\uDE38":"1f638","\uD83D\uDE39":"1f639","\uD83D\uDE3A":"1f63a","\uD83D\uDE3B":"1f63b","\uD83D\uDE3C":"1f63c","\uD83D\uDE3D":"1f63d","\uD83D\uDE3E":"1f63e","\uD83D\uDE3F":"1f63f","\uD83D\uDE40":"1f640","\uD83D\uDE45":"1f645","\uD83D\uDE46":"1f646","\uD83D\uDE47":"1f647","\uD83D\uDE48":"1f648","\uD83D\uDE49":"1f649","\uD83D\uDE4A":"1f64a","\uD83D\uDE4B":"1f64b","\uD83D\uDE4C":"1f64c","\uD83D\uDE4D":"1f64d","\uD83D\uDE4E":"1f64e","\uD83D\uDE4F":"1f64f","\uD83D\uDE80":"1f680","\uD83D\uDE83":"1f683","\uD83D\uDE84":"1f684","\uD83D\uDE85":"1f685","\uD83D\uDE87":"1f687","\uD83D\uDE89":"1f689","\uD83D\uDE8C":"1f68c","\uD83D\uDE8F":"1f68f","\uD83D\uDE91":"1f691","\uD83D\uDE92":"1f692","\uD83D\uDE93":"1f693","\uD83D\uDE95":"1f695","\uD83D\uDE97":"1f697","\uD83D\uDE99":"1f699","\uD83D\uDE9A":"1f69a","\uD83D\uDEA2":"1f6a2","\uD83D\uDEA4":"1f6a4","\uD83D\uDEA5":"1f6a5","\uD83D\uDEA7":"1f6a7","\uD83D\uDEA8":"1f6a8","\uD83D\uDEA9":"1f6a9","\uD83D\uDEAA":"1f6aa","\uD83D\uDEAB":"1f6ab","\uD83D\uDEAC":"1f6ac","\uD83D\uDEAD":"1f6ad","\uD83D\uDEB2":"1f6b2","\uD83D\uDEB6":"1f6b6","\uD83D\uDEB9":"1f6b9","\uD83D\uDEBA":"1f6ba","\uD83D\uDEBB":"1f6bb","\uD83D\uDEBC":"1f6bc","\uD83D\uDEBD":"1f6bd","\uD83D\uDEBE":"1f6be","\uD83D\uDEC0":"1f6c0","\uD83E\uDD18":"1f918","\uD83D\uDE00":"1f600","\uD83D\uDE07":"1f607","\uD83D\uDE08":"1f608","\uD83D\uDE0E":"1f60e","\uD83D\uDE10":"1f610","\uD83D\uDE11":"1f611","\uD83D\uDE15":"1f615","\uD83D\uDE17":"1f617","\uD83D\uDE19":"1f619","\uD83D\uDE1B":"1f61b","\uD83D\uDE1F":"1f61f","\uD83D\uDE26":"1f626","\uD83D\uDE27":"1f627","\uD83D\uDE2C":"1f62c","\uD83D\uDE2E":"1f62e","\uD83D\uDE2F":"1f62f","\uD83D\uDE34":"1f634","\uD83D\uDE36":"1f636","\uD83D\uDE81":"1f681","\uD83D\uDE82":"1f682","\uD83D\uDE86":"1f686","\uD83D\uDE88":"1f688","\uD83D\uDE8A":"1f68a","\uD83D\uDE8D":"1f68d","\uD83D\uDE8E":"1f68e","\uD83D\uDE90":"1f690","\uD83D\uDE94":"1f694","\uD83D\uDE96":"1f696","\uD83D\uDE98":"1f698","\uD83D\uDE9B":"1f69b","\uD83D\uDE9C":"1f69c","\uD83D\uDE9D":"1f69d","\uD83D\uDE9E":"1f69e","\uD83D\uDE9F":"1f69f","\uD83D\uDEA0":"1f6a0","\uD83D\uDEA1":"1f6a1","\uD83D\uDEA3":"1f6a3","\uD83D\uDEA6":"1f6a6","\uD83D\uDEAE":"1f6ae","\uD83D\uDEAF":"1f6af","\uD83D\uDEB0":"1f6b0","\uD83D\uDEB1":"1f6b1","\uD83D\uDEB3":"1f6b3","\uD83D\uDEB4":"1f6b4","\uD83D\uDEB5":"1f6b5","\uD83D\uDEB7":"1f6b7","\uD83D\uDEB8":"1f6b8","\uD83D\uDEBF":"1f6bf","\uD83D\uDEC1":"1f6c1","\uD83D\uDEC2":"1f6c2","\uD83D\uDEC3":"1f6c3","\uD83D\uDEC4":"1f6c4","\uD83D\uDEC5":"1f6c5","\uD83C\uDF0D":"1f30d","\uD83C\uDF0E":"1f30e","\uD83C\uDF10":"1f310","\uD83C\uDF12":"1f312","\uD83C\uDF16":"1f316","\uD83C\uDF17":"1f317","\uD83C\uDF18":"1f318","\uD83C\uDF1A":"1f31a","\uD83C\uDF1C":"1f31c","\uD83C\uDF1D":"1f31d","\uD83C\uDF1E":"1f31e","\uD83C\uDF32":"1f332","\uD83C\uDF33":"1f333","\uD83C\uDF4B":"1f34b","\uD83C\uDF50":"1f350","\uD83C\uDF7C":"1f37c","\uD83C\uDFC7":"1f3c7","\uD83C\uDFC9":"1f3c9","\uD83C\uDFE4":"1f3e4","\uD83D\uDC00":"1f400","\uD83D\uDC01":"1f401","\uD83D\uDC02":"1f402","\uD83D\uDC03":"1f403","\uD83D\uDC04":"1f404","\uD83D\uDC05":"1f405","\uD83D\uDC06":"1f406","\uD83D\uDC07":"1f407","\uD83D\uDC08":"1f408","\uD83D\uDC09":"1f409","\uD83D\uDC0A":"1f40a","\uD83D\uDC0B":"1f40b","\uD83D\uDC0F":"1f40f","\uD83D\uDC10":"1f410","\uD83D\uDC13":"1f413","\uD83D\uDC15":"1f415","\uD83D\uDC16":"1f416","\uD83D\uDC2A":"1f42a","\uD83D\uDC65":"1f465","\uD83D\uDC6C":"1f46c","\uD83D\uDC6D":"1f46d","\uD83D\uDCAD":"1f4ad","\uD83D\uDCB6":"1f4b6","\uD83D\uDCB7":"1f4b7","\uD83D\uDCEC":"1f4ec","\uD83D\uDCED":"1f4ed","\uD83D\uDCEF":"1f4ef","\uD83D\uDCF5":"1f4f5","\uD83D\uDD00":"1f500","\uD83D\uDD01":"1f501","\uD83D\uDD02":"1f502","\uD83D\uDD04":"1f504","\uD83D\uDD05":"1f505","\uD83D\uDD06":"1f506","\uD83D\uDD07":"1f507","\uD83D\uDD09":"1f509","\uD83D\uDD15":"1f515","\uD83D\uDD2C":"1f52c","\uD83D\uDD2D":"1f52d","\uD83D\uDD5C":"1f55c","\uD83D\uDD5D":"1f55d","\uD83D\uDD5E":"1f55e","\uD83D\uDD5F":"1f55f","\uD83D\uDD60":"1f560","\uD83D\uDD61":"1f561","\uD83D\uDD62":"1f562","\uD83D\uDD63":"1f563","\uD83D\uDD64":"1f564","\uD83D\uDD65":"1f565","\uD83D\uDD66":"1f566","\uD83D\uDD67":"1f567","\uD83D\uDD08":"1f508","\uD83D\uDE8B":"1f68b","\uD83C\uDFC5":"1f3c5","\uD83C\uDFF4":"1f3f4","\uD83D\uDCF8":"1f4f8","\uD83D\uDECC":"1f6cc","\uD83D\uDD95":"1f595","\uD83D\uDD96":"1f596","\uD83D\uDE41":"1f641","\uD83D\uDE42":"1f642","\uD83D\uDEEB":"1f6eb","\uD83D\uDEEC":"1f6ec","\uD83C\uDFFB":"1f3fb","\uD83C\uDFFC":"1f3fc","\uD83C\uDFFD":"1f3fd","\uD83C\uDFFE":"1f3fe","\uD83C\uDFFF":"1f3ff","\uD83D\uDE43":"1f643","\uD83E\uDD11":"1f911","\uD83E\uDD13":"1f913","\uD83E\uDD17":"1f917","\uD83D\uDE44":"1f644","\uD83E\uDD14":"1f914","\uD83E\uDD10":"1f910","\uD83E\uDD12":"1f912","\uD83E\uDD15":"1f915","\uD83E\uDD16":"1f916","\uD83E\uDD81":"1f981","\uD83E\uDD84":"1f984","\uD83E\uDD82":"1f982","\uD83E\uDD80":"1f980","\uD83E\uDD83":"1f983","\uD83E\uDDC0":"1f9c0","\uD83C\uDF2D":"1f32d","\uD83C\uDF2E":"1f32e","\uD83C\uDF2F":"1f32f","\uD83C\uDF7F":"1f37f","\uD83C\uDF7E":"1f37e","\uD83C\uDFF9":"1f3f9","\uD83C\uDFFA":"1f3fa","\uD83D\uDED0":"1f6d0","\uD83D\uDD4B":"1f54b","\uD83D\uDD4C":"1f54c","\uD83D\uDD4D":"1f54d","\uD83D\uDD4E":"1f54e","\uD83D\uDCFF":"1f4ff","\uD83C\uDFCF":"1f3cf","\uD83C\uDFD0":"1f3d0","\uD83C\uDFD1":"1f3d1","\uD83C\uDFD2":"1f3d2","\uD83C\uDFD3":"1f3d3","\uD83C\uDFF8":"1f3f8","\uD83E\uDD41":"1f941","\uD83E\uDD90":"1f990","\uD83E\uDD91":"1f991","\uD83E\uDD5A":"1f95a","\uD83E\uDD5B":"1f95b","\uD83E\uDD5C":"1f95c","\uD83E\uDD5D":"1f95d","\uD83E\uDD5E":"1f95e","\uD83C\uDDFC":"1f1fc","\uD83C\uDDFB":"1f1fb","\uD83C\uDDFA":"1f1fa","\uD83C\uDDF9":"1f1f9","\uD83C\uDDF8":"1f1f8","\uD83C\uDDF7":"1f1f7","\uD83C\uDDF6":"1f1f6","\uD83C\uDDF5":"1f1f5","\uD83C\uDDF4":"1f1f4","\uD83C\uDDF3":"1f1f3","\uD83C\uDDF2":"1f1f2","\uD83C\uDDF1":"1f1f1","\uD83C\uDDF0":"1f1f0","\uD83C\uDDEF":"1f1ef","\uD83C\uDDEE":"1f1ee","\uD83C\uDDED":"1f1ed","\uD83C\uDDEC":"1f1ec","\uD83C\uDDEB":"1f1eb","\uD83C\uDDEA":"1f1ea","\uD83C\uDDE9":"1f1e9","\uD83C\uDDE8":"1f1e8","\uD83C\uDDE7":"1f1e7","\uD83C\uDDE6":"1f1e6","\u23E9":"23e9","\u23EA":"23ea","\u23EB":"23eb","\u23EC":"23ec","\u23F0":"23f0","\u23F3":"23f3","*":"002a","\u26CE":"26ce","\u2705":"2705","\u270A":"270a","\u270B":"270b","\u2728":"2728","\u274C":"274c","\u274E":"274e","\u2753":"2753","\u2754":"2754","\u2755":"2755","\u2795":"2795","\u2796":"2796","\u2797":"2797","\u27B0":"27b0","#":"0023","\u27BF":"27bf","9":"0039","8":"0038","7":"0037","6":"0036","5":"0035","4":"0034","3":"0033","2":"0032","1":"0031","0":"0030","\u00A9":"00a9","\u00AE":"00ae","\u203C":"203c","\u2049":"2049","\u2122":"2122","\u2139":"2139","\u2194":"2194","\u2195":"2195","\u2196":"2196","\u2197":"2197","\u2198":"2198","\u2199":"2199","\u21A9":"21a9","\u21AA":"21aa","\u231A":"231a","\u231B":"231b","\u24C2":"24c2","\u25AA":"25aa","\u25AB":"25ab","\u25B6":"25b6","\u25C0":"25c0","\u25FB":"25fb","\u25FC":"25fc","\u25FD":"25fd","\u25FE":"25fe","\u2600":"2600","\u2601":"2601","\u260E":"260e","\u2611":"2611","\u2614":"2614","\u2615":"2615","\u261D":"261d","\u263A":"263a","\u2648":"2648","\u2649":"2649","\u264A":"264a","\u264B":"264b","\u264C":"264c","\u264D":"264d","\u264E":"264e","\u264F":"264f","\u2650":"2650","\u2651":"2651","\u2652":"2652","\u2653":"2653","\u2660":"2660","\u2663":"2663","\u2665":"2665","\u2666":"2666","\u2668":"2668","\u267B":"267b","\u267F":"267f","\u2693":"2693","\u26A0":"26a0","\u26A1":"26a1","\u26AA":"26aa","\u26AB":"26ab","\u26BD":"26bd","\u26BE":"26be","\u26C4":"26c4","\u26C5":"26c5","\u26D4":"26d4","\u26EA":"26ea","\u26F2":"26f2","\u26F3":"26f3","\u26F5":"26f5","\u26FA":"26fa","\u26FD":"26fd","\u2702":"2702","\u2708":"2708","\u2709":"2709","\u270C":"270c","\u270F":"270f","\u2712":"2712","\u2714":"2714","\u2716":"2716","\u2733":"2733","\u2734":"2734","\u2744":"2744","\u2747":"2747","\u2757":"2757","\u2764":"2764","\u27A1":"27a1","\u2934":"2934","\u2935":"2935","\u2B05":"2b05","\u2B06":"2b06","\u2B07":"2b07","\u2B1B":"2b1b","\u2B1C":"2b1c","\u2B50":"2b50","\u2B55":"2b55","\u3030":"3030","\u303D":"303d","\u3297":"3297","\u3299":"3299","\uD83C\uDC04":"1f004","\uD83C\uDD7F":"1f17f","\uD83C\uDE02":"1f202","\uD83C\uDE1A":"1f21a","\uD83C\uDE2F":"1f22f","\uD83C\uDE37":"1f237","\uD83C\uDF9E":"1f39e","\uD83C\uDF9F":"1f39f","\uD83C\uDFCB":"1f3cb","\uD83C\uDFCC":"1f3cc","\uD83C\uDFCD":"1f3cd","\uD83C\uDFCE":"1f3ce","\uD83C\uDF96":"1f396","\uD83C\uDF97":"1f397","\uD83C\uDF36":"1f336","\uD83C\uDF27":"1f327","\uD83C\uDF28":"1f328","\uD83C\uDF29":"1f329","\uD83C\uDF2A":"1f32a","\uD83C\uDF2B":"1f32b","\uD83C\uDF2C":"1f32c","\uD83D\uDC3F":"1f43f","\uD83D\uDD77":"1f577","\uD83D\uDD78":"1f578","\uD83C\uDF21":"1f321","\uD83C\uDF99":"1f399","\uD83C\uDF9A":"1f39a","\uD83C\uDF9B":"1f39b","\uD83C\uDFF3":"1f3f3","\uD83C\uDFF5":"1f3f5","\uD83C\uDFF7":"1f3f7","\uD83D\uDCFD":"1f4fd","\u271D":"271d","\uD83D\uDD49":"1f549","\uD83D\uDD4A":"1f54a","\uD83D\uDD6F":"1f56f","\uD83D\uDD70":"1f570","\uD83D\uDD73":"1f573","\uD83D\uDD76":"1f576","\uD83D\uDD79":"1f579","\uD83D\uDD87":"1f587","\uD83D\uDD8A":"1f58a","\uD83D\uDD8B":"1f58b","\uD83D\uDD8C":"1f58c","\uD83D\uDD8D":"1f58d","\uD83D\uDDA5":"1f5a5","\uD83D\uDDA8":"1f5a8","\u2328":"2328","\uD83D\uDDB2":"1f5b2","\uD83D\uDDBC":"1f5bc","\uD83D\uDDC2":"1f5c2","\uD83D\uDDC3":"1f5c3","\uD83D\uDDC4":"1f5c4","\uD83D\uDDD1":"1f5d1","\uD83D\uDDD2":"1f5d2","\uD83D\uDDD3":"1f5d3","\uD83D\uDDDC":"1f5dc","\uD83D\uDDDD":"1f5dd","\uD83D\uDDDE":"1f5de","\uD83D\uDDE1":"1f5e1","\uD83D\uDDE3":"1f5e3","\uD83D\uDDE8":"1f5e8","\uD83D\uDDEF":"1f5ef","\uD83D\uDDF3":"1f5f3","\uD83D\uDDFA":"1f5fa","\uD83D\uDEE0":"1f6e0","\uD83D\uDEE1":"1f6e1","\uD83D\uDEE2":"1f6e2","\uD83D\uDEF0":"1f6f0","\uD83C\uDF7D":"1f37d","\uD83D\uDC41":"1f441","\uD83D\uDD74":"1f574","\uD83D\uDD75":"1f575","\u270D":"270d","\uD83D\uDD90":"1f590","\uD83C\uDFD4":"1f3d4","\uD83C\uDFD5":"1f3d5","\uD83C\uDFD6":"1f3d6","\uD83C\uDFD7":"1f3d7","\uD83C\uDFD8":"1f3d8","\uD83C\uDFD9":"1f3d9","\uD83C\uDFDA":"1f3da","\uD83C\uDFDB":"1f3db","\uD83C\uDFDC":"1f3dc","\uD83C\uDFDD":"1f3dd","\uD83C\uDFDE":"1f3de","\uD83C\uDFDF":"1f3df","\uD83D\uDECB":"1f6cb","\uD83D\uDECD":"1f6cd","\uD83D\uDECE":"1f6ce","\uD83D\uDECF":"1f6cf","\uD83D\uDEE3":"1f6e3","\uD83D\uDEE4":"1f6e4","\uD83D\uDEE5":"1f6e5","\uD83D\uDEE9":"1f6e9","\uD83D\uDEF3":"1f6f3","\u23CF":"23cf","\u23ED":"23ed","\u23EE":"23ee","\u23EF":"23ef","\u23F1":"23f1","\u23F2":"23f2","\u23F8":"23f8","\u23F9":"23f9","\u23FA":"23fa","\u2602":"2602","\u2603":"2603","\u2604":"2604","\u2618":"2618","\u2620":"2620","\u2622":"2622","\u2623":"2623","\u2626":"2626","\u262A":"262a","\u262E":"262e","\u262F":"262f","\u2638":"2638","\u2639":"2639","\u2692":"2692","\u2694":"2694","\u2696":"2696","\u2697":"2697","\u2699":"2699","\u269B":"269b","\u269C":"269c","\u26B0":"26b0","\u26B1":"26b1","\u26C8":"26c8","\u26CF":"26cf","\u26D1":"26d1","\u26D3":"26d3","\u26E9":"26e9","\u26F0":"26f0","\u26F1":"26f1","\u26F4":"26f4","\u26F7":"26f7","\u26F8":"26f8","\u26F9":"26f9","\u2721":"2721","\u2763":"2763","\uD83C\uDF24":"1f324","\uD83C\uDF25":"1f325","\uD83C\uDF26":"1f326","\uD83D\uDDB1":"1f5b1"}; + ns.imagePathPNG = '//cdn.jsdelivr.net/emojione/assets/png/'; + ns.imagePathSVG = '//cdn.jsdelivr.net/emojione/assets/svg/'; + ns.imagePathSVGSprites = './../assets/sprites/emojione.sprites.svg'; + ns.imageType = 'png'; // or svg + ns.sprites = false; // if this is true then sprite markup will be used (if SVG image type is set then you must include the SVG sprite file locally) + ns.unicodeAlt = true; // use the unicode char as the alt attribute (makes copy and pasting the resulting text better) + ns.ascii = false; // change to true to convert ascii smileys + ns.cacheBustParam = '?v=2.2.6'; // you can [optionally] modify this to force browsers to refresh their cache. it will be appended to the send of the filenames + + ns.regShortNames = new RegExp("]*>.*?<\/object>|]*>.*?<\/span>|<(?:object|embed|svg|img|div|span|p|a)[^>]*>|("+ns.shortnames+")", "gi"); + ns.regAscii = new RegExp("]*>.*?<\/object>|]*>.*?<\/span>|<(?:object|embed|svg|img|div|span|p|a)[^>]*>|((\\s|^)"+ns.asciiRegexp+"(?=\\s|$|[!,.?]))", "g"); + ns.regUnicode = new RegExp("]*>.*?<\/object>|]*>.*?<\/span>|<(?:object|embed|svg|img|div|span|p|a)[^>]*>|("+ns.unicodeRegexp+")", "gi"); + + ns.toImage = function(str) { + str = ns.unicodeToImage(str); + str = ns.shortnameToImage(str); + return str; + }; + + // Uses toShort to transform all unicode into a standard shortname + // then transforms the shortname into unicode + // This is done for standardization when converting several unicode types + ns.unifyUnicode = function(str) { + str = ns.toShort(str); + str = ns.shortnameToUnicode(str); + return str; + }; + + // Replace shortnames (:wink:) with Ascii equivalents ( ;^) ) + // Useful for systems that dont support unicode nor images + ns.shortnameToAscii = function(str) { + var unicode, + // something to keep in mind here is that array flip will destroy + // half of the ascii text "emojis" because the unicode numbers are duplicated + // this is ok for what it's being used for + unicodeToAscii = ns.objectFlip(ns.asciiList); + + str = str.replace(ns.regShortNames, function(shortname) { + if( (typeof shortname === 'undefined') || (shortname === '') || (!(shortname in ns.emojioneList)) ) { + // if the shortname doesnt exist just return the entire match + return shortname; + } + else { + unicode = ns.emojioneList[shortname].unicode[ns.emojioneList[shortname].unicode.length-1]; + if(typeof unicodeToAscii[unicode] !== 'undefined') { + return unicodeToAscii[unicode]; + } else { + return shortname; + } + } + }); + return str; + }; + + // will output unicode from shortname + // useful for sending emojis back to mobile devices + ns.shortnameToUnicode = function(str) { + // replace regular shortnames first + var unicode; + str = str.replace(ns.regShortNames, function(shortname) { + if( (typeof shortname === 'undefined') || (shortname === '') || (!(shortname in ns.emojioneList)) ) { + // if the shortname doesnt exist just return the entire match + return shortname; + } + unicode = ns.emojioneList[shortname].unicode[0].toUpperCase(); + return ns.convert(unicode); + }); + + // if ascii smileys are turned on, then we'll replace them! + if (ns.ascii) { + + str = str.replace(ns.regAscii, function(entire, m1, m2, m3) { + if( (typeof m3 === 'undefined') || (m3 === '') || (!(ns.unescapeHTML(m3) in ns.asciiList)) ) { + // if the shortname doesnt exist just return the entire match + return entire; + } + + m3 = ns.unescapeHTML(m3); + unicode = ns.asciiList[m3].toUpperCase(); + return m2+ns.convert(unicode); + }); + } + + return str; + }; + + ns.shortnameToImage = function(str) { + // replace regular shortnames first + var replaceWith,unicode,alt; + str = str.replace(ns.regShortNames, function(shortname) { + if( (typeof shortname === 'undefined') || (shortname === '') || (!(shortname in ns.emojioneList)) ) { + // if the shortname doesnt exist just return the entire match + return shortname; + } + else { + unicode = ns.emojioneList[shortname].unicode[ns.emojioneList[shortname].unicode.length-1]; + + // depending on the settings, we'll either add the native unicode as the alt tag, otherwise the shortname + alt = (ns.unicodeAlt) ? ns.convert(unicode.toUpperCase()) : shortname; + + if(ns.imageType === 'png') { + if(ns.sprites) { + replaceWith = ''+alt+''; + } + else { + replaceWith = ''+alt+''; + } + } + else { + // svg + if(ns.sprites) { + replaceWith = ''+alt+''; + } + else { + replaceWith = ''+alt+''; + } + } + + return replaceWith; + } + }); + + // if ascii smileys are turned on, then we'll replace them! + if (ns.ascii) { + + str = str.replace(ns.regAscii, function(entire, m1, m2, m3) { + if( (typeof m3 === 'undefined') || (m3 === '') || (!(ns.unescapeHTML(m3) in ns.asciiList)) ) { + // if the shortname doesnt exist just return the entire match + return entire; + } + + m3 = ns.unescapeHTML(m3); + unicode = ns.asciiList[m3]; + + // depending on the settings, we'll either add the native unicode as the alt tag, otherwise the shortname + alt = (ns.unicodeAlt) ? ns.convert(unicode.toUpperCase()) : ns.escapeHTML(m3); + + if(ns.imageType === 'png') { + if(ns.sprites) { + replaceWith = m2+''+alt+''; + } + else { + replaceWith = m2+''+alt+''; + } + } + else { + // svg + if(ns.sprites) { + replaceWith = ''+alt+''; + } + else { + replaceWith = m2+''+alt+''; + } + } + + return replaceWith; + }); + } + + return str; + }; + + ns.unicodeToImage = function(str) { + + var replaceWith,unicode,alt; + + if((!ns.unicodeAlt) || (ns.sprites)) { + // if we are using the shortname as the alt tag then we need a reversed array to map unicode code point to shortnames + var mappedUnicode = ns.mapUnicodeToShort(); + } + + str = str.replace(ns.regUnicode, function(unicodeChar) { + if( (typeof unicodeChar === 'undefined') || (unicodeChar === '') || (!(unicodeChar in ns.jsEscapeMap)) ) { + // if the unicodeChar doesnt exist just return the entire match + return unicodeChar; + } + else { + // get the unicode codepoint from the actual char + unicode = ns.jsEscapeMap[unicodeChar]; + + // depending on the settings, we'll either add the native unicode as the alt tag, otherwise the shortname + alt = (ns.unicodeAlt) ? ns.convert(unicode.toUpperCase()) : mappedUnicode[unicode]; + + if(ns.imageType === 'png') { + if(ns.sprites) { + replaceWith = ''+alt+''; + } + else { + replaceWith = ''+alt+''; + } + } + else { + // svg + if(ns.sprites) { + replaceWith = ''+alt+''; + } + else { + replaceWith = ''+alt+''; + } + } + + return replaceWith; + } + }); + + return str; + }; + + // this is really just unicodeToShortname() but I opted for the shorthand name to match toImage() + ns.toShort = function(str) { + var find = ns.getUnicodeReplacementRegEx(), + replacementList = ns.mapUnicodeCharactersToShort(); + return ns.replaceAll(str, find,replacementList); + }; + + // for converting unicode code points and code pairs to their respective characters + ns.convert = function(unicode) { + if(unicode.indexOf("-") > -1) { + var parts = []; + var s = unicode.split('-'); + for(var i = 0; i < s.length; i++) { + var part = parseInt(s[i], 16); + if (part >= 0x10000 && part <= 0x10FFFF) { + var hi = Math.floor((part - 0x10000) / 0x400) + 0xD800; + var lo = ((part - 0x10000) % 0x400) + 0xDC00; + part = (String.fromCharCode(hi) + String.fromCharCode(lo)); + } + else { + part = String.fromCharCode(part); + } + parts.push(part); + } + return parts.join(''); + } + else { + var s = parseInt(unicode, 16); + if (s >= 0x10000 && s <= 0x10FFFF) { + var hi = Math.floor((s - 0x10000) / 0x400) + 0xD800; + var lo = ((s - 0x10000) % 0x400) + 0xDC00; + return (String.fromCharCode(hi) + String.fromCharCode(lo)); + } + else { + return String.fromCharCode(s); + } + } + }; + + ns.escapeHTML = function (string) { + var escaped = { + '&' : '&', + '<' : '<', + '>' : '>', + '"' : '"', + '\'': ''' + }; + + return string.replace(/[&<>"']/g, function (match) { + return escaped[match]; + }); + }; + ns.unescapeHTML = function (string) { + var unescaped = { + '&' : '&', + '&' : '&', + '&' : '&', + '<' : '<', + '<' : '<', + '<' : '<', + '>' : '>', + '>' : '>', + '>' : '>', + '"' : '"', + '"' : '"', + '"' : '"', + ''' : '\'', + ''' : '\'', + ''' : '\'' + }; + + return string.replace(/&(?:amp|#38|#x26|lt|#60|#x3C|gt|#62|#x3E|apos|#39|#x27|quot|#34|#x22);/ig, function (match) { + return unescaped[match]; + }); + }; + + ns.mapEmojioneList = function (addToMapStorage) { + for (var shortname in ns.emojioneList) { + if (!ns.emojioneList.hasOwnProperty(shortname)) { continue; } + for (var i = 0, len = ns.emojioneList[shortname].unicode.length; i < len; i++) { + var unicode = ns.emojioneList[shortname].unicode[i]; + addToMapStorage(unicode, shortname); + } + } + }; + + ns.mapUnicodeToShort = function() { + if (!ns.memMapShortToUnicode) { + ns.memMapShortToUnicode = {}; + ns.mapEmojioneList(function (unicode, shortname) { + ns.memMapShortToUnicode[unicode] = shortname; + }); + } + return ns.memMapShortToUnicode; + }; + + ns.memoizeReplacement = function() { + if (!ns.unicodeReplacementRegEx || !ns.memMapShortToUnicodeCharacters) { + var unicodeList = []; + ns.memMapShortToUnicodeCharacters = {}; + ns.mapEmojioneList(function (unicode, shortname) { + var emojiCharacter = ns.convert(unicode); + if(ns.emojioneList[shortname].isCanonical) { + ns.memMapShortToUnicodeCharacters[emojiCharacter] = shortname; + } + unicodeList.push(emojiCharacter); + }); + ns.unicodeReplacementRegEx = unicodeList.join('|'); + } + }; + + ns.mapUnicodeCharactersToShort = function() { + ns.memoizeReplacement(); + return ns.memMapShortToUnicodeCharacters; + }; + + ns.getUnicodeReplacementRegEx = function() { + ns.memoizeReplacement(); + return ns.unicodeReplacementRegEx; + }; + + //reverse an object + ns.objectFlip = function (obj) { + var key, tmp_obj = {}; + + for (key in obj) { + if (obj.hasOwnProperty(key)) { + tmp_obj[obj[key]] = key; + } + } + + return tmp_obj; + }; + + ns.escapeRegExp = function(string) { + return string.replace(/[-[\]{}()*+?.,;:&\\^$#\s]/g, "\\$&"); + }; + + ns.replaceAll = function(string, find, replacementList) { + var escapedFind = ns.escapeRegExp(find); + var search = new RegExp("]*>.*?<\/object>|]*>.*?<\/span>|<(?:object|embed|svg|img|div|span|p|a)[^>]*>|("+escapedFind+")", "gi"); + + // callback prevents replacing anything inside of these common html tags as well as between an tag + var replace = function(entire, m1) { + return ((typeof m1 === 'undefined') || (m1 === '')) ? entire : replacementList[m1]; + }; + + return string.replace(search,replace); + }; + +}(this.emojione = this.emojione || {})); +if(typeof module === "object") module.exports = this.emojione; diff --git a/pagure/static/emoji/emojione-2.2.6.min.js b/pagure/static/emoji/emojione-2.2.6.min.js new file mode 100644 index 0000000..bfccc49 --- /dev/null +++ b/pagure/static/emoji/emojione-2.2.6.min.js @@ -0,0 +1,8 @@ +/*! emojione 15-07-2016 */ +!function(a){a.emojioneList={":kiss_ww:":{unicode:["1f469-200d-2764-fe0f-200d-1f48b-200d-1f469","1f469-2764-1f48b-1f469"],isCanonical:!0},":couplekiss_ww:":{unicode:["1f469-200d-2764-fe0f-200d-1f48b-200d-1f469","1f469-2764-1f48b-1f469"],isCanonical:!1},":kiss_mm:":{unicode:["1f468-200d-2764-fe0f-200d-1f48b-200d-1f468","1f468-2764-1f48b-1f468"],isCanonical:!0},":couplekiss_mm:":{unicode:["1f468-200d-2764-fe0f-200d-1f48b-200d-1f468","1f468-2764-1f48b-1f468"],isCanonical:!1},":family_mmbb:":{unicode:["1f468-200d-1f468-200d-1f466-200d-1f466","1f468-1f468-1f466-1f466"],isCanonical:!0},":family_mmgb:":{unicode:["1f468-200d-1f468-200d-1f467-200d-1f466","1f468-1f468-1f467-1f466"],isCanonical:!0},":family_mmgg:":{unicode:["1f468-200d-1f468-200d-1f467-200d-1f467","1f468-1f468-1f467-1f467"],isCanonical:!0},":family_mwbb:":{unicode:["1f468-200d-1f469-200d-1f466-200d-1f466","1f468-1f469-1f466-1f466"],isCanonical:!0},":family_mwgb:":{unicode:["1f468-200d-1f469-200d-1f467-200d-1f466","1f468-1f469-1f467-1f466"],isCanonical:!0},":family_mwgg:":{unicode:["1f468-200d-1f469-200d-1f467-200d-1f467","1f468-1f469-1f467-1f467"],isCanonical:!0},":family_wwbb:":{unicode:["1f469-200d-1f469-200d-1f466-200d-1f466","1f469-1f469-1f466-1f466"],isCanonical:!0},":family_wwgb:":{unicode:["1f469-200d-1f469-200d-1f467-200d-1f466","1f469-1f469-1f467-1f466"],isCanonical:!0},":family_wwgg:":{unicode:["1f469-200d-1f469-200d-1f467-200d-1f467","1f469-1f469-1f467-1f467"],isCanonical:!0},":couple_ww:":{unicode:["1f469-200d-2764-fe0f-200d-1f469","1f469-2764-1f469"],isCanonical:!0},":couple_with_heart_ww:":{unicode:["1f469-200d-2764-fe0f-200d-1f469","1f469-2764-1f469"],isCanonical:!1},":couple_mm:":{unicode:["1f468-200d-2764-fe0f-200d-1f468","1f468-2764-1f468"],isCanonical:!0},":couple_with_heart_mm:":{unicode:["1f468-200d-2764-fe0f-200d-1f468","1f468-2764-1f468"],isCanonical:!1},":family_mmb:":{unicode:["1f468-200d-1f468-200d-1f466","1f468-1f468-1f466"],isCanonical:!0},":family_mmg:":{unicode:["1f468-200d-1f468-200d-1f467","1f468-1f468-1f467"],isCanonical:!0},":family_mwg:":{unicode:["1f468-200d-1f469-200d-1f467","1f468-1f469-1f467"],isCanonical:!0},":family_wwb:":{unicode:["1f469-200d-1f469-200d-1f466","1f469-1f469-1f466"],isCanonical:!0},":family_wwg:":{unicode:["1f469-200d-1f469-200d-1f467","1f469-1f469-1f467"],isCanonical:!0},":eye_in_speech_bubble:":{unicode:["1f441-200d-1f5e8","1f441-1f5e8"],isCanonical:!0},":hash:":{unicode:["0023-fe0f-20e3","0023-20e3"],isCanonical:!0},":zero:":{unicode:["0030-fe0f-20e3","0030-20e3"],isCanonical:!0},":one:":{unicode:["0031-fe0f-20e3","0031-20e3"],isCanonical:!0},":two:":{unicode:["0032-fe0f-20e3","0032-20e3"],isCanonical:!0},":three:":{unicode:["0033-fe0f-20e3","0033-20e3"],isCanonical:!0},":four:":{unicode:["0034-fe0f-20e3","0034-20e3"],isCanonical:!0},":five:":{unicode:["0035-fe0f-20e3","0035-20e3"],isCanonical:!0},":six:":{unicode:["0036-fe0f-20e3","0036-20e3"],isCanonical:!0},":seven:":{unicode:["0037-fe0f-20e3","0037-20e3"],isCanonical:!0},":eight:":{unicode:["0038-fe0f-20e3","0038-20e3"],isCanonical:!0},":nine:":{unicode:["0039-fe0f-20e3","0039-20e3"],isCanonical:!0},":asterisk:":{unicode:["002a-fe0f-20e3","002a-20e3"],isCanonical:!0},":keycap_asterisk:":{unicode:["002a-fe0f-20e3","002a-20e3"],isCanonical:!1},":handball_tone5:":{unicode:["1f93e-1f3ff"],isCanonical:!0},":handball_tone4:":{unicode:["1f93e-1f3fe"],isCanonical:!0},":handball_tone3:":{unicode:["1f93e-1f3fd"],isCanonical:!0},":handball_tone2:":{unicode:["1f93e-1f3fc"],isCanonical:!0},":handball_tone1:":{unicode:["1f93e-1f3fb"],isCanonical:!0},":water_polo_tone5:":{unicode:["1f93d-1f3ff"],isCanonical:!0},":water_polo_tone4:":{unicode:["1f93d-1f3fe"],isCanonical:!0},":water_polo_tone3:":{unicode:["1f93d-1f3fd"],isCanonical:!0},":water_polo_tone2:":{unicode:["1f93d-1f3fc"],isCanonical:!0},":water_polo_tone1:":{unicode:["1f93d-1f3fb"],isCanonical:!0},":wrestlers_tone5:":{unicode:["1f93c-1f3ff"],isCanonical:!0},":wrestling_tone5:":{unicode:["1f93c-1f3ff"],isCanonical:!1},":wrestlers_tone4:":{unicode:["1f93c-1f3fe"],isCanonical:!0},":wrestling_tone4:":{unicode:["1f93c-1f3fe"],isCanonical:!1},":wrestlers_tone3:":{unicode:["1f93c-1f3fd"],isCanonical:!0},":wrestling_tone3:":{unicode:["1f93c-1f3fd"],isCanonical:!1},":wrestlers_tone2:":{unicode:["1f93c-1f3fc"],isCanonical:!0},":wrestling_tone2:":{unicode:["1f93c-1f3fc"],isCanonical:!1},":wrestlers_tone1:":{unicode:["1f93c-1f3fb"],isCanonical:!0},":wrestling_tone1:":{unicode:["1f93c-1f3fb"],isCanonical:!1},":juggling_tone5:":{unicode:["1f939-1f3ff"],isCanonical:!0},":juggler_tone5:":{unicode:["1f939-1f3ff"],isCanonical:!1},":juggling_tone4:":{unicode:["1f939-1f3fe"],isCanonical:!0},":juggler_tone4:":{unicode:["1f939-1f3fe"],isCanonical:!1},":juggling_tone3:":{unicode:["1f939-1f3fd"],isCanonical:!0},":juggler_tone3:":{unicode:["1f939-1f3fd"],isCanonical:!1},":juggling_tone2:":{unicode:["1f939-1f3fc"],isCanonical:!0},":juggler_tone2:":{unicode:["1f939-1f3fc"],isCanonical:!1},":juggling_tone1:":{unicode:["1f939-1f3fb"],isCanonical:!0},":juggler_tone1:":{unicode:["1f939-1f3fb"],isCanonical:!1},":cartwheel_tone5:":{unicode:["1f938-1f3ff"],isCanonical:!0},":person_doing_cartwheel_tone5:":{unicode:["1f938-1f3ff"],isCanonical:!1},":cartwheel_tone4:":{unicode:["1f938-1f3fe"],isCanonical:!0},":person_doing_cartwheel_tone4:":{unicode:["1f938-1f3fe"],isCanonical:!1},":cartwheel_tone3:":{unicode:["1f938-1f3fd"],isCanonical:!0},":person_doing_cartwheel_tone3:":{unicode:["1f938-1f3fd"],isCanonical:!1},":cartwheel_tone2:":{unicode:["1f938-1f3fc"],isCanonical:!0},":person_doing_cartwheel_tone2:":{unicode:["1f938-1f3fc"],isCanonical:!1},":cartwheel_tone1:":{unicode:["1f938-1f3fb"],isCanonical:!0},":person_doing_cartwheel_tone1:":{unicode:["1f938-1f3fb"],isCanonical:!1},":shrug_tone5:":{unicode:["1f937-1f3ff"],isCanonical:!0},":shrug_tone4:":{unicode:["1f937-1f3fe"],isCanonical:!0},":shrug_tone3:":{unicode:["1f937-1f3fd"],isCanonical:!0},":shrug_tone2:":{unicode:["1f937-1f3fc"],isCanonical:!0},":shrug_tone1:":{unicode:["1f937-1f3fb"],isCanonical:!0},":mrs_claus_tone5:":{unicode:["1f936-1f3ff"],isCanonical:!0},":mother_christmas_tone5:":{unicode:["1f936-1f3ff"],isCanonical:!1},":mrs_claus_tone4:":{unicode:["1f936-1f3fe"],isCanonical:!0},":mother_christmas_tone4:":{unicode:["1f936-1f3fe"],isCanonical:!1},":mrs_claus_tone3:":{unicode:["1f936-1f3fd"],isCanonical:!0},":mother_christmas_tone3:":{unicode:["1f936-1f3fd"],isCanonical:!1},":mrs_claus_tone2:":{unicode:["1f936-1f3fc"],isCanonical:!0},":mother_christmas_tone2:":{unicode:["1f936-1f3fc"],isCanonical:!1},":mrs_claus_tone1:":{unicode:["1f936-1f3fb"],isCanonical:!0},":mother_christmas_tone1:":{unicode:["1f936-1f3fb"],isCanonical:!1},":man_in_tuxedo_tone5:":{unicode:["1f935-1f3ff"],isCanonical:!0},":tuxedo_tone5:":{unicode:["1f935-1f3ff"],isCanonical:!1},":man_in_tuxedo_tone4:":{unicode:["1f935-1f3fe"],isCanonical:!0},":tuxedo_tone4:":{unicode:["1f935-1f3fe"],isCanonical:!1},":man_in_tuxedo_tone3:":{unicode:["1f935-1f3fd"],isCanonical:!0},":tuxedo_tone3:":{unicode:["1f935-1f3fd"],isCanonical:!1},":man_in_tuxedo_tone2:":{unicode:["1f935-1f3fc"],isCanonical:!0},":tuxedo_tone2:":{unicode:["1f935-1f3fc"],isCanonical:!1},":man_in_tuxedo_tone1:":{unicode:["1f935-1f3fb"],isCanonical:!0},":tuxedo_tone1:":{unicode:["1f935-1f3fb"],isCanonical:!1},":prince_tone5:":{unicode:["1f934-1f3ff"],isCanonical:!0},":prince_tone4:":{unicode:["1f934-1f3fe"],isCanonical:!0},":prince_tone3:":{unicode:["1f934-1f3fd"],isCanonical:!0},":prince_tone2:":{unicode:["1f934-1f3fc"],isCanonical:!0},":prince_tone1:":{unicode:["1f934-1f3fb"],isCanonical:!0},":selfie_tone5:":{unicode:["1f933-1f3ff"],isCanonical:!0},":selfie_tone4:":{unicode:["1f933-1f3fe"],isCanonical:!0},":selfie_tone3:":{unicode:["1f933-1f3fd"],isCanonical:!0},":selfie_tone2:":{unicode:["1f933-1f3fc"],isCanonical:!0},":selfie_tone1:":{unicode:["1f933-1f3fb"],isCanonical:!0},":pregnant_woman_tone5:":{unicode:["1f930-1f3ff"],isCanonical:!0},":expecting_woman_tone5:":{unicode:["1f930-1f3ff"],isCanonical:!1},":pregnant_woman_tone4:":{unicode:["1f930-1f3fe"],isCanonical:!0},":expecting_woman_tone4:":{unicode:["1f930-1f3fe"],isCanonical:!1},":pregnant_woman_tone3:":{unicode:["1f930-1f3fd"],isCanonical:!0},":expecting_woman_tone3:":{unicode:["1f930-1f3fd"],isCanonical:!1},":pregnant_woman_tone2:":{unicode:["1f930-1f3fc"],isCanonical:!0},":expecting_woman_tone2:":{unicode:["1f930-1f3fc"],isCanonical:!1},":pregnant_woman_tone1:":{unicode:["1f930-1f3fb"],isCanonical:!0},":expecting_woman_tone1:":{unicode:["1f930-1f3fb"],isCanonical:!1},":face_palm_tone5:":{unicode:["1f926-1f3ff"],isCanonical:!0},":facepalm_tone5:":{unicode:["1f926-1f3ff"],isCanonical:!1},":face_palm_tone4:":{unicode:["1f926-1f3fe"],isCanonical:!0},":facepalm_tone4:":{unicode:["1f926-1f3fe"],isCanonical:!1},":face_palm_tone3:":{unicode:["1f926-1f3fd"],isCanonical:!0},":facepalm_tone3:":{unicode:["1f926-1f3fd"],isCanonical:!1},":face_palm_tone2:":{unicode:["1f926-1f3fc"],isCanonical:!0},":facepalm_tone2:":{unicode:["1f926-1f3fc"],isCanonical:!1},":face_palm_tone1:":{unicode:["1f926-1f3fb"],isCanonical:!0},":facepalm_tone1:":{unicode:["1f926-1f3fb"],isCanonical:!1},":fingers_crossed_tone5:":{unicode:["1f91e-1f3ff"],isCanonical:!0},":hand_with_index_and_middle_fingers_crossed_tone5:":{unicode:["1f91e-1f3ff"],isCanonical:!1},":fingers_crossed_tone4:":{unicode:["1f91e-1f3fe"],isCanonical:!0},":hand_with_index_and_middle_fingers_crossed_tone4:":{unicode:["1f91e-1f3fe"],isCanonical:!1},":fingers_crossed_tone3:":{unicode:["1f91e-1f3fd"],isCanonical:!0},":hand_with_index_and_middle_fingers_crossed_tone3:":{unicode:["1f91e-1f3fd"],isCanonical:!1},":fingers_crossed_tone2:":{unicode:["1f91e-1f3fc"],isCanonical:!0},":hand_with_index_and_middle_fingers_crossed_tone2:":{unicode:["1f91e-1f3fc"],isCanonical:!1},":fingers_crossed_tone1:":{unicode:["1f91e-1f3fb"],isCanonical:!0},":hand_with_index_and_middle_fingers_crossed_tone1:":{unicode:["1f91e-1f3fb"],isCanonical:!1},":handshake_tone5:":{unicode:["1f91d-1f3ff"],isCanonical:!0},":shaking_hands_tone5:":{unicode:["1f91d-1f3ff"],isCanonical:!1},":handshake_tone4:":{unicode:["1f91d-1f3fe"],isCanonical:!0},":shaking_hands_tone4:":{unicode:["1f91d-1f3fe"],isCanonical:!1},":handshake_tone3:":{unicode:["1f91d-1f3fd"],isCanonical:!0},":shaking_hands_tone3:":{unicode:["1f91d-1f3fd"],isCanonical:!1},":handshake_tone2:":{unicode:["1f91d-1f3fc"],isCanonical:!0},":shaking_hands_tone2:":{unicode:["1f91d-1f3fc"],isCanonical:!1},":handshake_tone1:":{unicode:["1f91d-1f3fb"],isCanonical:!0},":shaking_hands_tone1:":{unicode:["1f91d-1f3fb"],isCanonical:!1},":right_facing_fist_tone5:":{unicode:["1f91c-1f3ff"],isCanonical:!0},":right_fist_tone5:":{unicode:["1f91c-1f3ff"],isCanonical:!1},":right_facing_fist_tone4:":{unicode:["1f91c-1f3fe"],isCanonical:!0},":right_fist_tone4:":{unicode:["1f91c-1f3fe"],isCanonical:!1},":right_facing_fist_tone3:":{unicode:["1f91c-1f3fd"],isCanonical:!0},":right_fist_tone3:":{unicode:["1f91c-1f3fd"],isCanonical:!1},":right_facing_fist_tone2:":{unicode:["1f91c-1f3fc"],isCanonical:!0},":right_fist_tone2:":{unicode:["1f91c-1f3fc"],isCanonical:!1},":right_facing_fist_tone1:":{unicode:["1f91c-1f3fb"],isCanonical:!0},":right_fist_tone1:":{unicode:["1f91c-1f3fb"],isCanonical:!1},":left_facing_fist_tone5:":{unicode:["1f91b-1f3ff"],isCanonical:!0},":left_fist_tone5:":{unicode:["1f91b-1f3ff"],isCanonical:!1},":left_facing_fist_tone4:":{unicode:["1f91b-1f3fe"],isCanonical:!0},":left_fist_tone4:":{unicode:["1f91b-1f3fe"],isCanonical:!1},":left_facing_fist_tone3:":{unicode:["1f91b-1f3fd"],isCanonical:!0},":left_fist_tone3:":{unicode:["1f91b-1f3fd"],isCanonical:!1},":left_facing_fist_tone2:":{unicode:["1f91b-1f3fc"],isCanonical:!0},":left_fist_tone2:":{unicode:["1f91b-1f3fc"],isCanonical:!1},":left_facing_fist_tone1:":{unicode:["1f91b-1f3fb"],isCanonical:!0},":left_fist_tone1:":{unicode:["1f91b-1f3fb"],isCanonical:!1},":raised_back_of_hand_tone5:":{unicode:["1f91a-1f3ff"],isCanonical:!0},":back_of_hand_tone5:":{unicode:["1f91a-1f3ff"],isCanonical:!1},":raised_back_of_hand_tone4:":{unicode:["1f91a-1f3fe"],isCanonical:!0},":back_of_hand_tone4:":{unicode:["1f91a-1f3fe"],isCanonical:!1},":raised_back_of_hand_tone3:":{unicode:["1f91a-1f3fd"],isCanonical:!0},":back_of_hand_tone3:":{unicode:["1f91a-1f3fd"],isCanonical:!1},":raised_back_of_hand_tone2:":{unicode:["1f91a-1f3fc"],isCanonical:!0},":back_of_hand_tone2:":{unicode:["1f91a-1f3fc"],isCanonical:!1},":raised_back_of_hand_tone1:":{unicode:["1f91a-1f3fb"],isCanonical:!0},":back_of_hand_tone1:":{unicode:["1f91a-1f3fb"],isCanonical:!1},":call_me_tone5:":{unicode:["1f919-1f3ff"],isCanonical:!0},":call_me_hand_tone5:":{unicode:["1f919-1f3ff"],isCanonical:!1},":call_me_tone4:":{unicode:["1f919-1f3fe"],isCanonical:!0},":call_me_hand_tone4:":{unicode:["1f919-1f3fe"],isCanonical:!1},":call_me_tone3:":{unicode:["1f919-1f3fd"],isCanonical:!0},":call_me_hand_tone3:":{unicode:["1f919-1f3fd"],isCanonical:!1},":call_me_tone2:":{unicode:["1f919-1f3fc"],isCanonical:!0},":call_me_hand_tone2:":{unicode:["1f919-1f3fc"],isCanonical:!1},":call_me_tone1:":{unicode:["1f919-1f3fb"],isCanonical:!0},":call_me_hand_tone1:":{unicode:["1f919-1f3fb"],isCanonical:!1},":metal_tone5:":{unicode:["1f918-1f3ff"],isCanonical:!0},":sign_of_the_horns_tone5:":{unicode:["1f918-1f3ff"],isCanonical:!1},":metal_tone4:":{unicode:["1f918-1f3fe"],isCanonical:!0},":sign_of_the_horns_tone4:":{unicode:["1f918-1f3fe"],isCanonical:!1},":metal_tone3:":{unicode:["1f918-1f3fd"],isCanonical:!0},":sign_of_the_horns_tone3:":{unicode:["1f918-1f3fd"],isCanonical:!1},":metal_tone2:":{unicode:["1f918-1f3fc"],isCanonical:!0},":sign_of_the_horns_tone2:":{unicode:["1f918-1f3fc"],isCanonical:!1},":metal_tone1:":{unicode:["1f918-1f3fb"],isCanonical:!0},":sign_of_the_horns_tone1:":{unicode:["1f918-1f3fb"],isCanonical:!1},":bath_tone5:":{unicode:["1f6c0-1f3ff"],isCanonical:!0},":bath_tone4:":{unicode:["1f6c0-1f3fe"],isCanonical:!0},":bath_tone3:":{unicode:["1f6c0-1f3fd"],isCanonical:!0},":bath_tone2:":{unicode:["1f6c0-1f3fc"],isCanonical:!0},":bath_tone1:":{unicode:["1f6c0-1f3fb"],isCanonical:!0},":walking_tone5:":{unicode:["1f6b6-1f3ff"],isCanonical:!0},":walking_tone4:":{unicode:["1f6b6-1f3fe"],isCanonical:!0},":walking_tone3:":{unicode:["1f6b6-1f3fd"],isCanonical:!0},":walking_tone2:":{unicode:["1f6b6-1f3fc"],isCanonical:!0},":walking_tone1:":{unicode:["1f6b6-1f3fb"],isCanonical:!0},":mountain_bicyclist_tone5:":{unicode:["1f6b5-1f3ff"],isCanonical:!0},":mountain_bicyclist_tone4:":{unicode:["1f6b5-1f3fe"],isCanonical:!0},":mountain_bicyclist_tone3:":{unicode:["1f6b5-1f3fd"],isCanonical:!0},":mountain_bicyclist_tone2:":{unicode:["1f6b5-1f3fc"],isCanonical:!0},":mountain_bicyclist_tone1:":{unicode:["1f6b5-1f3fb"],isCanonical:!0},":bicyclist_tone5:":{unicode:["1f6b4-1f3ff"],isCanonical:!0},":bicyclist_tone4:":{unicode:["1f6b4-1f3fe"],isCanonical:!0},":bicyclist_tone3:":{unicode:["1f6b4-1f3fd"],isCanonical:!0},":bicyclist_tone2:":{unicode:["1f6b4-1f3fc"],isCanonical:!0},":bicyclist_tone1:":{unicode:["1f6b4-1f3fb"],isCanonical:!0},":rowboat_tone5:":{unicode:["1f6a3-1f3ff"],isCanonical:!0},":rowboat_tone4:":{unicode:["1f6a3-1f3fe"],isCanonical:!0},":rowboat_tone3:":{unicode:["1f6a3-1f3fd"],isCanonical:!0},":rowboat_tone2:":{unicode:["1f6a3-1f3fc"],isCanonical:!0},":rowboat_tone1:":{unicode:["1f6a3-1f3fb"],isCanonical:!0},":pray_tone5:":{unicode:["1f64f-1f3ff"],isCanonical:!0},":pray_tone4:":{unicode:["1f64f-1f3fe"],isCanonical:!0},":pray_tone3:":{unicode:["1f64f-1f3fd"],isCanonical:!0},":pray_tone2:":{unicode:["1f64f-1f3fc"],isCanonical:!0},":pray_tone1:":{unicode:["1f64f-1f3fb"],isCanonical:!0},":person_with_pouting_face_tone5:":{unicode:["1f64e-1f3ff"],isCanonical:!0},":person_with_pouting_face_tone4:":{unicode:["1f64e-1f3fe"],isCanonical:!0},":person_with_pouting_face_tone3:":{unicode:["1f64e-1f3fd"],isCanonical:!0},":person_with_pouting_face_tone2:":{unicode:["1f64e-1f3fc"],isCanonical:!0},":person_with_pouting_face_tone1:":{unicode:["1f64e-1f3fb"],isCanonical:!0},":person_frowning_tone5:":{unicode:["1f64d-1f3ff"],isCanonical:!0},":person_frowning_tone4:":{unicode:["1f64d-1f3fe"],isCanonical:!0},":person_frowning_tone3:":{unicode:["1f64d-1f3fd"],isCanonical:!0},":person_frowning_tone2:":{unicode:["1f64d-1f3fc"],isCanonical:!0},":person_frowning_tone1:":{unicode:["1f64d-1f3fb"],isCanonical:!0},":raised_hands_tone5:":{unicode:["1f64c-1f3ff"],isCanonical:!0},":raised_hands_tone4:":{unicode:["1f64c-1f3fe"],isCanonical:!0},":raised_hands_tone3:":{unicode:["1f64c-1f3fd"],isCanonical:!0},":raised_hands_tone2:":{unicode:["1f64c-1f3fc"],isCanonical:!0},":raised_hands_tone1:":{unicode:["1f64c-1f3fb"],isCanonical:!0},":raising_hand_tone5:":{unicode:["1f64b-1f3ff"],isCanonical:!0},":raising_hand_tone4:":{unicode:["1f64b-1f3fe"],isCanonical:!0},":raising_hand_tone3:":{unicode:["1f64b-1f3fd"],isCanonical:!0},":raising_hand_tone2:":{unicode:["1f64b-1f3fc"],isCanonical:!0},":raising_hand_tone1:":{unicode:["1f64b-1f3fb"],isCanonical:!0},":bow_tone5:":{unicode:["1f647-1f3ff"],isCanonical:!0},":bow_tone4:":{unicode:["1f647-1f3fe"],isCanonical:!0},":bow_tone3:":{unicode:["1f647-1f3fd"],isCanonical:!0},":bow_tone2:":{unicode:["1f647-1f3fc"],isCanonical:!0},":bow_tone1:":{unicode:["1f647-1f3fb"],isCanonical:!0},":ok_woman_tone5:":{unicode:["1f646-1f3ff"],isCanonical:!0},":ok_woman_tone4:":{unicode:["1f646-1f3fe"],isCanonical:!0},":ok_woman_tone3:":{unicode:["1f646-1f3fd"],isCanonical:!0},":ok_woman_tone2:":{unicode:["1f646-1f3fc"],isCanonical:!0},":ok_woman_tone1:":{unicode:["1f646-1f3fb"],isCanonical:!0},":no_good_tone5:":{unicode:["1f645-1f3ff"],isCanonical:!0},":no_good_tone4:":{unicode:["1f645-1f3fe"],isCanonical:!0},":no_good_tone3:":{unicode:["1f645-1f3fd"],isCanonical:!0},":no_good_tone2:":{unicode:["1f645-1f3fc"],isCanonical:!0},":no_good_tone1:":{unicode:["1f645-1f3fb"],isCanonical:!0},":vulcan_tone5:":{unicode:["1f596-1f3ff"],isCanonical:!0},":raised_hand_with_part_between_middle_and_ring_fingers_tone5:":{unicode:["1f596-1f3ff"],isCanonical:!1},":vulcan_tone4:":{unicode:["1f596-1f3fe"],isCanonical:!0},":raised_hand_with_part_between_middle_and_ring_fingers_tone4:":{unicode:["1f596-1f3fe"],isCanonical:!1},":vulcan_tone3:":{unicode:["1f596-1f3fd"],isCanonical:!0},":raised_hand_with_part_between_middle_and_ring_fingers_tone3:":{unicode:["1f596-1f3fd"],isCanonical:!1},":vulcan_tone2:":{unicode:["1f596-1f3fc"],isCanonical:!0},":raised_hand_with_part_between_middle_and_ring_fingers_tone2:":{unicode:["1f596-1f3fc"],isCanonical:!1},":vulcan_tone1:":{unicode:["1f596-1f3fb"],isCanonical:!0},":raised_hand_with_part_between_middle_and_ring_fingers_tone1:":{unicode:["1f596-1f3fb"],isCanonical:!1},":middle_finger_tone5:":{unicode:["1f595-1f3ff"],isCanonical:!0},":reversed_hand_with_middle_finger_extended_tone5:":{unicode:["1f595-1f3ff"],isCanonical:!1},":middle_finger_tone4:":{unicode:["1f595-1f3fe"],isCanonical:!0},":reversed_hand_with_middle_finger_extended_tone4:":{unicode:["1f595-1f3fe"],isCanonical:!1},":middle_finger_tone3:":{unicode:["1f595-1f3fd"],isCanonical:!0},":reversed_hand_with_middle_finger_extended_tone3:":{unicode:["1f595-1f3fd"],isCanonical:!1},":middle_finger_tone2:":{unicode:["1f595-1f3fc"],isCanonical:!0},":reversed_hand_with_middle_finger_extended_tone2:":{unicode:["1f595-1f3fc"],isCanonical:!1},":middle_finger_tone1:":{unicode:["1f595-1f3fb"],isCanonical:!0},":reversed_hand_with_middle_finger_extended_tone1:":{unicode:["1f595-1f3fb"],isCanonical:!1},":hand_splayed_tone5:":{unicode:["1f590-1f3ff"],isCanonical:!0},":raised_hand_with_fingers_splayed_tone5:":{unicode:["1f590-1f3ff"],isCanonical:!1},":hand_splayed_tone4:":{unicode:["1f590-1f3fe"],isCanonical:!0},":raised_hand_with_fingers_splayed_tone4:":{unicode:["1f590-1f3fe"],isCanonical:!1},":hand_splayed_tone3:":{unicode:["1f590-1f3fd"],isCanonical:!0},":raised_hand_with_fingers_splayed_tone3:":{unicode:["1f590-1f3fd"],isCanonical:!1},":hand_splayed_tone2:":{unicode:["1f590-1f3fc"],isCanonical:!0},":raised_hand_with_fingers_splayed_tone2:":{unicode:["1f590-1f3fc"],isCanonical:!1},":hand_splayed_tone1:":{unicode:["1f590-1f3fb"],isCanonical:!0},":raised_hand_with_fingers_splayed_tone1:":{unicode:["1f590-1f3fb"],isCanonical:!1},":man_dancing_tone5:":{unicode:["1f57a-1f3ff"],isCanonical:!0},":male_dancer_tone5:":{unicode:["1f57a-1f3ff"],isCanonical:!1},":man_dancing_tone4:":{unicode:["1f57a-1f3fe"],isCanonical:!0},":male_dancer_tone4:":{unicode:["1f57a-1f3fe"],isCanonical:!1},":man_dancing_tone3:":{unicode:["1f57a-1f3fd"],isCanonical:!0},":male_dancer_tone3:":{unicode:["1f57a-1f3fd"],isCanonical:!1},":man_dancing_tone2:":{unicode:["1f57a-1f3fc"],isCanonical:!0},":male_dancer_tone2:":{unicode:["1f57a-1f3fc"],isCanonical:!1},":man_dancing_tone1:":{unicode:["1f57a-1f3fb"],isCanonical:!0},":male_dancer_tone1:":{unicode:["1f57a-1f3fb"],isCanonical:!1},":spy_tone5:":{unicode:["1f575-1f3ff"],isCanonical:!0},":sleuth_or_spy_tone5:":{unicode:["1f575-1f3ff"],isCanonical:!1},":spy_tone4:":{unicode:["1f575-1f3fe"],isCanonical:!0},":sleuth_or_spy_tone4:":{unicode:["1f575-1f3fe"],isCanonical:!1},":spy_tone3:":{unicode:["1f575-1f3fd"],isCanonical:!0},":sleuth_or_spy_tone3:":{unicode:["1f575-1f3fd"],isCanonical:!1},":spy_tone2:":{unicode:["1f575-1f3fc"],isCanonical:!0},":sleuth_or_spy_tone2:":{unicode:["1f575-1f3fc"],isCanonical:!1},":spy_tone1:":{unicode:["1f575-1f3fb"],isCanonical:!0},":sleuth_or_spy_tone1:":{unicode:["1f575-1f3fb"],isCanonical:!1},":muscle_tone5:":{unicode:["1f4aa-1f3ff"],isCanonical:!0},":muscle_tone4:":{unicode:["1f4aa-1f3fe"],isCanonical:!0},":muscle_tone3:":{unicode:["1f4aa-1f3fd"],isCanonical:!0},":muscle_tone2:":{unicode:["1f4aa-1f3fc"],isCanonical:!0},":muscle_tone1:":{unicode:["1f4aa-1f3fb"],isCanonical:!0},":haircut_tone5:":{unicode:["1f487-1f3ff"],isCanonical:!0},":haircut_tone4:":{unicode:["1f487-1f3fe"],isCanonical:!0},":haircut_tone3:":{unicode:["1f487-1f3fd"],isCanonical:!0},":haircut_tone2:":{unicode:["1f487-1f3fc"],isCanonical:!0},":haircut_tone1:":{unicode:["1f487-1f3fb"],isCanonical:!0},":massage_tone5:":{unicode:["1f486-1f3ff"],isCanonical:!0},":massage_tone4:":{unicode:["1f486-1f3fe"],isCanonical:!0},":massage_tone3:":{unicode:["1f486-1f3fd"],isCanonical:!0},":massage_tone2:":{unicode:["1f486-1f3fc"],isCanonical:!0},":massage_tone1:":{unicode:["1f486-1f3fb"],isCanonical:!0},":nail_care_tone5:":{unicode:["1f485-1f3ff"],isCanonical:!0},":nail_care_tone4:":{unicode:["1f485-1f3fe"],isCanonical:!0},":nail_care_tone3:":{unicode:["1f485-1f3fd"],isCanonical:!0},":nail_care_tone2:":{unicode:["1f485-1f3fc"],isCanonical:!0},":nail_care_tone1:":{unicode:["1f485-1f3fb"],isCanonical:!0},":dancer_tone5:":{unicode:["1f483-1f3ff"],isCanonical:!0},":dancer_tone4:":{unicode:["1f483-1f3fe"],isCanonical:!0},":dancer_tone3:":{unicode:["1f483-1f3fd"],isCanonical:!0},":dancer_tone2:":{unicode:["1f483-1f3fc"],isCanonical:!0},":dancer_tone1:":{unicode:["1f483-1f3fb"],isCanonical:!0},":guardsman_tone5:":{unicode:["1f482-1f3ff"],isCanonical:!0},":guardsman_tone4:":{unicode:["1f482-1f3fe"],isCanonical:!0},":guardsman_tone3:":{unicode:["1f482-1f3fd"],isCanonical:!0},":guardsman_tone2:":{unicode:["1f482-1f3fc"],isCanonical:!0},":guardsman_tone1:":{unicode:["1f482-1f3fb"],isCanonical:!0},":information_desk_person_tone5:":{unicode:["1f481-1f3ff"],isCanonical:!0},":information_desk_person_tone4:":{unicode:["1f481-1f3fe"],isCanonical:!0},":information_desk_person_tone3:":{unicode:["1f481-1f3fd"],isCanonical:!0},":information_desk_person_tone2:":{unicode:["1f481-1f3fc"],isCanonical:!0},":information_desk_person_tone1:":{unicode:["1f481-1f3fb"],isCanonical:!0},":angel_tone5:":{unicode:["1f47c-1f3ff"],isCanonical:!0},":angel_tone4:":{unicode:["1f47c-1f3fe"],isCanonical:!0},":angel_tone3:":{unicode:["1f47c-1f3fd"],isCanonical:!0},":angel_tone2:":{unicode:["1f47c-1f3fc"],isCanonical:!0},":angel_tone1:":{unicode:["1f47c-1f3fb"],isCanonical:!0},":princess_tone5:":{unicode:["1f478-1f3ff"],isCanonical:!0},":princess_tone4:":{unicode:["1f478-1f3fe"],isCanonical:!0},":princess_tone3:":{unicode:["1f478-1f3fd"],isCanonical:!0},":princess_tone2:":{unicode:["1f478-1f3fc"],isCanonical:!0},":princess_tone1:":{unicode:["1f478-1f3fb"],isCanonical:!0},":construction_worker_tone5:":{unicode:["1f477-1f3ff"],isCanonical:!0},":construction_worker_tone4:":{unicode:["1f477-1f3fe"],isCanonical:!0},":construction_worker_tone3:":{unicode:["1f477-1f3fd"],isCanonical:!0},":construction_worker_tone2:":{unicode:["1f477-1f3fc"],isCanonical:!0},":construction_worker_tone1:":{unicode:["1f477-1f3fb"],isCanonical:!0},":baby_tone5:":{unicode:["1f476-1f3ff"],isCanonical:!0},":baby_tone4:":{unicode:["1f476-1f3fe"],isCanonical:!0},":baby_tone3:":{unicode:["1f476-1f3fd"],isCanonical:!0},":baby_tone2:":{unicode:["1f476-1f3fc"],isCanonical:!0},":baby_tone1:":{unicode:["1f476-1f3fb"],isCanonical:!0},":older_woman_tone5:":{unicode:["1f475-1f3ff"],isCanonical:!0},":grandma_tone5:":{unicode:["1f475-1f3ff"],isCanonical:!1},":older_woman_tone4:":{unicode:["1f475-1f3fe"],isCanonical:!0},":grandma_tone4:":{unicode:["1f475-1f3fe"],isCanonical:!1},":older_woman_tone3:":{unicode:["1f475-1f3fd"],isCanonical:!0},":grandma_tone3:":{unicode:["1f475-1f3fd"],isCanonical:!1},":older_woman_tone2:":{unicode:["1f475-1f3fc"],isCanonical:!0},":grandma_tone2:":{unicode:["1f475-1f3fc"],isCanonical:!1},":older_woman_tone1:":{unicode:["1f475-1f3fb"],isCanonical:!0},":grandma_tone1:":{unicode:["1f475-1f3fb"],isCanonical:!1},":older_man_tone5:":{unicode:["1f474-1f3ff"],isCanonical:!0},":older_man_tone4:":{unicode:["1f474-1f3fe"],isCanonical:!0},":older_man_tone3:":{unicode:["1f474-1f3fd"],isCanonical:!0},":older_man_tone2:":{unicode:["1f474-1f3fc"],isCanonical:!0},":older_man_tone1:":{unicode:["1f474-1f3fb"],isCanonical:!0},":man_with_turban_tone5:":{unicode:["1f473-1f3ff"],isCanonical:!0},":man_with_turban_tone4:":{unicode:["1f473-1f3fe"],isCanonical:!0},":man_with_turban_tone3:":{unicode:["1f473-1f3fd"],isCanonical:!0},":man_with_turban_tone2:":{unicode:["1f473-1f3fc"],isCanonical:!0},":man_with_turban_tone1:":{unicode:["1f473-1f3fb"],isCanonical:!0},":man_with_gua_pi_mao_tone5:":{unicode:["1f472-1f3ff"],isCanonical:!0},":man_with_gua_pi_mao_tone4:":{unicode:["1f472-1f3fe"],isCanonical:!0},":man_with_gua_pi_mao_tone3:":{unicode:["1f472-1f3fd"],isCanonical:!0},":man_with_gua_pi_mao_tone2:":{unicode:["1f472-1f3fc"],isCanonical:!0},":man_with_gua_pi_mao_tone1:":{unicode:["1f472-1f3fb"],isCanonical:!0},":person_with_blond_hair_tone5:":{unicode:["1f471-1f3ff"],isCanonical:!0},":person_with_blond_hair_tone4:":{unicode:["1f471-1f3fe"],isCanonical:!0},":person_with_blond_hair_tone3:":{unicode:["1f471-1f3fd"],isCanonical:!0},":person_with_blond_hair_tone2:":{unicode:["1f471-1f3fc"],isCanonical:!0},":person_with_blond_hair_tone1:":{unicode:["1f471-1f3fb"],isCanonical:!0},":bride_with_veil_tone5:":{unicode:["1f470-1f3ff"],isCanonical:!0},":bride_with_veil_tone4:":{unicode:["1f470-1f3fe"],isCanonical:!0},":bride_with_veil_tone3:":{unicode:["1f470-1f3fd"],isCanonical:!0},":bride_with_veil_tone2:":{unicode:["1f470-1f3fc"],isCanonical:!0},":bride_with_veil_tone1:":{unicode:["1f470-1f3fb"],isCanonical:!0},":cop_tone5:":{unicode:["1f46e-1f3ff"],isCanonical:!0},":cop_tone4:":{unicode:["1f46e-1f3fe"],isCanonical:!0},":cop_tone3:":{unicode:["1f46e-1f3fd"],isCanonical:!0},":cop_tone2:":{unicode:["1f46e-1f3fc"],isCanonical:!0},":cop_tone1:":{unicode:["1f46e-1f3fb"],isCanonical:!0},":woman_tone5:":{unicode:["1f469-1f3ff"],isCanonical:!0},":woman_tone4:":{unicode:["1f469-1f3fe"],isCanonical:!0},":woman_tone3:":{unicode:["1f469-1f3fd"],isCanonical:!0},":woman_tone2:":{unicode:["1f469-1f3fc"],isCanonical:!0},":woman_tone1:":{unicode:["1f469-1f3fb"],isCanonical:!0},":man_tone5:":{unicode:["1f468-1f3ff"],isCanonical:!0},":man_tone4:":{unicode:["1f468-1f3fe"],isCanonical:!0},":man_tone3:":{unicode:["1f468-1f3fd"],isCanonical:!0},":man_tone2:":{unicode:["1f468-1f3fc"],isCanonical:!0},":man_tone1:":{unicode:["1f468-1f3fb"],isCanonical:!0},":girl_tone5:":{unicode:["1f467-1f3ff"],isCanonical:!0},":girl_tone4:":{unicode:["1f467-1f3fe"],isCanonical:!0},":girl_tone3:":{unicode:["1f467-1f3fd"],isCanonical:!0},":girl_tone2:":{unicode:["1f467-1f3fc"],isCanonical:!0},":girl_tone1:":{unicode:["1f467-1f3fb"],isCanonical:!0},":boy_tone5:":{unicode:["1f466-1f3ff"],isCanonical:!0},":boy_tone4:":{unicode:["1f466-1f3fe"],isCanonical:!0},":boy_tone3:":{unicode:["1f466-1f3fd"],isCanonical:!0},":boy_tone2:":{unicode:["1f466-1f3fc"],isCanonical:!0},":boy_tone1:":{unicode:["1f466-1f3fb"],isCanonical:!0},":open_hands_tone5:":{unicode:["1f450-1f3ff"],isCanonical:!0},":open_hands_tone4:":{unicode:["1f450-1f3fe"],isCanonical:!0},":open_hands_tone3:":{unicode:["1f450-1f3fd"],isCanonical:!0},":open_hands_tone2:":{unicode:["1f450-1f3fc"],isCanonical:!0},":open_hands_tone1:":{unicode:["1f450-1f3fb"],isCanonical:!0},":clap_tone5:":{unicode:["1f44f-1f3ff"],isCanonical:!0},":clap_tone4:":{unicode:["1f44f-1f3fe"],isCanonical:!0},":clap_tone3:":{unicode:["1f44f-1f3fd"],isCanonical:!0},":clap_tone2:":{unicode:["1f44f-1f3fc"],isCanonical:!0},":clap_tone1:":{unicode:["1f44f-1f3fb"],isCanonical:!0},":thumbsdown_tone5:":{unicode:["1f44e-1f3ff"],isCanonical:!0},":-1_tone5:":{unicode:["1f44e-1f3ff"],isCanonical:!1},":thumbdown_tone5:":{unicode:["1f44e-1f3ff"],isCanonical:!1},":thumbsdown_tone4:":{unicode:["1f44e-1f3fe"],isCanonical:!0},":-1_tone4:":{unicode:["1f44e-1f3fe"],isCanonical:!1},":thumbdown_tone4:":{unicode:["1f44e-1f3fe"],isCanonical:!1},":thumbsdown_tone3:":{unicode:["1f44e-1f3fd"],isCanonical:!0},":-1_tone3:":{unicode:["1f44e-1f3fd"],isCanonical:!1},":thumbdown_tone3:":{unicode:["1f44e-1f3fd"],isCanonical:!1},":thumbsdown_tone2:":{unicode:["1f44e-1f3fc"],isCanonical:!0},":-1_tone2:":{unicode:["1f44e-1f3fc"],isCanonical:!1},":thumbdown_tone2:":{unicode:["1f44e-1f3fc"],isCanonical:!1},":thumbsdown_tone1:":{unicode:["1f44e-1f3fb"],isCanonical:!0},":-1_tone1:":{unicode:["1f44e-1f3fb"],isCanonical:!1},":thumbdown_tone1:":{unicode:["1f44e-1f3fb"],isCanonical:!1},":thumbsup_tone5:":{unicode:["1f44d-1f3ff"],isCanonical:!0},":+1_tone5:":{unicode:["1f44d-1f3ff"],isCanonical:!1},":thumbup_tone5:":{unicode:["1f44d-1f3ff"],isCanonical:!1},":thumbsup_tone4:":{unicode:["1f44d-1f3fe"],isCanonical:!0},":+1_tone4:":{unicode:["1f44d-1f3fe"],isCanonical:!1},":thumbup_tone4:":{unicode:["1f44d-1f3fe"],isCanonical:!1},":thumbsup_tone3:":{unicode:["1f44d-1f3fd"],isCanonical:!0},":+1_tone3:":{unicode:["1f44d-1f3fd"],isCanonical:!1},":thumbup_tone3:":{unicode:["1f44d-1f3fd"],isCanonical:!1},":thumbsup_tone2:":{unicode:["1f44d-1f3fc"],isCanonical:!0},":+1_tone2:":{unicode:["1f44d-1f3fc"],isCanonical:!1},":thumbup_tone2:":{unicode:["1f44d-1f3fc"],isCanonical:!1},":thumbsup_tone1:":{unicode:["1f44d-1f3fb"],isCanonical:!0},":+1_tone1:":{unicode:["1f44d-1f3fb"],isCanonical:!1},":thumbup_tone1:":{unicode:["1f44d-1f3fb"],isCanonical:!1},":ok_hand_tone5:":{unicode:["1f44c-1f3ff"],isCanonical:!0},":ok_hand_tone4:":{unicode:["1f44c-1f3fe"],isCanonical:!0},":ok_hand_tone3:":{unicode:["1f44c-1f3fd"],isCanonical:!0},":ok_hand_tone2:":{unicode:["1f44c-1f3fc"],isCanonical:!0},":ok_hand_tone1:":{unicode:["1f44c-1f3fb"],isCanonical:!0},":wave_tone5:":{unicode:["1f44b-1f3ff"],isCanonical:!0},":wave_tone4:":{unicode:["1f44b-1f3fe"],isCanonical:!0},":wave_tone3:":{unicode:["1f44b-1f3fd"],isCanonical:!0},":wave_tone2:":{unicode:["1f44b-1f3fc"],isCanonical:!0},":wave_tone1:":{unicode:["1f44b-1f3fb"],isCanonical:!0},":punch_tone5:":{unicode:["1f44a-1f3ff"],isCanonical:!0},":punch_tone4:":{unicode:["1f44a-1f3fe"],isCanonical:!0},":punch_tone3:":{unicode:["1f44a-1f3fd"],isCanonical:!0},":punch_tone2:":{unicode:["1f44a-1f3fc"],isCanonical:!0},":punch_tone1:":{unicode:["1f44a-1f3fb"],isCanonical:!0},":point_right_tone5:":{unicode:["1f449-1f3ff"],isCanonical:!0},":point_right_tone4:":{unicode:["1f449-1f3fe"],isCanonical:!0},":point_right_tone3:":{unicode:["1f449-1f3fd"],isCanonical:!0},":point_right_tone2:":{unicode:["1f449-1f3fc"],isCanonical:!0},":point_right_tone1:":{unicode:["1f449-1f3fb"],isCanonical:!0 +},":point_left_tone5:":{unicode:["1f448-1f3ff"],isCanonical:!0},":point_left_tone4:":{unicode:["1f448-1f3fe"],isCanonical:!0},":point_left_tone3:":{unicode:["1f448-1f3fd"],isCanonical:!0},":point_left_tone2:":{unicode:["1f448-1f3fc"],isCanonical:!0},":point_left_tone1:":{unicode:["1f448-1f3fb"],isCanonical:!0},":point_down_tone5:":{unicode:["1f447-1f3ff"],isCanonical:!0},":point_down_tone4:":{unicode:["1f447-1f3fe"],isCanonical:!0},":point_down_tone3:":{unicode:["1f447-1f3fd"],isCanonical:!0},":point_down_tone2:":{unicode:["1f447-1f3fc"],isCanonical:!0},":point_down_tone1:":{unicode:["1f447-1f3fb"],isCanonical:!0},":point_up_2_tone5:":{unicode:["1f446-1f3ff"],isCanonical:!0},":point_up_2_tone4:":{unicode:["1f446-1f3fe"],isCanonical:!0},":point_up_2_tone3:":{unicode:["1f446-1f3fd"],isCanonical:!0},":point_up_2_tone2:":{unicode:["1f446-1f3fc"],isCanonical:!0},":point_up_2_tone1:":{unicode:["1f446-1f3fb"],isCanonical:!0},":nose_tone5:":{unicode:["1f443-1f3ff"],isCanonical:!0},":nose_tone4:":{unicode:["1f443-1f3fe"],isCanonical:!0},":nose_tone3:":{unicode:["1f443-1f3fd"],isCanonical:!0},":nose_tone2:":{unicode:["1f443-1f3fc"],isCanonical:!0},":nose_tone1:":{unicode:["1f443-1f3fb"],isCanonical:!0},":ear_tone5:":{unicode:["1f442-1f3ff"],isCanonical:!0},":ear_tone4:":{unicode:["1f442-1f3fe"],isCanonical:!0},":ear_tone3:":{unicode:["1f442-1f3fd"],isCanonical:!0},":ear_tone2:":{unicode:["1f442-1f3fc"],isCanonical:!0},":ear_tone1:":{unicode:["1f442-1f3fb"],isCanonical:!0},":gay_pride_flag:":{unicode:["1f3f3-1f308"],isCanonical:!0},":rainbow_flag:":{unicode:["1f3f3-1f308"],isCanonical:!1},":lifter_tone5:":{unicode:["1f3cb-1f3ff"],isCanonical:!0},":weight_lifter_tone5:":{unicode:["1f3cb-1f3ff"],isCanonical:!1},":lifter_tone4:":{unicode:["1f3cb-1f3fe"],isCanonical:!0},":weight_lifter_tone4:":{unicode:["1f3cb-1f3fe"],isCanonical:!1},":lifter_tone3:":{unicode:["1f3cb-1f3fd"],isCanonical:!0},":weight_lifter_tone3:":{unicode:["1f3cb-1f3fd"],isCanonical:!1},":lifter_tone2:":{unicode:["1f3cb-1f3fc"],isCanonical:!0},":weight_lifter_tone2:":{unicode:["1f3cb-1f3fc"],isCanonical:!1},":lifter_tone1:":{unicode:["1f3cb-1f3fb"],isCanonical:!0},":weight_lifter_tone1:":{unicode:["1f3cb-1f3fb"],isCanonical:!1},":swimmer_tone5:":{unicode:["1f3ca-1f3ff"],isCanonical:!0},":swimmer_tone4:":{unicode:["1f3ca-1f3fe"],isCanonical:!0},":swimmer_tone3:":{unicode:["1f3ca-1f3fd"],isCanonical:!0},":swimmer_tone2:":{unicode:["1f3ca-1f3fc"],isCanonical:!0},":swimmer_tone1:":{unicode:["1f3ca-1f3fb"],isCanonical:!0},":horse_racing_tone5:":{unicode:["1f3c7-1f3ff"],isCanonical:!0},":horse_racing_tone4:":{unicode:["1f3c7-1f3fe"],isCanonical:!0},":horse_racing_tone3:":{unicode:["1f3c7-1f3fd"],isCanonical:!0},":horse_racing_tone2:":{unicode:["1f3c7-1f3fc"],isCanonical:!0},":horse_racing_tone1:":{unicode:["1f3c7-1f3fb"],isCanonical:!0},":surfer_tone5:":{unicode:["1f3c4-1f3ff"],isCanonical:!0},":surfer_tone4:":{unicode:["1f3c4-1f3fe"],isCanonical:!0},":surfer_tone3:":{unicode:["1f3c4-1f3fd"],isCanonical:!0},":surfer_tone2:":{unicode:["1f3c4-1f3fc"],isCanonical:!0},":surfer_tone1:":{unicode:["1f3c4-1f3fb"],isCanonical:!0},":runner_tone5:":{unicode:["1f3c3-1f3ff"],isCanonical:!0},":runner_tone4:":{unicode:["1f3c3-1f3fe"],isCanonical:!0},":runner_tone3:":{unicode:["1f3c3-1f3fd"],isCanonical:!0},":runner_tone2:":{unicode:["1f3c3-1f3fc"],isCanonical:!0},":runner_tone1:":{unicode:["1f3c3-1f3fb"],isCanonical:!0},":santa_tone5:":{unicode:["1f385-1f3ff"],isCanonical:!0},":santa_tone4:":{unicode:["1f385-1f3fe"],isCanonical:!0},":santa_tone3:":{unicode:["1f385-1f3fd"],isCanonical:!0},":santa_tone2:":{unicode:["1f385-1f3fc"],isCanonical:!0},":santa_tone1:":{unicode:["1f385-1f3fb"],isCanonical:!0},":flag_zw:":{unicode:["1f1ff-1f1fc"],isCanonical:!0},":zw:":{unicode:["1f1ff-1f1fc"],isCanonical:!1},":flag_zm:":{unicode:["1f1ff-1f1f2"],isCanonical:!0},":zm:":{unicode:["1f1ff-1f1f2"],isCanonical:!1},":flag_za:":{unicode:["1f1ff-1f1e6"],isCanonical:!0},":za:":{unicode:["1f1ff-1f1e6"],isCanonical:!1},":flag_yt:":{unicode:["1f1fe-1f1f9"],isCanonical:!0},":yt:":{unicode:["1f1fe-1f1f9"],isCanonical:!1},":flag_ye:":{unicode:["1f1fe-1f1ea"],isCanonical:!0},":ye:":{unicode:["1f1fe-1f1ea"],isCanonical:!1},":flag_xk:":{unicode:["1f1fd-1f1f0"],isCanonical:!0},":xk:":{unicode:["1f1fd-1f1f0"],isCanonical:!1},":flag_ws:":{unicode:["1f1fc-1f1f8"],isCanonical:!0},":ws:":{unicode:["1f1fc-1f1f8"],isCanonical:!1},":flag_wf:":{unicode:["1f1fc-1f1eb"],isCanonical:!0},":wf:":{unicode:["1f1fc-1f1eb"],isCanonical:!1},":flag_vu:":{unicode:["1f1fb-1f1fa"],isCanonical:!0},":vu:":{unicode:["1f1fb-1f1fa"],isCanonical:!1},":flag_vn:":{unicode:["1f1fb-1f1f3"],isCanonical:!0},":vn:":{unicode:["1f1fb-1f1f3"],isCanonical:!1},":flag_vi:":{unicode:["1f1fb-1f1ee"],isCanonical:!0},":vi:":{unicode:["1f1fb-1f1ee"],isCanonical:!1},":flag_vg:":{unicode:["1f1fb-1f1ec"],isCanonical:!0},":vg:":{unicode:["1f1fb-1f1ec"],isCanonical:!1},":flag_ve:":{unicode:["1f1fb-1f1ea"],isCanonical:!0},":ve:":{unicode:["1f1fb-1f1ea"],isCanonical:!1},":flag_vc:":{unicode:["1f1fb-1f1e8"],isCanonical:!0},":vc:":{unicode:["1f1fb-1f1e8"],isCanonical:!1},":flag_va:":{unicode:["1f1fb-1f1e6"],isCanonical:!0},":va:":{unicode:["1f1fb-1f1e6"],isCanonical:!1},":flag_uz:":{unicode:["1f1fa-1f1ff"],isCanonical:!0},":uz:":{unicode:["1f1fa-1f1ff"],isCanonical:!1},":flag_uy:":{unicode:["1f1fa-1f1fe"],isCanonical:!0},":uy:":{unicode:["1f1fa-1f1fe"],isCanonical:!1},":flag_us:":{unicode:["1f1fa-1f1f8"],isCanonical:!0},":us:":{unicode:["1f1fa-1f1f8"],isCanonical:!1},":flag_um:":{unicode:["1f1fa-1f1f2"],isCanonical:!0},":um:":{unicode:["1f1fa-1f1f2"],isCanonical:!1},":flag_ug:":{unicode:["1f1fa-1f1ec"],isCanonical:!0},":ug:":{unicode:["1f1fa-1f1ec"],isCanonical:!1},":flag_ua:":{unicode:["1f1fa-1f1e6"],isCanonical:!0},":ua:":{unicode:["1f1fa-1f1e6"],isCanonical:!1},":flag_tz:":{unicode:["1f1f9-1f1ff"],isCanonical:!0},":tz:":{unicode:["1f1f9-1f1ff"],isCanonical:!1},":flag_tw:":{unicode:["1f1f9-1f1fc"],isCanonical:!0},":tw:":{unicode:["1f1f9-1f1fc"],isCanonical:!1},":flag_tv:":{unicode:["1f1f9-1f1fb"],isCanonical:!0},":tuvalu:":{unicode:["1f1f9-1f1fb"],isCanonical:!1},":flag_tt:":{unicode:["1f1f9-1f1f9"],isCanonical:!0},":tt:":{unicode:["1f1f9-1f1f9"],isCanonical:!1},":flag_tr:":{unicode:["1f1f9-1f1f7"],isCanonical:!0},":tr:":{unicode:["1f1f9-1f1f7"],isCanonical:!1},":flag_to:":{unicode:["1f1f9-1f1f4"],isCanonical:!0},":to:":{unicode:["1f1f9-1f1f4"],isCanonical:!1},":flag_tn:":{unicode:["1f1f9-1f1f3"],isCanonical:!0},":tn:":{unicode:["1f1f9-1f1f3"],isCanonical:!1},":flag_tm:":{unicode:["1f1f9-1f1f2"],isCanonical:!0},":turkmenistan:":{unicode:["1f1f9-1f1f2"],isCanonical:!1},":flag_tl:":{unicode:["1f1f9-1f1f1"],isCanonical:!0},":tl:":{unicode:["1f1f9-1f1f1"],isCanonical:!1},":flag_tk:":{unicode:["1f1f9-1f1f0"],isCanonical:!0},":tk:":{unicode:["1f1f9-1f1f0"],isCanonical:!1},":flag_tj:":{unicode:["1f1f9-1f1ef"],isCanonical:!0},":tj:":{unicode:["1f1f9-1f1ef"],isCanonical:!1},":flag_th:":{unicode:["1f1f9-1f1ed"],isCanonical:!0},":th:":{unicode:["1f1f9-1f1ed"],isCanonical:!1},":flag_tg:":{unicode:["1f1f9-1f1ec"],isCanonical:!0},":tg:":{unicode:["1f1f9-1f1ec"],isCanonical:!1},":flag_tf:":{unicode:["1f1f9-1f1eb"],isCanonical:!0},":tf:":{unicode:["1f1f9-1f1eb"],isCanonical:!1},":flag_td:":{unicode:["1f1f9-1f1e9"],isCanonical:!0},":td:":{unicode:["1f1f9-1f1e9"],isCanonical:!1},":flag_tc:":{unicode:["1f1f9-1f1e8"],isCanonical:!0},":tc:":{unicode:["1f1f9-1f1e8"],isCanonical:!1},":flag_ta:":{unicode:["1f1f9-1f1e6"],isCanonical:!0},":ta:":{unicode:["1f1f9-1f1e6"],isCanonical:!1},":flag_sz:":{unicode:["1f1f8-1f1ff"],isCanonical:!0},":sz:":{unicode:["1f1f8-1f1ff"],isCanonical:!1},":flag_sy:":{unicode:["1f1f8-1f1fe"],isCanonical:!0},":sy:":{unicode:["1f1f8-1f1fe"],isCanonical:!1},":flag_sx:":{unicode:["1f1f8-1f1fd"],isCanonical:!0},":sx:":{unicode:["1f1f8-1f1fd"],isCanonical:!1},":flag_sv:":{unicode:["1f1f8-1f1fb"],isCanonical:!0},":sv:":{unicode:["1f1f8-1f1fb"],isCanonical:!1},":flag_st:":{unicode:["1f1f8-1f1f9"],isCanonical:!0},":st:":{unicode:["1f1f8-1f1f9"],isCanonical:!1},":flag_ss:":{unicode:["1f1f8-1f1f8"],isCanonical:!0},":ss:":{unicode:["1f1f8-1f1f8"],isCanonical:!1},":flag_sr:":{unicode:["1f1f8-1f1f7"],isCanonical:!0},":sr:":{unicode:["1f1f8-1f1f7"],isCanonical:!1},":flag_so:":{unicode:["1f1f8-1f1f4"],isCanonical:!0},":so:":{unicode:["1f1f8-1f1f4"],isCanonical:!1},":flag_sn:":{unicode:["1f1f8-1f1f3"],isCanonical:!0},":sn:":{unicode:["1f1f8-1f1f3"],isCanonical:!1},":flag_sm:":{unicode:["1f1f8-1f1f2"],isCanonical:!0},":sm:":{unicode:["1f1f8-1f1f2"],isCanonical:!1},":flag_sl:":{unicode:["1f1f8-1f1f1"],isCanonical:!0},":sl:":{unicode:["1f1f8-1f1f1"],isCanonical:!1},":flag_sk:":{unicode:["1f1f8-1f1f0"],isCanonical:!0},":sk:":{unicode:["1f1f8-1f1f0"],isCanonical:!1},":flag_sj:":{unicode:["1f1f8-1f1ef"],isCanonical:!0},":sj:":{unicode:["1f1f8-1f1ef"],isCanonical:!1},":flag_si:":{unicode:["1f1f8-1f1ee"],isCanonical:!0},":si:":{unicode:["1f1f8-1f1ee"],isCanonical:!1},":flag_sh:":{unicode:["1f1f8-1f1ed"],isCanonical:!0},":sh:":{unicode:["1f1f8-1f1ed"],isCanonical:!1},":flag_sg:":{unicode:["1f1f8-1f1ec"],isCanonical:!0},":sg:":{unicode:["1f1f8-1f1ec"],isCanonical:!1},":flag_se:":{unicode:["1f1f8-1f1ea"],isCanonical:!0},":se:":{unicode:["1f1f8-1f1ea"],isCanonical:!1},":flag_sd:":{unicode:["1f1f8-1f1e9"],isCanonical:!0},":sd:":{unicode:["1f1f8-1f1e9"],isCanonical:!1},":flag_sc:":{unicode:["1f1f8-1f1e8"],isCanonical:!0},":sc:":{unicode:["1f1f8-1f1e8"],isCanonical:!1},":flag_sb:":{unicode:["1f1f8-1f1e7"],isCanonical:!0},":sb:":{unicode:["1f1f8-1f1e7"],isCanonical:!1},":flag_sa:":{unicode:["1f1f8-1f1e6"],isCanonical:!0},":saudiarabia:":{unicode:["1f1f8-1f1e6"],isCanonical:!1},":saudi:":{unicode:["1f1f8-1f1e6"],isCanonical:!1},":flag_rw:":{unicode:["1f1f7-1f1fc"],isCanonical:!0},":rw:":{unicode:["1f1f7-1f1fc"],isCanonical:!1},":flag_ru:":{unicode:["1f1f7-1f1fa"],isCanonical:!0},":ru:":{unicode:["1f1f7-1f1fa"],isCanonical:!1},":flag_rs:":{unicode:["1f1f7-1f1f8"],isCanonical:!0},":rs:":{unicode:["1f1f7-1f1f8"],isCanonical:!1},":flag_ro:":{unicode:["1f1f7-1f1f4"],isCanonical:!0},":ro:":{unicode:["1f1f7-1f1f4"],isCanonical:!1},":flag_re:":{unicode:["1f1f7-1f1ea"],isCanonical:!0},":re:":{unicode:["1f1f7-1f1ea"],isCanonical:!1},":flag_qa:":{unicode:["1f1f6-1f1e6"],isCanonical:!0},":qa:":{unicode:["1f1f6-1f1e6"],isCanonical:!1},":flag_py:":{unicode:["1f1f5-1f1fe"],isCanonical:!0},":py:":{unicode:["1f1f5-1f1fe"],isCanonical:!1},":flag_pw:":{unicode:["1f1f5-1f1fc"],isCanonical:!0},":pw:":{unicode:["1f1f5-1f1fc"],isCanonical:!1},":flag_pt:":{unicode:["1f1f5-1f1f9"],isCanonical:!0},":pt:":{unicode:["1f1f5-1f1f9"],isCanonical:!1},":flag_ps:":{unicode:["1f1f5-1f1f8"],isCanonical:!0},":ps:":{unicode:["1f1f5-1f1f8"],isCanonical:!1},":flag_pr:":{unicode:["1f1f5-1f1f7"],isCanonical:!0},":pr:":{unicode:["1f1f5-1f1f7"],isCanonical:!1},":flag_pn:":{unicode:["1f1f5-1f1f3"],isCanonical:!0},":pn:":{unicode:["1f1f5-1f1f3"],isCanonical:!1},":flag_pm:":{unicode:["1f1f5-1f1f2"],isCanonical:!0},":pm:":{unicode:["1f1f5-1f1f2"],isCanonical:!1},":flag_pl:":{unicode:["1f1f5-1f1f1"],isCanonical:!0},":pl:":{unicode:["1f1f5-1f1f1"],isCanonical:!1},":flag_pk:":{unicode:["1f1f5-1f1f0"],isCanonical:!0},":pk:":{unicode:["1f1f5-1f1f0"],isCanonical:!1},":flag_ph:":{unicode:["1f1f5-1f1ed"],isCanonical:!0},":ph:":{unicode:["1f1f5-1f1ed"],isCanonical:!1},":flag_pg:":{unicode:["1f1f5-1f1ec"],isCanonical:!0},":pg:":{unicode:["1f1f5-1f1ec"],isCanonical:!1},":flag_pf:":{unicode:["1f1f5-1f1eb"],isCanonical:!0},":pf:":{unicode:["1f1f5-1f1eb"],isCanonical:!1},":flag_pe:":{unicode:["1f1f5-1f1ea"],isCanonical:!0},":pe:":{unicode:["1f1f5-1f1ea"],isCanonical:!1},":flag_pa:":{unicode:["1f1f5-1f1e6"],isCanonical:!0},":pa:":{unicode:["1f1f5-1f1e6"],isCanonical:!1},":flag_om:":{unicode:["1f1f4-1f1f2"],isCanonical:!0},":om:":{unicode:["1f1f4-1f1f2"],isCanonical:!1},":flag_nz:":{unicode:["1f1f3-1f1ff"],isCanonical:!0},":nz:":{unicode:["1f1f3-1f1ff"],isCanonical:!1},":flag_nu:":{unicode:["1f1f3-1f1fa"],isCanonical:!0},":nu:":{unicode:["1f1f3-1f1fa"],isCanonical:!1},":flag_nr:":{unicode:["1f1f3-1f1f7"],isCanonical:!0},":nr:":{unicode:["1f1f3-1f1f7"],isCanonical:!1},":flag_np:":{unicode:["1f1f3-1f1f5"],isCanonical:!0},":np:":{unicode:["1f1f3-1f1f5"],isCanonical:!1},":flag_no:":{unicode:["1f1f3-1f1f4"],isCanonical:!0},":no:":{unicode:["1f1f3-1f1f4"],isCanonical:!1},":flag_nl:":{unicode:["1f1f3-1f1f1"],isCanonical:!0},":nl:":{unicode:["1f1f3-1f1f1"],isCanonical:!1},":flag_ni:":{unicode:["1f1f3-1f1ee"],isCanonical:!0},":ni:":{unicode:["1f1f3-1f1ee"],isCanonical:!1},":flag_ng:":{unicode:["1f1f3-1f1ec"],isCanonical:!0},":nigeria:":{unicode:["1f1f3-1f1ec"],isCanonical:!1},":flag_nf:":{unicode:["1f1f3-1f1eb"],isCanonical:!0},":nf:":{unicode:["1f1f3-1f1eb"],isCanonical:!1},":flag_ne:":{unicode:["1f1f3-1f1ea"],isCanonical:!0},":ne:":{unicode:["1f1f3-1f1ea"],isCanonical:!1},":flag_nc:":{unicode:["1f1f3-1f1e8"],isCanonical:!0},":nc:":{unicode:["1f1f3-1f1e8"],isCanonical:!1},":flag_na:":{unicode:["1f1f3-1f1e6"],isCanonical:!0},":na:":{unicode:["1f1f3-1f1e6"],isCanonical:!1},":flag_mz:":{unicode:["1f1f2-1f1ff"],isCanonical:!0},":mz:":{unicode:["1f1f2-1f1ff"],isCanonical:!1},":flag_my:":{unicode:["1f1f2-1f1fe"],isCanonical:!0},":my:":{unicode:["1f1f2-1f1fe"],isCanonical:!1},":flag_mx:":{unicode:["1f1f2-1f1fd"],isCanonical:!0},":mx:":{unicode:["1f1f2-1f1fd"],isCanonical:!1},":flag_mw:":{unicode:["1f1f2-1f1fc"],isCanonical:!0},":mw:":{unicode:["1f1f2-1f1fc"],isCanonical:!1},":flag_mv:":{unicode:["1f1f2-1f1fb"],isCanonical:!0},":mv:":{unicode:["1f1f2-1f1fb"],isCanonical:!1},":flag_mu:":{unicode:["1f1f2-1f1fa"],isCanonical:!0},":mu:":{unicode:["1f1f2-1f1fa"],isCanonical:!1},":flag_mt:":{unicode:["1f1f2-1f1f9"],isCanonical:!0},":mt:":{unicode:["1f1f2-1f1f9"],isCanonical:!1},":flag_ms:":{unicode:["1f1f2-1f1f8"],isCanonical:!0},":ms:":{unicode:["1f1f2-1f1f8"],isCanonical:!1},":flag_mr:":{unicode:["1f1f2-1f1f7"],isCanonical:!0},":mr:":{unicode:["1f1f2-1f1f7"],isCanonical:!1},":flag_mq:":{unicode:["1f1f2-1f1f6"],isCanonical:!0},":mq:":{unicode:["1f1f2-1f1f6"],isCanonical:!1},":flag_mp:":{unicode:["1f1f2-1f1f5"],isCanonical:!0},":mp:":{unicode:["1f1f2-1f1f5"],isCanonical:!1},":flag_mo:":{unicode:["1f1f2-1f1f4"],isCanonical:!0},":mo:":{unicode:["1f1f2-1f1f4"],isCanonical:!1},":flag_mn:":{unicode:["1f1f2-1f1f3"],isCanonical:!0},":mn:":{unicode:["1f1f2-1f1f3"],isCanonical:!1},":flag_mm:":{unicode:["1f1f2-1f1f2"],isCanonical:!0},":mm:":{unicode:["1f1f2-1f1f2"],isCanonical:!1},":flag_ml:":{unicode:["1f1f2-1f1f1"],isCanonical:!0},":ml:":{unicode:["1f1f2-1f1f1"],isCanonical:!1},":flag_mk:":{unicode:["1f1f2-1f1f0"],isCanonical:!0},":mk:":{unicode:["1f1f2-1f1f0"],isCanonical:!1},":flag_mh:":{unicode:["1f1f2-1f1ed"],isCanonical:!0},":mh:":{unicode:["1f1f2-1f1ed"],isCanonical:!1},":flag_mg:":{unicode:["1f1f2-1f1ec"],isCanonical:!0},":mg:":{unicode:["1f1f2-1f1ec"],isCanonical:!1},":flag_mf:":{unicode:["1f1f2-1f1eb"],isCanonical:!0},":mf:":{unicode:["1f1f2-1f1eb"],isCanonical:!1},":flag_me:":{unicode:["1f1f2-1f1ea"],isCanonical:!0},":me:":{unicode:["1f1f2-1f1ea"],isCanonical:!1},":flag_md:":{unicode:["1f1f2-1f1e9"],isCanonical:!0},":md:":{unicode:["1f1f2-1f1e9"],isCanonical:!1},":flag_mc:":{unicode:["1f1f2-1f1e8"],isCanonical:!0},":mc:":{unicode:["1f1f2-1f1e8"],isCanonical:!1},":flag_ma:":{unicode:["1f1f2-1f1e6"],isCanonical:!0},":ma:":{unicode:["1f1f2-1f1e6"],isCanonical:!1},":flag_ly:":{unicode:["1f1f1-1f1fe"],isCanonical:!0},":ly:":{unicode:["1f1f1-1f1fe"],isCanonical:!1},":flag_lv:":{unicode:["1f1f1-1f1fb"],isCanonical:!0},":lv:":{unicode:["1f1f1-1f1fb"],isCanonical:!1},":flag_lu:":{unicode:["1f1f1-1f1fa"],isCanonical:!0},":lu:":{unicode:["1f1f1-1f1fa"],isCanonical:!1},":flag_lt:":{unicode:["1f1f1-1f1f9"],isCanonical:!0},":lt:":{unicode:["1f1f1-1f1f9"],isCanonical:!1},":flag_ls:":{unicode:["1f1f1-1f1f8"],isCanonical:!0},":ls:":{unicode:["1f1f1-1f1f8"],isCanonical:!1},":flag_lr:":{unicode:["1f1f1-1f1f7"],isCanonical:!0},":lr:":{unicode:["1f1f1-1f1f7"],isCanonical:!1},":flag_lk:":{unicode:["1f1f1-1f1f0"],isCanonical:!0},":lk:":{unicode:["1f1f1-1f1f0"],isCanonical:!1},":flag_li:":{unicode:["1f1f1-1f1ee"],isCanonical:!0},":li:":{unicode:["1f1f1-1f1ee"],isCanonical:!1},":flag_lc:":{unicode:["1f1f1-1f1e8"],isCanonical:!0},":lc:":{unicode:["1f1f1-1f1e8"],isCanonical:!1},":flag_lb:":{unicode:["1f1f1-1f1e7"],isCanonical:!0},":lb:":{unicode:["1f1f1-1f1e7"],isCanonical:!1},":flag_la:":{unicode:["1f1f1-1f1e6"],isCanonical:!0},":la:":{unicode:["1f1f1-1f1e6"],isCanonical:!1},":flag_kz:":{unicode:["1f1f0-1f1ff"],isCanonical:!0},":kz:":{unicode:["1f1f0-1f1ff"],isCanonical:!1},":flag_ky:":{unicode:["1f1f0-1f1fe"],isCanonical:!0},":ky:":{unicode:["1f1f0-1f1fe"],isCanonical:!1},":flag_kw:":{unicode:["1f1f0-1f1fc"],isCanonical:!0},":kw:":{unicode:["1f1f0-1f1fc"],isCanonical:!1},":flag_kr:":{unicode:["1f1f0-1f1f7"],isCanonical:!0},":kr:":{unicode:["1f1f0-1f1f7"],isCanonical:!1},":flag_kp:":{unicode:["1f1f0-1f1f5"],isCanonical:!0},":kp:":{unicode:["1f1f0-1f1f5"],isCanonical:!1},":flag_kn:":{unicode:["1f1f0-1f1f3"],isCanonical:!0},":kn:":{unicode:["1f1f0-1f1f3"],isCanonical:!1},":flag_km:":{unicode:["1f1f0-1f1f2"],isCanonical:!0},":km:":{unicode:["1f1f0-1f1f2"],isCanonical:!1},":flag_ki:":{unicode:["1f1f0-1f1ee"],isCanonical:!0},":ki:":{unicode:["1f1f0-1f1ee"],isCanonical:!1},":flag_kh:":{unicode:["1f1f0-1f1ed"],isCanonical:!0},":kh:":{unicode:["1f1f0-1f1ed"],isCanonical:!1},":flag_kg:":{unicode:["1f1f0-1f1ec"],isCanonical:!0},":kg:":{unicode:["1f1f0-1f1ec"],isCanonical:!1},":flag_ke:":{unicode:["1f1f0-1f1ea"],isCanonical:!0},":ke:":{unicode:["1f1f0-1f1ea"],isCanonical:!1},":flag_jp:":{unicode:["1f1ef-1f1f5"],isCanonical:!0},":jp:":{unicode:["1f1ef-1f1f5"],isCanonical:!1},":flag_jo:":{unicode:["1f1ef-1f1f4"],isCanonical:!0},":jo:":{unicode:["1f1ef-1f1f4"],isCanonical:!1},":flag_jm:":{unicode:["1f1ef-1f1f2"],isCanonical:!0},":jm:":{unicode:["1f1ef-1f1f2"],isCanonical:!1},":flag_je:":{unicode:["1f1ef-1f1ea"],isCanonical:!0},":je:":{unicode:["1f1ef-1f1ea"],isCanonical:!1},":flag_it:":{unicode:["1f1ee-1f1f9"],isCanonical:!0},":it:":{unicode:["1f1ee-1f1f9"],isCanonical:!1},":flag_is:":{unicode:["1f1ee-1f1f8"],isCanonical:!0},":is:":{unicode:["1f1ee-1f1f8"],isCanonical:!1},":flag_ir:":{unicode:["1f1ee-1f1f7"],isCanonical:!0},":ir:":{unicode:["1f1ee-1f1f7"],isCanonical:!1},":flag_iq:":{unicode:["1f1ee-1f1f6"],isCanonical:!0},":iq:":{unicode:["1f1ee-1f1f6"],isCanonical:!1},":flag_io:":{unicode:["1f1ee-1f1f4"],isCanonical:!0},":io:":{unicode:["1f1ee-1f1f4"],isCanonical:!1},":flag_in:":{unicode:["1f1ee-1f1f3"],isCanonical:!0},":in:":{unicode:["1f1ee-1f1f3"],isCanonical:!1},":flag_im:":{unicode:["1f1ee-1f1f2"],isCanonical:!0},":im:":{unicode:["1f1ee-1f1f2"],isCanonical:!1},":flag_il:":{unicode:["1f1ee-1f1f1"],isCanonical:!0},":il:":{unicode:["1f1ee-1f1f1"],isCanonical:!1},":flag_ie:":{unicode:["1f1ee-1f1ea"],isCanonical:!0},":ie:":{unicode:["1f1ee-1f1ea"],isCanonical:!1},":flag_id:":{unicode:["1f1ee-1f1e9"],isCanonical:!0},":indonesia:":{unicode:["1f1ee-1f1e9"],isCanonical:!1},":flag_ic:":{unicode:["1f1ee-1f1e8"],isCanonical:!0},":ic:":{unicode:["1f1ee-1f1e8"],isCanonical:!1},":flag_hu:":{unicode:["1f1ed-1f1fa"],isCanonical:!0},":hu:":{unicode:["1f1ed-1f1fa"],isCanonical:!1},":flag_ht:":{unicode:["1f1ed-1f1f9"],isCanonical:!0},":ht:":{unicode:["1f1ed-1f1f9"],isCanonical:!1},":flag_hr:":{unicode:["1f1ed-1f1f7"],isCanonical:!0},":hr:":{unicode:["1f1ed-1f1f7"],isCanonical:!1},":flag_hn:":{unicode:["1f1ed-1f1f3"],isCanonical:!0},":hn:":{unicode:["1f1ed-1f1f3"],isCanonical:!1},":flag_hm:":{unicode:["1f1ed-1f1f2"],isCanonical:!0},":hm:":{unicode:["1f1ed-1f1f2"],isCanonical:!1},":flag_hk:":{unicode:["1f1ed-1f1f0"],isCanonical:!0},":hk:":{unicode:["1f1ed-1f1f0"],isCanonical:!1},":flag_gy:":{unicode:["1f1ec-1f1fe"],isCanonical:!0},":gy:":{unicode:["1f1ec-1f1fe"],isCanonical:!1},":flag_gw:":{unicode:["1f1ec-1f1fc"],isCanonical:!0},":gw:":{unicode:["1f1ec-1f1fc"],isCanonical:!1},":flag_gu:":{unicode:["1f1ec-1f1fa"],isCanonical:!0},":gu:":{unicode:["1f1ec-1f1fa"],isCanonical:!1},":flag_gt:":{unicode:["1f1ec-1f1f9"],isCanonical:!0},":gt:":{unicode:["1f1ec-1f1f9"],isCanonical:!1},":flag_gs:":{unicode:["1f1ec-1f1f8"],isCanonical:!0},":gs:":{unicode:["1f1ec-1f1f8"],isCanonical:!1},":flag_gr:":{unicode:["1f1ec-1f1f7"],isCanonical:!0},":gr:":{unicode:["1f1ec-1f1f7"],isCanonical:!1},":flag_gq:":{unicode:["1f1ec-1f1f6"],isCanonical:!0},":gq:":{unicode:["1f1ec-1f1f6"],isCanonical:!1},":flag_gp:":{unicode:["1f1ec-1f1f5"],isCanonical:!0},":gp:":{unicode:["1f1ec-1f1f5"],isCanonical:!1},":flag_gn:":{unicode:["1f1ec-1f1f3"],isCanonical:!0},":gn:":{unicode:["1f1ec-1f1f3"],isCanonical:!1},":flag_gm:":{unicode:["1f1ec-1f1f2"],isCanonical:!0},":gm:":{unicode:["1f1ec-1f1f2"],isCanonical:!1},":flag_gl:":{unicode:["1f1ec-1f1f1"],isCanonical:!0},":gl:":{unicode:["1f1ec-1f1f1"],isCanonical:!1},":flag_gi:":{unicode:["1f1ec-1f1ee"],isCanonical:!0},":gi:":{unicode:["1f1ec-1f1ee"],isCanonical:!1},":flag_gh:":{unicode:["1f1ec-1f1ed"],isCanonical:!0},":gh:":{unicode:["1f1ec-1f1ed"],isCanonical:!1},":flag_gg:":{unicode:["1f1ec-1f1ec"],isCanonical:!0},":gg:":{unicode:["1f1ec-1f1ec"],isCanonical:!1},":flag_gf:":{unicode:["1f1ec-1f1eb"],isCanonical:!0},":gf:":{unicode:["1f1ec-1f1eb"],isCanonical:!1},":flag_ge:":{unicode:["1f1ec-1f1ea"],isCanonical:!0},":ge:":{unicode:["1f1ec-1f1ea"],isCanonical:!1},":flag_gd:":{unicode:["1f1ec-1f1e9"],isCanonical:!0},":gd:":{unicode:["1f1ec-1f1e9"],isCanonical:!1},":flag_gb:":{unicode:["1f1ec-1f1e7"],isCanonical:!0},":gb:":{unicode:["1f1ec-1f1e7"],isCanonical:!1},":flag_ga:":{unicode:["1f1ec-1f1e6"],isCanonical:!0},":ga:":{unicode:["1f1ec-1f1e6"],isCanonical:!1},":flag_fr:":{unicode:["1f1eb-1f1f7"],isCanonical:!0},":fr:":{unicode:["1f1eb-1f1f7"],isCanonical:!1},":flag_fo:":{unicode:["1f1eb-1f1f4"],isCanonical:!0},":fo:":{unicode:["1f1eb-1f1f4"],isCanonical:!1},":flag_fm:":{unicode:["1f1eb-1f1f2"],isCanonical:!0},":fm:":{unicode:["1f1eb-1f1f2"],isCanonical:!1},":flag_fk:":{unicode:["1f1eb-1f1f0"],isCanonical:!0},":fk:":{unicode:["1f1eb-1f1f0"],isCanonical:!1},":flag_fj:":{unicode:["1f1eb-1f1ef"],isCanonical:!0},":fj:":{unicode:["1f1eb-1f1ef"],isCanonical:!1},":flag_fi:":{unicode:["1f1eb-1f1ee"],isCanonical:!0},":fi:":{unicode:["1f1eb-1f1ee"],isCanonical:!1},":flag_eu:":{unicode:["1f1ea-1f1fa"],isCanonical:!0},":eu:":{unicode:["1f1ea-1f1fa"],isCanonical:!1},":flag_et:":{unicode:["1f1ea-1f1f9"],isCanonical:!0},":et:":{unicode:["1f1ea-1f1f9"],isCanonical:!1},":flag_es:":{unicode:["1f1ea-1f1f8"],isCanonical:!0},":es:":{unicode:["1f1ea-1f1f8"],isCanonical:!1},":flag_er:":{unicode:["1f1ea-1f1f7"],isCanonical:!0},":er:":{unicode:["1f1ea-1f1f7"],isCanonical:!1},":flag_eh:":{unicode:["1f1ea-1f1ed"],isCanonical:!0},":eh:":{unicode:["1f1ea-1f1ed"],isCanonical:!1},":flag_eg:":{unicode:["1f1ea-1f1ec"],isCanonical:!0},":eg:":{unicode:["1f1ea-1f1ec"],isCanonical:!1},":flag_ee:":{unicode:["1f1ea-1f1ea"],isCanonical:!0},":ee:":{unicode:["1f1ea-1f1ea"],isCanonical:!1},":flag_ec:":{unicode:["1f1ea-1f1e8"],isCanonical:!0},":ec:":{unicode:["1f1ea-1f1e8"],isCanonical:!1},":flag_ea:":{unicode:["1f1ea-1f1e6"],isCanonical:!0},":ea:":{unicode:["1f1ea-1f1e6"],isCanonical:!1},":flag_dz:":{unicode:["1f1e9-1f1ff"],isCanonical:!0},":dz:":{unicode:["1f1e9-1f1ff"],isCanonical:!1},":flag_do:":{unicode:["1f1e9-1f1f4"],isCanonical:!0},":do:":{unicode:["1f1e9-1f1f4"],isCanonical:!1},":flag_dm:":{unicode:["1f1e9-1f1f2"],isCanonical:!0},":dm:":{unicode:["1f1e9-1f1f2"],isCanonical:!1},":flag_dk:":{unicode:["1f1e9-1f1f0"],isCanonical:!0},":dk:":{unicode:["1f1e9-1f1f0"],isCanonical:!1},":flag_dj:":{unicode:["1f1e9-1f1ef"],isCanonical:!0},":dj:":{unicode:["1f1e9-1f1ef"],isCanonical:!1},":flag_dg:":{unicode:["1f1e9-1f1ec"],isCanonical:!0},":dg:":{unicode:["1f1e9-1f1ec"],isCanonical:!1},":flag_de:":{unicode:["1f1e9-1f1ea"],isCanonical:!0},":de:":{unicode:["1f1e9-1f1ea"],isCanonical:!1},":flag_cz:":{unicode:["1f1e8-1f1ff"],isCanonical:!0},":cz:":{unicode:["1f1e8-1f1ff"],isCanonical:!1},":flag_cy:":{unicode:["1f1e8-1f1fe"],isCanonical:!0},":cy:":{unicode:["1f1e8-1f1fe"],isCanonical:!1},":flag_cx:":{unicode:["1f1e8-1f1fd"],isCanonical:!0},":cx:":{unicode:["1f1e8-1f1fd"],isCanonical:!1},":flag_cw:":{unicode:["1f1e8-1f1fc"],isCanonical:!0},":cw:":{unicode:["1f1e8-1f1fc"],isCanonical:!1},":flag_cv:":{unicode:["1f1e8-1f1fb"],isCanonical:!0},":cv:":{unicode:["1f1e8-1f1fb"],isCanonical:!1},":flag_cu:":{unicode:["1f1e8-1f1fa"],isCanonical:!0},":cu:":{unicode:["1f1e8-1f1fa"],isCanonical:!1},":flag_cr:":{unicode:["1f1e8-1f1f7"],isCanonical:!0},":cr:":{unicode:["1f1e8-1f1f7"],isCanonical:!1},":flag_cp:":{unicode:["1f1e8-1f1f5"],isCanonical:!0},":cp:":{unicode:["1f1e8-1f1f5"],isCanonical:!1},":flag_co:":{unicode:["1f1e8-1f1f4"],isCanonical:!0},":co:":{unicode:["1f1e8-1f1f4"],isCanonical:!1},":flag_cn:":{unicode:["1f1e8-1f1f3"],isCanonical:!0},":cn:":{unicode:["1f1e8-1f1f3"],isCanonical:!1},":flag_cm:":{unicode:["1f1e8-1f1f2"],isCanonical:!0},":cm:":{unicode:["1f1e8-1f1f2"],isCanonical:!1},":flag_cl:":{unicode:["1f1e8-1f1f1"],isCanonical:!0},":chile:":{unicode:["1f1e8-1f1f1"],isCanonical:!1},":flag_ck:":{unicode:["1f1e8-1f1f0"],isCanonical:!0},":ck:":{unicode:["1f1e8-1f1f0"],isCanonical:!1},":flag_ci:":{unicode:["1f1e8-1f1ee"],isCanonical:!0},":ci:":{unicode:["1f1e8-1f1ee"],isCanonical:!1},":flag_ch:":{unicode:["1f1e8-1f1ed"],isCanonical:!0},":ch:":{unicode:["1f1e8-1f1ed"],isCanonical:!1},":flag_cg:":{unicode:["1f1e8-1f1ec"],isCanonical:!0},":cg:":{unicode:["1f1e8-1f1ec"],isCanonical:!1},":flag_cf:":{unicode:["1f1e8-1f1eb"],isCanonical:!0},":cf:":{unicode:["1f1e8-1f1eb"],isCanonical:!1},":flag_cd:":{unicode:["1f1e8-1f1e9"],isCanonical:!0},":congo:":{unicode:["1f1e8-1f1e9"],isCanonical:!1},":flag_cc:":{unicode:["1f1e8-1f1e8"],isCanonical:!0},":cc:":{unicode:["1f1e8-1f1e8"],isCanonical:!1},":flag_ca:":{unicode:["1f1e8-1f1e6"],isCanonical:!0},":ca:":{unicode:["1f1e8-1f1e6"],isCanonical:!1},":flag_bz:":{unicode:["1f1e7-1f1ff"],isCanonical:!0},":bz:":{unicode:["1f1e7-1f1ff"],isCanonical:!1},":flag_by:":{unicode:["1f1e7-1f1fe"],isCanonical:!0},":by:":{unicode:["1f1e7-1f1fe"],isCanonical:!1},":flag_bw:":{unicode:["1f1e7-1f1fc"],isCanonical:!0},":bw:":{unicode:["1f1e7-1f1fc"],isCanonical:!1},":flag_bv:":{unicode:["1f1e7-1f1fb"],isCanonical:!0},":bv:":{unicode:["1f1e7-1f1fb"],isCanonical:!1},":flag_bt:":{unicode:["1f1e7-1f1f9"],isCanonical:!0},":bt:":{unicode:["1f1e7-1f1f9"],isCanonical:!1},":flag_bs:":{unicode:["1f1e7-1f1f8"],isCanonical:!0},":bs:":{unicode:["1f1e7-1f1f8"],isCanonical:!1},":flag_br:":{unicode:["1f1e7-1f1f7"],isCanonical:!0},":br:":{unicode:["1f1e7-1f1f7"],isCanonical:!1},":flag_bq:":{unicode:["1f1e7-1f1f6"],isCanonical:!0},":bq:":{unicode:["1f1e7-1f1f6"],isCanonical:!1},":flag_bo:":{unicode:["1f1e7-1f1f4"],isCanonical:!0},":bo:":{unicode:["1f1e7-1f1f4"],isCanonical:!1},":flag_bn:":{unicode:["1f1e7-1f1f3"],isCanonical:!0},":bn:":{unicode:["1f1e7-1f1f3"],isCanonical:!1},":flag_bm:":{unicode:["1f1e7-1f1f2"],isCanonical:!0},":bm:":{unicode:["1f1e7-1f1f2"],isCanonical:!1},":flag_bl:":{unicode:["1f1e7-1f1f1"],isCanonical:!0},":bl:":{unicode:["1f1e7-1f1f1"],isCanonical:!1},":flag_bj:":{unicode:["1f1e7-1f1ef"],isCanonical:!0},":bj:":{unicode:["1f1e7-1f1ef"],isCanonical:!1},":flag_bi:":{unicode:["1f1e7-1f1ee"],isCanonical:!0},":bi:":{unicode:["1f1e7-1f1ee"],isCanonical:!1},":flag_bh:":{unicode:["1f1e7-1f1ed"],isCanonical:!0},":bh:":{unicode:["1f1e7-1f1ed"],isCanonical:!1},":flag_bg:":{unicode:["1f1e7-1f1ec"],isCanonical:!0},":bg:":{unicode:["1f1e7-1f1ec"],isCanonical:!1},":flag_bf:":{unicode:["1f1e7-1f1eb"],isCanonical:!0},":bf:":{unicode:["1f1e7-1f1eb"],isCanonical:!1},":flag_be:":{unicode:["1f1e7-1f1ea"],isCanonical:!0},":be:":{unicode:["1f1e7-1f1ea"],isCanonical:!1},":flag_bd:":{unicode:["1f1e7-1f1e9"],isCanonical:!0},":bd:":{unicode:["1f1e7-1f1e9"],isCanonical:!1},":flag_bb:":{unicode:["1f1e7-1f1e7"],isCanonical:!0},":bb:":{unicode:["1f1e7-1f1e7"],isCanonical:!1},":flag_ba:":{unicode:["1f1e7-1f1e6"],isCanonical:!0},":ba:":{unicode:["1f1e7-1f1e6"],isCanonical:!1},":flag_az:":{unicode:["1f1e6-1f1ff"],isCanonical:!0},":az:":{unicode:["1f1e6-1f1ff"],isCanonical:!1},":flag_ax:":{unicode:["1f1e6-1f1fd"],isCanonical:!0},":ax:":{unicode:["1f1e6-1f1fd"],isCanonical:!1},":flag_aw:":{unicode:["1f1e6-1f1fc"],isCanonical:!0},":aw:":{unicode:["1f1e6-1f1fc"],isCanonical:!1},":flag_au:":{unicode:["1f1e6-1f1fa"],isCanonical:!0},":au:":{unicode:["1f1e6-1f1fa"],isCanonical:!1},":flag_at:":{unicode:["1f1e6-1f1f9"],isCanonical:!0},":at:":{unicode:["1f1e6-1f1f9"],isCanonical:!1},":flag_as:":{unicode:["1f1e6-1f1f8"],isCanonical:!0},":as:":{unicode:["1f1e6-1f1f8"],isCanonical:!1},":flag_ar:":{unicode:["1f1e6-1f1f7"],isCanonical:!0},":ar:":{unicode:["1f1e6-1f1f7"],isCanonical:!1},":flag_aq:":{unicode:["1f1e6-1f1f6"],isCanonical:!0},":aq:":{unicode:["1f1e6-1f1f6"],isCanonical:!1},":flag_ao:":{unicode:["1f1e6-1f1f4"],isCanonical:!0},":ao:":{unicode:["1f1e6-1f1f4"],isCanonical:!1},":flag_am:":{unicode:["1f1e6-1f1f2"],isCanonical:!0},":am:":{unicode:["1f1e6-1f1f2"],isCanonical:!1},":flag_al:":{unicode:["1f1e6-1f1f1"],isCanonical:!0},":al:":{unicode:["1f1e6-1f1f1"],isCanonical:!1},":flag_ai:":{unicode:["1f1e6-1f1ee"],isCanonical:!0},":ai:":{unicode:["1f1e6-1f1ee"],isCanonical:!1},":flag_ag:":{unicode:["1f1e6-1f1ec"],isCanonical:!0},":ag:":{unicode:["1f1e6-1f1ec"],isCanonical:!1},":flag_af:":{unicode:["1f1e6-1f1eb"],isCanonical:!0},":af:":{unicode:["1f1e6-1f1eb"],isCanonical:!1},":flag_ae:":{unicode:["1f1e6-1f1ea"],isCanonical:!0},":ae:":{unicode:["1f1e6-1f1ea"],isCanonical:!1},":flag_ad:":{unicode:["1f1e6-1f1e9"],isCanonical:!0},":ad:":{unicode:["1f1e6-1f1e9"],isCanonical:!1},":flag_ac:":{unicode:["1f1e6-1f1e8"],isCanonical:!0},":ac:":{unicode:["1f1e6-1f1e8"],isCanonical:!1},":mahjong:":{unicode:["1f004-fe0f","1f004"],isCanonical:!0},":parking:":{unicode:["1f17f-fe0f","1f17f"],isCanonical:!0},":sa:":{unicode:["1f202-fe0f","1f202"],isCanonical:!0},":u7121:":{unicode:["1f21a-fe0f","1f21a"],isCanonical:!0},":u6307:":{unicode:["1f22f-fe0f","1f22f"],isCanonical:!0},":u6708:":{unicode:["1f237-fe0f","1f237"],isCanonical:!0},":film_frames:":{unicode:["1f39e-fe0f","1f39e"],isCanonical:!0},":tickets:":{unicode:["1f39f-fe0f","1f39f"],isCanonical:!0},":admission_tickets:":{unicode:["1f39f-fe0f","1f39f"],isCanonical:!1},":lifter:":{unicode:["1f3cb-fe0f","1f3cb"],isCanonical:!0},":weight_lifter:":{unicode:["1f3cb-fe0f","1f3cb"],isCanonical:!1},":golfer:":{unicode:["1f3cc-fe0f","1f3cc"],isCanonical:!0},":motorcycle:":{unicode:["1f3cd-fe0f","1f3cd"],isCanonical:!0},":racing_motorcycle:":{unicode:["1f3cd-fe0f","1f3cd"],isCanonical:!1},":race_car:":{unicode:["1f3ce-fe0f","1f3ce"],isCanonical:!0},":racing_car:":{unicode:["1f3ce-fe0f","1f3ce"],isCanonical:!1},":military_medal:":{unicode:["1f396-fe0f","1f396"],isCanonical:!0},":reminder_ribbon:":{unicode:["1f397-fe0f","1f397"],isCanonical:!0},":hot_pepper:":{unicode:["1f336-fe0f","1f336"],isCanonical:!0},":cloud_rain:":{unicode:["1f327-fe0f","1f327"],isCanonical:!0},":cloud_with_rain:":{unicode:["1f327-fe0f","1f327"],isCanonical:!1},":cloud_snow:":{unicode:["1f328-fe0f","1f328"],isCanonical:!0},":cloud_with_snow:":{unicode:["1f328-fe0f","1f328"],isCanonical:!1},":cloud_lightning:":{unicode:["1f329-fe0f","1f329"],isCanonical:!0},":cloud_with_lightning:":{unicode:["1f329-fe0f","1f329"],isCanonical:!1},":cloud_tornado:":{unicode:["1f32a-fe0f","1f32a"],isCanonical:!0},":cloud_with_tornado:":{unicode:["1f32a-fe0f","1f32a"],isCanonical:!1},":fog:":{unicode:["1f32b-fe0f","1f32b"],isCanonical:!0},":wind_blowing_face:":{unicode:["1f32c-fe0f","1f32c"],isCanonical:!0},":chipmunk:":{unicode:["1f43f-fe0f","1f43f"],isCanonical:!0},":spider:":{unicode:["1f577-fe0f","1f577"],isCanonical:!0},":spider_web:":{unicode:["1f578-fe0f","1f578"],isCanonical:!0},":thermometer:":{unicode:["1f321-fe0f","1f321"],isCanonical:!0},":microphone2:":{unicode:["1f399-fe0f","1f399"],isCanonical:!0},":studio_microphone:":{unicode:["1f399-fe0f","1f399"],isCanonical:!1},":level_slider:":{unicode:["1f39a-fe0f","1f39a"], +isCanonical:!0},":control_knobs:":{unicode:["1f39b-fe0f","1f39b"],isCanonical:!0},":flag_white:":{unicode:["1f3f3-fe0f","1f3f3"],isCanonical:!0},":waving_white_flag:":{unicode:["1f3f3-fe0f","1f3f3"],isCanonical:!1},":rosette:":{unicode:["1f3f5-fe0f","1f3f5"],isCanonical:!0},":label:":{unicode:["1f3f7-fe0f","1f3f7"],isCanonical:!0},":projector:":{unicode:["1f4fd-fe0f","1f4fd"],isCanonical:!0},":film_projector:":{unicode:["1f4fd-fe0f","1f4fd"],isCanonical:!1},":om_symbol:":{unicode:["1f549-fe0f","1f549"],isCanonical:!0},":dove:":{unicode:["1f54a-fe0f","1f54a"],isCanonical:!0},":dove_of_peace:":{unicode:["1f54a-fe0f","1f54a"],isCanonical:!1},":candle:":{unicode:["1f56f-fe0f","1f56f"],isCanonical:!0},":clock:":{unicode:["1f570-fe0f","1f570"],isCanonical:!0},":mantlepiece_clock:":{unicode:["1f570-fe0f","1f570"],isCanonical:!1},":hole:":{unicode:["1f573-fe0f","1f573"],isCanonical:!0},":dark_sunglasses:":{unicode:["1f576-fe0f","1f576"],isCanonical:!0},":joystick:":{unicode:["1f579-fe0f","1f579"],isCanonical:!0},":paperclips:":{unicode:["1f587-fe0f","1f587"],isCanonical:!0},":linked_paperclips:":{unicode:["1f587-fe0f","1f587"],isCanonical:!1},":pen_ballpoint:":{unicode:["1f58a-fe0f","1f58a"],isCanonical:!0},":lower_left_ballpoint_pen:":{unicode:["1f58a-fe0f","1f58a"],isCanonical:!1},":pen_fountain:":{unicode:["1f58b-fe0f","1f58b"],isCanonical:!0},":lower_left_fountain_pen:":{unicode:["1f58b-fe0f","1f58b"],isCanonical:!1},":paintbrush:":{unicode:["1f58c-fe0f","1f58c"],isCanonical:!0},":lower_left_paintbrush:":{unicode:["1f58c-fe0f","1f58c"],isCanonical:!1},":crayon:":{unicode:["1f58d-fe0f","1f58d"],isCanonical:!0},":lower_left_crayon:":{unicode:["1f58d-fe0f","1f58d"],isCanonical:!1},":desktop:":{unicode:["1f5a5-fe0f","1f5a5"],isCanonical:!0},":desktop_computer:":{unicode:["1f5a5-fe0f","1f5a5"],isCanonical:!1},":printer:":{unicode:["1f5a8-fe0f","1f5a8"],isCanonical:!0},":trackball:":{unicode:["1f5b2-fe0f","1f5b2"],isCanonical:!0},":frame_photo:":{unicode:["1f5bc-fe0f","1f5bc"],isCanonical:!0},":frame_with_picture:":{unicode:["1f5bc-fe0f","1f5bc"],isCanonical:!1},":dividers:":{unicode:["1f5c2-fe0f","1f5c2"],isCanonical:!0},":card_index_dividers:":{unicode:["1f5c2-fe0f","1f5c2"],isCanonical:!1},":card_box:":{unicode:["1f5c3-fe0f","1f5c3"],isCanonical:!0},":card_file_box:":{unicode:["1f5c3-fe0f","1f5c3"],isCanonical:!1},":file_cabinet:":{unicode:["1f5c4-fe0f","1f5c4"],isCanonical:!0},":wastebasket:":{unicode:["1f5d1-fe0f","1f5d1"],isCanonical:!0},":notepad_spiral:":{unicode:["1f5d2-fe0f","1f5d2"],isCanonical:!0},":spiral_note_pad:":{unicode:["1f5d2-fe0f","1f5d2"],isCanonical:!1},":calendar_spiral:":{unicode:["1f5d3-fe0f","1f5d3"],isCanonical:!0},":spiral_calendar_pad:":{unicode:["1f5d3-fe0f","1f5d3"],isCanonical:!1},":compression:":{unicode:["1f5dc-fe0f","1f5dc"],isCanonical:!0},":key2:":{unicode:["1f5dd-fe0f","1f5dd"],isCanonical:!0},":old_key:":{unicode:["1f5dd-fe0f","1f5dd"],isCanonical:!1},":newspaper2:":{unicode:["1f5de-fe0f","1f5de"],isCanonical:!0},":rolled_up_newspaper:":{unicode:["1f5de-fe0f","1f5de"],isCanonical:!1},":dagger:":{unicode:["1f5e1-fe0f","1f5e1"],isCanonical:!0},":dagger_knife:":{unicode:["1f5e1-fe0f","1f5e1"],isCanonical:!1},":speaking_head:":{unicode:["1f5e3-fe0f","1f5e3"],isCanonical:!0},":speaking_head_in_silhouette:":{unicode:["1f5e3-fe0f","1f5e3"],isCanonical:!1},":speech_left:":{unicode:["1f5e8-fe0f","1f5e8"],isCanonical:!0},":left_speech_bubble:":{unicode:["1f5e8-fe0f","1f5e8"],isCanonical:!1},":anger_right:":{unicode:["1f5ef-fe0f","1f5ef"],isCanonical:!0},":right_anger_bubble:":{unicode:["1f5ef-fe0f","1f5ef"],isCanonical:!1},":ballot_box:":{unicode:["1f5f3-fe0f","1f5f3"],isCanonical:!0},":ballot_box_with_ballot:":{unicode:["1f5f3-fe0f","1f5f3"],isCanonical:!1},":map:":{unicode:["1f5fa-fe0f","1f5fa"],isCanonical:!0},":world_map:":{unicode:["1f5fa-fe0f","1f5fa"],isCanonical:!1},":tools:":{unicode:["1f6e0-fe0f","1f6e0"],isCanonical:!0},":hammer_and_wrench:":{unicode:["1f6e0-fe0f","1f6e0"],isCanonical:!1},":shield:":{unicode:["1f6e1-fe0f","1f6e1"],isCanonical:!0},":oil:":{unicode:["1f6e2-fe0f","1f6e2"],isCanonical:!0},":oil_drum:":{unicode:["1f6e2-fe0f","1f6e2"],isCanonical:!1},":satellite_orbital:":{unicode:["1f6f0-fe0f","1f6f0"],isCanonical:!0},":fork_knife_plate:":{unicode:["1f37d-fe0f","1f37d"],isCanonical:!0},":fork_and_knife_with_plate:":{unicode:["1f37d-fe0f","1f37d"],isCanonical:!1},":eye:":{unicode:["1f441-fe0f","1f441"],isCanonical:!0},":levitate:":{unicode:["1f574-fe0f","1f574"],isCanonical:!0},":man_in_business_suit_levitating:":{unicode:["1f574-fe0f","1f574"],isCanonical:!1},":spy:":{unicode:["1f575-fe0f","1f575"],isCanonical:!0},":sleuth_or_spy:":{unicode:["1f575-fe0f","1f575"],isCanonical:!1},":hand_splayed:":{unicode:["1f590-fe0f","1f590"],isCanonical:!0},":raised_hand_with_fingers_splayed:":{unicode:["1f590-fe0f","1f590"],isCanonical:!1},":mountain_snow:":{unicode:["1f3d4-fe0f","1f3d4"],isCanonical:!0},":snow_capped_mountain:":{unicode:["1f3d4-fe0f","1f3d4"],isCanonical:!1},":camping:":{unicode:["1f3d5-fe0f","1f3d5"],isCanonical:!0},":beach:":{unicode:["1f3d6-fe0f","1f3d6"],isCanonical:!0},":beach_with_umbrella:":{unicode:["1f3d6-fe0f","1f3d6"],isCanonical:!1},":construction_site:":{unicode:["1f3d7-fe0f","1f3d7"],isCanonical:!0},":building_construction:":{unicode:["1f3d7-fe0f","1f3d7"],isCanonical:!1},":homes:":{unicode:["1f3d8-fe0f","1f3d8"],isCanonical:!0},":house_buildings:":{unicode:["1f3d8-fe0f","1f3d8"],isCanonical:!1},":cityscape:":{unicode:["1f3d9-fe0f","1f3d9"],isCanonical:!0},":house_abandoned:":{unicode:["1f3da-fe0f","1f3da"],isCanonical:!0},":derelict_house_building:":{unicode:["1f3da-fe0f","1f3da"],isCanonical:!1},":classical_building:":{unicode:["1f3db-fe0f","1f3db"],isCanonical:!0},":desert:":{unicode:["1f3dc-fe0f","1f3dc"],isCanonical:!0},":island:":{unicode:["1f3dd-fe0f","1f3dd"],isCanonical:!0},":desert_island:":{unicode:["1f3dd-fe0f","1f3dd"],isCanonical:!1},":park:":{unicode:["1f3de-fe0f","1f3de"],isCanonical:!0},":national_park:":{unicode:["1f3de-fe0f","1f3de"],isCanonical:!1},":stadium:":{unicode:["1f3df-fe0f","1f3df"],isCanonical:!0},":couch:":{unicode:["1f6cb-fe0f","1f6cb"],isCanonical:!0},":couch_and_lamp:":{unicode:["1f6cb-fe0f","1f6cb"],isCanonical:!1},":shopping_bags:":{unicode:["1f6cd-fe0f","1f6cd"],isCanonical:!0},":bellhop:":{unicode:["1f6ce-fe0f","1f6ce"],isCanonical:!0},":bellhop_bell:":{unicode:["1f6ce-fe0f","1f6ce"],isCanonical:!1},":bed:":{unicode:["1f6cf-fe0f","1f6cf"],isCanonical:!0},":motorway:":{unicode:["1f6e3-fe0f","1f6e3"],isCanonical:!0},":railway_track:":{unicode:["1f6e4-fe0f","1f6e4"],isCanonical:!0},":railroad_track:":{unicode:["1f6e4-fe0f","1f6e4"],isCanonical:!1},":motorboat:":{unicode:["1f6e5-fe0f","1f6e5"],isCanonical:!0},":airplane_small:":{unicode:["1f6e9-fe0f","1f6e9"],isCanonical:!0},":small_airplane:":{unicode:["1f6e9-fe0f","1f6e9"],isCanonical:!1},":cruise_ship:":{unicode:["1f6f3-fe0f","1f6f3"],isCanonical:!0},":passenger_ship:":{unicode:["1f6f3-fe0f","1f6f3"],isCanonical:!1},":white_sun_small_cloud:":{unicode:["1f324-fe0f","1f324"],isCanonical:!0},":white_sun_with_small_cloud:":{unicode:["1f324-fe0f","1f324"],isCanonical:!1},":white_sun_cloud:":{unicode:["1f325-fe0f","1f325"],isCanonical:!0},":white_sun_behind_cloud:":{unicode:["1f325-fe0f","1f325"],isCanonical:!1},":white_sun_rain_cloud:":{unicode:["1f326-fe0f","1f326"],isCanonical:!0},":white_sun_behind_cloud_with_rain:":{unicode:["1f326-fe0f","1f326"],isCanonical:!1},":mouse_three_button:":{unicode:["1f5b1-fe0f","1f5b1"],isCanonical:!0},":three_button_mouse:":{unicode:["1f5b1-fe0f","1f5b1"],isCanonical:!1},":point_up_tone1:":{unicode:["261d-1f3fb"],isCanonical:!0},":point_up_tone2:":{unicode:["261d-1f3fc"],isCanonical:!0},":point_up_tone3:":{unicode:["261d-1f3fd"],isCanonical:!0},":point_up_tone4:":{unicode:["261d-1f3fe"],isCanonical:!0},":point_up_tone5:":{unicode:["261d-1f3ff"],isCanonical:!0},":v_tone1:":{unicode:["270c-1f3fb"],isCanonical:!0},":v_tone2:":{unicode:["270c-1f3fc"],isCanonical:!0},":v_tone3:":{unicode:["270c-1f3fd"],isCanonical:!0},":v_tone4:":{unicode:["270c-1f3fe"],isCanonical:!0},":v_tone5:":{unicode:["270c-1f3ff"],isCanonical:!0},":fist_tone1:":{unicode:["270a-1f3fb"],isCanonical:!0},":fist_tone2:":{unicode:["270a-1f3fc"],isCanonical:!0},":fist_tone3:":{unicode:["270a-1f3fd"],isCanonical:!0},":fist_tone4:":{unicode:["270a-1f3fe"],isCanonical:!0},":fist_tone5:":{unicode:["270a-1f3ff"],isCanonical:!0},":raised_hand_tone1:":{unicode:["270b-1f3fb"],isCanonical:!0},":raised_hand_tone2:":{unicode:["270b-1f3fc"],isCanonical:!0},":raised_hand_tone3:":{unicode:["270b-1f3fd"],isCanonical:!0},":raised_hand_tone4:":{unicode:["270b-1f3fe"],isCanonical:!0},":raised_hand_tone5:":{unicode:["270b-1f3ff"],isCanonical:!0},":writing_hand_tone1:":{unicode:["270d-1f3fb"],isCanonical:!0},":writing_hand_tone2:":{unicode:["270d-1f3fc"],isCanonical:!0},":writing_hand_tone3:":{unicode:["270d-1f3fd"],isCanonical:!0},":writing_hand_tone4:":{unicode:["270d-1f3fe"],isCanonical:!0},":writing_hand_tone5:":{unicode:["270d-1f3ff"],isCanonical:!0},":basketball_player_tone1:":{unicode:["26f9-1f3fb"],isCanonical:!0},":person_with_ball_tone1:":{unicode:["26f9-1f3fb"],isCanonical:!1},":basketball_player_tone2:":{unicode:["26f9-1f3fc"],isCanonical:!0},":person_with_ball_tone2:":{unicode:["26f9-1f3fc"],isCanonical:!1},":basketball_player_tone3:":{unicode:["26f9-1f3fd"],isCanonical:!0},":person_with_ball_tone3:":{unicode:["26f9-1f3fd"],isCanonical:!1},":basketball_player_tone4:":{unicode:["26f9-1f3fe"],isCanonical:!0},":person_with_ball_tone4:":{unicode:["26f9-1f3fe"],isCanonical:!1},":basketball_player_tone5:":{unicode:["26f9-1f3ff"],isCanonical:!0},":person_with_ball_tone5:":{unicode:["26f9-1f3ff"],isCanonical:!1},":copyright:":{unicode:["00a9-fe0f","00a9"],isCanonical:!0},":registered:":{unicode:["00ae-fe0f","00ae"],isCanonical:!0},":bangbang:":{unicode:["203c-fe0f","203c"],isCanonical:!0},":interrobang:":{unicode:["2049-fe0f","2049"],isCanonical:!0},":tm:":{unicode:["2122-fe0f","2122"],isCanonical:!0},":information_source:":{unicode:["2139-fe0f","2139"],isCanonical:!0},":left_right_arrow:":{unicode:["2194-fe0f","2194"],isCanonical:!0},":arrow_up_down:":{unicode:["2195-fe0f","2195"],isCanonical:!0},":arrow_upper_left:":{unicode:["2196-fe0f","2196"],isCanonical:!0},":arrow_upper_right:":{unicode:["2197-fe0f","2197"],isCanonical:!0},":arrow_lower_right:":{unicode:["2198-fe0f","2198"],isCanonical:!0},":arrow_lower_left:":{unicode:["2199-fe0f","2199"],isCanonical:!0},":leftwards_arrow_with_hook:":{unicode:["21a9-fe0f","21a9"],isCanonical:!0},":arrow_right_hook:":{unicode:["21aa-fe0f","21aa"],isCanonical:!0},":watch:":{unicode:["231a-fe0f","231a"],isCanonical:!0},":hourglass:":{unicode:["231b-fe0f","231b"],isCanonical:!0},":m:":{unicode:["24c2-fe0f","24c2"],isCanonical:!0},":black_small_square:":{unicode:["25aa-fe0f","25aa"],isCanonical:!0},":white_small_square:":{unicode:["25ab-fe0f","25ab"],isCanonical:!0},":arrow_forward:":{unicode:["25b6-fe0f","25b6"],isCanonical:!0},":arrow_backward:":{unicode:["25c0-fe0f","25c0"],isCanonical:!0},":white_medium_square:":{unicode:["25fb-fe0f","25fb"],isCanonical:!0},":black_medium_square:":{unicode:["25fc-fe0f","25fc"],isCanonical:!0},":white_medium_small_square:":{unicode:["25fd-fe0f","25fd"],isCanonical:!0},":black_medium_small_square:":{unicode:["25fe-fe0f","25fe"],isCanonical:!0},":sunny:":{unicode:["2600-fe0f","2600"],isCanonical:!0},":cloud:":{unicode:["2601-fe0f","2601"],isCanonical:!0},":telephone:":{unicode:["260e-fe0f","260e"],isCanonical:!0},":ballot_box_with_check:":{unicode:["2611-fe0f","2611"],isCanonical:!0},":umbrella:":{unicode:["2614-fe0f","2614"],isCanonical:!0},":coffee:":{unicode:["2615-fe0f","2615"],isCanonical:!0},":point_up:":{unicode:["261d-fe0f","261d"],isCanonical:!0},":relaxed:":{unicode:["263a-fe0f","263a"],isCanonical:!0},":aries:":{unicode:["2648-fe0f","2648"],isCanonical:!0},":taurus:":{unicode:["2649-fe0f","2649"],isCanonical:!0},":gemini:":{unicode:["264a-fe0f","264a"],isCanonical:!0},":cancer:":{unicode:["264b-fe0f","264b"],isCanonical:!0},":leo:":{unicode:["264c-fe0f","264c"],isCanonical:!0},":virgo:":{unicode:["264d-fe0f","264d"],isCanonical:!0},":libra:":{unicode:["264e-fe0f","264e"],isCanonical:!0},":scorpius:":{unicode:["264f-fe0f","264f"],isCanonical:!0},":sagittarius:":{unicode:["2650-fe0f","2650"],isCanonical:!0},":capricorn:":{unicode:["2651-fe0f","2651"],isCanonical:!0},":aquarius:":{unicode:["2652-fe0f","2652"],isCanonical:!0},":pisces:":{unicode:["2653-fe0f","2653"],isCanonical:!0},":spades:":{unicode:["2660-fe0f","2660"],isCanonical:!0},":clubs:":{unicode:["2663-fe0f","2663"],isCanonical:!0},":hearts:":{unicode:["2665-fe0f","2665"],isCanonical:!0},":diamonds:":{unicode:["2666-fe0f","2666"],isCanonical:!0},":hotsprings:":{unicode:["2668-fe0f","2668"],isCanonical:!0},":recycle:":{unicode:["267b-fe0f","267b"],isCanonical:!0},":wheelchair:":{unicode:["267f-fe0f","267f"],isCanonical:!0},":anchor:":{unicode:["2693-fe0f","2693"],isCanonical:!0},":warning:":{unicode:["26a0-fe0f","26a0"],isCanonical:!0},":zap:":{unicode:["26a1-fe0f","26a1"],isCanonical:!0},":white_circle:":{unicode:["26aa-fe0f","26aa"],isCanonical:!0},":black_circle:":{unicode:["26ab-fe0f","26ab"],isCanonical:!0},":soccer:":{unicode:["26bd-fe0f","26bd"],isCanonical:!0},":baseball:":{unicode:["26be-fe0f","26be"],isCanonical:!0},":snowman:":{unicode:["26c4-fe0f","26c4"],isCanonical:!0},":partly_sunny:":{unicode:["26c5-fe0f","26c5"],isCanonical:!0},":no_entry:":{unicode:["26d4-fe0f","26d4"],isCanonical:!0},":church:":{unicode:["26ea-fe0f","26ea"],isCanonical:!0},":fountain:":{unicode:["26f2-fe0f","26f2"],isCanonical:!0},":golf:":{unicode:["26f3-fe0f","26f3"],isCanonical:!0},":sailboat:":{unicode:["26f5-fe0f","26f5"],isCanonical:!0},":tent:":{unicode:["26fa-fe0f","26fa"],isCanonical:!0},":fuelpump:":{unicode:["26fd-fe0f","26fd"],isCanonical:!0},":scissors:":{unicode:["2702-fe0f","2702"],isCanonical:!0},":airplane:":{unicode:["2708-fe0f","2708"],isCanonical:!0},":envelope:":{unicode:["2709-fe0f","2709"],isCanonical:!0},":v:":{unicode:["270c-fe0f","270c"],isCanonical:!0},":pencil2:":{unicode:["270f-fe0f","270f"],isCanonical:!0},":black_nib:":{unicode:["2712-fe0f","2712"],isCanonical:!0},":heavy_check_mark:":{unicode:["2714-fe0f","2714"],isCanonical:!0},":heavy_multiplication_x:":{unicode:["2716-fe0f","2716"],isCanonical:!0},":eight_spoked_asterisk:":{unicode:["2733-fe0f","2733"],isCanonical:!0},":eight_pointed_black_star:":{unicode:["2734-fe0f","2734"],isCanonical:!0},":snowflake:":{unicode:["2744-fe0f","2744"],isCanonical:!0},":sparkle:":{unicode:["2747-fe0f","2747"],isCanonical:!0},":exclamation:":{unicode:["2757-fe0f","2757"],isCanonical:!0},":heart:":{unicode:["2764-fe0f","2764"],isCanonical:!0},":arrow_right:":{unicode:["27a1-fe0f","27a1"],isCanonical:!0},":arrow_heading_up:":{unicode:["2934-fe0f","2934"],isCanonical:!0},":arrow_heading_down:":{unicode:["2935-fe0f","2935"],isCanonical:!0},":arrow_left:":{unicode:["2b05-fe0f","2b05"],isCanonical:!0},":arrow_up:":{unicode:["2b06-fe0f","2b06"],isCanonical:!0},":arrow_down:":{unicode:["2b07-fe0f","2b07"],isCanonical:!0},":black_large_square:":{unicode:["2b1b-fe0f","2b1b"],isCanonical:!0},":white_large_square:":{unicode:["2b1c-fe0f","2b1c"],isCanonical:!0},":star:":{unicode:["2b50-fe0f","2b50"],isCanonical:!0},":o:":{unicode:["2b55-fe0f","2b55"],isCanonical:!0},":wavy_dash:":{unicode:["3030-fe0f","3030"],isCanonical:!0},":part_alternation_mark:":{unicode:["303d-fe0f","303d"],isCanonical:!0},":congratulations:":{unicode:["3297-fe0f","3297"],isCanonical:!0},":secret:":{unicode:["3299-fe0f","3299"],isCanonical:!0},":cross:":{unicode:["271d-fe0f","271d"],isCanonical:!0},":latin_cross:":{unicode:["271d-fe0f","271d"],isCanonical:!1},":keyboard:":{unicode:["2328-fe0f","2328"],isCanonical:!0},":writing_hand:":{unicode:["270d-fe0f","270d"],isCanonical:!0},":eject:":{unicode:["23cf-fe0f","23cf"],isCanonical:!0},":eject_symbol:":{unicode:["23cf-fe0f","23cf"],isCanonical:!1},":track_next:":{unicode:["23ed-fe0f","23ed"],isCanonical:!0},":next_track:":{unicode:["23ed-fe0f","23ed"],isCanonical:!1},":track_previous:":{unicode:["23ee-fe0f","23ee"],isCanonical:!0},":previous_track:":{unicode:["23ee-fe0f","23ee"],isCanonical:!1},":play_pause:":{unicode:["23ef-fe0f","23ef"],isCanonical:!0},":stopwatch:":{unicode:["23f1-fe0f","23f1"],isCanonical:!0},":timer:":{unicode:["23f2-fe0f","23f2"],isCanonical:!0},":timer_clock:":{unicode:["23f2-fe0f","23f2"],isCanonical:!1},":pause_button:":{unicode:["23f8-fe0f","23f8"],isCanonical:!0},":double_vertical_bar:":{unicode:["23f8-fe0f","23f8"],isCanonical:!1},":stop_button:":{unicode:["23f9-fe0f","23f9"],isCanonical:!0},":record_button:":{unicode:["23fa-fe0f","23fa"],isCanonical:!0},":umbrella2:":{unicode:["2602-fe0f","2602"],isCanonical:!0},":snowman2:":{unicode:["2603-fe0f","2603"],isCanonical:!0},":comet:":{unicode:["2604-fe0f","2604"],isCanonical:!0},":shamrock:":{unicode:["2618-fe0f","2618"],isCanonical:!0},":skull_crossbones:":{unicode:["2620-fe0f","2620"],isCanonical:!0},":skull_and_crossbones:":{unicode:["2620-fe0f","2620"],isCanonical:!1},":radioactive:":{unicode:["2622-fe0f","2622"],isCanonical:!0},":radioactive_sign:":{unicode:["2622-fe0f","2622"],isCanonical:!1},":biohazard:":{unicode:["2623-fe0f","2623"],isCanonical:!0},":biohazard_sign:":{unicode:["2623-fe0f","2623"],isCanonical:!1},":orthodox_cross:":{unicode:["2626-fe0f","2626"],isCanonical:!0},":star_and_crescent:":{unicode:["262a-fe0f","262a"],isCanonical:!0},":peace:":{unicode:["262e-fe0f","262e"],isCanonical:!0},":peace_symbol:":{unicode:["262e-fe0f","262e"],isCanonical:!1},":yin_yang:":{unicode:["262f-fe0f","262f"],isCanonical:!0},":wheel_of_dharma:":{unicode:["2638-fe0f","2638"],isCanonical:!0},":frowning2:":{unicode:["2639-fe0f","2639"],isCanonical:!0},":white_frowning_face:":{unicode:["2639-fe0f","2639"],isCanonical:!1},":hammer_pick:":{unicode:["2692-fe0f","2692"],isCanonical:!0},":hammer_and_pick:":{unicode:["2692-fe0f","2692"],isCanonical:!1},":crossed_swords:":{unicode:["2694-fe0f","2694"],isCanonical:!0},":scales:":{unicode:["2696-fe0f","2696"],isCanonical:!0},":alembic:":{unicode:["2697-fe0f","2697"],isCanonical:!0},":gear:":{unicode:["2699-fe0f","2699"],isCanonical:!0},":atom:":{unicode:["269b-fe0f","269b"],isCanonical:!0},":atom_symbol:":{unicode:["269b-fe0f","269b"],isCanonical:!1},":fleur-de-lis:":{unicode:["269c-fe0f","269c"],isCanonical:!0},":coffin:":{unicode:["26b0-fe0f","26b0"],isCanonical:!0},":urn:":{unicode:["26b1-fe0f","26b1"],isCanonical:!0},":funeral_urn:":{unicode:["26b1-fe0f","26b1"],isCanonical:!1},":thunder_cloud_rain:":{unicode:["26c8-fe0f","26c8"],isCanonical:!0},":thunder_cloud_and_rain:":{unicode:["26c8-fe0f","26c8"],isCanonical:!1},":pick:":{unicode:["26cf-fe0f","26cf"],isCanonical:!0},":helmet_with_cross:":{unicode:["26d1-fe0f","26d1"],isCanonical:!0},":helmet_with_white_cross:":{unicode:["26d1-fe0f","26d1"],isCanonical:!1},":chains:":{unicode:["26d3-fe0f","26d3"],isCanonical:!0},":shinto_shrine:":{unicode:["26e9-fe0f","26e9"],isCanonical:!0},":mountain:":{unicode:["26f0-fe0f","26f0"],isCanonical:!0},":beach_umbrella:":{unicode:["26f1-fe0f","26f1"],isCanonical:!0},":umbrella_on_ground:":{unicode:["26f1-fe0f","26f1"],isCanonical:!1},":ferry:":{unicode:["26f4-fe0f","26f4"],isCanonical:!0},":skier:":{unicode:["26f7-fe0f","26f7"],isCanonical:!0},":ice_skate:":{unicode:["26f8-fe0f","26f8"],isCanonical:!0},":basketball_player:":{unicode:["26f9-fe0f","26f9"],isCanonical:!0},":person_with_ball:":{unicode:["26f9-fe0f","26f9"],isCanonical:!1},":star_of_david:":{unicode:["2721-fe0f","2721"],isCanonical:!0},":heart_exclamation:":{unicode:["2763-fe0f","2763"],isCanonical:!0},":heavy_heart_exclamation_mark_ornament:":{unicode:["2763-fe0f","2763"],isCanonical:!1},":third_place:":{unicode:["1f949"],isCanonical:!0},":third_place_medal:":{unicode:["1f949"],isCanonical:!1},":second_place:":{unicode:["1f948"],isCanonical:!0},":second_place_medal:":{unicode:["1f948"],isCanonical:!1},":first_place:":{unicode:["1f947"],isCanonical:!0},":first_place_medal:":{unicode:["1f947"],isCanonical:!1},":fencer:":{unicode:["1f93a"],isCanonical:!0},":fencing:":{unicode:["1f93a"],isCanonical:!1},":goal:":{unicode:["1f945"],isCanonical:!0},":goal_net:":{unicode:["1f945"],isCanonical:!1},":handball:":{unicode:["1f93e"],isCanonical:!0},":regional_indicator_z:":{unicode:["1f1ff"],isCanonical:!0},":water_polo:":{unicode:["1f93d"],isCanonical:!0},":martial_arts_uniform:":{unicode:["1f94b"],isCanonical:!0},":karate_uniform:":{unicode:["1f94b"],isCanonical:!1},":boxing_glove:":{unicode:["1f94a"],isCanonical:!0},":boxing_gloves:":{unicode:["1f94a"],isCanonical:!1},":wrestlers:":{unicode:["1f93c"],isCanonical:!0},":wrestling:":{unicode:["1f93c"],isCanonical:!1},":juggling:":{unicode:["1f939"],isCanonical:!0},":juggler:":{unicode:["1f939"],isCanonical:!1},":cartwheel:":{unicode:["1f938"],isCanonical:!0},":person_doing_cartwheel:":{unicode:["1f938"],isCanonical:!1},":canoe:":{unicode:["1f6f6"],isCanonical:!0},":kayak:":{unicode:["1f6f6"],isCanonical:!1},":motor_scooter:":{unicode:["1f6f5"],isCanonical:!0},":motorbike:":{unicode:["1f6f5"],isCanonical:!1},":scooter:":{unicode:["1f6f4"],isCanonical:!0},":shopping_cart:":{unicode:["1f6d2"],isCanonical:!0},":shopping_trolley:":{unicode:["1f6d2"],isCanonical:!1},":black_joker:":{unicode:["1f0cf"],isCanonical:!0},":a:":{unicode:["1f170"],isCanonical:!0},":b:":{unicode:["1f171"],isCanonical:!0},":o2:":{unicode:["1f17e"],isCanonical:!0},":octagonal_sign:":{unicode:["1f6d1"],isCanonical:!0},":stop_sign:":{unicode:["1f6d1"],isCanonical:!1},":ab:":{unicode:["1f18e"],isCanonical:!0},":cl:":{unicode:["1f191"],isCanonical:!0},":regional_indicator_y:":{unicode:["1f1fe"],isCanonical:!0},":cool:":{unicode:["1f192"],isCanonical:!0},":free:":{unicode:["1f193"],isCanonical:!0},":id:":{unicode:["1f194"],isCanonical:!0},":new:":{unicode:["1f195"],isCanonical:!0},":ng:":{unicode:["1f196"],isCanonical:!0},":ok:":{unicode:["1f197"],isCanonical:!0},":sos:":{unicode:["1f198"],isCanonical:!0},":spoon:":{unicode:["1f944"],isCanonical:!0},":up:":{unicode:["1f199"],isCanonical:!0},":vs:":{unicode:["1f19a"],isCanonical:!0},":champagne_glass:":{unicode:["1f942"],isCanonical:!0},":clinking_glass:":{unicode:["1f942"],isCanonical:!1},":tumbler_glass:":{unicode:["1f943"],isCanonical:!0},":whisky:":{unicode:["1f943"],isCanonical:!1},":koko:":{unicode:["1f201"],isCanonical:!0},":stuffed_flatbread:":{unicode:["1f959"],isCanonical:!0},":stuffed_pita:":{unicode:["1f959"],isCanonical:!1},":u7981:":{unicode:["1f232"],isCanonical:!0},":u7a7a:":{unicode:["1f233"],isCanonical:!0},":u5408:":{unicode:["1f234"],isCanonical:!0},":u6e80:":{unicode:["1f235"],isCanonical:!0},":u6709:":{unicode:["1f236"],isCanonical:!0},":shallow_pan_of_food:":{unicode:["1f958"],isCanonical:!0},":paella:":{unicode:["1f958"],isCanonical:!1},":u7533:":{unicode:["1f238"],isCanonical:!0},":u5272:":{unicode:["1f239"],isCanonical:!0},":salad:":{unicode:["1f957"],isCanonical:!0},":green_salad:":{unicode:["1f957"],isCanonical:!1},":u55b6:":{unicode:["1f23a"],isCanonical:!0},":ideograph_advantage:":{unicode:["1f250"],isCanonical:!0},":accept:":{unicode:["1f251"],isCanonical:!0},":cyclone:":{unicode:["1f300"],isCanonical:!0},":french_bread:":{unicode:["1f956"],isCanonical:!0},":baguette_bread:":{unicode:["1f956"],isCanonical:!1},":foggy:":{unicode:["1f301"],isCanonical:!0},":closed_umbrella:":{unicode:["1f302"],isCanonical:!0},":night_with_stars:":{unicode:["1f303"],isCanonical:!0},":sunrise_over_mountains:":{unicode:["1f304"],isCanonical:!0},":sunrise:":{unicode:["1f305"],isCanonical:!0},":city_dusk:":{unicode:["1f306"],isCanonical:!0},":carrot:":{unicode:["1f955"],isCanonical:!0},":city_sunset:":{unicode:["1f307"],isCanonical:!0},":city_sunrise:":{unicode:["1f307"],isCanonical:!1},":rainbow:":{unicode:["1f308"],isCanonical:!0},":potato:":{unicode:["1f954"],isCanonical:!0},":bridge_at_night:":{unicode:["1f309"],isCanonical:!0},":ocean:":{unicode:["1f30a"],isCanonical:!0},":volcano:":{unicode:["1f30b"],isCanonical:!0},":milky_way:":{unicode:["1f30c"],isCanonical:!0},":earth_asia:":{unicode:["1f30f"],isCanonical:!0},":new_moon:":{unicode:["1f311"],isCanonical:!0},":bacon:":{unicode:["1f953"],isCanonical:!0},":first_quarter_moon:":{unicode:["1f313"],isCanonical:!0},":waxing_gibbous_moon:":{unicode:["1f314"],isCanonical:!0},":full_moon:":{unicode:["1f315"],isCanonical:!0},":crescent_moon:":{unicode:["1f319"],isCanonical:!0},":first_quarter_moon_with_face:":{unicode:["1f31b"],isCanonical:!0},":star2:":{unicode:["1f31f"],isCanonical:!0},":cucumber:":{unicode:["1f952"],isCanonical:!0},":stars:":{unicode:["1f320"],isCanonical:!0},":chestnut:":{unicode:["1f330"],isCanonical:!0},":avocado:":{unicode:["1f951"],isCanonical:!0},":seedling:":{unicode:["1f331"],isCanonical:!0},":palm_tree:":{unicode:["1f334"],isCanonical:!0},":cactus:":{unicode:["1f335"],isCanonical:!0},":tulip:":{unicode:["1f337"],isCanonical:!0},":cherry_blossom:":{unicode:["1f338"],isCanonical:!0},":rose:":{unicode:["1f339"],isCanonical:!0},":hibiscus:":{unicode:["1f33a"],isCanonical:!0},":sunflower:":{unicode:["1f33b"],isCanonical:!0},":blossom:":{unicode:["1f33c"],isCanonical:!0},":corn:":{unicode:["1f33d"],isCanonical:!0},":croissant:":{unicode:["1f950"],isCanonical:!0},":ear_of_rice:":{unicode:["1f33e"],isCanonical:!0},":herb:":{unicode:["1f33f"],isCanonical:!0},":four_leaf_clover:":{unicode:["1f340"],isCanonical:!0},":maple_leaf:":{unicode:["1f341"],isCanonical:!0},":fallen_leaf:":{unicode:["1f342"],isCanonical:!0},":leaves:":{unicode:["1f343"],isCanonical:!0},":mushroom:":{unicode:["1f344"],isCanonical:!0},":tomato:":{unicode:["1f345"],isCanonical:!0},":eggplant:":{unicode:["1f346"],isCanonical:!0},":grapes:":{unicode:["1f347"],isCanonical:!0},":melon:":{unicode:["1f348"],isCanonical:!0},":watermelon:":{unicode:["1f349"],isCanonical:!0},":tangerine:":{unicode:["1f34a"],isCanonical:!0},":wilted_rose:":{unicode:["1f940"],isCanonical:!0},":wilted_flower:":{unicode:["1f940"],isCanonical:!1},":banana:":{unicode:["1f34c"],isCanonical:!0},":pineapple:":{unicode:["1f34d"],isCanonical:!0},":apple:":{unicode:["1f34e"],isCanonical:!0},":green_apple:":{unicode:["1f34f"],isCanonical:!0},":peach:":{unicode:["1f351"],isCanonical:!0},":cherries:":{unicode:["1f352"],isCanonical:!0},":strawberry:":{unicode:["1f353"],isCanonical:!0},":rhino:":{unicode:["1f98f"],isCanonical:!0},":rhinoceros:":{unicode:["1f98f"],isCanonical:!1},":hamburger:":{unicode:["1f354"],isCanonical:!0},":pizza:":{unicode:["1f355"],isCanonical:!0},":meat_on_bone:":{unicode:["1f356"],isCanonical:!0},":lizard:":{unicode:["1f98e"],isCanonical:!0},":poultry_leg:":{unicode:["1f357"],isCanonical:!0},":rice_cracker:":{unicode:["1f358"],isCanonical:!0},":rice_ball:":{unicode:["1f359"],isCanonical:!0},":gorilla:":{unicode:["1f98d"],isCanonical:!0},":rice:":{unicode:["1f35a"],isCanonical:!0},":curry:":{unicode:["1f35b"],isCanonical:!0},":deer:":{unicode:["1f98c"],isCanonical:!0},":ramen:":{unicode:["1f35c"],isCanonical:!0},":spaghetti:":{unicode:["1f35d"],isCanonical:!0},":bread:":{unicode:["1f35e"],isCanonical:!0},":fries:":{unicode:["1f35f"],isCanonical:!0},":butterfly:":{unicode:["1f98b"],isCanonical:!0},":sweet_potato:":{unicode:["1f360"],isCanonical:!0},":dango:":{unicode:["1f361"],isCanonical:!0},":fox:":{unicode:["1f98a"],isCanonical:!0},":fox_face:":{unicode:["1f98a"],isCanonical:!1},":oden:":{unicode:["1f362"],isCanonical:!0},":sushi:":{unicode:["1f363"],isCanonical:!0},":owl:":{unicode:["1f989"],isCanonical:!0},":fried_shrimp:":{unicode:["1f364"],isCanonical:!0},":fish_cake:":{unicode:["1f365"],isCanonical:!0},":shark:":{unicode:["1f988"],isCanonical:!0},":icecream:":{unicode:["1f366"],isCanonical:!0},":bat:":{unicode:["1f987"],isCanonical:!0},":shaved_ice:":{unicode:["1f367"],isCanonical:!0},":regional_indicator_x:":{unicode:["1f1fd"],isCanonical:!0},":ice_cream:":{unicode:["1f368"],isCanonical:!0},":duck:":{unicode:["1f986"],isCanonical:!0},":doughnut:":{unicode:["1f369"],isCanonical:!0},":eagle:":{unicode:["1f985"],isCanonical:!0},":cookie:":{unicode:["1f36a"],isCanonical:!0},":black_heart:":{unicode:["1f5a4"],isCanonical:!0},":chocolate_bar:":{unicode:["1f36b"],isCanonical:!0},":candy:":{unicode:["1f36c"],isCanonical:!0},":lollipop:":{unicode:["1f36d"],isCanonical:!0},":custard:":{unicode:["1f36e"],isCanonical:!0},":pudding:":{unicode:["1f36e"],isCanonical:!1},":flan:":{unicode:["1f36e"],isCanonical:!1},":honey_pot:":{unicode:["1f36f"],isCanonical:!0},":fingers_crossed:":{unicode:["1f91e"],isCanonical:!0},":hand_with_index_and_middle_finger_crossed:":{unicode:["1f91e"],isCanonical:!1},":cake:":{unicode:["1f370"],isCanonical:!0},":bento:":{unicode:["1f371"],isCanonical:!0},":stew:":{unicode:["1f372"],isCanonical:!0},":handshake:":{unicode:["1f91d"],isCanonical:!0},":shaking_hands:":{unicode:["1f91d"],isCanonical:!1},":cooking:":{unicode:["1f373"],isCanonical:!0},":fork_and_knife:":{unicode:["1f374"],isCanonical:!0},":tea:":{unicode:["1f375"],isCanonical:!0},":sake:":{unicode:["1f376"],isCanonical:!0},":wine_glass:":{unicode:["1f377"],isCanonical:!0},":cocktail:":{unicode:["1f378"],isCanonical:!0},":tropical_drink:":{unicode:["1f379"],isCanonical:!0},":beer:":{unicode:["1f37a"],isCanonical:!0},":beers:":{unicode:["1f37b"],isCanonical:!0},":ribbon:":{unicode:["1f380"],isCanonical:!0},":gift:":{unicode:["1f381"],isCanonical:!0},":birthday:":{unicode:["1f382"],isCanonical:!0},":jack_o_lantern:":{unicode:["1f383"],isCanonical:!0},":left_facing_fist:":{unicode:["1f91b"],isCanonical:!0},":left_fist:":{unicode:["1f91b"],isCanonical:!1},":right_facing_fist:":{unicode:["1f91c"],isCanonical:!0},":right_fist:":{unicode:["1f91c"],isCanonical:!1},":christmas_tree:":{unicode:["1f384"],isCanonical:!0},":santa:":{unicode:["1f385"],isCanonical:!0},":fireworks:":{unicode:["1f386"],isCanonical:!0},":raised_back_of_hand:":{unicode:["1f91a"],isCanonical:!0},":back_of_hand:":{unicode:["1f91a"],isCanonical:!1},":sparkler:":{unicode:["1f387"],isCanonical:!0},":balloon:":{unicode:["1f388"],isCanonical:!0},":tada:":{unicode:["1f389"],isCanonical:!0},":confetti_ball:":{unicode:["1f38a"],isCanonical:!0},":tanabata_tree:":{unicode:["1f38b"],isCanonical:!0},":crossed_flags:":{unicode:["1f38c"],isCanonical:!0},":call_me:":{unicode:["1f919"],isCanonical:!0},":call_me_hand:":{unicode:["1f919"],isCanonical:!1},":bamboo:":{unicode:["1f38d"],isCanonical:!0},":man_dancing:":{unicode:["1f57a"],isCanonical:!0},":male_dancer:":{unicode:["1f57a"],isCanonical:!1},":dolls:":{unicode:["1f38e"],isCanonical:!0},":selfie:":{unicode:["1f933"],isCanonical:!0},":flags:":{unicode:["1f38f"],isCanonical:!0},":pregnant_woman:":{unicode:["1f930"],isCanonical:!0},":expecting_woman:":{unicode:["1f930"],isCanonical:!1},":wind_chime:":{unicode:["1f390"],isCanonical:!0},":face_palm:":{unicode:["1f926"],isCanonical:!0},":facepalm:":{unicode:["1f926"],isCanonical:!1},":shrug:":{unicode:["1f937"],isCanonical:!0},":rice_scene:":{unicode:["1f391"],isCanonical:!0},":school_satchel:":{unicode:["1f392"],isCanonical:!0},":mortar_board:":{unicode:["1f393"],isCanonical:!0},":carousel_horse:":{unicode:["1f3a0"],isCanonical:!0},":ferris_wheel:":{unicode:["1f3a1"],isCanonical:!0},":roller_coaster:":{unicode:["1f3a2"],isCanonical:!0},":fishing_pole_and_fish:":{unicode:["1f3a3"],isCanonical:!0},":microphone:":{unicode:["1f3a4"],isCanonical:!0},":movie_camera:":{unicode:["1f3a5"],isCanonical:!0},":cinema:":{unicode:["1f3a6"],isCanonical:!0},":headphones:":{unicode:["1f3a7"],isCanonical:!0},":mrs_claus:":{unicode:["1f936"],isCanonical:!0},":mother_christmas:":{unicode:["1f936"],isCanonical:!1},":art:":{unicode:["1f3a8"],isCanonical:!0},":man_in_tuxedo:":{unicode:["1f935"],isCanonical:!0},":tophat:":{unicode:["1f3a9"],isCanonical:!0},":circus_tent:":{unicode:["1f3aa"],isCanonical:!0},":prince:":{unicode:["1f934"],isCanonical:!0},":ticket:":{unicode:["1f3ab"],isCanonical:!0},":clapper:":{unicode:["1f3ac"],isCanonical:!0},":performing_arts:":{unicode:["1f3ad"],isCanonical:!0},":sneezing_face:":{unicode:["1f927"], +isCanonical:!0},":sneeze:":{unicode:["1f927"],isCanonical:!1},":video_game:":{unicode:["1f3ae"],isCanonical:!0},":dart:":{unicode:["1f3af"],isCanonical:!0},":slot_machine:":{unicode:["1f3b0"],isCanonical:!0},":8ball:":{unicode:["1f3b1"],isCanonical:!0},":game_die:":{unicode:["1f3b2"],isCanonical:!0},":bowling:":{unicode:["1f3b3"],isCanonical:!0},":flower_playing_cards:":{unicode:["1f3b4"],isCanonical:!0},":lying_face:":{unicode:["1f925"],isCanonical:!0},":liar:":{unicode:["1f925"],isCanonical:!1},":musical_note:":{unicode:["1f3b5"],isCanonical:!0},":notes:":{unicode:["1f3b6"],isCanonical:!0},":saxophone:":{unicode:["1f3b7"],isCanonical:!0},":drooling_face:":{unicode:["1f924"],isCanonical:!0},":drool:":{unicode:["1f924"],isCanonical:!1},":guitar:":{unicode:["1f3b8"],isCanonical:!0},":musical_keyboard:":{unicode:["1f3b9"],isCanonical:!0},":trumpet:":{unicode:["1f3ba"],isCanonical:!0},":rofl:":{unicode:["1f923"],isCanonical:!0},":rolling_on_the_floor_laughing:":{unicode:["1f923"],isCanonical:!1},":violin:":{unicode:["1f3bb"],isCanonical:!0},":musical_score:":{unicode:["1f3bc"],isCanonical:!0},":running_shirt_with_sash:":{unicode:["1f3bd"],isCanonical:!0},":nauseated_face:":{unicode:["1f922"],isCanonical:!0},":sick:":{unicode:["1f922"],isCanonical:!1},":tennis:":{unicode:["1f3be"],isCanonical:!0},":ski:":{unicode:["1f3bf"],isCanonical:!0},":basketball:":{unicode:["1f3c0"],isCanonical:!0},":checkered_flag:":{unicode:["1f3c1"],isCanonical:!0},":clown:":{unicode:["1f921"],isCanonical:!0},":clown_face:":{unicode:["1f921"],isCanonical:!1},":snowboarder:":{unicode:["1f3c2"],isCanonical:!0},":runner:":{unicode:["1f3c3"],isCanonical:!0},":surfer:":{unicode:["1f3c4"],isCanonical:!0},":trophy:":{unicode:["1f3c6"],isCanonical:!0},":football:":{unicode:["1f3c8"],isCanonical:!0},":swimmer:":{unicode:["1f3ca"],isCanonical:!0},":house:":{unicode:["1f3e0"],isCanonical:!0},":house_with_garden:":{unicode:["1f3e1"],isCanonical:!0},":office:":{unicode:["1f3e2"],isCanonical:!0},":post_office:":{unicode:["1f3e3"],isCanonical:!0},":hospital:":{unicode:["1f3e5"],isCanonical:!0},":bank:":{unicode:["1f3e6"],isCanonical:!0},":atm:":{unicode:["1f3e7"],isCanonical:!0},":hotel:":{unicode:["1f3e8"],isCanonical:!0},":love_hotel:":{unicode:["1f3e9"],isCanonical:!0},":convenience_store:":{unicode:["1f3ea"],isCanonical:!0},":school:":{unicode:["1f3eb"],isCanonical:!0},":department_store:":{unicode:["1f3ec"],isCanonical:!0},":cowboy:":{unicode:["1f920"],isCanonical:!0},":face_with_cowboy_hat:":{unicode:["1f920"],isCanonical:!1},":factory:":{unicode:["1f3ed"],isCanonical:!0},":izakaya_lantern:":{unicode:["1f3ee"],isCanonical:!0},":japanese_castle:":{unicode:["1f3ef"],isCanonical:!0},":european_castle:":{unicode:["1f3f0"],isCanonical:!0},":snail:":{unicode:["1f40c"],isCanonical:!0},":snake:":{unicode:["1f40d"],isCanonical:!0},":racehorse:":{unicode:["1f40e"],isCanonical:!0},":sheep:":{unicode:["1f411"],isCanonical:!0},":monkey:":{unicode:["1f412"],isCanonical:!0},":chicken:":{unicode:["1f414"],isCanonical:!0},":boar:":{unicode:["1f417"],isCanonical:!0},":elephant:":{unicode:["1f418"],isCanonical:!0},":octopus:":{unicode:["1f419"],isCanonical:!0},":shell:":{unicode:["1f41a"],isCanonical:!0},":bug:":{unicode:["1f41b"],isCanonical:!0},":ant:":{unicode:["1f41c"],isCanonical:!0},":bee:":{unicode:["1f41d"],isCanonical:!0},":beetle:":{unicode:["1f41e"],isCanonical:!0},":fish:":{unicode:["1f41f"],isCanonical:!0},":tropical_fish:":{unicode:["1f420"],isCanonical:!0},":blowfish:":{unicode:["1f421"],isCanonical:!0},":turtle:":{unicode:["1f422"],isCanonical:!0},":hatching_chick:":{unicode:["1f423"],isCanonical:!0},":baby_chick:":{unicode:["1f424"],isCanonical:!0},":hatched_chick:":{unicode:["1f425"],isCanonical:!0},":bird:":{unicode:["1f426"],isCanonical:!0},":penguin:":{unicode:["1f427"],isCanonical:!0},":koala:":{unicode:["1f428"],isCanonical:!0},":poodle:":{unicode:["1f429"],isCanonical:!0},":camel:":{unicode:["1f42b"],isCanonical:!0},":dolphin:":{unicode:["1f42c"],isCanonical:!0},":mouse:":{unicode:["1f42d"],isCanonical:!0},":cow:":{unicode:["1f42e"],isCanonical:!0},":tiger:":{unicode:["1f42f"],isCanonical:!0},":rabbit:":{unicode:["1f430"],isCanonical:!0},":cat:":{unicode:["1f431"],isCanonical:!0},":dragon_face:":{unicode:["1f432"],isCanonical:!0},":whale:":{unicode:["1f433"],isCanonical:!0},":horse:":{unicode:["1f434"],isCanonical:!0},":monkey_face:":{unicode:["1f435"],isCanonical:!0},":dog:":{unicode:["1f436"],isCanonical:!0},":pig:":{unicode:["1f437"],isCanonical:!0},":frog:":{unicode:["1f438"],isCanonical:!0},":hamster:":{unicode:["1f439"],isCanonical:!0},":wolf:":{unicode:["1f43a"],isCanonical:!0},":bear:":{unicode:["1f43b"],isCanonical:!0},":panda_face:":{unicode:["1f43c"],isCanonical:!0},":pig_nose:":{unicode:["1f43d"],isCanonical:!0},":feet:":{unicode:["1f43e"],isCanonical:!0},":paw_prints:":{unicode:["1f43e"],isCanonical:!1},":eyes:":{unicode:["1f440"],isCanonical:!0},":ear:":{unicode:["1f442"],isCanonical:!0},":nose:":{unicode:["1f443"],isCanonical:!0},":lips:":{unicode:["1f444"],isCanonical:!0},":tongue:":{unicode:["1f445"],isCanonical:!0},":point_up_2:":{unicode:["1f446"],isCanonical:!0},":point_down:":{unicode:["1f447"],isCanonical:!0},":point_left:":{unicode:["1f448"],isCanonical:!0},":point_right:":{unicode:["1f449"],isCanonical:!0},":punch:":{unicode:["1f44a"],isCanonical:!0},":wave:":{unicode:["1f44b"],isCanonical:!0},":ok_hand:":{unicode:["1f44c"],isCanonical:!0},":thumbsup:":{unicode:["1f44d"],isCanonical:!0},":+1:":{unicode:["1f44d"],isCanonical:!1},":thumbup:":{unicode:["1f44d"],isCanonical:!1},":thumbsdown:":{unicode:["1f44e"],isCanonical:!0},":-1:":{unicode:["1f44e"],isCanonical:!1},":thumbdown:":{unicode:["1f44e"],isCanonical:!1},":clap:":{unicode:["1f44f"],isCanonical:!0},":open_hands:":{unicode:["1f450"],isCanonical:!0},":crown:":{unicode:["1f451"],isCanonical:!0},":womans_hat:":{unicode:["1f452"],isCanonical:!0},":eyeglasses:":{unicode:["1f453"],isCanonical:!0},":necktie:":{unicode:["1f454"],isCanonical:!0},":shirt:":{unicode:["1f455"],isCanonical:!0},":jeans:":{unicode:["1f456"],isCanonical:!0},":dress:":{unicode:["1f457"],isCanonical:!0},":kimono:":{unicode:["1f458"],isCanonical:!0},":bikini:":{unicode:["1f459"],isCanonical:!0},":womans_clothes:":{unicode:["1f45a"],isCanonical:!0},":purse:":{unicode:["1f45b"],isCanonical:!0},":handbag:":{unicode:["1f45c"],isCanonical:!0},":pouch:":{unicode:["1f45d"],isCanonical:!0},":mans_shoe:":{unicode:["1f45e"],isCanonical:!0},":athletic_shoe:":{unicode:["1f45f"],isCanonical:!0},":high_heel:":{unicode:["1f460"],isCanonical:!0},":sandal:":{unicode:["1f461"],isCanonical:!0},":boot:":{unicode:["1f462"],isCanonical:!0},":footprints:":{unicode:["1f463"],isCanonical:!0},":bust_in_silhouette:":{unicode:["1f464"],isCanonical:!0},":boy:":{unicode:["1f466"],isCanonical:!0},":girl:":{unicode:["1f467"],isCanonical:!0},":man:":{unicode:["1f468"],isCanonical:!0},":woman:":{unicode:["1f469"],isCanonical:!0},":family:":{unicode:["1f46a"],isCanonical:!0},":couple:":{unicode:["1f46b"],isCanonical:!0},":cop:":{unicode:["1f46e"],isCanonical:!0},":dancers:":{unicode:["1f46f"],isCanonical:!0},":bride_with_veil:":{unicode:["1f470"],isCanonical:!0},":person_with_blond_hair:":{unicode:["1f471"],isCanonical:!0},":man_with_gua_pi_mao:":{unicode:["1f472"],isCanonical:!0},":man_with_turban:":{unicode:["1f473"],isCanonical:!0},":older_man:":{unicode:["1f474"],isCanonical:!0},":older_woman:":{unicode:["1f475"],isCanonical:!0},":grandma:":{unicode:["1f475"],isCanonical:!1},":baby:":{unicode:["1f476"],isCanonical:!0},":construction_worker:":{unicode:["1f477"],isCanonical:!0},":princess:":{unicode:["1f478"],isCanonical:!0},":japanese_ogre:":{unicode:["1f479"],isCanonical:!0},":japanese_goblin:":{unicode:["1f47a"],isCanonical:!0},":ghost:":{unicode:["1f47b"],isCanonical:!0},":angel:":{unicode:["1f47c"],isCanonical:!0},":alien:":{unicode:["1f47d"],isCanonical:!0},":space_invader:":{unicode:["1f47e"],isCanonical:!0},":imp:":{unicode:["1f47f"],isCanonical:!0},":skull:":{unicode:["1f480"],isCanonical:!0},":skeleton:":{unicode:["1f480"],isCanonical:!1},":card_index:":{unicode:["1f4c7"],isCanonical:!0},":information_desk_person:":{unicode:["1f481"],isCanonical:!0},":guardsman:":{unicode:["1f482"],isCanonical:!0},":dancer:":{unicode:["1f483"],isCanonical:!0},":lipstick:":{unicode:["1f484"],isCanonical:!0},":nail_care:":{unicode:["1f485"],isCanonical:!0},":ledger:":{unicode:["1f4d2"],isCanonical:!0},":massage:":{unicode:["1f486"],isCanonical:!0},":notebook:":{unicode:["1f4d3"],isCanonical:!0},":haircut:":{unicode:["1f487"],isCanonical:!0},":notebook_with_decorative_cover:":{unicode:["1f4d4"],isCanonical:!0},":barber:":{unicode:["1f488"],isCanonical:!0},":closed_book:":{unicode:["1f4d5"],isCanonical:!0},":syringe:":{unicode:["1f489"],isCanonical:!0},":book:":{unicode:["1f4d6"],isCanonical:!0},":pill:":{unicode:["1f48a"],isCanonical:!0},":green_book:":{unicode:["1f4d7"],isCanonical:!0},":kiss:":{unicode:["1f48b"],isCanonical:!0},":blue_book:":{unicode:["1f4d8"],isCanonical:!0},":love_letter:":{unicode:["1f48c"],isCanonical:!0},":orange_book:":{unicode:["1f4d9"],isCanonical:!0},":ring:":{unicode:["1f48d"],isCanonical:!0},":books:":{unicode:["1f4da"],isCanonical:!0},":gem:":{unicode:["1f48e"],isCanonical:!0},":name_badge:":{unicode:["1f4db"],isCanonical:!0},":couplekiss:":{unicode:["1f48f"],isCanonical:!0},":scroll:":{unicode:["1f4dc"],isCanonical:!0},":bouquet:":{unicode:["1f490"],isCanonical:!0},":pencil:":{unicode:["1f4dd"],isCanonical:!0},":couple_with_heart:":{unicode:["1f491"],isCanonical:!0},":telephone_receiver:":{unicode:["1f4de"],isCanonical:!0},":wedding:":{unicode:["1f492"],isCanonical:!0},":pager:":{unicode:["1f4df"],isCanonical:!0},":fax:":{unicode:["1f4e0"],isCanonical:!0},":heartbeat:":{unicode:["1f493"],isCanonical:!0},":satellite:":{unicode:["1f4e1"],isCanonical:!0},":loudspeaker:":{unicode:["1f4e2"],isCanonical:!0},":broken_heart:":{unicode:["1f494"],isCanonical:!0},":mega:":{unicode:["1f4e3"],isCanonical:!0},":outbox_tray:":{unicode:["1f4e4"],isCanonical:!0},":two_hearts:":{unicode:["1f495"],isCanonical:!0},":inbox_tray:":{unicode:["1f4e5"],isCanonical:!0},":package:":{unicode:["1f4e6"],isCanonical:!0},":sparkling_heart:":{unicode:["1f496"],isCanonical:!0},":e-mail:":{unicode:["1f4e7"],isCanonical:!0},":email:":{unicode:["1f4e7"],isCanonical:!1},":incoming_envelope:":{unicode:["1f4e8"],isCanonical:!0},":heartpulse:":{unicode:["1f497"],isCanonical:!0},":envelope_with_arrow:":{unicode:["1f4e9"],isCanonical:!0},":mailbox_closed:":{unicode:["1f4ea"],isCanonical:!0},":cupid:":{unicode:["1f498"],isCanonical:!0},":mailbox:":{unicode:["1f4eb"],isCanonical:!0},":postbox:":{unicode:["1f4ee"],isCanonical:!0},":blue_heart:":{unicode:["1f499"],isCanonical:!0},":newspaper:":{unicode:["1f4f0"],isCanonical:!0},":iphone:":{unicode:["1f4f1"],isCanonical:!0},":green_heart:":{unicode:["1f49a"],isCanonical:!0},":calling:":{unicode:["1f4f2"],isCanonical:!0},":vibration_mode:":{unicode:["1f4f3"],isCanonical:!0},":yellow_heart:":{unicode:["1f49b"],isCanonical:!0},":mobile_phone_off:":{unicode:["1f4f4"],isCanonical:!0},":signal_strength:":{unicode:["1f4f6"],isCanonical:!0},":purple_heart:":{unicode:["1f49c"],isCanonical:!0},":camera:":{unicode:["1f4f7"],isCanonical:!0},":video_camera:":{unicode:["1f4f9"],isCanonical:!0},":gift_heart:":{unicode:["1f49d"],isCanonical:!0},":tv:":{unicode:["1f4fa"],isCanonical:!0},":radio:":{unicode:["1f4fb"],isCanonical:!0},":revolving_hearts:":{unicode:["1f49e"],isCanonical:!0},":vhs:":{unicode:["1f4fc"],isCanonical:!0},":arrows_clockwise:":{unicode:["1f503"],isCanonical:!0},":heart_decoration:":{unicode:["1f49f"],isCanonical:!0},":loud_sound:":{unicode:["1f50a"],isCanonical:!0},":battery:":{unicode:["1f50b"],isCanonical:!0},":diamond_shape_with_a_dot_inside:":{unicode:["1f4a0"],isCanonical:!0},":electric_plug:":{unicode:["1f50c"],isCanonical:!0},":mag:":{unicode:["1f50d"],isCanonical:!0},":bulb:":{unicode:["1f4a1"],isCanonical:!0},":mag_right:":{unicode:["1f50e"],isCanonical:!0},":lock_with_ink_pen:":{unicode:["1f50f"],isCanonical:!0},":anger:":{unicode:["1f4a2"],isCanonical:!0},":closed_lock_with_key:":{unicode:["1f510"],isCanonical:!0},":key:":{unicode:["1f511"],isCanonical:!0},":bomb:":{unicode:["1f4a3"],isCanonical:!0},":lock:":{unicode:["1f512"],isCanonical:!0},":unlock:":{unicode:["1f513"],isCanonical:!0},":zzz:":{unicode:["1f4a4"],isCanonical:!0},":bell:":{unicode:["1f514"],isCanonical:!0},":bookmark:":{unicode:["1f516"],isCanonical:!0},":boom:":{unicode:["1f4a5"],isCanonical:!0},":link:":{unicode:["1f517"],isCanonical:!0},":radio_button:":{unicode:["1f518"],isCanonical:!0},":sweat_drops:":{unicode:["1f4a6"],isCanonical:!0},":back:":{unicode:["1f519"],isCanonical:!0},":end:":{unicode:["1f51a"],isCanonical:!0},":droplet:":{unicode:["1f4a7"],isCanonical:!0},":on:":{unicode:["1f51b"],isCanonical:!0},":soon:":{unicode:["1f51c"],isCanonical:!0},":dash:":{unicode:["1f4a8"],isCanonical:!0},":top:":{unicode:["1f51d"],isCanonical:!0},":underage:":{unicode:["1f51e"],isCanonical:!0},":poop:":{unicode:["1f4a9"],isCanonical:!0},":shit:":{unicode:["1f4a9"],isCanonical:!1},":hankey:":{unicode:["1f4a9"],isCanonical:!1},":poo:":{unicode:["1f4a9"],isCanonical:!1},":keycap_ten:":{unicode:["1f51f"],isCanonical:!0},":muscle:":{unicode:["1f4aa"],isCanonical:!0},":capital_abcd:":{unicode:["1f520"],isCanonical:!0},":abcd:":{unicode:["1f521"],isCanonical:!0},":dizzy:":{unicode:["1f4ab"],isCanonical:!0},":1234:":{unicode:["1f522"],isCanonical:!0},":symbols:":{unicode:["1f523"],isCanonical:!0},":speech_balloon:":{unicode:["1f4ac"],isCanonical:!0},":abc:":{unicode:["1f524"],isCanonical:!0},":fire:":{unicode:["1f525"],isCanonical:!0},":flame:":{unicode:["1f525"],isCanonical:!1},":white_flower:":{unicode:["1f4ae"],isCanonical:!0},":flashlight:":{unicode:["1f526"],isCanonical:!0},":wrench:":{unicode:["1f527"],isCanonical:!0},":100:":{unicode:["1f4af"],isCanonical:!0},":hammer:":{unicode:["1f528"],isCanonical:!0},":nut_and_bolt:":{unicode:["1f529"],isCanonical:!0},":moneybag:":{unicode:["1f4b0"],isCanonical:!0},":knife:":{unicode:["1f52a"],isCanonical:!0},":gun:":{unicode:["1f52b"],isCanonical:!0},":currency_exchange:":{unicode:["1f4b1"],isCanonical:!0},":crystal_ball:":{unicode:["1f52e"],isCanonical:!0},":heavy_dollar_sign:":{unicode:["1f4b2"],isCanonical:!0},":six_pointed_star:":{unicode:["1f52f"],isCanonical:!0},":credit_card:":{unicode:["1f4b3"],isCanonical:!0},":beginner:":{unicode:["1f530"],isCanonical:!0},":trident:":{unicode:["1f531"],isCanonical:!0},":yen:":{unicode:["1f4b4"],isCanonical:!0},":black_square_button:":{unicode:["1f532"],isCanonical:!0},":white_square_button:":{unicode:["1f533"],isCanonical:!0},":dollar:":{unicode:["1f4b5"],isCanonical:!0},":red_circle:":{unicode:["1f534"],isCanonical:!0},":large_blue_circle:":{unicode:["1f535"],isCanonical:!0},":money_with_wings:":{unicode:["1f4b8"],isCanonical:!0},":large_orange_diamond:":{unicode:["1f536"],isCanonical:!0},":large_blue_diamond:":{unicode:["1f537"],isCanonical:!0},":chart:":{unicode:["1f4b9"],isCanonical:!0},":small_orange_diamond:":{unicode:["1f538"],isCanonical:!0},":small_blue_diamond:":{unicode:["1f539"],isCanonical:!0},":seat:":{unicode:["1f4ba"],isCanonical:!0},":small_red_triangle:":{unicode:["1f53a"],isCanonical:!0},":small_red_triangle_down:":{unicode:["1f53b"],isCanonical:!0},":computer:":{unicode:["1f4bb"],isCanonical:!0},":arrow_up_small:":{unicode:["1f53c"],isCanonical:!0},":briefcase:":{unicode:["1f4bc"],isCanonical:!0},":arrow_down_small:":{unicode:["1f53d"],isCanonical:!0},":clock1:":{unicode:["1f550"],isCanonical:!0},":minidisc:":{unicode:["1f4bd"],isCanonical:!0},":clock2:":{unicode:["1f551"],isCanonical:!0},":floppy_disk:":{unicode:["1f4be"],isCanonical:!0},":clock3:":{unicode:["1f552"],isCanonical:!0},":cd:":{unicode:["1f4bf"],isCanonical:!0},":clock4:":{unicode:["1f553"],isCanonical:!0},":dvd:":{unicode:["1f4c0"],isCanonical:!0},":clock5:":{unicode:["1f554"],isCanonical:!0},":clock6:":{unicode:["1f555"],isCanonical:!0},":file_folder:":{unicode:["1f4c1"],isCanonical:!0},":clock7:":{unicode:["1f556"],isCanonical:!0},":clock8:":{unicode:["1f557"],isCanonical:!0},":open_file_folder:":{unicode:["1f4c2"],isCanonical:!0},":clock9:":{unicode:["1f558"],isCanonical:!0},":clock10:":{unicode:["1f559"],isCanonical:!0},":page_with_curl:":{unicode:["1f4c3"],isCanonical:!0},":clock11:":{unicode:["1f55a"],isCanonical:!0},":clock12:":{unicode:["1f55b"],isCanonical:!0},":page_facing_up:":{unicode:["1f4c4"],isCanonical:!0},":mount_fuji:":{unicode:["1f5fb"],isCanonical:!0},":tokyo_tower:":{unicode:["1f5fc"],isCanonical:!0},":date:":{unicode:["1f4c5"],isCanonical:!0},":statue_of_liberty:":{unicode:["1f5fd"],isCanonical:!0},":japan:":{unicode:["1f5fe"],isCanonical:!0},":calendar:":{unicode:["1f4c6"],isCanonical:!0},":moyai:":{unicode:["1f5ff"],isCanonical:!0},":grin:":{unicode:["1f601"],isCanonical:!0},":joy:":{unicode:["1f602"],isCanonical:!0},":smiley:":{unicode:["1f603"],isCanonical:!0},":chart_with_upwards_trend:":{unicode:["1f4c8"],isCanonical:!0},":smile:":{unicode:["1f604"],isCanonical:!0},":sweat_smile:":{unicode:["1f605"],isCanonical:!0},":chart_with_downwards_trend:":{unicode:["1f4c9"],isCanonical:!0},":laughing:":{unicode:["1f606"],isCanonical:!0},":satisfied:":{unicode:["1f606"],isCanonical:!1},":wink:":{unicode:["1f609"],isCanonical:!0},":bar_chart:":{unicode:["1f4ca"],isCanonical:!0},":blush:":{unicode:["1f60a"],isCanonical:!0},":yum:":{unicode:["1f60b"],isCanonical:!0},":clipboard:":{unicode:["1f4cb"],isCanonical:!0},":relieved:":{unicode:["1f60c"],isCanonical:!0},":heart_eyes:":{unicode:["1f60d"],isCanonical:!0},":pushpin:":{unicode:["1f4cc"],isCanonical:!0},":smirk:":{unicode:["1f60f"],isCanonical:!0},":unamused:":{unicode:["1f612"],isCanonical:!0},":round_pushpin:":{unicode:["1f4cd"],isCanonical:!0},":sweat:":{unicode:["1f613"],isCanonical:!0},":pensive:":{unicode:["1f614"],isCanonical:!0},":paperclip:":{unicode:["1f4ce"],isCanonical:!0},":confounded:":{unicode:["1f616"],isCanonical:!0},":kissing_heart:":{unicode:["1f618"],isCanonical:!0},":straight_ruler:":{unicode:["1f4cf"],isCanonical:!0},":kissing_closed_eyes:":{unicode:["1f61a"],isCanonical:!0},":stuck_out_tongue_winking_eye:":{unicode:["1f61c"],isCanonical:!0},":triangular_ruler:":{unicode:["1f4d0"],isCanonical:!0},":stuck_out_tongue_closed_eyes:":{unicode:["1f61d"],isCanonical:!0},":disappointed:":{unicode:["1f61e"],isCanonical:!0},":bookmark_tabs:":{unicode:["1f4d1"],isCanonical:!0},":angry:":{unicode:["1f620"],isCanonical:!0},":rage:":{unicode:["1f621"],isCanonical:!0},":cry:":{unicode:["1f622"],isCanonical:!0},":persevere:":{unicode:["1f623"],isCanonical:!0},":triumph:":{unicode:["1f624"],isCanonical:!0},":disappointed_relieved:":{unicode:["1f625"],isCanonical:!0},":fearful:":{unicode:["1f628"],isCanonical:!0},":weary:":{unicode:["1f629"],isCanonical:!0},":sleepy:":{unicode:["1f62a"],isCanonical:!0},":tired_face:":{unicode:["1f62b"],isCanonical:!0},":sob:":{unicode:["1f62d"],isCanonical:!0},":cold_sweat:":{unicode:["1f630"],isCanonical:!0},":scream:":{unicode:["1f631"],isCanonical:!0},":astonished:":{unicode:["1f632"],isCanonical:!0},":flushed:":{unicode:["1f633"],isCanonical:!0},":dizzy_face:":{unicode:["1f635"],isCanonical:!0},":mask:":{unicode:["1f637"],isCanonical:!0},":smile_cat:":{unicode:["1f638"],isCanonical:!0},":joy_cat:":{unicode:["1f639"],isCanonical:!0},":smiley_cat:":{unicode:["1f63a"],isCanonical:!0},":heart_eyes_cat:":{unicode:["1f63b"],isCanonical:!0},":smirk_cat:":{unicode:["1f63c"],isCanonical:!0},":kissing_cat:":{unicode:["1f63d"],isCanonical:!0},":pouting_cat:":{unicode:["1f63e"],isCanonical:!0},":crying_cat_face:":{unicode:["1f63f"],isCanonical:!0},":scream_cat:":{unicode:["1f640"],isCanonical:!0},":no_good:":{unicode:["1f645"],isCanonical:!0},":ok_woman:":{unicode:["1f646"],isCanonical:!0},":bow:":{unicode:["1f647"],isCanonical:!0},":see_no_evil:":{unicode:["1f648"],isCanonical:!0},":hear_no_evil:":{unicode:["1f649"],isCanonical:!0},":speak_no_evil:":{unicode:["1f64a"],isCanonical:!0},":raising_hand:":{unicode:["1f64b"],isCanonical:!0},":raised_hands:":{unicode:["1f64c"],isCanonical:!0},":person_frowning:":{unicode:["1f64d"],isCanonical:!0},":person_with_pouting_face:":{unicode:["1f64e"],isCanonical:!0},":pray:":{unicode:["1f64f"],isCanonical:!0},":rocket:":{unicode:["1f680"],isCanonical:!0},":railway_car:":{unicode:["1f683"],isCanonical:!0},":bullettrain_side:":{unicode:["1f684"],isCanonical:!0},":bullettrain_front:":{unicode:["1f685"],isCanonical:!0},":metro:":{unicode:["1f687"],isCanonical:!0},":station:":{unicode:["1f689"],isCanonical:!0},":bus:":{unicode:["1f68c"],isCanonical:!0},":busstop:":{unicode:["1f68f"],isCanonical:!0},":ambulance:":{unicode:["1f691"],isCanonical:!0},":fire_engine:":{unicode:["1f692"],isCanonical:!0},":police_car:":{unicode:["1f693"],isCanonical:!0},":taxi:":{unicode:["1f695"],isCanonical:!0},":red_car:":{unicode:["1f697"],isCanonical:!0},":blue_car:":{unicode:["1f699"],isCanonical:!0},":truck:":{unicode:["1f69a"],isCanonical:!0},":ship:":{unicode:["1f6a2"],isCanonical:!0},":speedboat:":{unicode:["1f6a4"],isCanonical:!0},":traffic_light:":{unicode:["1f6a5"],isCanonical:!0},":construction:":{unicode:["1f6a7"],isCanonical:!0},":rotating_light:":{unicode:["1f6a8"],isCanonical:!0},":triangular_flag_on_post:":{unicode:["1f6a9"],isCanonical:!0},":door:":{unicode:["1f6aa"],isCanonical:!0},":no_entry_sign:":{unicode:["1f6ab"],isCanonical:!0},":smoking:":{unicode:["1f6ac"],isCanonical:!0},":no_smoking:":{unicode:["1f6ad"],isCanonical:!0},":bike:":{unicode:["1f6b2"],isCanonical:!0},":walking:":{unicode:["1f6b6"],isCanonical:!0},":mens:":{unicode:["1f6b9"],isCanonical:!0},":womens:":{unicode:["1f6ba"],isCanonical:!0},":restroom:":{unicode:["1f6bb"],isCanonical:!0},":baby_symbol:":{unicode:["1f6bc"],isCanonical:!0},":toilet:":{unicode:["1f6bd"],isCanonical:!0},":wc:":{unicode:["1f6be"],isCanonical:!0},":bath:":{unicode:["1f6c0"],isCanonical:!0},":metal:":{unicode:["1f918"],isCanonical:!0},":sign_of_the_horns:":{unicode:["1f918"],isCanonical:!1},":grinning:":{unicode:["1f600"],isCanonical:!0},":innocent:":{unicode:["1f607"],isCanonical:!0},":smiling_imp:":{unicode:["1f608"],isCanonical:!0},":sunglasses:":{unicode:["1f60e"],isCanonical:!0},":neutral_face:":{unicode:["1f610"],isCanonical:!0},":expressionless:":{unicode:["1f611"],isCanonical:!0},":confused:":{unicode:["1f615"],isCanonical:!0},":kissing:":{unicode:["1f617"],isCanonical:!0},":kissing_smiling_eyes:":{unicode:["1f619"],isCanonical:!0},":stuck_out_tongue:":{unicode:["1f61b"],isCanonical:!0},":worried:":{unicode:["1f61f"],isCanonical:!0},":frowning:":{unicode:["1f626"],isCanonical:!0},":anguished:":{unicode:["1f627"],isCanonical:!0},":grimacing:":{unicode:["1f62c"],isCanonical:!0},":open_mouth:":{unicode:["1f62e"],isCanonical:!0},":hushed:":{unicode:["1f62f"],isCanonical:!0},":sleeping:":{unicode:["1f634"],isCanonical:!0},":no_mouth:":{unicode:["1f636"],isCanonical:!0},":helicopter:":{unicode:["1f681"],isCanonical:!0},":steam_locomotive:":{unicode:["1f682"],isCanonical:!0},":train2:":{unicode:["1f686"],isCanonical:!0},":light_rail:":{unicode:["1f688"],isCanonical:!0},":tram:":{unicode:["1f68a"],isCanonical:!0},":oncoming_bus:":{unicode:["1f68d"],isCanonical:!0},":trolleybus:":{unicode:["1f68e"],isCanonical:!0},":minibus:":{unicode:["1f690"],isCanonical:!0},":oncoming_police_car:":{unicode:["1f694"],isCanonical:!0},":oncoming_taxi:":{unicode:["1f696"],isCanonical:!0},":oncoming_automobile:":{unicode:["1f698"],isCanonical:!0},":articulated_lorry:":{unicode:["1f69b"],isCanonical:!0},":tractor:":{unicode:["1f69c"],isCanonical:!0},":monorail:":{unicode:["1f69d"],isCanonical:!0},":mountain_railway:":{unicode:["1f69e"],isCanonical:!0},":suspension_railway:":{unicode:["1f69f"],isCanonical:!0},":mountain_cableway:":{unicode:["1f6a0"],isCanonical:!0},":aerial_tramway:":{unicode:["1f6a1"],isCanonical:!0},":rowboat:":{unicode:["1f6a3"],isCanonical:!0},":vertical_traffic_light:":{unicode:["1f6a6"],isCanonical:!0},":put_litter_in_its_place:":{unicode:["1f6ae"],isCanonical:!0},":do_not_litter:":{unicode:["1f6af"],isCanonical:!0},":potable_water:":{unicode:["1f6b0"],isCanonical:!0},":non-potable_water:":{unicode:["1f6b1"],isCanonical:!0},":no_bicycles:":{unicode:["1f6b3"],isCanonical:!0},":bicyclist:":{unicode:["1f6b4"],isCanonical:!0},":mountain_bicyclist:":{unicode:["1f6b5"],isCanonical:!0},":no_pedestrians:":{unicode:["1f6b7"],isCanonical:!0},":children_crossing:":{unicode:["1f6b8"],isCanonical:!0},":shower:":{unicode:["1f6bf"],isCanonical:!0},":bathtub:":{unicode:["1f6c1"],isCanonical:!0},":passport_control:":{unicode:["1f6c2"],isCanonical:!0},":customs:":{unicode:["1f6c3"],isCanonical:!0},":baggage_claim:":{unicode:["1f6c4"],isCanonical:!0},":left_luggage:":{unicode:["1f6c5"],isCanonical:!0},":earth_africa:":{unicode:["1f30d"],isCanonical:!0},":earth_americas:":{unicode:["1f30e"],isCanonical:!0},":globe_with_meridians:":{unicode:["1f310"],isCanonical:!0},":waxing_crescent_moon:":{unicode:["1f312"],isCanonical:!0},":waning_gibbous_moon:":{unicode:["1f316"],isCanonical:!0},":last_quarter_moon:":{unicode:["1f317"],isCanonical:!0},":waning_crescent_moon:":{unicode:["1f318"],isCanonical:!0},":new_moon_with_face:":{unicode:["1f31a"],isCanonical:!0},":last_quarter_moon_with_face:":{unicode:["1f31c"],isCanonical:!0},":full_moon_with_face:":{unicode:["1f31d"],isCanonical:!0},":sun_with_face:":{unicode:["1f31e"],isCanonical:!0},":evergreen_tree:":{unicode:["1f332"],isCanonical:!0},":deciduous_tree:":{unicode:["1f333"],isCanonical:!0},":lemon:":{unicode:["1f34b"],isCanonical:!0},":pear:":{unicode:["1f350"],isCanonical:!0},":baby_bottle:":{unicode:["1f37c"],isCanonical:!0},":horse_racing:":{unicode:["1f3c7"],isCanonical:!0},":rugby_football:":{unicode:["1f3c9"],isCanonical:!0},":european_post_office:":{unicode:["1f3e4"],isCanonical:!0},":rat:":{unicode:["1f400"],isCanonical:!0},":mouse2:":{unicode:["1f401"],isCanonical:!0},":ox:":{unicode:["1f402"],isCanonical:!0},":water_buffalo:":{unicode:["1f403"],isCanonical:!0},":cow2:":{unicode:["1f404"],isCanonical:!0},":tiger2:":{unicode:["1f405"],isCanonical:!0},":leopard:":{unicode:["1f406"],isCanonical:!0},":rabbit2:":{unicode:["1f407"],isCanonical:!0},":cat2:":{unicode:["1f408"],isCanonical:!0},":dragon:":{unicode:["1f409"],isCanonical:!0},":crocodile:":{unicode:["1f40a"],isCanonical:!0},":whale2:":{unicode:["1f40b"],isCanonical:!0},":ram:":{unicode:["1f40f"],isCanonical:!0},":goat:":{unicode:["1f410"],isCanonical:!0},":rooster:":{unicode:["1f413"],isCanonical:!0},":dog2:":{unicode:["1f415"],isCanonical:!0},":pig2:":{unicode:["1f416"],isCanonical:!0},":dromedary_camel:":{unicode:["1f42a"],isCanonical:!0},":busts_in_silhouette:":{unicode:["1f465"],isCanonical:!0},":two_men_holding_hands:":{unicode:["1f46c"],isCanonical:!0},":two_women_holding_hands:":{unicode:["1f46d"],isCanonical:!0},":thought_balloon:":{unicode:["1f4ad"],isCanonical:!0},":euro:":{unicode:["1f4b6"],isCanonical:!0},":pound:":{unicode:["1f4b7"],isCanonical:!0},":mailbox_with_mail:":{unicode:["1f4ec"],isCanonical:!0},":mailbox_with_no_mail:":{unicode:["1f4ed"],isCanonical:!0},":postal_horn:":{unicode:["1f4ef"],isCanonical:!0},":no_mobile_phones:":{unicode:["1f4f5"],isCanonical:!0},":twisted_rightwards_arrows:":{unicode:["1f500"],isCanonical:!0},":repeat:":{unicode:["1f501"],isCanonical:!0},":repeat_one:":{unicode:["1f502"],isCanonical:!0},":arrows_counterclockwise:":{unicode:["1f504"],isCanonical:!0},":low_brightness:":{unicode:["1f505"],isCanonical:!0},":high_brightness:":{unicode:["1f506"],isCanonical:!0},":mute:":{unicode:["1f507"],isCanonical:!0},":sound:":{unicode:["1f509"],isCanonical:!0},":no_bell:":{unicode:["1f515"],isCanonical:!0},":microscope:":{unicode:["1f52c"],isCanonical:!0},":telescope:":{unicode:["1f52d"],isCanonical:!0},":clock130:":{unicode:["1f55c"],isCanonical:!0},":clock230:":{unicode:["1f55d"],isCanonical:!0},":clock330:":{unicode:["1f55e"],isCanonical:!0},":clock430:":{unicode:["1f55f"],isCanonical:!0},":clock530:":{unicode:["1f560"],isCanonical:!0},":clock630:":{unicode:["1f561"],isCanonical:!0},":clock730:":{unicode:["1f562"],isCanonical:!0},":clock830:":{unicode:["1f563"],isCanonical:!0},":clock930:":{unicode:["1f564"],isCanonical:!0},":clock1030:":{unicode:["1f565"],isCanonical:!0},":clock1130:":{unicode:["1f566"],isCanonical:!0},":clock1230:":{unicode:["1f567"],isCanonical:!0},":speaker:":{unicode:["1f508"],isCanonical:!0},":train:":{unicode:["1f68b"],isCanonical:!0},":medal:":{unicode:["1f3c5"],isCanonical:!0},":sports_medal:":{unicode:["1f3c5"],isCanonical:!1},":flag_black:":{unicode:["1f3f4"],isCanonical:!0},":waving_black_flag:":{unicode:["1f3f4"],isCanonical:!1},":camera_with_flash:":{unicode:["1f4f8"],isCanonical:!0},":sleeping_accommodation:":{unicode:["1f6cc"],isCanonical:!0},":middle_finger:":{unicode:["1f595"],isCanonical:!0},":reversed_hand_with_middle_finger_extended:":{unicode:["1f595"],isCanonical:!1},":vulcan:":{unicode:["1f596"],isCanonical:!0},":raised_hand_with_part_between_middle_and_ring_fingers:":{unicode:["1f596"],isCanonical:!1},":slight_frown:":{unicode:["1f641"],isCanonical:!0},":slightly_frowning_face:":{unicode:["1f641"],isCanonical:!1},":slight_smile:":{unicode:["1f642"],isCanonical:!0},":slightly_smiling_face:":{unicode:["1f642"],isCanonical:!1},":airplane_departure:":{unicode:["1f6eb"],isCanonical:!0},":airplane_arriving:":{unicode:["1f6ec"],isCanonical:!0},":tone1:":{unicode:["1f3fb"],isCanonical:!0},":tone2:":{unicode:["1f3fc"],isCanonical:!0},":tone3:":{unicode:["1f3fd"],isCanonical:!0},":tone4:":{unicode:["1f3fe"],isCanonical:!0},":tone5:":{unicode:["1f3ff"],isCanonical:!0},":upside_down:":{unicode:["1f643"],isCanonical:!0},":upside_down_face:":{unicode:["1f643"],isCanonical:!1},":money_mouth:":{unicode:["1f911"],isCanonical:!0},":money_mouth_face:":{unicode:["1f911"],isCanonical:!1},":nerd:":{unicode:["1f913"],isCanonical:!0},":nerd_face:":{unicode:["1f913"],isCanonical:!1},":hugging:":{unicode:["1f917"],isCanonical:!0},":hugging_face:":{unicode:["1f917"],isCanonical:!1},":rolling_eyes:":{unicode:["1f644"],isCanonical:!0},":face_with_rolling_eyes:":{unicode:["1f644"],isCanonical:!1},":thinking:":{unicode:["1f914"],isCanonical:!0},":thinking_face:":{unicode:["1f914"],isCanonical:!1},":zipper_mouth:":{unicode:["1f910"],isCanonical:!0},":zipper_mouth_face:":{unicode:["1f910"],isCanonical:!1},":thermometer_face:":{unicode:["1f912"],isCanonical:!0},":face_with_thermometer:":{unicode:["1f912"],isCanonical:!1},":head_bandage:":{unicode:["1f915"],isCanonical:!0},":face_with_head_bandage:":{unicode:["1f915"],isCanonical:!1},":robot:":{unicode:["1f916"],isCanonical:!0},":robot_face:":{unicode:["1f916"],isCanonical:!1},":lion_face:":{unicode:["1f981"],isCanonical:!0},":lion:":{unicode:["1f981"],isCanonical:!1},":unicorn:":{unicode:["1f984"],isCanonical:!0},":unicorn_face:":{unicode:["1f984"],isCanonical:!1},":scorpion:":{unicode:["1f982"],isCanonical:!0},":crab:":{unicode:["1f980"],isCanonical:!0},":turkey:":{unicode:["1f983"],isCanonical:!0},":cheese:":{unicode:["1f9c0"],isCanonical:!0},":cheese_wedge:":{unicode:["1f9c0"],isCanonical:!1},":hotdog:":{unicode:["1f32d"],isCanonical:!0},":hot_dog:":{unicode:["1f32d"],isCanonical:!1},":taco:":{unicode:["1f32e"],isCanonical:!0},":burrito:":{unicode:["1f32f"],isCanonical:!0},":popcorn:":{unicode:["1f37f"],isCanonical:!0},":champagne:":{unicode:["1f37e"],isCanonical:!0},":bottle_with_popping_cork:":{unicode:["1f37e"],isCanonical:!1},":bow_and_arrow:":{unicode:["1f3f9"],isCanonical:!0},":archery:":{unicode:["1f3f9"],isCanonical:!1},":amphora:":{unicode:["1f3fa"],isCanonical:!0},":place_of_worship:":{unicode:["1f6d0"],isCanonical:!0},":worship_symbol:":{unicode:["1f6d0"],isCanonical:!1},":kaaba:":{unicode:["1f54b"],isCanonical:!0},":mosque:":{unicode:["1f54c"],isCanonical:!0},":synagogue:":{unicode:["1f54d"],isCanonical:!0},":menorah:":{unicode:["1f54e"],isCanonical:!0},":prayer_beads:":{unicode:["1f4ff"],isCanonical:!0},":cricket:":{unicode:["1f3cf"],isCanonical:!0},":cricket_bat_ball:":{ +unicode:["1f3cf"],isCanonical:!1},":volleyball:":{unicode:["1f3d0"],isCanonical:!0},":field_hockey:":{unicode:["1f3d1"],isCanonical:!0},":hockey:":{unicode:["1f3d2"],isCanonical:!0},":ping_pong:":{unicode:["1f3d3"],isCanonical:!0},":table_tennis:":{unicode:["1f3d3"],isCanonical:!1},":badminton:":{unicode:["1f3f8"],isCanonical:!0},":drum:":{unicode:["1f941"],isCanonical:!0},":drum_with_drumsticks:":{unicode:["1f941"],isCanonical:!1},":shrimp:":{unicode:["1f990"],isCanonical:!0},":squid:":{unicode:["1f991"],isCanonical:!0},":egg:":{unicode:["1f95a"],isCanonical:!0},":milk:":{unicode:["1f95b"],isCanonical:!0},":glass_of_milk:":{unicode:["1f95b"],isCanonical:!1},":peanuts:":{unicode:["1f95c"],isCanonical:!0},":shelled_peanut:":{unicode:["1f95c"],isCanonical:!1},":kiwi:":{unicode:["1f95d"],isCanonical:!0},":kiwifruit:":{unicode:["1f95d"],isCanonical:!1},":pancakes:":{unicode:["1f95e"],isCanonical:!0},":regional_indicator_w:":{unicode:["1f1fc"],isCanonical:!0},":regional_indicator_v:":{unicode:["1f1fb"],isCanonical:!0},":regional_indicator_u:":{unicode:["1f1fa"],isCanonical:!0},":regional_indicator_t:":{unicode:["1f1f9"],isCanonical:!0},":regional_indicator_s:":{unicode:["1f1f8"],isCanonical:!0},":regional_indicator_r:":{unicode:["1f1f7"],isCanonical:!0},":regional_indicator_q:":{unicode:["1f1f6"],isCanonical:!0},":regional_indicator_p:":{unicode:["1f1f5"],isCanonical:!0},":regional_indicator_o:":{unicode:["1f1f4"],isCanonical:!0},":regional_indicator_n:":{unicode:["1f1f3"],isCanonical:!0},":regional_indicator_m:":{unicode:["1f1f2"],isCanonical:!0},":regional_indicator_l:":{unicode:["1f1f1"],isCanonical:!0},":regional_indicator_k:":{unicode:["1f1f0"],isCanonical:!0},":regional_indicator_j:":{unicode:["1f1ef"],isCanonical:!0},":regional_indicator_i:":{unicode:["1f1ee"],isCanonical:!0},":regional_indicator_h:":{unicode:["1f1ed"],isCanonical:!0},":regional_indicator_g:":{unicode:["1f1ec"],isCanonical:!0},":regional_indicator_f:":{unicode:["1f1eb"],isCanonical:!0},":regional_indicator_e:":{unicode:["1f1ea"],isCanonical:!0},":regional_indicator_d:":{unicode:["1f1e9"],isCanonical:!0},":regional_indicator_c:":{unicode:["1f1e8"],isCanonical:!0},":regional_indicator_b:":{unicode:["1f1e7"],isCanonical:!0},":regional_indicator_a:":{unicode:["1f1e6"],isCanonical:!0},":fast_forward:":{unicode:["23e9"],isCanonical:!0},":rewind:":{unicode:["23ea"],isCanonical:!0},":arrow_double_up:":{unicode:["23eb"],isCanonical:!0},":arrow_double_down:":{unicode:["23ec"],isCanonical:!0},":alarm_clock:":{unicode:["23f0"],isCanonical:!0},":hourglass_flowing_sand:":{unicode:["23f3"],isCanonical:!0},":ophiuchus:":{unicode:["26ce"],isCanonical:!0},":white_check_mark:":{unicode:["2705"],isCanonical:!0},":fist:":{unicode:["270a"],isCanonical:!0},":raised_hand:":{unicode:["270b"],isCanonical:!0},":sparkles:":{unicode:["2728"],isCanonical:!0},":x:":{unicode:["274c"],isCanonical:!0},":negative_squared_cross_mark:":{unicode:["274e"],isCanonical:!0},":question:":{unicode:["2753"],isCanonical:!0},":grey_question:":{unicode:["2754"],isCanonical:!0},":grey_exclamation:":{unicode:["2755"],isCanonical:!0},":heavy_plus_sign:":{unicode:["2795"],isCanonical:!0},":heavy_minus_sign:":{unicode:["2796"],isCanonical:!0},":heavy_division_sign:":{unicode:["2797"],isCanonical:!0},":curly_loop:":{unicode:["27b0"],isCanonical:!0},":loop:":{unicode:["27bf"],isCanonical:!0}};var b,c=[];for(b in a.emojioneList)a.emojioneList.hasOwnProperty(b)&&c.push(b.replace(/[+]/g,"\\$&"));a.shortnames=c.join("|"),a.asciiList={"<3":"2764",":)":"1f606",">;)":"1f606",">:-)":"1f606",">=)":"1f606",";)":"1f609",";-)":"1f609","*-)":"1f609","*)":"1f609",";-]":"1f609",";]":"1f609",";D":"1f609",";^)":"1f609","':(":"1f613","':-(":"1f613","'=(":"1f613",":*":"1f618",":-*":"1f618","=*":"1f618",":^*":"1f618",">:P":"1f61c","X-P":"1f61c","x-p":"1f61c",">:[":"1f61e",":-(":"1f61e",":(":"1f61e",":-[":"1f61e",":[":"1f61e","=(":"1f61e",">:(":"1f620",">:-(":"1f620",":@":"1f620",":'(":"1f622",":'-(":"1f622",";(":"1f622",";-(":"1f622",">.<":"1f623","D:":"1f628",":$":"1f633","=$":"1f633","#-)":"1f635","#)":"1f635","%-)":"1f635","%)":"1f635","X)":"1f635","X-)":"1f635","*\\0/*":"1f646","\\0/":"1f646","*\\O/*":"1f646","\\O/":"1f646","O:-)":"1f607","0:-3":"1f607","0:3":"1f607","0:-)":"1f607","0:)":"1f607","0;^)":"1f607","O:)":"1f607","O;-)":"1f607","O=)":"1f607","0;-)":"1f607","O:-3":"1f607","O:3":"1f607","B-)":"1f60e","B)":"1f60e","8)":"1f60e","8-)":"1f60e","B-D":"1f60e","8-D":"1f60e","-_-":"1f611","-__-":"1f611","-___-":"1f611",">:\\":"1f615",">:/":"1f615",":-/":"1f615",":-.":"1f615",":/":"1f615",":\\":"1f615","=/":"1f615","=\\":"1f615",":L":"1f615","=L":"1f615",":P":"1f61b",":-P":"1f61b","=P":"1f61b",":-p":"1f61b",":p":"1f61b","=p":"1f61b",":-Þ":"1f61b",":Þ":"1f61b",":þ":"1f61b",":-þ":"1f61b",":-b":"1f61b",":b":"1f61b","d:":"1f61b",":-O":"1f62e",":O":"1f62e",":-o":"1f62e",":o":"1f62e",O_O:"1f62e",">:O":"1f62e",":-X":"1f636",":X":"1f636",":-#":"1f636",":#":"1f636","=X":"1f636","=x":"1f636",":x":"1f636",":-x":"1f636","=#":"1f636"},a.asciiRegexp="(\\<3|<3|\\<\\/3|<\\/3|\\:'\\)|\\:'\\-\\)|\\:D|\\:\\-D|\\=D|\\:\\)|\\:\\-\\)|\\=\\]|\\=\\)|\\:\\]|'\\:\\)|'\\:\\-\\)|'\\=\\)|'\\:D|'\\:\\-D|'\\=D|\\>\\:\\)|>\\:\\)|\\>;\\)|>;\\)|\\>\\:\\-\\)|>\\:\\-\\)|\\>\\=\\)|>\\=\\)|;\\)|;\\-\\)|\\*\\-\\)|\\*\\)|;\\-\\]|;\\]|;D|;\\^\\)|'\\:\\(|'\\:\\-\\(|'\\=\\(|\\:\\*|\\:\\-\\*|\\=\\*|\\:\\^\\*|\\>\\:P|>\\:P|X\\-P|x\\-p|\\>\\:\\[|>\\:\\[|\\:\\-\\(|\\:\\(|\\:\\-\\[|\\:\\[|\\=\\(|\\>\\:\\(|>\\:\\(|\\>\\:\\-\\(|>\\:\\-\\(|\\:@|\\:'\\(|\\:'\\-\\(|;\\(|;\\-\\(|\\>\\.\\<|>\\.<|D\\:|\\:\\$|\\=\\$|#\\-\\)|#\\)|%\\-\\)|%\\)|X\\)|X\\-\\)|\\*\\\\0\\/\\*|\\\\0\\/|\\*\\\\O\\/\\*|\\\\O\\/|O\\:\\-\\)|0\\:\\-3|0\\:3|0\\:\\-\\)|0\\:\\)|0;\\^\\)|O\\:\\-\\)|O\\:\\)|O;\\-\\)|O\\=\\)|0;\\-\\)|O\\:\\-3|O\\:3|B\\-\\)|B\\)|8\\)|8\\-\\)|B\\-D|8\\-D|\\-_\\-|\\-__\\-|\\-___\\-|\\>\\:\\\\|>\\:\\\\|\\>\\:\\/|>\\:\\/|\\:\\-\\/|\\:\\-\\.|\\:\\/|\\:\\\\|\\=\\/|\\=\\\\|\\:L|\\=L|\\:P|\\:\\-P|\\=P|\\:\\-p|\\:p|\\=p|\\:\\-Þ|\\:\\-Þ|\\:Þ|\\:Þ|\\:þ|\\:þ|\\:\\-þ|\\:\\-þ|\\:\\-b|\\:b|d\\:|\\:\\-O|\\:O|\\:\\-o|\\:o|O_O|\\>\\:O|>\\:O|\\:\\-X|\\:X|\\:\\-#|\\:#|\\=X|\\=x|\\:x|\\:\\-x|\\=#)",a.unicodeRegexp="(\\uD83D\\uDC69\\u200D\\u2764\\uFE0F\\u200D\\uD83D\\uDC8B\\u200D\\uD83D\\uDC69|\\uD83D\\uDC68\\u200D\\u2764\\uFE0F\\u200D\\uD83D\\uDC8B\\u200D\\uD83D\\uDC68|\\uD83D\\uDC68\\u200D\\uD83D\\uDC68\\u200D\\uD83D\\uDC67\\u200D\\uD83D\\uDC66|\\uD83D\\uDC68\\u200D\\uD83D\\uDC68\\u200D\\uD83D\\uDC67\\u200D\\uD83D\\uDC67|\\uD83D\\uDC68\\u200D\\uD83D\\uDC69\\u200D\\uD83D\\uDC66\\u200D\\uD83D\\uDC66|\\uD83D\\uDC68\\u200D\\uD83D\\uDC69\\u200D\\uD83D\\uDC67\\u200D\\uD83D\\uDC66|\\uD83D\\uDC68\\u200D\\uD83D\\uDC69\\u200D\\uD83D\\uDC67\\u200D\\uD83D\\uDC67|\\uD83D\\uDC69\\u200D\\uD83D\\uDC69\\u200D\\uD83D\\uDC66\\u200D\\uD83D\\uDC66|\\uD83D\\uDC69\\u200D\\uD83D\\uDC69\\u200D\\uD83D\\uDC67\\u200D\\uD83D\\uDC66|\\uD83D\\uDC69\\u200D\\uD83D\\uDC69\\u200D\\uD83D\\uDC67\\u200D\\uD83D\\uDC67|\\uD83D\\uDC68\\u200D\\uD83D\\uDC68\\u200D\\uD83D\\uDC66\\u200D\\uD83D\\uDC66|\\uD83D\\uDC68\\u200D\\u2764\\uFE0F\\u200D\\uD83D\\uDC68|\\uD83D\\uDC68\\u200D\\uD83D\\uDC68\\u200D\\uD83D\\uDC67|\\uD83D\\uDC68\\u200D\\uD83D\\uDC69\\u200D\\uD83D\\uDC67|\\uD83D\\uDC69\\u200D\\uD83D\\uDC69\\u200D\\uD83D\\uDC66|\\uD83D\\uDC69\\u200D\\uD83D\\uDC69\\u200D\\uD83D\\uDC67|\\uD83D\\uDC69\\u200D\\u2764\\uFE0F\\u200D\\uD83D\\uDC69|\\uD83D\\uDC68\\u200D\\uD83D\\uDC68\\u200D\\uD83D\\uDC66|\\uD83D\\uDC41\\u200D\\uD83D\\uDDE8|\\uD83C\\uDDE6\\uD83C\\uDDE9|\\uD83C\\uDDE6\\uD83C\\uDDEA|\\uD83C\\uDDE6\\uD83C\\uDDEB|\\uD83C\\uDDE6\\uD83C\\uDDEC|\\uD83C\\uDDE6\\uD83C\\uDDEE|\\uD83C\\uDDE6\\uD83C\\uDDF1|\\uD83C\\uDDE6\\uD83C\\uDDF2|\\uD83C\\uDDE6\\uD83C\\uDDF4|\\uD83C\\uDDE6\\uD83C\\uDDF6|\\uD83C\\uDDE6\\uD83C\\uDDF7|\\uD83C\\uDDE6\\uD83C\\uDDF8|\\uD83E\\uDD18\\uD83C\\uDFFF|\\uD83E\\uDD18\\uD83C\\uDFFE|\\uD83E\\uDD18\\uD83C\\uDFFD|\\uD83E\\uDD18\\uD83C\\uDFFC|\\uD83E\\uDD18\\uD83C\\uDFFB|\\uD83D\\uDEC0\\uD83C\\uDFFF|\\uD83D\\uDEC0\\uD83C\\uDFFE|\\uD83D\\uDEC0\\uD83C\\uDFFD|\\uD83D\\uDEC0\\uD83C\\uDFFC|\\uD83D\\uDEC0\\uD83C\\uDFFB|\\uD83D\\uDEB6\\uD83C\\uDFFF|\\uD83D\\uDEB6\\uD83C\\uDFFE|\\uD83D\\uDEB6\\uD83C\\uDFFD|\\uD83D\\uDEB6\\uD83C\\uDFFC|\\uD83D\\uDEB6\\uD83C\\uDFFB|\\uD83D\\uDEB5\\uD83C\\uDFFF|\\uD83D\\uDEB5\\uD83C\\uDFFE|\\uD83D\\uDEB5\\uD83C\\uDFFD|\\uD83D\\uDEB5\\uD83C\\uDFFC|\\uD83D\\uDEB5\\uD83C\\uDFFB|\\uD83D\\uDEB4\\uD83C\\uDFFF|\\uD83D\\uDEB4\\uD83C\\uDFFE|\\uD83D\\uDEB4\\uD83C\\uDFFD|\\uD83D\\uDEB4\\uD83C\\uDFFC|\\uD83D\\uDEB4\\uD83C\\uDFFB|\\uD83D\\uDEA3\\uD83C\\uDFFF|\\uD83D\\uDEA3\\uD83C\\uDFFE|\\uD83D\\uDEA3\\uD83C\\uDFFD|\\uD83D\\uDEA3\\uD83C\\uDFFC|\\uD83D\\uDEA3\\uD83C\\uDFFB|\\uD83D\\uDE4F\\uD83C\\uDFFF|\\uD83D\\uDE4F\\uD83C\\uDFFE|\\uD83D\\uDE4F\\uD83C\\uDFFD|\\uD83D\\uDE4F\\uD83C\\uDFFC|\\uD83D\\uDE4F\\uD83C\\uDFFB|\\uD83D\\uDE4E\\uD83C\\uDFFF|\\uD83D\\uDE4E\\uD83C\\uDFFE|\\uD83D\\uDE4E\\uD83C\\uDFFD|\\uD83D\\uDE4E\\uD83C\\uDFFC|\\uD83D\\uDE4E\\uD83C\\uDFFB|\\uD83D\\uDE4D\\uD83C\\uDFFF|\\uD83D\\uDE4D\\uD83C\\uDFFE|\\uD83D\\uDE4D\\uD83C\\uDFFD|\\uD83D\\uDE4D\\uD83C\\uDFFC|\\uD83D\\uDE4D\\uD83C\\uDFFB|\\uD83D\\uDE4C\\uD83C\\uDFFF|\\uD83D\\uDE4C\\uD83C\\uDFFE|\\uD83D\\uDE4C\\uD83C\\uDFFD|\\uD83D\\uDE4C\\uD83C\\uDFFC|\\uD83D\\uDE4C\\uD83C\\uDFFB|\\uD83D\\uDE4B\\uD83C\\uDFFF|\\uD83D\\uDE4B\\uD83C\\uDFFE|\\uD83D\\uDE4B\\uD83C\\uDFFD|\\uD83D\\uDE4B\\uD83C\\uDFFC|\\uD83D\\uDE4B\\uD83C\\uDFFB|\\uD83D\\uDE47\\uD83C\\uDFFF|\\uD83D\\uDE47\\uD83C\\uDFFE|\\uD83D\\uDE47\\uD83C\\uDFFD|\\uD83D\\uDE47\\uD83C\\uDFFC|\\uD83D\\uDE47\\uD83C\\uDFFB|\\uD83D\\uDE46\\uD83C\\uDFFF|\\uD83D\\uDE46\\uD83C\\uDFFE|\\uD83D\\uDE46\\uD83C\\uDFFD|\\uD83D\\uDE46\\uD83C\\uDFFC|\\uD83D\\uDE46\\uD83C\\uDFFB|\\uD83D\\uDE45\\uD83C\\uDFFF|\\uD83D\\uDE45\\uD83C\\uDFFE|\\uD83D\\uDE45\\uD83C\\uDFFD|\\uD83D\\uDE45\\uD83C\\uDFFC|\\uD83D\\uDE45\\uD83C\\uDFFB|\\uD83D\\uDD96\\uD83C\\uDFFF|\\uD83D\\uDD96\\uD83C\\uDFFE|\\uD83D\\uDD96\\uD83C\\uDFFD|\\uD83D\\uDD96\\uD83C\\uDFFC|\\uD83D\\uDD96\\uD83C\\uDFFB|\\uD83D\\uDD95\\uD83C\\uDFFF|\\uD83D\\uDD95\\uD83C\\uDFFE|\\uD83D\\uDD95\\uD83C\\uDFFD|\\uD83D\\uDD95\\uD83C\\uDFFC|\\uD83D\\uDD95\\uD83C\\uDFFB|\\uD83D\\uDD90\\uD83C\\uDFFF|\\uD83D\\uDD90\\uD83C\\uDFFE|\\uD83D\\uDD90\\uD83C\\uDFFD|\\uD83D\\uDD90\\uD83C\\uDFFC|\\uD83D\\uDD90\\uD83C\\uDFFB|\\uD83D\\uDD75\\uD83C\\uDFFF|\\uD83D\\uDD75\\uD83C\\uDFFE|\\uD83D\\uDD75\\uD83C\\uDFFD|\\uD83D\\uDD75\\uD83C\\uDFFC|\\uD83D\\uDD75\\uD83C\\uDFFB|\\uD83D\\uDCAA\\uD83C\\uDFFF|\\uD83D\\uDCAA\\uD83C\\uDFFE|\\uD83D\\uDCAA\\uD83C\\uDFFD|\\uD83D\\uDCAA\\uD83C\\uDFFC|\\uD83D\\uDCAA\\uD83C\\uDFFB|\\uD83D\\uDC87\\uD83C\\uDFFF|\\uD83D\\uDC87\\uD83C\\uDFFE|\\uD83D\\uDC87\\uD83C\\uDFFD|\\uD83D\\uDC87\\uD83C\\uDFFC|\\uD83D\\uDC87\\uD83C\\uDFFB|\\uD83D\\uDC86\\uD83C\\uDFFF|\\uD83D\\uDC86\\uD83C\\uDFFE|\\uD83D\\uDC86\\uD83C\\uDFFD|\\uD83D\\uDC86\\uD83C\\uDFFC|\\uD83D\\uDC86\\uD83C\\uDFFB|\\uD83D\\uDC85\\uD83C\\uDFFF|\\uD83D\\uDC85\\uD83C\\uDFFE|\\uD83D\\uDC85\\uD83C\\uDFFD|\\uD83D\\uDC85\\uD83C\\uDFFC|\\uD83D\\uDC85\\uD83C\\uDFFB|\\uD83D\\uDC83\\uD83C\\uDFFF|\\uD83D\\uDC83\\uD83C\\uDFFE|\\uD83D\\uDC83\\uD83C\\uDFFD|\\uD83D\\uDC83\\uD83C\\uDFFC|\\uD83D\\uDC83\\uD83C\\uDFFB|\\uD83D\\uDC82\\uD83C\\uDFFF|\\uD83D\\uDC82\\uD83C\\uDFFE|\\uD83D\\uDC82\\uD83C\\uDFFD|\\uD83D\\uDC82\\uD83C\\uDFFC|\\uD83D\\uDC82\\uD83C\\uDFFB|\\uD83D\\uDC81\\uD83C\\uDFFF|\\uD83D\\uDC81\\uD83C\\uDFFE|\\uD83D\\uDC81\\uD83C\\uDFFD|\\uD83D\\uDC81\\uD83C\\uDFFC|\\uD83D\\uDC81\\uD83C\\uDFFB|\\uD83D\\uDC7C\\uD83C\\uDFFF|\\uD83D\\uDC7C\\uD83C\\uDFFE|\\uD83D\\uDC7C\\uD83C\\uDFFD|\\uD83D\\uDC7C\\uD83C\\uDFFC|\\uD83D\\uDC7C\\uD83C\\uDFFB|\\uD83D\\uDC78\\uD83C\\uDFFF|\\uD83D\\uDC78\\uD83C\\uDFFE|\\uD83D\\uDC78\\uD83C\\uDFFD|\\uD83D\\uDC78\\uD83C\\uDFFC|\\uD83D\\uDC78\\uD83C\\uDFFB|\\uD83D\\uDC77\\uD83C\\uDFFF|\\uD83D\\uDC77\\uD83C\\uDFFE|\\uD83D\\uDC77\\uD83C\\uDFFD|\\uD83D\\uDC77\\uD83C\\uDFFC|\\uD83D\\uDC77\\uD83C\\uDFFB|\\uD83D\\uDC76\\uD83C\\uDFFF|\\uD83D\\uDC76\\uD83C\\uDFFE|\\uD83D\\uDC76\\uD83C\\uDFFD|\\uD83D\\uDC76\\uD83C\\uDFFC|\\uD83D\\uDC76\\uD83C\\uDFFB|\\uD83D\\uDC75\\uD83C\\uDFFF|\\uD83D\\uDC75\\uD83C\\uDFFE|\\uD83D\\uDC75\\uD83C\\uDFFD|\\uD83D\\uDC75\\uD83C\\uDFFC|\\uD83D\\uDC75\\uD83C\\uDFFB|\\uD83D\\uDC74\\uD83C\\uDFFF|\\uD83D\\uDC74\\uD83C\\uDFFE|\\uD83D\\uDC74\\uD83C\\uDFFD|\\uD83D\\uDC74\\uD83C\\uDFFC|\\uD83D\\uDC74\\uD83C\\uDFFB|\\uD83D\\uDC73\\uD83C\\uDFFF|\\uD83D\\uDC73\\uD83C\\uDFFE|\\uD83D\\uDC73\\uD83C\\uDFFD|\\uD83D\\uDC73\\uD83C\\uDFFC|\\uD83D\\uDC73\\uD83C\\uDFFB|\\uD83D\\uDC72\\uD83C\\uDFFF|\\uD83D\\uDC72\\uD83C\\uDFFE|\\uD83D\\uDC72\\uD83C\\uDFFD|\\uD83D\\uDC72\\uD83C\\uDFFC|\\uD83D\\uDC72\\uD83C\\uDFFB|\\uD83D\\uDC71\\uD83C\\uDFFF|\\uD83D\\uDC71\\uD83C\\uDFFE|\\uD83D\\uDC71\\uD83C\\uDFFD|\\uD83D\\uDC71\\uD83C\\uDFFC|\\uD83D\\uDC71\\uD83C\\uDFFB|\\uD83D\\uDC70\\uD83C\\uDFFF|\\uD83D\\uDC70\\uD83C\\uDFFE|\\uD83D\\uDC70\\uD83C\\uDFFD|\\uD83D\\uDC70\\uD83C\\uDFFC|\\uD83D\\uDC70\\uD83C\\uDFFB|\\uD83D\\uDC6E\\uD83C\\uDFFF|\\uD83D\\uDC6E\\uD83C\\uDFFE|\\uD83D\\uDC6E\\uD83C\\uDFFD|\\uD83D\\uDC6E\\uD83C\\uDFFC|\\uD83D\\uDC6E\\uD83C\\uDFFB|\\uD83D\\uDC69\\uD83C\\uDFFF|\\uD83D\\uDC69\\uD83C\\uDFFE|\\uD83D\\uDC69\\uD83C\\uDFFD|\\uD83D\\uDC69\\uD83C\\uDFFC|\\uD83D\\uDC69\\uD83C\\uDFFB|\\uD83D\\uDC68\\uD83C\\uDFFF|\\uD83D\\uDC68\\uD83C\\uDFFE|\\uD83D\\uDC68\\uD83C\\uDFFD|\\uD83D\\uDC68\\uD83C\\uDFFC|\\uD83D\\uDC68\\uD83C\\uDFFB|\\uD83D\\uDC67\\uD83C\\uDFFF|\\uD83D\\uDC67\\uD83C\\uDFFE|\\uD83D\\uDC67\\uD83C\\uDFFD|\\uD83D\\uDC67\\uD83C\\uDFFC|\\uD83D\\uDC67\\uD83C\\uDFFB|\\uD83D\\uDC66\\uD83C\\uDFFF|\\uD83D\\uDC66\\uD83C\\uDFFE|\\uD83D\\uDC66\\uD83C\\uDFFD|\\uD83D\\uDC66\\uD83C\\uDFFC|\\uD83D\\uDC66\\uD83C\\uDFFB|\\uD83D\\uDC50\\uD83C\\uDFFF|\\uD83D\\uDC50\\uD83C\\uDFFE|\\uD83D\\uDC50\\uD83C\\uDFFD|\\uD83D\\uDC50\\uD83C\\uDFFC|\\uD83D\\uDC50\\uD83C\\uDFFB|\\uD83D\\uDC4F\\uD83C\\uDFFF|\\uD83D\\uDC4F\\uD83C\\uDFFE|\\uD83D\\uDC4F\\uD83C\\uDFFD|\\uD83D\\uDC4F\\uD83C\\uDFFC|\\uD83D\\uDC4F\\uD83C\\uDFFB|\\uD83D\\uDC4E\\uD83C\\uDFFF|\\uD83D\\uDC4E\\uD83C\\uDFFE|\\uD83D\\uDC4E\\uD83C\\uDFFD|\\uD83D\\uDC4E\\uD83C\\uDFFC|\\uD83D\\uDC4E\\uD83C\\uDFFB|\\uD83D\\uDC4D\\uD83C\\uDFFF|\\uD83D\\uDC4D\\uD83C\\uDFFE|\\uD83D\\uDC4D\\uD83C\\uDFFD|\\uD83D\\uDC4D\\uD83C\\uDFFC|\\uD83D\\uDC4D\\uD83C\\uDFFB|\\uD83D\\uDC4C\\uD83C\\uDFFF|\\uD83D\\uDC4C\\uD83C\\uDFFE|\\uD83D\\uDC4C\\uD83C\\uDFFD|\\uD83D\\uDC4C\\uD83C\\uDFFC|\\uD83D\\uDC4C\\uD83C\\uDFFB|\\uD83D\\uDC4B\\uD83C\\uDFFF|\\uD83D\\uDC4B\\uD83C\\uDFFE|\\uD83D\\uDC4B\\uD83C\\uDFFD|\\uD83D\\uDC4B\\uD83C\\uDFFC|\\uD83D\\uDC4B\\uD83C\\uDFFB|\\uD83D\\uDC4A\\uD83C\\uDFFF|\\uD83D\\uDC4A\\uD83C\\uDFFE|\\uD83D\\uDC4A\\uD83C\\uDFFD|\\uD83D\\uDC4A\\uD83C\\uDFFC|\\uD83D\\uDC4A\\uD83C\\uDFFB|\\uD83D\\uDC49\\uD83C\\uDFFF|\\uD83D\\uDC49\\uD83C\\uDFFE|\\uD83D\\uDC49\\uD83C\\uDFFD|\\uD83D\\uDC49\\uD83C\\uDFFC|\\uD83D\\uDC49\\uD83C\\uDFFB|\\uD83D\\uDC48\\uD83C\\uDFFF|\\uD83D\\uDC48\\uD83C\\uDFFE|\\uD83D\\uDC48\\uD83C\\uDFFD|\\uD83D\\uDC48\\uD83C\\uDFFC|\\uD83D\\uDC48\\uD83C\\uDFFB|\\uD83D\\uDC47\\uD83C\\uDFFF|\\uD83D\\uDC47\\uD83C\\uDFFE|\\uD83D\\uDC47\\uD83C\\uDFFD|\\uD83D\\uDC47\\uD83C\\uDFFC|\\uD83D\\uDC47\\uD83C\\uDFFB|\\uD83D\\uDC46\\uD83C\\uDFFF|\\uD83D\\uDC46\\uD83C\\uDFFE|\\uD83D\\uDC46\\uD83C\\uDFFD|\\uD83D\\uDC46\\uD83C\\uDFFC|\\uD83D\\uDC46\\uD83C\\uDFFB|\\uD83D\\uDC43\\uD83C\\uDFFF|\\uD83D\\uDC43\\uD83C\\uDFFE|\\uD83D\\uDC43\\uD83C\\uDFFD|\\uD83D\\uDC43\\uD83C\\uDFFC|\\uD83D\\uDC43\\uD83C\\uDFFB|\\uD83D\\uDC42\\uD83C\\uDFFF|\\uD83D\\uDC42\\uD83C\\uDFFE|\\uD83D\\uDC42\\uD83C\\uDFFD|\\uD83D\\uDC42\\uD83C\\uDFFC|\\uD83D\\uDC42\\uD83C\\uDFFB|\\uD83C\\uDFCB\\uD83C\\uDFFF|\\uD83C\\uDFCB\\uD83C\\uDFFE|\\uD83C\\uDFCB\\uD83C\\uDFFD|\\uD83C\\uDFCB\\uD83C\\uDFFC|\\uD83C\\uDFCB\\uD83C\\uDFFB|\\uD83C\\uDFCA\\uD83C\\uDFFF|\\uD83C\\uDFCA\\uD83C\\uDFFE|\\uD83C\\uDFCA\\uD83C\\uDFFD|\\uD83C\\uDFCA\\uD83C\\uDFFC|\\uD83C\\uDFCA\\uD83C\\uDFFB|\\uD83C\\uDFC7\\uD83C\\uDFFF|\\uD83C\\uDFC7\\uD83C\\uDFFE|\\uD83C\\uDFC7\\uD83C\\uDFFD|\\uD83C\\uDFC7\\uD83C\\uDFFC|\\uD83C\\uDFC7\\uD83C\\uDFFB|\\uD83C\\uDFC4\\uD83C\\uDFFF|\\uD83C\\uDFC4\\uD83C\\uDFFE|\\uD83C\\uDFC4\\uD83C\\uDFFD|\\uD83C\\uDFC4\\uD83C\\uDFFC|\\uD83C\\uDFC4\\uD83C\\uDFFB|\\uD83C\\uDFC3\\uD83C\\uDFFF|\\uD83C\\uDFC3\\uD83C\\uDFFE|\\uD83C\\uDFC3\\uD83C\\uDFFD|\\uD83C\\uDFC3\\uD83C\\uDFFC|\\uD83C\\uDFC3\\uD83C\\uDFFB|\\uD83C\\uDF85\\uD83C\\uDFFF|\\uD83C\\uDF85\\uD83C\\uDFFE|\\uD83C\\uDF85\\uD83C\\uDFFD|\\uD83C\\uDF85\\uD83C\\uDFFC|\\uD83C\\uDF85\\uD83C\\uDFFB|\\uD83C\\uDDFF\\uD83C\\uDDFC|\\uD83C\\uDDFF\\uD83C\\uDDF2|\\uD83C\\uDDFF\\uD83C\\uDDE6|\\uD83C\\uDDFE\\uD83C\\uDDF9|\\uD83C\\uDDFE\\uD83C\\uDDEA|\\uD83C\\uDDFD\\uD83C\\uDDF0|\\uD83C\\uDDFC\\uD83C\\uDDF8|\\uD83C\\uDDFC\\uD83C\\uDDEB|\\uD83C\\uDDFB\\uD83C\\uDDFA|\\uD83C\\uDDFB\\uD83C\\uDDF3|\\uD83C\\uDDFB\\uD83C\\uDDEE|\\uD83C\\uDDFB\\uD83C\\uDDEC|\\uD83C\\uDDFB\\uD83C\\uDDEA|\\uD83C\\uDDFB\\uD83C\\uDDE8|\\uD83C\\uDDFB\\uD83C\\uDDE6|\\uD83C\\uDDFA\\uD83C\\uDDFF|\\uD83C\\uDDFA\\uD83C\\uDDFE|\\uD83C\\uDDFA\\uD83C\\uDDF8|\\uD83C\\uDDFA\\uD83C\\uDDF2|\\uD83C\\uDDFA\\uD83C\\uDDEC|\\uD83C\\uDDFA\\uD83C\\uDDE6|\\uD83C\\uDDF9\\uD83C\\uDDFF|\\uD83C\\uDDF9\\uD83C\\uDDFC|\\uD83C\\uDDF9\\uD83C\\uDDFB|\\uD83C\\uDDF9\\uD83C\\uDDF9|\\uD83C\\uDDF9\\uD83C\\uDDF7|\\uD83C\\uDDF9\\uD83C\\uDDF4|\\uD83C\\uDDF9\\uD83C\\uDDF3|\\uD83C\\uDDF9\\uD83C\\uDDF2|\\uD83C\\uDDF9\\uD83C\\uDDF1|\\uD83C\\uDDF9\\uD83C\\uDDF0|\\uD83C\\uDDF9\\uD83C\\uDDEF|\\uD83C\\uDDF9\\uD83C\\uDDED|\\uD83C\\uDDF9\\uD83C\\uDDEC|\\uD83C\\uDDF9\\uD83C\\uDDEB|\\uD83C\\uDDE6\\uD83C\\uDDE8|\\uD83C\\uDDF9\\uD83C\\uDDE8|\\uD83C\\uDDF9\\uD83C\\uDDE6|\\uD83C\\uDDF8\\uD83C\\uDDFF|\\uD83C\\uDDF8\\uD83C\\uDDFE|\\uD83C\\uDDF8\\uD83C\\uDDFD|\\uD83C\\uDDF8\\uD83C\\uDDFB|\\uD83C\\uDDF8\\uD83C\\uDDF9|\\uD83C\\uDDF8\\uD83C\\uDDF8|\\uD83C\\uDDF8\\uD83C\\uDDF7|\\uD83C\\uDDF8\\uD83C\\uDDF4|\\uD83C\\uDDF8\\uD83C\\uDDF3|\\uD83C\\uDDF8\\uD83C\\uDDF2|\\uD83C\\uDDF8\\uD83C\\uDDF1|\\uD83C\\uDDF8\\uD83C\\uDDF0|\\uD83C\\uDDF8\\uD83C\\uDDEF|\\uD83C\\uDDF8\\uD83C\\uDDEE|\\uD83C\\uDDF8\\uD83C\\uDDED|\\uD83C\\uDDF8\\uD83C\\uDDEC|\\uD83C\\uDDF8\\uD83C\\uDDEA|\\uD83C\\uDDF8\\uD83C\\uDDE9|\\uD83C\\uDDF8\\uD83C\\uDDE8|\\uD83C\\uDDF8\\uD83C\\uDDE7|\\uD83C\\uDDF8\\uD83C\\uDDE6|\\uD83C\\uDDF7\\uD83C\\uDDFC|\\uD83C\\uDDF7\\uD83C\\uDDFA|\\uD83C\\uDDF7\\uD83C\\uDDF8|\\uD83C\\uDDF7\\uD83C\\uDDF4|\\uD83C\\uDDF7\\uD83C\\uDDEA|\\uD83C\\uDDF6\\uD83C\\uDDE6|\\uD83C\\uDDF5\\uD83C\\uDDFE|\\uD83C\\uDDF5\\uD83C\\uDDFC|\\uD83C\\uDDF5\\uD83C\\uDDF9|\\uD83C\\uDDF5\\uD83C\\uDDF8|\\uD83C\\uDDF5\\uD83C\\uDDF7|\\uD83C\\uDDF5\\uD83C\\uDDF3|\\uD83C\\uDDF5\\uD83C\\uDDF2|\\uD83C\\uDDF5\\uD83C\\uDDF1|\\uD83C\\uDDF5\\uD83C\\uDDF0|\\uD83C\\uDDF5\\uD83C\\uDDED|\\uD83C\\uDDF5\\uD83C\\uDDEC|\\uD83C\\uDDF5\\uD83C\\uDDEB|\\uD83C\\uDDF5\\uD83C\\uDDEA|\\uD83C\\uDDF5\\uD83C\\uDDE6|\\uD83C\\uDDF4\\uD83C\\uDDF2|\\uD83C\\uDDF3\\uD83C\\uDDFF|\\uD83C\\uDDF3\\uD83C\\uDDFA|\\uD83C\\uDDF3\\uD83C\\uDDF7|\\uD83C\\uDDF3\\uD83C\\uDDF5|\\uD83C\\uDDF3\\uD83C\\uDDF4|\\uD83C\\uDDF3\\uD83C\\uDDF1|\\uD83C\\uDDF3\\uD83C\\uDDEE|\\uD83C\\uDDF3\\uD83C\\uDDEC|\\uD83C\\uDDF3\\uD83C\\uDDEB|\\uD83C\\uDDF3\\uD83C\\uDDEA|\\uD83C\\uDDF3\\uD83C\\uDDE8|\\uD83C\\uDDF3\\uD83C\\uDDE6|\\uD83C\\uDDF2\\uD83C\\uDDFF|\\uD83C\\uDDF2\\uD83C\\uDDFE|\\uD83C\\uDDF2\\uD83C\\uDDFD|\\uD83C\\uDDF2\\uD83C\\uDDFC|\\uD83C\\uDDF2\\uD83C\\uDDFB|\\uD83C\\uDDF2\\uD83C\\uDDFA|\\uD83C\\uDDF2\\uD83C\\uDDF9|\\uD83C\\uDDF2\\uD83C\\uDDF8|\\uD83C\\uDDF2\\uD83C\\uDDF7|\\uD83C\\uDDF2\\uD83C\\uDDF6|\\uD83C\\uDDF2\\uD83C\\uDDF5|\\uD83C\\uDDF2\\uD83C\\uDDF4|\\uD83C\\uDDF2\\uD83C\\uDDF3|\\uD83C\\uDDF2\\uD83C\\uDDF2|\\uD83C\\uDDF2\\uD83C\\uDDF1|\\uD83C\\uDDF2\\uD83C\\uDDF0|\\uD83C\\uDDF2\\uD83C\\uDDED|\\uD83C\\uDDF2\\uD83C\\uDDEC|\\uD83C\\uDDF2\\uD83C\\uDDEB|\\uD83C\\uDDF2\\uD83C\\uDDEA|\\uD83C\\uDDF2\\uD83C\\uDDE9|\\uD83C\\uDDF2\\uD83C\\uDDE8|\\uD83C\\uDDF2\\uD83C\\uDDE6|\\uD83C\\uDDF1\\uD83C\\uDDFE|\\uD83C\\uDDF1\\uD83C\\uDDFB|\\uD83C\\uDDF1\\uD83C\\uDDFA|\\uD83C\\uDDF1\\uD83C\\uDDF9|\\uD83C\\uDDF1\\uD83C\\uDDF8|\\uD83C\\uDDF1\\uD83C\\uDDF7|\\uD83C\\uDDF1\\uD83C\\uDDF0|\\uD83C\\uDDF1\\uD83C\\uDDEE|\\uD83C\\uDDF1\\uD83C\\uDDE8|\\uD83C\\uDDF1\\uD83C\\uDDE7|\\uD83C\\uDDF1\\uD83C\\uDDE6|\\uD83C\\uDDF0\\uD83C\\uDDFF|\\uD83C\\uDDF0\\uD83C\\uDDFE|\\uD83C\\uDDF0\\uD83C\\uDDFC|\\uD83C\\uDDF0\\uD83C\\uDDF7|\\uD83C\\uDDF0\\uD83C\\uDDF5|\\uD83C\\uDDF0\\uD83C\\uDDF3|\\uD83C\\uDDF0\\uD83C\\uDDF2|\\uD83C\\uDDF0\\uD83C\\uDDEE|\\uD83C\\uDDF0\\uD83C\\uDDED|\\uD83C\\uDDF0\\uD83C\\uDDEC|\\uD83C\\uDDF0\\uD83C\\uDDEA|\\uD83C\\uDDEF\\uD83C\\uDDF5|\\uD83C\\uDDEF\\uD83C\\uDDF4|\\uD83C\\uDDEF\\uD83C\\uDDF2|\\uD83C\\uDDEF\\uD83C\\uDDEA|\\uD83C\\uDDEE\\uD83C\\uDDF9|\\uD83C\\uDDEE\\uD83C\\uDDF8|\\uD83C\\uDDEE\\uD83C\\uDDF7|\\uD83C\\uDDEE\\uD83C\\uDDF6|\\uD83C\\uDDEE\\uD83C\\uDDF4|\\uD83C\\uDDEE\\uD83C\\uDDF3|\\uD83C\\uDDEE\\uD83C\\uDDF2|\\uD83C\\uDDEE\\uD83C\\uDDF1|\\uD83C\\uDDEE\\uD83C\\uDDEA|\\uD83C\\uDDEE\\uD83C\\uDDE9|\\uD83C\\uDDEE\\uD83C\\uDDE8|\\uD83C\\uDDED\\uD83C\\uDDFA|\\uD83C\\uDDED\\uD83C\\uDDF9|\\uD83C\\uDDED\\uD83C\\uDDF7|\\uD83C\\uDDED\\uD83C\\uDDF3|\\uD83C\\uDDED\\uD83C\\uDDF2|\\uD83C\\uDDED\\uD83C\\uDDF0|\\uD83C\\uDDEC\\uD83C\\uDDFE|\\uD83C\\uDDEC\\uD83C\\uDDFC|\\uD83C\\uDDEC\\uD83C\\uDDFA|\\uD83C\\uDDEC\\uD83C\\uDDF9|\\uD83C\\uDDEC\\uD83C\\uDDF8|\\uD83C\\uDDEC\\uD83C\\uDDF7|\\uD83C\\uDDEC\\uD83C\\uDDF6|\\uD83C\\uDDEC\\uD83C\\uDDF5|\\uD83C\\uDDEC\\uD83C\\uDDF3|\\uD83C\\uDDEC\\uD83C\\uDDF2|\\uD83C\\uDDEC\\uD83C\\uDDF1|\\uD83C\\uDDEC\\uD83C\\uDDEE|\\uD83C\\uDDEC\\uD83C\\uDDED|\\uD83C\\uDDEC\\uD83C\\uDDEC|\\uD83C\\uDDEC\\uD83C\\uDDEB|\\uD83C\\uDDEC\\uD83C\\uDDEA|\\uD83C\\uDDEC\\uD83C\\uDDE9|\\uD83C\\uDDEC\\uD83C\\uDDE7|\\uD83C\\uDDEC\\uD83C\\uDDE6|\\uD83C\\uDDEB\\uD83C\\uDDF7|\\uD83C\\uDDEB\\uD83C\\uDDF4|\\uD83C\\uDDEB\\uD83C\\uDDF2|\\uD83C\\uDDEB\\uD83C\\uDDF0|\\uD83C\\uDDEB\\uD83C\\uDDEF|\\uD83C\\uDDEB\\uD83C\\uDDEE|\\uD83C\\uDDEA\\uD83C\\uDDFA|\\uD83C\\uDDEA\\uD83C\\uDDF9|\\uD83C\\uDDEA\\uD83C\\uDDF8|\\uD83C\\uDDEA\\uD83C\\uDDF7|\\uD83C\\uDDEA\\uD83C\\uDDED|\\uD83C\\uDDEA\\uD83C\\uDDEC|\\uD83C\\uDDEA\\uD83C\\uDDEA|\\uD83C\\uDDEA\\uD83C\\uDDE8|\\uD83C\\uDDEA\\uD83C\\uDDE6|\\uD83C\\uDDE9\\uD83C\\uDDFF|\\uD83C\\uDDE9\\uD83C\\uDDF4|\\uD83C\\uDDE9\\uD83C\\uDDF2|\\uD83C\\uDDE9\\uD83C\\uDDF0|\\uD83C\\uDDE9\\uD83C\\uDDEF|\\uD83C\\uDDE9\\uD83C\\uDDEC|\\uD83C\\uDDE9\\uD83C\\uDDEA|\\uD83C\\uDDE8\\uD83C\\uDDFF|\\uD83C\\uDDE8\\uD83C\\uDDFE|\\uD83C\\uDDE8\\uD83C\\uDDFD|\\uD83C\\uDDE8\\uD83C\\uDDFC|\\uD83C\\uDDE8\\uD83C\\uDDFB|\\uD83C\\uDDE8\\uD83C\\uDDFA|\\uD83C\\uDDE8\\uD83C\\uDDF7|\\uD83C\\uDDE8\\uD83C\\uDDF5|\\uD83C\\uDDE8\\uD83C\\uDDF4|\\uD83C\\uDDE8\\uD83C\\uDDF3|\\uD83C\\uDDE8\\uD83C\\uDDF2|\\uD83C\\uDDE8\\uD83C\\uDDF1|\\uD83C\\uDDE8\\uD83C\\uDDF0|\\uD83C\\uDDE8\\uD83C\\uDDEE|\\uD83C\\uDDE8\\uD83C\\uDDED|\\uD83C\\uDDE8\\uD83C\\uDDEC|\\uD83C\\uDDE8\\uD83C\\uDDEB|\\uD83C\\uDDE8\\uD83C\\uDDE9|\\uD83C\\uDDE8\\uD83C\\uDDE8|\\uD83C\\uDDE8\\uD83C\\uDDE6|\\uD83C\\uDDE7\\uD83C\\uDDFF|\\uD83C\\uDDE7\\uD83C\\uDDFE|\\uD83C\\uDDE7\\uD83C\\uDDFC|\\uD83C\\uDDE7\\uD83C\\uDDFB|\\uD83C\\uDDE7\\uD83C\\uDDF9|\\uD83C\\uDDE7\\uD83C\\uDDF8|\\uD83C\\uDDE7\\uD83C\\uDDF7|\\uD83C\\uDDE7\\uD83C\\uDDF6|\\uD83C\\uDDE7\\uD83C\\uDDF4|\\uD83C\\uDDE7\\uD83C\\uDDF3|\\uD83C\\uDDE7\\uD83C\\uDDF2|\\uD83C\\uDDE7\\uD83C\\uDDF1|\\uD83C\\uDDE7\\uD83C\\uDDEF|\\uD83C\\uDDE7\\uD83C\\uDDEE|\\uD83C\\uDDE7\\uD83C\\uDDED|\\uD83C\\uDDE7\\uD83C\\uDDEC|\\uD83C\\uDDE7\\uD83C\\uDDEB|\\uD83C\\uDDE7\\uD83C\\uDDEA|\\uD83C\\uDDE7\\uD83C\\uDDE9|\\uD83C\\uDDE7\\uD83C\\uDDE7|\\uD83C\\uDDE7\\uD83C\\uDDE6|\\uD83C\\uDDE6\\uD83C\\uDDFF|\\uD83C\\uDDE6\\uD83C\\uDDFD|\\uD83C\\uDDE6\\uD83C\\uDDFC|\\uD83C\\uDDE6\\uD83C\\uDDFA|\\uD83C\\uDDE6\\uD83C\\uDDF9|\\uD83C\\uDDF9\\uD83C\\uDDE9|\\uD83D\\uDDE1\\uFE0F|\\u26F9\\uD83C\\uDFFF|\\u26F9\\uD83C\\uDFFE|\\u26F9\\uD83C\\uDFFD|\\u26F9\\uD83C\\uDFFC|\\u26F9\\uD83C\\uDFFB|\\u270D\\uD83C\\uDFFF|\\u270D\\uD83C\\uDFFE|\\u270D\\uD83C\\uDFFD|\\u270D\\uD83C\\uDFFC|\\u270D\\uD83C\\uDFFB|\\uD83C\\uDC04\\uFE0F|\\uD83C\\uDD7F\\uFE0F|\\uD83C\\uDE02\\uFE0F|\\uD83C\\uDE1A\\uFE0F|\\uD83C\\uDE2F\\uFE0F|\\uD83C\\uDE37\\uFE0F|\\uD83C\\uDF9E\\uFE0F|\\uD83C\\uDF9F\\uFE0F|\\uD83C\\uDFCB\\uFE0F|\\uD83C\\uDFCC\\uFE0F|\\uD83C\\uDFCD\\uFE0F|\\uD83C\\uDFCE\\uFE0F|\\uD83C\\uDF96\\uFE0F|\\uD83C\\uDF97\\uFE0F|\\uD83C\\uDF36\\uFE0F|\\uD83C\\uDF27\\uFE0F|\\uD83C\\uDF28\\uFE0F|\\uD83C\\uDF29\\uFE0F|\\uD83C\\uDF2A\\uFE0F|\\uD83C\\uDF2B\\uFE0F|\\uD83C\\uDF2C\\uFE0F|\\uD83D\\uDC3F\\uFE0F|\\uD83D\\uDD77\\uFE0F|\\uD83D\\uDD78\\uFE0F|\\uD83C\\uDF21\\uFE0F|\\uD83C\\uDF99\\uFE0F|\\uD83C\\uDF9A\\uFE0F|\\uD83C\\uDF9B\\uFE0F|\\uD83C\\uDFF3\\uFE0F|\\uD83C\\uDFF5\\uFE0F|\\uD83C\\uDFF7\\uFE0F|\\uD83D\\uDCFD\\uFE0F|\\uD83D\\uDD49\\uFE0F|\\uD83D\\uDD4A\\uFE0F|\\uD83D\\uDD6F\\uFE0F|\\uD83D\\uDD70\\uFE0F|\\uD83D\\uDD73\\uFE0F|\\uD83D\\uDD76\\uFE0F|\\uD83D\\uDD79\\uFE0F|\\uD83D\\uDD87\\uFE0F|\\uD83D\\uDD8A\\uFE0F|\\uD83D\\uDD8B\\uFE0F|\\uD83D\\uDD8C\\uFE0F|\\uD83D\\uDD8D\\uFE0F|\\uD83D\\uDDA5\\uFE0F|\\uD83D\\uDDA8\\uFE0F|\\uD83D\\uDDB2\\uFE0F|\\uD83D\\uDDBC\\uFE0F|\\uD83D\\uDDC2\\uFE0F|\\uD83D\\uDDC3\\uFE0F|\\uD83D\\uDDC4\\uFE0F|\\uD83D\\uDDD1\\uFE0F|\\uD83D\\uDDD2\\uFE0F|\\uD83D\\uDDD3\\uFE0F|\\uD83D\\uDDDC\\uFE0F|\\uD83D\\uDDDD\\uFE0F|\\uD83D\\uDDDE\\uFE0F|\\u270B\\uD83C\\uDFFF|\\uD83D\\uDDE3\\uFE0F|\\uD83D\\uDDEF\\uFE0F|\\uD83D\\uDDF3\\uFE0F|\\uD83D\\uDDFA\\uFE0F|\\uD83D\\uDEE0\\uFE0F|\\uD83D\\uDEE1\\uFE0F|\\uD83D\\uDEE2\\uFE0F|\\uD83D\\uDEF0\\uFE0F|\\uD83C\\uDF7D\\uFE0F|\\uD83D\\uDC41\\uFE0F|\\uD83D\\uDD74\\uFE0F|\\uD83D\\uDD75\\uFE0F|\\uD83D\\uDD90\\uFE0F|\\uD83C\\uDFD4\\uFE0F|\\uD83C\\uDFD5\\uFE0F|\\uD83C\\uDFD6\\uFE0F|\\uD83C\\uDFD7\\uFE0F|\\uD83C\\uDFD8\\uFE0F|\\uD83C\\uDFD9\\uFE0F|\\uD83C\\uDFDA\\uFE0F|\\uD83C\\uDFDB\\uFE0F|\\uD83C\\uDFDC\\uFE0F|\\uD83C\\uDFDD\\uFE0F|\\uD83C\\uDFDE\\uFE0F|\\uD83C\\uDFDF\\uFE0F|\\uD83D\\uDECB\\uFE0F|\\uD83D\\uDECD\\uFE0F|\\uD83D\\uDECE\\uFE0F|\\uD83D\\uDECF\\uFE0F|\\uD83D\\uDEE3\\uFE0F|\\uD83D\\uDEE4\\uFE0F|\\uD83D\\uDEE5\\uFE0F|\\uD83D\\uDEE9\\uFE0F|\\uD83D\\uDEF3\\uFE0F|\\uD83C\\uDF24\\uFE0F|\\uD83C\\uDF25\\uFE0F|\\uD83C\\uDF26\\uFE0F|\\uD83D\\uDDB1\\uFE0F|\\u261D\\uD83C\\uDFFB|\\u261D\\uD83C\\uDFFC|\\u261D\\uD83C\\uDFFD|\\u261D\\uD83C\\uDFFE|\\u261D\\uD83C\\uDFFF|\\u270C\\uD83C\\uDFFB|\\u270C\\uD83C\\uDFFC|\\u270C\\uD83C\\uDFFD|\\u270C\\uD83C\\uDFFE|\\u270C\\uD83C\\uDFFF|\\u270A\\uD83C\\uDFFB|\\u270A\\uD83C\\uDFFC|\\u270A\\uD83C\\uDFFD|\\u270A\\uD83C\\uDFFE|\\u270A\\uD83C\\uDFFF|\\u270B\\uD83C\\uDFFB|\\u270B\\uD83C\\uDFFC|\\u270B\\uD83C\\uDFFD|\\u270B\\uD83C\\uDFFE|4\\uFE0F\\u20E3|9\\uFE0F\\u20E3|0\\uFE0F\\u20E3|1\\uFE0F\\u20E3|2\\uFE0F\\u20E3|3\\uFE0F\\u20E3|#\\uFE0F\\u20E3|5\\uFE0F\\u20E3|6\\uFE0F\\u20E3|7\\uFE0F\\u20E3|8\\uFE0F\\u20E3|\\*\\uFE0F\\u20E3|\\u00A9\\uFE0F|\\u00AE\\uFE0F|\\u203C\\uFE0F|\\u2049\\uFE0F|\\u2122\\uFE0F|\\u2139\\uFE0F|\\u2194\\uFE0F|\\u2195\\uFE0F|\\u2196\\uFE0F|\\u2197\\uFE0F|\\u2198\\uFE0F|\\u2199\\uFE0F|\\u21A9\\uFE0F|\\u21AA\\uFE0F|\\u231A\\uFE0F|\\u231B\\uFE0F|\\u24C2\\uFE0F|\\u25AA\\uFE0F|\\u25AB\\uFE0F|\\u25B6\\uFE0F|\\u25C0\\uFE0F|\\u25FB\\uFE0F|\\u25FC\\uFE0F|\\u25FD\\uFE0F|\\u25FE\\uFE0F|\\u2600\\uFE0F|\\u2601\\uFE0F|\\u260E\\uFE0F|\\u2611\\uFE0F|\\u2614\\uFE0F|\\u2615\\uFE0F|\\u261D\\uFE0F|\\u263A\\uFE0F|\\u2648\\uFE0F|\\u2649\\uFE0F|\\u264A\\uFE0F|\\u264B\\uFE0F|\\u264C\\uFE0F|\\u264D\\uFE0F|\\u264E\\uFE0F|\\u264F\\uFE0F|\\u2650\\uFE0F|\\u2651\\uFE0F|\\u2652\\uFE0F|\\u2653\\uFE0F|\\u2660\\uFE0F|\\u2663\\uFE0F|\\u2665\\uFE0F|\\u2666\\uFE0F|\\u2668\\uFE0F|\\u267B\\uFE0F|\\u267F\\uFE0F|\\u2693\\uFE0F|\\u26A0\\uFE0F|\\u26A1\\uFE0F|\\u26AA\\uFE0F|\\u26AB\\uFE0F|\\u26BD\\uFE0F|\\u26BE\\uFE0F|\\u26C4\\uFE0F|\\u26C5\\uFE0F|\\u26D4\\uFE0F|\\u26EA\\uFE0F|\\u26F2\\uFE0F|\\u26F3\\uFE0F|\\u26F5\\uFE0F|\\u26FA\\uFE0F|\\u26FD\\uFE0F|\\u2702\\uFE0F|\\u2708\\uFE0F|\\u2709\\uFE0F|\\u270C\\uFE0F|\\u270F\\uFE0F|\\u2712\\uFE0F|\\u2714\\uFE0F|\\u2716\\uFE0F|\\u2733\\uFE0F|\\u2734\\uFE0F|\\u2744\\uFE0F|\\u2747\\uFE0F|\\u2757\\uFE0F|\\u2764\\uFE0F|\\u27A1\\uFE0F|\\u2934\\uFE0F|\\u2935\\uFE0F|\\u2B05\\uFE0F|\\u2B06\\uFE0F|\\u2B07\\uFE0F|\\u2B1B\\uFE0F|\\u2B1C\\uFE0F|\\u2B50\\uFE0F|\\u2B55\\uFE0F|\\u3030\\uFE0F|\\u303D\\uFE0F|\\u3297\\uFE0F|\\u3299\\uFE0F|\\u271D\\uFE0F|\\u2328\\uFE0F|\\u270D\\uFE0F|\\u23ED\\uFE0F|\\u23EE\\uFE0F|\\u23EF\\uFE0F|\\u23F1\\uFE0F|\\u23F2\\uFE0F|\\u23F8\\uFE0F|\\u23F9\\uFE0F|\\u23FA\\uFE0F|\\u2602\\uFE0F|\\u2603\\uFE0F|\\u2604\\uFE0F|\\u2618\\uFE0F|\\u2620\\uFE0F|\\u2622\\uFE0F|\\u2623\\uFE0F|\\u2626\\uFE0F|\\u262A\\uFE0F|\\u262E\\uFE0F|\\u262F\\uFE0F|\\u2638\\uFE0F|\\u2639\\uFE0F|\\u2692\\uFE0F|\\u2694\\uFE0F|\\u2696\\uFE0F|\\u2697\\uFE0F|\\u2699\\uFE0F|\\u269B\\uFE0F|\\u269C\\uFE0F|\\u26B0\\uFE0F|\\u26B1\\uFE0F|\\u26C8\\uFE0F|\\u26CF\\uFE0F|\\u26D1\\uFE0F|\\u26D3\\uFE0F|\\u26E9\\uFE0F|\\u26F0\\uFE0F|\\u26F1\\uFE0F|\\u26F4\\uFE0F|\\u26F7\\uFE0F|\\u26F8\\uFE0F|\\u26F9\\uFE0F|\\u2721\\uFE0F|\\u2763\\uFE0F|\\uD83C\\uDCCF|\\uD83C\\uDD70|\\uD83C\\uDD71|\\uD83C\\uDD7E|\\uD83C\\uDD8E|\\uD83C\\uDD91|\\uD83C\\uDD92|\\uD83C\\uDD93|\\uD83C\\uDD94|\\uD83C\\uDD95|\\uD83C\\uDD96|\\uD83C\\uDD97|\\uD83C\\uDD98|\\uD83C\\uDD99|\\uD83C\\uDD9A|\\uD83C\\uDE01|\\uD83C\\uDE32|\\uD83C\\uDE33|\\uD83C\\uDE34|\\uD83C\\uDE35|\\uD83C\\uDE36|\\uD83C\\uDE38|\\uD83C\\uDE39|\\uD83C\\uDE3A|\\uD83C\\uDE50|\\uD83C\\uDE51|\\uD83C\\uDF00|\\uD83C\\uDF01|\\uD83C\\uDF02|\\uD83C\\uDF03|\\uD83C\\uDF04|\\uD83C\\uDF05|\\uD83C\\uDF06|\\uD83C\\uDF07|\\uD83C\\uDF08|\\uD83C\\uDF09|\\uD83C\\uDF0A|\\uD83C\\uDF0B|\\uD83C\\uDF0C|\\uD83C\\uDF0F|\\uD83C\\uDF11|\\uD83C\\uDF13|\\uD83C\\uDF14|\\uD83C\\uDF15|\\uD83C\\uDF19|\\uD83C\\uDF1B|\\uD83C\\uDF1F|\\uD83C\\uDF20|\\uD83C\\uDF30|\\uD83C\\uDF31|\\uD83C\\uDF34|\\uD83C\\uDF35|\\uD83C\\uDF37|\\uD83C\\uDF38|\\uD83C\\uDF39|\\uD83C\\uDF3A|\\uD83C\\uDF3B|\\uD83C\\uDF3C|\\uD83C\\uDF3D|\\uD83C\\uDF3E|\\uD83C\\uDF3F|\\uD83C\\uDF40|\\uD83C\\uDF41|\\uD83C\\uDF42|\\uD83C\\uDF43|\\uD83C\\uDF44|\\uD83C\\uDF45|\\uD83C\\uDF46|\\uD83C\\uDF47|\\uD83C\\uDF48|\\uD83C\\uDF49|\\uD83C\\uDF4A|\\uD83C\\uDF4C|\\uD83C\\uDF4D|\\uD83C\\uDF4E|\\uD83C\\uDF4F|\\uD83C\\uDF51|\\uD83C\\uDF52|\\uD83C\\uDF53|\\uD83C\\uDF54|\\uD83C\\uDF55|\\uD83C\\uDF56|\\uD83C\\uDF57|\\uD83C\\uDF58|\\uD83C\\uDF59|\\uD83C\\uDF5A|\\uD83C\\uDF5B|\\uD83C\\uDF5C|\\uD83C\\uDF5D|\\uD83C\\uDF5E|\\uD83C\\uDF5F|\\uD83C\\uDF60|\\uD83C\\uDF61|\\uD83C\\uDF62|\\uD83C\\uDF63|\\uD83C\\uDF64|\\uD83C\\uDF65|\\uD83C\\uDF66|\\uD83C\\uDF67|\\uD83C\\uDF68|\\uD83C\\uDF69|\\uD83C\\uDF6A|\\uD83C\\uDF6B|\\uD83C\\uDF6C|\\uD83C\\uDF6D|\\uD83C\\uDF6E|\\uD83C\\uDF6F|\\uD83C\\uDF70|\\uD83C\\uDF71|\\uD83C\\uDF72|\\uD83C\\uDF73|\\uD83C\\uDF74|\\uD83C\\uDF75|\\uD83C\\uDF76|\\uD83C\\uDF77|\\uD83C\\uDF78|\\uD83C\\uDF79|\\uD83C\\uDF7A|\\uD83C\\uDF7B|\\uD83C\\uDF80|\\uD83C\\uDF81|\\uD83C\\uDF82|\\uD83C\\uDF83|\\uD83C\\uDF84|\\uD83C\\uDF85|\\uD83C\\uDF86|\\uD83C\\uDF87|\\uD83C\\uDF88|\\uD83C\\uDF89|\\uD83C\\uDF8A|\\uD83C\\uDF8B|\\uD83C\\uDF8C|\\uD83C\\uDF8D|\\uD83C\\uDF8E|\\uD83C\\uDF8F|\\uD83C\\uDF90|\\uD83C\\uDF91|\\uD83C\\uDF92|\\uD83C\\uDF93|\\uD83C\\uDFA0|\\uD83C\\uDFA1|\\uD83C\\uDFA2|\\uD83C\\uDFA3|\\uD83C\\uDFA4|\\uD83C\\uDFA5|\\uD83C\\uDFA6|\\uD83C\\uDFA7|\\uD83C\\uDFA8|\\uD83C\\uDFA9|\\uD83C\\uDFAA|\\uD83C\\uDFAB|\\uD83C\\uDFAC|\\uD83C\\uDFAD|\\uD83C\\uDFAE|\\uD83C\\uDFAF|\\uD83C\\uDFB0|\\uD83C\\uDFB1|\\uD83C\\uDFB2|\\uD83C\\uDFB3|\\uD83C\\uDFB4|\\uD83C\\uDFB5|\\uD83C\\uDFB6|\\uD83C\\uDFB7|\\uD83C\\uDFB8|\\uD83C\\uDFB9|\\uD83C\\uDFBA|\\uD83C\\uDFBB|\\uD83C\\uDFBC|\\uD83C\\uDFBD|\\uD83C\\uDFBE|\\uD83C\\uDFBF|\\uD83C\\uDFC0|\\uD83C\\uDFC1|\\uD83C\\uDFC2|\\uD83C\\uDFC3|\\uD83C\\uDFC4|\\uD83C\\uDFC6|\\uD83C\\uDFC8|\\uD83C\\uDFCA|\\uD83C\\uDFE0|\\uD83D\\uDDB1|\\uD83C\\uDFE2|\\uD83C\\uDFE3|\\uD83C\\uDFE5|\\uD83C\\uDFE6|\\uD83C\\uDFE7|\\uD83C\\uDFE8|\\uD83C\\uDFE9|\\uD83C\\uDFEA|\\uD83C\\uDFEB|\\uD83C\\uDFEC|\\uD83C\\uDFED|\\uD83C\\uDFEE|\\uD83C\\uDFEF|\\uD83C\\uDFF0|\\uD83D\\uDC0C|\\uD83D\\uDC0D|\\uD83D\\uDC0E|\\uD83D\\uDC11|\\uD83D\\uDC12|\\uD83D\\uDC14|\\uD83D\\uDC17|\\uD83D\\uDC18|\\uD83D\\uDC19|\\uD83D\\uDC1A|\\uD83D\\uDC1B|\\uD83D\\uDC1C|\\uD83D\\uDC1D|\\uD83D\\uDC1E|\\uD83D\\uDC1F|\\uD83D\\uDC20|\\uD83D\\uDC21|\\uD83D\\uDC22|\\uD83D\\uDC23|\\uD83D\\uDC24|\\uD83D\\uDC25|\\uD83D\\uDC26|\\uD83D\\uDC27|\\uD83D\\uDC28|\\uD83D\\uDC29|\\uD83D\\uDC2B|\\uD83D\\uDC2C|\\uD83D\\uDC2D|\\uD83D\\uDC2E|\\uD83D\\uDC2F|\\uD83D\\uDC30|\\uD83D\\uDC31|\\uD83D\\uDC32|\\uD83D\\uDC33|\\uD83D\\uDC34|\\uD83D\\uDC35|\\uD83D\\uDC36|\\uD83D\\uDC37|\\uD83D\\uDC38|\\uD83D\\uDC39|\\uD83D\\uDC3A|\\uD83D\\uDC3B|\\uD83D\\uDC3C|\\uD83D\\uDC3D|\\uD83D\\uDC3E|\\uD83D\\uDC40|\\uD83D\\uDC42|\\uD83D\\uDC43|\\uD83D\\uDC44|\\uD83D\\uDC45|\\uD83D\\uDC46|\\uD83D\\uDC47|\\uD83D\\uDC48|\\uD83D\\uDC49|\\uD83D\\uDC4A|\\uD83D\\uDC4B|\\uD83D\\uDC4C|\\uD83D\\uDC4D|\\uD83D\\uDC4E|\\uD83D\\uDC4F|\\uD83D\\uDC50|\\uD83D\\uDC51|\\uD83D\\uDC52|\\uD83D\\uDC53|\\uD83D\\uDC54|\\uD83D\\uDC55|\\uD83D\\uDC56|\\uD83D\\uDC57|\\uD83D\\uDC58|\\uD83D\\uDC59|\\uD83D\\uDC5A|\\uD83D\\uDC5B|\\uD83D\\uDC5C|\\uD83D\\uDC5D|\\uD83D\\uDC5E|\\uD83D\\uDC5F|\\uD83D\\uDC60|\\uD83D\\uDC61|\\uD83D\\uDC62|\\uD83D\\uDC63|\\uD83D\\uDC64|\\uD83D\\uDC66|\\uD83D\\uDC67|\\uD83D\\uDC68|\\uD83D\\uDC69|\\uD83D\\uDC6A|\\uD83D\\uDC6B|\\uD83D\\uDC6E|\\uD83D\\uDC6F|\\uD83D\\uDC70|\\uD83D\\uDC71|\\uD83D\\uDC72|\\uD83D\\uDC73|\\uD83D\\uDC74|\\uD83D\\uDC75|\\uD83D\\uDC76|\\uD83D\\uDC77|\\uD83D\\uDC78|\\uD83D\\uDC79|\\uD83D\\uDC7A|\\uD83D\\uDC7B|\\uD83D\\uDC7C|\\uD83D\\uDC7D|\\uD83D\\uDC7E|\\uD83D\\uDC7F|\\uD83D\\uDC80|\\uD83D\\uDCC7|\\uD83D\\uDC81|\\uD83D\\uDC82|\\uD83D\\uDC83|\\uD83D\\uDC84|\\uD83D\\uDC85|\\uD83D\\uDCD2|\\uD83D\\uDC86|\\uD83D\\uDCD3|\\uD83D\\uDC87|\\uD83D\\uDCD4|\\uD83D\\uDC88|\\uD83D\\uDCD5|\\uD83D\\uDC89|\\uD83D\\uDCD6|\\uD83D\\uDC8A|\\uD83D\\uDCD7|\\uD83D\\uDC8B|\\uD83D\\uDCD8|\\uD83D\\uDC8C|\\uD83D\\uDCD9|\\uD83D\\uDC8D|\\uD83D\\uDCDA|\\uD83D\\uDC8E|\\uD83D\\uDCDB|\\uD83D\\uDC8F|\\uD83D\\uDCDC|\\uD83D\\uDC90|\\uD83D\\uDCDD|\\uD83D\\uDC91|\\uD83D\\uDCDE|\\uD83D\\uDC92|\\uD83D\\uDCDF|\\uD83D\\uDCE0|\\uD83D\\uDC93|\\uD83D\\uDCE1|\\uD83D\\uDCE2|\\uD83D\\uDC94|\\uD83D\\uDCE3|\\uD83D\\uDCE4|\\uD83D\\uDC95|\\uD83D\\uDCE5|\\uD83D\\uDCE6|\\uD83D\\uDC96|\\uD83D\\uDCE7|\\uD83D\\uDCE8|\\uD83D\\uDC97|\\uD83D\\uDCE9|\\uD83D\\uDCEA|\\uD83D\\uDC98|\\uD83D\\uDCEB|\\uD83D\\uDCEE|\\uD83D\\uDC99|\\uD83D\\uDCF0|\\uD83D\\uDCF1|\\uD83D\\uDC9A|\\uD83D\\uDCF2|\\uD83D\\uDCF3|\\uD83D\\uDC9B|\\uD83D\\uDCF4|\\uD83D\\uDCF6|\\uD83D\\uDC9C|\\uD83D\\uDCF7|\\uD83D\\uDCF9|\\uD83D\\uDC9D|\\uD83D\\uDCFA|\\uD83D\\uDCFB|\\uD83D\\uDC9E|\\uD83D\\uDCFC|\\uD83D\\uDD03|\\uD83D\\uDC9F|\\uD83D\\uDD0A|\\uD83D\\uDD0B|\\uD83D\\uDCA0|\\uD83D\\uDD0C|\\uD83D\\uDD0D|\\uD83D\\uDCA1|\\uD83D\\uDD0E|\\uD83D\\uDD0F|\\uD83D\\uDCA2|\\uD83D\\uDD10|\\uD83D\\uDD11|\\uD83D\\uDCA3|\\uD83D\\uDD12|\\uD83D\\uDD13|\\uD83D\\uDCA4|\\uD83D\\uDD14|\\uD83D\\uDD16|\\uD83D\\uDCA5|\\uD83D\\uDD17|\\uD83D\\uDD18|\\uD83D\\uDCA6|\\uD83D\\uDD19|\\uD83D\\uDD1A|\\uD83D\\uDCA7|\\uD83D\\uDD1B|\\uD83D\\uDD1C|\\uD83D\\uDCA8|\\uD83D\\uDD1D|\\uD83D\\uDD1E|\\uD83D\\uDCA9|\\uD83D\\uDD1F|\\uD83D\\uDCAA|\\uD83D\\uDD20|\\uD83D\\uDD21|\\uD83D\\uDCAB|\\uD83D\\uDD22|\\uD83D\\uDD23|\\uD83D\\uDCAC|\\uD83D\\uDD24|\\uD83D\\uDD25|\\uD83D\\uDCAE|\\uD83D\\uDD26|\\uD83D\\uDD27|\\uD83D\\uDCAF|\\uD83D\\uDD28|\\uD83D\\uDD29|\\uD83D\\uDCB0|\\uD83D\\uDD2A|\\uD83D\\uDD2B|\\uD83D\\uDCB1|\\uD83D\\uDD2E|\\uD83D\\uDCB2|\\uD83D\\uDD2F|\\uD83D\\uDCB3|\\uD83D\\uDD30|\\uD83D\\uDD31|\\uD83D\\uDCB4|\\uD83D\\uDD32|\\uD83D\\uDD33|\\uD83D\\uDCB5|\\uD83D\\uDD34|\\uD83D\\uDD35|\\uD83D\\uDCB8|\\uD83D\\uDD36|\\uD83D\\uDD37|\\uD83D\\uDCB9|\\uD83D\\uDD38|\\uD83D\\uDD39|\\uD83D\\uDCBA|\\uD83D\\uDD3A|\\uD83D\\uDD3B|\\uD83D\\uDCBB|\\uD83D\\uDD3C|\\uD83D\\uDCBC|\\uD83D\\uDD3D|\\uD83D\\uDD50|\\uD83D\\uDCBD|\\uD83D\\uDD51|\\uD83D\\uDCBE|\\uD83D\\uDD52|\\uD83D\\uDCBF|\\uD83D\\uDD53|\\uD83D\\uDCC0|\\uD83D\\uDD54|\\uD83D\\uDD55|\\uD83D\\uDCC1|\\uD83D\\uDD56|\\uD83D\\uDD57|\\uD83D\\uDCC2|\\uD83D\\uDD58|\\uD83D\\uDD59|\\uD83D\\uDCC3|\\uD83D\\uDD5A|\\uD83D\\uDD5B|\\uD83D\\uDCC4|\\uD83D\\uDDFB|\\uD83D\\uDDFC|\\uD83D\\uDCC5|\\uD83D\\uDDFD|\\uD83D\\uDDFE|\\uD83D\\uDCC6|\\uD83D\\uDDFF|\\uD83D\\uDE01|\\uD83D\\uDE02|\\uD83D\\uDE03|\\uD83D\\uDCC8|\\uD83D\\uDE04|\\uD83D\\uDE05|\\uD83D\\uDCC9|\\uD83D\\uDE06|\\uD83D\\uDE09|\\uD83D\\uDCCA|\\uD83D\\uDE0A|\\uD83D\\uDE0B|\\uD83D\\uDCCB|\\uD83D\\uDE0C|\\uD83D\\uDE0D|\\uD83D\\uDCCC|\\uD83D\\uDE0F|\\uD83D\\uDE12|\\uD83D\\uDCCD|\\uD83D\\uDE13|\\uD83D\\uDE14|\\uD83D\\uDCCE|\\uD83D\\uDE16|\\uD83D\\uDE18|\\uD83D\\uDCCF|\\uD83D\\uDE1A|\\uD83D\\uDE1C|\\uD83D\\uDCD0|\\uD83D\\uDE1D|\\uD83D\\uDE1E|\\uD83D\\uDCD1|\\uD83D\\uDE20|\\uD83D\\uDE21|\\uD83D\\uDE22|\\uD83D\\uDE23|\\uD83D\\uDE24|\\uD83D\\uDE25|\\uD83D\\uDE28|\\uD83D\\uDE29|\\uD83D\\uDE2A|\\uD83D\\uDE2B|\\uD83D\\uDE2D|\\uD83D\\uDE30|\\uD83D\\uDE31|\\uD83D\\uDE32|\\uD83D\\uDE33|\\uD83D\\uDE35|\\uD83D\\uDE37|\\uD83D\\uDE38|\\uD83D\\uDE39|\\uD83D\\uDE3A|\\uD83D\\uDE3B|\\uD83D\\uDE3C|\\uD83D\\uDE3D|\\uD83D\\uDE3E|\\uD83D\\uDE3F|\\uD83D\\uDE40|\\uD83D\\uDE45|\\uD83D\\uDE46|\\uD83D\\uDE47|\\uD83D\\uDE48|\\uD83D\\uDE49|\\uD83D\\uDE4A|\\uD83D\\uDE4B|\\uD83D\\uDE4C|\\uD83D\\uDE4D|\\uD83D\\uDE4E|\\uD83D\\uDE4F|\\uD83D\\uDE80|\\uD83D\\uDE83|\\uD83D\\uDE84|\\uD83D\\uDE85|\\uD83D\\uDE87|\\uD83D\\uDE89|\\uD83D\\uDE8C|\\uD83D\\uDE8F|\\uD83D\\uDE91|\\uD83D\\uDE92|\\uD83D\\uDE93|\\uD83D\\uDE95|\\uD83D\\uDE97|\\uD83D\\uDE99|\\uD83D\\uDE9A|\\uD83D\\uDEA2|\\uD83D\\uDEA4|\\uD83D\\uDEA5|\\uD83D\\uDEA7|\\uD83D\\uDEA8|\\uD83D\\uDEA9|\\uD83D\\uDEAA|\\uD83D\\uDEAB|\\uD83D\\uDEAC|\\uD83D\\uDEAD|\\uD83D\\uDEB2|\\uD83D\\uDEB6|\\uD83D\\uDEB9|\\uD83D\\uDEBA|\\uD83D\\uDEBB|\\uD83D\\uDEBC|\\uD83D\\uDEBD|\\uD83D\\uDEBE|\\uD83D\\uDEC0|\\uD83E\\uDD18|\\uD83D\\uDE00|\\uD83D\\uDE07|\\uD83D\\uDE08|\\uD83D\\uDE0E|\\uD83D\\uDE10|\\uD83D\\uDE11|\\uD83D\\uDE15|\\uD83D\\uDE17|\\uD83D\\uDE19|\\uD83D\\uDE1B|\\uD83D\\uDE1F|\\uD83D\\uDE26|\\uD83D\\uDE27|\\uD83D\\uDE2C|\\uD83D\\uDE2E|\\uD83D\\uDE2F|\\uD83D\\uDE34|\\uD83D\\uDE36|\\uD83D\\uDE81|\\uD83D\\uDE82|\\uD83D\\uDE86|\\uD83D\\uDE88|\\uD83D\\uDE8A|\\uD83D\\uDE8D|\\uD83D\\uDE8E|\\uD83D\\uDE90|\\uD83D\\uDE94|\\uD83D\\uDE96|\\uD83D\\uDE98|\\uD83D\\uDE9B|\\uD83D\\uDE9C|\\uD83D\\uDE9D|\\uD83D\\uDE9E|\\uD83D\\uDE9F|\\uD83D\\uDEA0|\\uD83D\\uDEA1|\\uD83D\\uDEA3|\\uD83D\\uDEA6|\\uD83D\\uDEAE|\\uD83D\\uDEAF|\\uD83D\\uDEB0|\\uD83D\\uDEB1|\\uD83D\\uDEB3|\\uD83D\\uDEB4|\\uD83D\\uDEB5|\\uD83D\\uDEB7|\\uD83D\\uDEB8|\\uD83D\\uDEBF|\\uD83D\\uDEC1|\\uD83D\\uDEC2|\\uD83D\\uDEC3|\\uD83D\\uDEC4|\\uD83D\\uDEC5|\\uD83C\\uDF0D|\\uD83C\\uDF0E|\\uD83C\\uDF10|\\uD83C\\uDF12|\\uD83C\\uDF16|\\uD83C\\uDF17|\\uD83C\\uDF18|\\uD83C\\uDF1A|\\uD83C\\uDF1C|\\uD83C\\uDF1D|\\uD83C\\uDF1E|\\uD83C\\uDF32|\\uD83C\\uDF33|\\uD83C\\uDF4B|\\uD83C\\uDF50|\\uD83C\\uDF7C|\\uD83C\\uDFC7|\\uD83C\\uDFC9|\\uD83C\\uDFE4|\\uD83D\\uDC00|\\uD83D\\uDC01|\\uD83D\\uDC02|\\uD83D\\uDC03|\\uD83D\\uDC04|\\uD83D\\uDC05|\\uD83D\\uDC06|\\uD83D\\uDC07|\\uD83D\\uDC08|\\uD83D\\uDC09|\\uD83D\\uDC0A|\\uD83D\\uDC0B|\\uD83D\\uDC0F|\\uD83D\\uDC10|\\uD83D\\uDC13|\\uD83D\\uDC15|\\uD83D\\uDC16|\\uD83D\\uDC2A|\\uD83D\\uDC65|\\uD83D\\uDC6C|\\uD83D\\uDC6D|\\uD83D\\uDCAD|\\uD83D\\uDCB6|\\uD83D\\uDCB7|\\uD83D\\uDCEC|\\uD83D\\uDCED|\\uD83D\\uDCEF|\\uD83D\\uDCF5|\\uD83D\\uDD00|\\uD83D\\uDD01|\\uD83D\\uDD02|\\uD83D\\uDD04|\\uD83D\\uDD05|\\uD83D\\uDD06|\\uD83D\\uDD07|\\uD83D\\uDD09|\\uD83D\\uDD15|\\uD83D\\uDD2C|\\uD83D\\uDD2D|\\uD83D\\uDD5C|\\uD83D\\uDD5D|\\uD83D\\uDD5E|\\uD83D\\uDD5F|\\uD83D\\uDD60|\\uD83D\\uDD61|\\uD83D\\uDD62|\\uD83D\\uDD63|\\uD83D\\uDD64|\\uD83D\\uDD65|\\uD83D\\uDD66|\\uD83D\\uDD67|\\uD83D\\uDD08|\\uD83D\\uDE8B|\\uD83C\\uDFC5|\\uD83C\\uDFF4|\\uD83D\\uDCF8|\\uD83D\\uDECC|\\uD83D\\uDD95|\\uD83D\\uDD96|\\uD83D\\uDE41|\\uD83D\\uDE42|\\uD83D\\uDEEB|\\uD83D\\uDEEC|\\uD83C\\uDFFB|\\uD83C\\uDFFC|\\uD83C\\uDFFD|\\uD83C\\uDFFE|\\uD83C\\uDFFF|\\uD83D\\uDE43|\\uD83E\\uDD11|\\uD83E\\uDD13|\\uD83E\\uDD17|\\uD83D\\uDE44|\\uD83E\\uDD14|\\uD83E\\uDD10|\\uD83E\\uDD12|\\uD83E\\uDD15|\\uD83E\\uDD16|\\uD83E\\uDD81|\\uD83E\\uDD84|\\uD83E\\uDD82|\\uD83E\\uDD80|\\uD83E\\uDD83|\\uD83E\\uDDC0|\\uD83C\\uDF2D|\\uD83C\\uDF2E|\\uD83C\\uDF2F|\\uD83C\\uDF7F|\\uD83C\\uDF7E|\\uD83C\\uDFF9|\\uD83C\\uDFFA|\\uD83D\\uDED0|\\uD83D\\uDD4B|\\uD83D\\uDD4C|\\uD83D\\uDD4D|\\uD83D\\uDD4E|\\uD83D\\uDCFF|\\uD83C\\uDFCF|\\uD83C\\uDFD0|\\uD83C\\uDFD1|\\uD83C\\uDFD2|\\uD83C\\uDFD3|\\uD83C\\uDFF8|\\uD83C\\uDF26|\\uD83C\\uDF25|\\uD83C\\uDF24|\\uD83D\\uDEF3|\\uD83D\\uDEE9|\\uD83D\\uDEE5|\\uD83D\\uDEE4|\\uD83D\\uDEE3|\\uD83D\\uDECF|\\uD83D\\uDECE|\\uD83D\\uDECD|\\uD83D\\uDECB|\\uD83C\\uDFDF|\\uD83C\\uDFDE|\\uD83C\\uDFDD|\\uD83C\\uDFDC|\\uD83C\\uDFDB|\\uD83C\\uDFDA|\\uD83C\\uDFD9|\\uD83C\\uDFD8|\\uD83C\\uDFD7|\\uD83C\\uDFD6|\\uD83C\\uDFD5|\\uD83C\\uDFD4|\\uD83D\\uDD90|\\uD83D\\uDD75|\\uD83D\\uDD74|\\uD83D\\uDC41|\\uD83C\\uDF7D|\\uD83D\\uDEF0|\\uD83D\\uDEE2|\\uD83D\\uDEE1|\\uD83D\\uDEE0|\\uD83D\\uDDFA|\\uD83D\\uDDF3|\\uD83D\\uDDEF|\\uD83D\\uDDE3|\\uD83D\\uDDE1|\\uD83D\\uDDDE|\\uD83D\\uDDDD|\\uD83D\\uDDDC|\\uD83D\\uDDD3|\\uD83D\\uDDD2|\\uD83D\\uDDD1|\\uD83D\\uDDC4|\\uD83D\\uDDC3|\\uD83D\\uDDC2|\\uD83D\\uDDBC|\\uD83D\\uDDB2|\\uD83D\\uDDA8|\\uD83D\\uDDA5|\\uD83D\\uDD8D|\\uD83D\\uDD8C|\\uD83D\\uDD8B|\\uD83D\\uDD8A|\\uD83D\\uDD87|\\uD83D\\uDD79|\\uD83D\\uDD76|\\uD83D\\uDD73|\\uD83D\\uDD70|\\uD83D\\uDD6F|\\uD83D\\uDD4A|\\uD83D\\uDD49|\\uD83D\\uDCFD|\\uD83C\\uDFF7|\\uD83C\\uDFF5|\\uD83C\\uDFF3|\\uD83C\\uDF9B|\\uD83C\\uDF9A|\\uD83C\\uDF99|\\uD83C\\uDF21|\\uD83D\\uDD78|\\uD83D\\uDD77|\\uD83D\\uDC3F|\\uD83C\\uDF2C|\\uD83C\\uDF2B|\\uD83C\\uDF2A|\\uD83C\\uDF29|\\uD83C\\uDF28|\\uD83C\\uDF27|\\uD83C\\uDF36|\\uD83C\\uDF97|\\uD83C\\uDF96|\\uD83C\\uDFCE|\\uD83C\\uDFCD|\\uD83C\\uDFCC|\\uD83C\\uDFCB|\\uD83C\\uDF9F|\\uD83C\\uDF9E|\\uD83C\\uDE37|\\uD83C\\uDE2F|\\uD83C\\uDE1A|\\uD83C\\uDE02|\\uD83C\\uDD7F|\\uD83C\\uDC04|\\uD83C\\uDFE1|\\u2714|\\u2733|\\u2734|\\u2744|\\u2747|\\u2757|\\u2764|\\u27A1|\\u2934|\\u2935|\\u2B05|\\u2B06|\\u2B07|\\u2B1B|\\u2B1C|\\u2B50|\\u2B55|\\u3030|\\u303D|\\u3297|\\u3299|\\u2712|\\u270F|\\u270C|\\u2709|\\u2708|\\u2702|\\u26FD|\\u26FA|\\u26F5|\\u26F3|\\u26F2|\\u26EA|\\u26D4|\\u26C5|\\u26C4|\\u26BE|\\u26BD|\\u26AB|\\u26AA|\\u26A1|\\u26A0|\\u2693|\\u267F|\\u267B|\\u2668|\\u2666|\\u2665|\\u2663|\\u2660|\\u2653|\\u2652|\\u2651|\\u271D|\\u2650|\\u264F|\\u264E|\\u264D|\\u264C|\\u264B|\\u264A|\\u2649|\\u2648|\\u263A|\\u261D|\\u2615|\\u2614|\\u2611|\\u2328|\\u260E|\\u2601|\\u2600|\\u25FE|\\u25FD|\\u25FC|\\u25FB|\\u25C0|\\u25B6|\\u25AB|\\u25AA|\\u24C2|\\u2716|\\u231A|\\u21AA|\\u21A9|\\u2199|\\u2198|\\u2197|\\u2196|\\u2195|\\u2194|\\u2139|\\u2122|\\u270D|\\u2049|\\u203C|\\u00AE|\\u00A9|\\u27BF|\\u27B0|\\u2797|\\u2796|\\u2795|\\u2755|\\u2754|\\u2753|\\u274E|\\u274C|\\u2728|\\u270B|\\u270A|\\u2705|\\u26CE|\\u23F3|\\u23F0|\\u23EC|\\u23ED|\\u23EE|\\u23EF|\\u23F1|\\u23F2|\\u23F8|\\u23F9|\\u23FA|\\u2602|\\u2603|\\u2604|\\u2618|\\u2620|\\u2622|\\u2623|\\u2626|\\u262A|\\u262E|\\u262F|\\u2638|\\u2639|\\u2692|\\u2694|\\u2696|\\u2697|\\u2699|\\u269B|\\u269C|\\u26B0|\\u26B1|\\u26C8|\\u26CF|\\u26D1|\\u26D3|\\u26E9|\\u26F0|\\u26F1|\\u26F4|\\u26F7|\\u26F8|\\u26F9|\\u2721|\\u2763|\\u23EB|\\u23EA|\\u23E9|\\u231B|\\uD83E\\uDD19\\uD83C\\uDFFE|\\uD83E\\uDD34\\uD83C\\uDFFB|\\uD83E\\uDD34\\uD83C\\uDFFE|\\uD83E\\uDD34\\uD83C\\uDFFF|\\uD83E\\uDD36\\uD83C\\uDFFB|\\uD83E\\uDD36\\uD83C\\uDFFC|\\uD83E\\uDD36\\uD83C\\uDFFD|\\uD83E\\uDD36\\uD83C\\uDFFE|\\uD83E\\uDD36\\uD83C\\uDFFF|\\uD83E\\uDD35\\uD83C\\uDFFB|\\uD83E\\uDD35\\uD83C\\uDFFC|\\uD83E\\uDD35\\uD83C\\uDFFD|\\uD83E\\uDD35\\uD83C\\uDFFE|\\uD83E\\uDD35\\uD83C\\uDFFF|\\uD83E\\uDD37\\uD83C\\uDFFB|\\uD83E\\uDD37\\uD83C\\uDFFC|\\uD83E\\uDD37\\uD83C\\uDFFD|\\uD83E\\uDD37\\uD83C\\uDFFE|\\uD83E\\uDD37\\uD83C\\uDFFF|\\uD83E\\uDD26\\uD83C\\uDFFB|\\uD83E\\uDD26\\uD83C\\uDFFC|\\uD83E\\uDD26\\uD83C\\uDFFD|\\uD83E\\uDD26\\uD83C\\uDFFE|\\uD83E\\uDD26\\uD83C\\uDFFF|\\uD83E\\uDD30\\uD83C\\uDFFB|\\uD83E\\uDD30\\uD83C\\uDFFC|\\uD83E\\uDD30\\uD83C\\uDFFD|\\uD83E\\uDD30\\uD83C\\uDFFE|\\uD83E\\uDD30\\uD83C\\uDFFF|\\uD83D\\uDD7A\\uD83C\\uDFFB|\\uD83D\\uDD7A\\uD83C\\uDFFC|\\uD83D\\uDD7A\\uD83C\\uDFFD|\\uD83D\\uDD7A\\uD83C\\uDFFE|\\uD83D\\uDD7A\\uD83C\\uDFFF|\\uD83E\\uDD33\\uD83C\\uDFFB|\\uD83E\\uDD33\\uD83C\\uDFFC|\\uD83E\\uDD33\\uD83C\\uDFFD|\\uD83E\\uDD33\\uD83C\\uDFFE|\\uD83E\\uDD33\\uD83C\\uDFFF|\\uD83E\\uDD1E\\uD83C\\uDFFB|\\uD83E\\uDD1E\\uD83C\\uDFFC|\\uD83E\\uDD1E\\uD83C\\uDFFD|\\uD83E\\uDD1E\\uD83C\\uDFFE|\\uD83E\\uDD1E\\uD83C\\uDFFF|\\uD83E\\uDD19\\uD83C\\uDFFB|\\uD83E\\uDD19\\uD83C\\uDFFC|\\uD83E\\uDD19\\uD83C\\uDFFD|\\uD83E\\uDD34\\uD83C\\uDFFD|\\uD83E\\uDD19\\uD83C\\uDFFF|\\uD83E\\uDD1B\\uD83C\\uDFFB|\\uD83E\\uDD1B\\uD83C\\uDFFC|\\uD83E\\uDD1B\\uD83C\\uDFFD|\\uD83E\\uDD1B\\uD83C\\uDFFE|\\uD83E\\uDD1B\\uD83C\\uDFFF|\\uD83E\\uDD1C\\uD83C\\uDFFB|\\uD83E\\uDD1C\\uD83C\\uDFFC|\\uD83E\\uDD1C\\uD83C\\uDFFD|\\uD83E\\uDD1C\\uD83C\\uDFFE|\\uD83E\\uDD1C\\uD83C\\uDFFF|\\uD83E\\uDD1A\\uD83C\\uDFFB|\\uD83E\\uDD1A\\uD83C\\uDFFC|\\uD83E\\uDD1A\\uD83C\\uDFFD|\\uD83E\\uDD1A\\uD83C\\uDFFE|\\uD83E\\uDD1A\\uD83C\\uDFFF|\\uD83E\\uDD1D\\uD83C\\uDFFB|\\uD83E\\uDD1D\\uD83C\\uDFFC|\\uD83E\\uDD1D\\uD83C\\uDFFD|\\uD83E\\uDD1D\\uD83C\\uDFFE|\\uD83E\\uDD1D\\uD83C\\uDFFF|\\uD83E\\uDD38\\uD83C\\uDFFB|\\uD83E\\uDD38\\uD83C\\uDFFC|\\uD83E\\uDD38\\uD83C\\uDFFD|\\uD83E\\uDD38\\uD83C\\uDFFE|\\uD83E\\uDD38\\uD83C\\uDFFF|\\uD83E\\uDD3C\\uD83C\\uDFFC|\\uD83E\\uDD3C\\uD83C\\uDFFB|\\uD83E\\uDD3C\\uD83C\\uDFFD|\\uD83E\\uDD3C\\uD83C\\uDFFE|\\uD83E\\uDD3C\\uD83C\\uDFFF|\\uD83E\\uDD3D\\uD83C\\uDFFB|\\uD83E\\uDD3D\\uD83C\\uDFFC|\\uD83E\\uDD3D\\uD83C\\uDFFD|\\uD83E\\uDD3D\\uD83C\\uDFFE|\\uD83E\\uDD3D\\uD83C\\uDFFF|\\uD83E\\uDD3E\\uD83C\\uDFFB|\\uD83E\\uDD3E\\uD83C\\uDFFC|\\uD83E\\uDD3E\\uD83C\\uDFFD|\\uD83E\\uDD3E\\uD83C\\uDFFE|\\uD83E\\uDD3E\\uD83C\\uDFFF|\\uD83E\\uDD39\\uD83C\\uDFFB|\\uD83E\\uDD39\\uD83C\\uDFFC|\\uD83E\\uDD39\\uD83C\\uDFFD|\\uD83E\\uDD39\\uD83C\\uDFFE|\\uD83E\\uDD39\\uD83C\\uDFFF|\\uD83E\\uDD34\\uD83C\\uDFFC|\\uD83E\\uDD49|\\uD83E\\uDD48|\\uD83E\\uDD47|\\uD83E\\uDD3A|\\uD83E\\uDD45|\\uD83E\\uDD3E|\\uD83C\\uDDFF|\\uD83E\\uDD3D|\\uD83E\\uDD4B|\\uD83E\\uDD4A|\\uD83E\\uDD3C|\\uD83E\\uDD39|\\uD83E\\uDD38|\\uD83D\\uDEF6|\\uD83D\\uDEF5|\\uD83D\\uDEF4|\\uD83D\\uDED2|\\uD83D\\uDED1|\\uD83C\\uDDFE|\\uD83E\\uDD44|\\uD83E\\uDD42|\\uD83E\\uDD43|\\uD83E\\uDD59|\\uD83E\\uDD58|\\uD83E\\uDD57|\\uD83E\\uDD56|\\uD83E\\uDD55|\\uD83E\\uDD54|\\uD83E\\uDD53|\\uD83E\\uDD52|\\uD83E\\uDD51|\\uD83E\\uDD50|\\uD83E\\uDD40|\\uD83E\\uDD8F|\\uD83E\\uDD8E|\\uD83E\\uDD8D|\\uD83E\\uDD8C|\\uD83E\\uDD8B|\\uD83E\\uDD8A|\\uD83E\\uDD89|\\uD83E\\uDD88|\\uD83E\\uDD87|\\uD83C\\uDDFD|\\uD83E\\uDD86|\\uD83E\\uDD85|\\uD83D\\uDDA4|\\uD83E\\uDD1E|\\uD83E\\uDD1D|\\uD83E\\uDD1B|\\uD83E\\uDD1C|\\uD83E\\uDD1A|\\uD83E\\uDD19|\\uD83D\\uDD7A|\\uD83E\\uDD33|\\uD83E\\uDD30|\\uD83E\\uDD26|\\uD83E\\uDD37|\\uD83E\\uDD36|\\uD83E\\uDD35|\\uD83E\\uDD34|\\uD83E\\uDD27|\\uD83E\\uDD25|\\uD83E\\uDD24|\\uD83E\\uDD23|\\uD83E\\uDD22|\\uD83E\\uDD21|\\uD83E\\uDD20|\\uD83E\\uDD41|\\uD83E\\uDD90|\\uD83E\\uDD91|\\uD83E\\uDD5A|\\uD83E\\uDD5B|\\uD83E\\uDD5C|\\uD83E\\uDD5D|\\uD83E\\uDD5E|\\uD83C\\uDDFC|\\uD83C\\uDDFB|\\uD83C\\uDDFA|\\uD83C\\uDDF9|\\uD83C\\uDDF8|\\uD83C\\uDDF7|\\uD83C\\uDDF6|\\uD83C\\uDDF5|\\uD83C\\uDDF4|\\uD83C\\uDDF3|\\uD83C\\uDDF2|\\uD83C\\uDDF1|\\uD83C\\uDDF0|\\uD83C\\uDDEF|\\uD83C\\uDDEE|\\uD83C\\uDDED|\\uD83C\\uDDEC|\\uD83C\\uDDEB|\\uD83C\\uDDEA|\\uD83C\\uDDE9|\\uD83C\\uDDE8|\\uD83C\\uDDE7|\\uD83C\\uDDE6|\\uD83C\\uDF26|\\uD83C\\uDF25|\\uD83C\\uDF24|\\uD83D\\uDEF3|\\uD83D\\uDEE9|\\uD83D\\uDEE5|\\uD83D\\uDEE4|\\uD83D\\uDEE3|\\uD83D\\uDECF|\\uD83D\\uDECE|\\uD83D\\uDECD|\\uD83D\\uDECB|\\uD83C\\uDFDF|\\uD83C\\uDFDE|\\uD83C\\uDFDD|\\uD83C\\uDFDC|\\uD83C\\uDFDB|\\uD83C\\uDFDA|\\uD83C\\uDFD9|\\uD83C\\uDFD8|\\uD83C\\uDFD7|\\uD83C\\uDFD6|\\uD83C\\uDFD5|\\uD83C\\uDFD4|\\uD83D\\uDD90|\\uD83D\\uDD75|\\uD83D\\uDD74|\\uD83D\\uDC41|\\uD83C\\uDF7D|\\uD83D\\uDDB1|\\uD83D\\uDEF0|\\uD83D\\uDEE2|\\uD83D\\uDEE1|\\uD83D\\uDEE0|\\uD83D\\uDDFA|\\uD83D\\uDDF3|\\uD83D\\uDDEF|\\uD83D\\uDDE8|\\uD83D\\uDDE3|\\uD83D\\uDDE1|\\uD83D\\uDDDE|\\uD83D\\uDDDD|\\uD83D\\uDDDC|\\uD83D\\uDDD3|\\uD83D\\uDDD2|\\uD83D\\uDDD1|\\uD83D\\uDDC4|\\uD83D\\uDDC3|\\uD83D\\uDDC2|\\uD83D\\uDDBC|\\uD83D\\uDDB2|\\uD83D\\uDDA8|\\uD83D\\uDDA5|\\uD83D\\uDD8D|\\uD83D\\uDD8C|\\uD83D\\uDD8B|\\uD83D\\uDD8A|\\uD83D\\uDD87|\\uD83D\\uDD79|\\uD83D\\uDD76|\\uD83D\\uDD73|\\uD83D\\uDD70|\\uD83D\\uDD6F|\\uD83D\\uDD4A|\\uD83D\\uDD49|\\uD83D\\uDCFD|\\uD83C\\uDFF7|\\uD83C\\uDFF5|\\uD83C\\uDFF3|\\uD83C\\uDF9B|\\uD83C\\uDF9A|\\uD83C\\uDF99|\\uD83C\\uDF21|\\uD83D\\uDD78|\\uD83D\\uDD77|\\uD83D\\uDC3F|\\uD83C\\uDF2C|\\uD83C\\uDF2B|\\uD83C\\uDF2A|\\uD83C\\uDF29|\\uD83C\\uDF28|\\uD83C\\uDF27|\\uD83C\\uDF36|\\uD83C\\uDF97|\\uD83C\\uDF96|\\uD83C\\uDFCE|\\uD83C\\uDFCD|\\uD83C\\uDFCC|\\uD83C\\uDFCB|\\uD83C\\uDF9F|\\uD83C\\uDF9E|\\uD83C\\uDE37|\\uD83C\\uDE2F|\\uD83C\\uDE1A|\\uD83C\\uDE02|\\uD83C\\uDD7F|\\uD83C\\uDC04|\\u25C0|\\u2B05|\\u2B07|\\u2B1B|\\u2B1C|\\u2B50|\\u2B55|\\u3030|\\u303D|\\u3297|\\u3299|\\u2935|\\u2934|\\u27A1|\\u2764|\\u2757|\\u2747|\\u2744|\\u2734|\\u2733|\\u2716|\\u2714|\\u2712|\\u270F|\\u270C|\\u2709|\\u2708|\\u2702|\\u26FD|\\u26FA|\\u26F5|\\u26F3|\\u26F2|\\u26EA|\\u26D4|\\u26C5|\\u26C4|\\u26BE|\\u26BD|\\u26AB|\\u26AA|\\u26A1|\\u26A0|\\u271D|\\u2693|\\u267F|\\u267B|\\u2668|\\u2666|\\u2665|\\u2663|\\u2660|\\u2653|\\u2652|\\u2651|\\u2650|\\u264F|\\u264E|\\u2328|\\u264D|\\u264C|\\u264B|\\u264A|\\u2649|\\u2648|\\u263A|\\u261D|\\u2615|\\u2614|\\u2611|\\u260E|\\u2601|\\u2600|\\u25FE|\\u25FD|\\u25FC|\\u25FB|\\u2B06|\\u25B6|\\u25AB|\\u24C2|\\u231B|\\u231A|\\u21AA|\\u270D|\\u21A9|\\u2199|\\u2198|\\u2197|\\u2196|\\u2195|\\u2194|\\u2139|\\u2122|\\u2049|\\u203C|\\u00AE|\\u00A9|\\u2763|\\u2721|\\u26F9|\\u26F8|\\u26F7|\\u26F4|\\u26F1|\\u26F0|\\u26E9|\\u23CF|\\u23ED|\\u23EE|\\u23EF|\\u23F1|\\u23F2|\\u23F8|\\u23F9|\\u23FA|\\u2602|\\u2603|\\u2604|\\u2618|\\u2620|\\u2622|\\u2623|\\u2626|\\u262A|\\u262E|\\u262F|\\u2638|\\u2639|\\u2692|\\u2694|\\u2696|\\u2697|\\u2699|\\u269B|\\u269C|\\u26B0|\\u26B1|\\u26C8|\\u26CF|\\u26D1|\\u26D3|\\u25AA)", +a.jsEscapeMap={"👩❤💋👩":"1f469-2764-1f48b-1f469","👨❤💋👨":"1f468-2764-1f48b-1f468","👨👨👦👦":"1f468-1f468-1f466-1f466","👨👨👧👦":"1f468-1f468-1f467-1f466","👨👨👧👧":"1f468-1f468-1f467-1f467","👨👩👦👦":"1f468-1f469-1f466-1f466","👨👩👧👦":"1f468-1f469-1f467-1f466","👨👩👧👧":"1f468-1f469-1f467-1f467","👩👩👦👦":"1f469-1f469-1f466-1f466","👩👩👧👦":"1f469-1f469-1f467-1f466","👩👩👧👧":"1f469-1f469-1f467-1f467","👩❤👩":"1f469-2764-1f469","👨❤👨":"1f468-2764-1f468","👨👨👦":"1f468-1f468-1f466","👨👨👧":"1f468-1f468-1f467","👨👩👧":"1f468-1f469-1f467","👩👩👦":"1f469-1f469-1f466","👩👩👧":"1f469-1f469-1f467","👁🗨":"1f441-1f5e8","#⃣":"0023-20e3","0⃣":"0030-20e3","1⃣":"0031-20e3","2⃣":"0032-20e3","3⃣":"0033-20e3","4⃣":"0034-20e3","5⃣":"0035-20e3","6⃣":"0036-20e3","7⃣":"0037-20e3","8⃣":"0038-20e3","9⃣":"0039-20e3","*⃣":"002a-20e3","🤾🏿":"1f93e-1f3ff","🤾🏾":"1f93e-1f3fe","🤾🏽":"1f93e-1f3fd","🤾🏼":"1f93e-1f3fc","🤾🏻":"1f93e-1f3fb","🤽🏿":"1f93d-1f3ff","🤽🏾":"1f93d-1f3fe","🤽🏽":"1f93d-1f3fd","🤽🏼":"1f93d-1f3fc","🤽🏻":"1f93d-1f3fb","🤼🏿":"1f93c-1f3ff","🤼🏾":"1f93c-1f3fe","🤼🏽":"1f93c-1f3fd","🤼🏼":"1f93c-1f3fc","🤼🏻":"1f93c-1f3fb","🤹🏿":"1f939-1f3ff","🤹🏾":"1f939-1f3fe","🤹🏽":"1f939-1f3fd","🤹🏼":"1f939-1f3fc","🤹🏻":"1f939-1f3fb","🤸🏿":"1f938-1f3ff","🤸🏾":"1f938-1f3fe","🤸🏽":"1f938-1f3fd","🤸🏼":"1f938-1f3fc","🤸🏻":"1f938-1f3fb","🤷🏿":"1f937-1f3ff","🤷🏾":"1f937-1f3fe","🤷🏽":"1f937-1f3fd","🤷🏼":"1f937-1f3fc","🤷🏻":"1f937-1f3fb","🤶🏿":"1f936-1f3ff","🤶🏾":"1f936-1f3fe","🤶🏽":"1f936-1f3fd","🤶🏼":"1f936-1f3fc","🤶🏻":"1f936-1f3fb","🤵🏿":"1f935-1f3ff","🤵🏾":"1f935-1f3fe","🤵🏽":"1f935-1f3fd","🤵🏼":"1f935-1f3fc","🤵🏻":"1f935-1f3fb","🤴🏿":"1f934-1f3ff","🤴🏾":"1f934-1f3fe","🤴🏽":"1f934-1f3fd","🤴🏼":"1f934-1f3fc","🤴🏻":"1f934-1f3fb","🤳🏿":"1f933-1f3ff","🤳🏾":"1f933-1f3fe","🤳🏽":"1f933-1f3fd","🤳🏼":"1f933-1f3fc","🤳🏻":"1f933-1f3fb","🤰🏿":"1f930-1f3ff","🤰🏾":"1f930-1f3fe","🤰🏽":"1f930-1f3fd","🤰🏼":"1f930-1f3fc","🤰🏻":"1f930-1f3fb","🤦🏿":"1f926-1f3ff","🤦🏾":"1f926-1f3fe","🤦🏽":"1f926-1f3fd","🤦🏼":"1f926-1f3fc","🤦🏻":"1f926-1f3fb","🤞🏿":"1f91e-1f3ff","🤞🏾":"1f91e-1f3fe","🤞🏽":"1f91e-1f3fd","🤞🏼":"1f91e-1f3fc","🤞🏻":"1f91e-1f3fb","🤝🏿":"1f91d-1f3ff","🤝🏾":"1f91d-1f3fe","🤝🏽":"1f91d-1f3fd","🤝🏼":"1f91d-1f3fc","🤝🏻":"1f91d-1f3fb","🤜🏿":"1f91c-1f3ff","🤜🏾":"1f91c-1f3fe","🤜🏽":"1f91c-1f3fd","🤜🏼":"1f91c-1f3fc","🤜🏻":"1f91c-1f3fb","🤛🏿":"1f91b-1f3ff","🤛🏾":"1f91b-1f3fe","🤛🏽":"1f91b-1f3fd","🤛🏼":"1f91b-1f3fc","🤛🏻":"1f91b-1f3fb","🤚🏿":"1f91a-1f3ff","🤚🏾":"1f91a-1f3fe","🤚🏽":"1f91a-1f3fd","🤚🏼":"1f91a-1f3fc","🤚🏻":"1f91a-1f3fb","🤙🏿":"1f919-1f3ff","🤙🏾":"1f919-1f3fe","🤙🏽":"1f919-1f3fd","🤙🏼":"1f919-1f3fc","🤙🏻":"1f919-1f3fb","🤘🏿":"1f918-1f3ff","🤘🏾":"1f918-1f3fe","🤘🏽":"1f918-1f3fd","🤘🏼":"1f918-1f3fc","🤘🏻":"1f918-1f3fb","🛀🏿":"1f6c0-1f3ff","🛀🏾":"1f6c0-1f3fe","🛀🏽":"1f6c0-1f3fd","🛀🏼":"1f6c0-1f3fc","🛀🏻":"1f6c0-1f3fb","🚶🏿":"1f6b6-1f3ff","🚶🏾":"1f6b6-1f3fe","🚶🏽":"1f6b6-1f3fd","🚶🏼":"1f6b6-1f3fc","🚶🏻":"1f6b6-1f3fb","🚵🏿":"1f6b5-1f3ff","🚵🏾":"1f6b5-1f3fe","🚵🏽":"1f6b5-1f3fd","🚵🏼":"1f6b5-1f3fc","🚵🏻":"1f6b5-1f3fb","🚴🏿":"1f6b4-1f3ff","🚴🏾":"1f6b4-1f3fe","🚴🏽":"1f6b4-1f3fd","🚴🏼":"1f6b4-1f3fc","🚴🏻":"1f6b4-1f3fb","🚣🏿":"1f6a3-1f3ff","🚣🏾":"1f6a3-1f3fe","🚣🏽":"1f6a3-1f3fd","🚣🏼":"1f6a3-1f3fc","🚣🏻":"1f6a3-1f3fb","🙏🏿":"1f64f-1f3ff","🙏🏾":"1f64f-1f3fe","🙏🏽":"1f64f-1f3fd","🙏🏼":"1f64f-1f3fc","🙏🏻":"1f64f-1f3fb","🙎🏿":"1f64e-1f3ff","🙎🏾":"1f64e-1f3fe","🙎🏽":"1f64e-1f3fd","🙎🏼":"1f64e-1f3fc","🙎🏻":"1f64e-1f3fb","🙍🏿":"1f64d-1f3ff","🙍🏾":"1f64d-1f3fe","🙍🏽":"1f64d-1f3fd","🙍🏼":"1f64d-1f3fc","🙍🏻":"1f64d-1f3fb","🙌🏿":"1f64c-1f3ff","🙌🏾":"1f64c-1f3fe","🙌🏽":"1f64c-1f3fd","🙌🏼":"1f64c-1f3fc","🙌🏻":"1f64c-1f3fb","🙋🏿":"1f64b-1f3ff","🙋🏾":"1f64b-1f3fe","🙋🏽":"1f64b-1f3fd","🙋🏼":"1f64b-1f3fc","🙋🏻":"1f64b-1f3fb","🙇🏿":"1f647-1f3ff","🙇🏾":"1f647-1f3fe","🙇🏽":"1f647-1f3fd","🙇🏼":"1f647-1f3fc","🙇🏻":"1f647-1f3fb","🙆🏿":"1f646-1f3ff","🙆🏾":"1f646-1f3fe","🙆🏽":"1f646-1f3fd","🙆🏼":"1f646-1f3fc","🙆🏻":"1f646-1f3fb","🙅🏿":"1f645-1f3ff","🙅🏾":"1f645-1f3fe","🙅🏽":"1f645-1f3fd","🙅🏼":"1f645-1f3fc","🙅🏻":"1f645-1f3fb","🖖🏿":"1f596-1f3ff","🖖🏾":"1f596-1f3fe","🖖🏽":"1f596-1f3fd","🖖🏼":"1f596-1f3fc","🖖🏻":"1f596-1f3fb","🖕🏿":"1f595-1f3ff","🖕🏾":"1f595-1f3fe","🖕🏽":"1f595-1f3fd","🖕🏼":"1f595-1f3fc","🖕🏻":"1f595-1f3fb","🖐🏿":"1f590-1f3ff","🖐🏾":"1f590-1f3fe","🖐🏽":"1f590-1f3fd","🖐🏼":"1f590-1f3fc","🖐🏻":"1f590-1f3fb","🕺🏿":"1f57a-1f3ff","🕺🏾":"1f57a-1f3fe","🕺🏽":"1f57a-1f3fd","🕺🏼":"1f57a-1f3fc","🕺🏻":"1f57a-1f3fb","🕵🏿":"1f575-1f3ff","🕵🏾":"1f575-1f3fe","🕵🏽":"1f575-1f3fd","🕵🏼":"1f575-1f3fc","🕵🏻":"1f575-1f3fb","💪🏿":"1f4aa-1f3ff","💪🏾":"1f4aa-1f3fe","💪🏽":"1f4aa-1f3fd","💪🏼":"1f4aa-1f3fc","💪🏻":"1f4aa-1f3fb","💇🏿":"1f487-1f3ff","💇🏾":"1f487-1f3fe","💇🏽":"1f487-1f3fd","💇🏼":"1f487-1f3fc","💇🏻":"1f487-1f3fb","💆🏿":"1f486-1f3ff","💆🏾":"1f486-1f3fe","💆🏽":"1f486-1f3fd","💆🏼":"1f486-1f3fc","💆🏻":"1f486-1f3fb","💅🏿":"1f485-1f3ff","💅🏾":"1f485-1f3fe","💅🏽":"1f485-1f3fd","💅🏼":"1f485-1f3fc","💅🏻":"1f485-1f3fb","💃🏿":"1f483-1f3ff","💃🏾":"1f483-1f3fe","💃🏽":"1f483-1f3fd","💃🏼":"1f483-1f3fc","💃🏻":"1f483-1f3fb","💂🏿":"1f482-1f3ff","💂🏾":"1f482-1f3fe","💂🏽":"1f482-1f3fd","💂🏼":"1f482-1f3fc","💂🏻":"1f482-1f3fb","💁🏿":"1f481-1f3ff","💁🏾":"1f481-1f3fe","💁🏽":"1f481-1f3fd","💁🏼":"1f481-1f3fc","💁🏻":"1f481-1f3fb","👼🏿":"1f47c-1f3ff","👼🏾":"1f47c-1f3fe","👼🏽":"1f47c-1f3fd","👼🏼":"1f47c-1f3fc","👼🏻":"1f47c-1f3fb","👸🏿":"1f478-1f3ff","👸🏾":"1f478-1f3fe","👸🏽":"1f478-1f3fd","👸🏼":"1f478-1f3fc","👸🏻":"1f478-1f3fb","👷🏿":"1f477-1f3ff","👷🏾":"1f477-1f3fe","👷🏽":"1f477-1f3fd","👷🏼":"1f477-1f3fc","👷🏻":"1f477-1f3fb","👶🏿":"1f476-1f3ff","👶🏾":"1f476-1f3fe","👶🏽":"1f476-1f3fd","👶🏼":"1f476-1f3fc","👶🏻":"1f476-1f3fb","👵🏿":"1f475-1f3ff","👵🏾":"1f475-1f3fe","👵🏽":"1f475-1f3fd","👵🏼":"1f475-1f3fc","👵🏻":"1f475-1f3fb","👴🏿":"1f474-1f3ff","👴🏾":"1f474-1f3fe","👴🏽":"1f474-1f3fd","👴🏼":"1f474-1f3fc","👴🏻":"1f474-1f3fb","👳🏿":"1f473-1f3ff","👳🏾":"1f473-1f3fe","👳🏽":"1f473-1f3fd","👳🏼":"1f473-1f3fc","👳🏻":"1f473-1f3fb","👲🏿":"1f472-1f3ff","👲🏾":"1f472-1f3fe","👲🏽":"1f472-1f3fd","👲🏼":"1f472-1f3fc","👲🏻":"1f472-1f3fb","👱🏿":"1f471-1f3ff","👱🏾":"1f471-1f3fe","👱🏽":"1f471-1f3fd","👱🏼":"1f471-1f3fc","👱🏻":"1f471-1f3fb","👰🏿":"1f470-1f3ff","👰🏾":"1f470-1f3fe","👰🏽":"1f470-1f3fd","👰🏼":"1f470-1f3fc","👰🏻":"1f470-1f3fb","👮🏿":"1f46e-1f3ff","👮🏾":"1f46e-1f3fe","👮🏽":"1f46e-1f3fd","👮🏼":"1f46e-1f3fc","👮🏻":"1f46e-1f3fb","👩🏿":"1f469-1f3ff","👩🏾":"1f469-1f3fe","👩🏽":"1f469-1f3fd","👩🏼":"1f469-1f3fc","👩🏻":"1f469-1f3fb","👨🏿":"1f468-1f3ff","👨🏾":"1f468-1f3fe","👨🏽":"1f468-1f3fd","👨🏼":"1f468-1f3fc","👨🏻":"1f468-1f3fb","👧🏿":"1f467-1f3ff","👧🏾":"1f467-1f3fe","👧🏽":"1f467-1f3fd","👧🏼":"1f467-1f3fc","👧🏻":"1f467-1f3fb","👦🏿":"1f466-1f3ff","👦🏾":"1f466-1f3fe","👦🏽":"1f466-1f3fd","👦🏼":"1f466-1f3fc","👦🏻":"1f466-1f3fb","👐🏿":"1f450-1f3ff","👐🏾":"1f450-1f3fe","👐🏽":"1f450-1f3fd","👐🏼":"1f450-1f3fc","👐🏻":"1f450-1f3fb","👏🏿":"1f44f-1f3ff","👏🏾":"1f44f-1f3fe","👏🏽":"1f44f-1f3fd","👏🏼":"1f44f-1f3fc","👏🏻":"1f44f-1f3fb","👎🏿":"1f44e-1f3ff","👎🏾":"1f44e-1f3fe","👎🏽":"1f44e-1f3fd","👎🏼":"1f44e-1f3fc","👎🏻":"1f44e-1f3fb","👍🏿":"1f44d-1f3ff","👍🏾":"1f44d-1f3fe","👍🏽":"1f44d-1f3fd","👍🏼":"1f44d-1f3fc","👍🏻":"1f44d-1f3fb","👌🏿":"1f44c-1f3ff","👌🏾":"1f44c-1f3fe","👌🏽":"1f44c-1f3fd","👌🏼":"1f44c-1f3fc","👌🏻":"1f44c-1f3fb","👋🏿":"1f44b-1f3ff","👋🏾":"1f44b-1f3fe","👋🏽":"1f44b-1f3fd","👋🏼":"1f44b-1f3fc","👋🏻":"1f44b-1f3fb","👊🏿":"1f44a-1f3ff","👊🏾":"1f44a-1f3fe","👊🏽":"1f44a-1f3fd","👊🏼":"1f44a-1f3fc","👊🏻":"1f44a-1f3fb","👉🏿":"1f449-1f3ff","👉🏾":"1f449-1f3fe","👉🏽":"1f449-1f3fd","👉🏼":"1f449-1f3fc","👉🏻":"1f449-1f3fb","👈🏿":"1f448-1f3ff","👈🏾":"1f448-1f3fe","👈🏽":"1f448-1f3fd","👈🏼":"1f448-1f3fc","👈🏻":"1f448-1f3fb","👇🏿":"1f447-1f3ff","👇🏾":"1f447-1f3fe","👇🏽":"1f447-1f3fd","👇🏼":"1f447-1f3fc","👇🏻":"1f447-1f3fb","👆🏿":"1f446-1f3ff","👆🏾":"1f446-1f3fe","👆🏽":"1f446-1f3fd","👆🏼":"1f446-1f3fc","👆🏻":"1f446-1f3fb","👃🏿":"1f443-1f3ff","👃🏾":"1f443-1f3fe","👃🏽":"1f443-1f3fd","👃🏼":"1f443-1f3fc","👃🏻":"1f443-1f3fb","👂🏿":"1f442-1f3ff","👂🏾":"1f442-1f3fe","👂🏽":"1f442-1f3fd","👂🏼":"1f442-1f3fc","👂🏻":"1f442-1f3fb","🏳🌈":"1f3f3-1f308","🏋🏿":"1f3cb-1f3ff","🏋🏾":"1f3cb-1f3fe","🏋🏽":"1f3cb-1f3fd","🏋🏼":"1f3cb-1f3fc","🏋🏻":"1f3cb-1f3fb","🏊🏿":"1f3ca-1f3ff","🏊🏾":"1f3ca-1f3fe","🏊🏽":"1f3ca-1f3fd","🏊🏼":"1f3ca-1f3fc","🏊🏻":"1f3ca-1f3fb","🏇🏿":"1f3c7-1f3ff","🏇🏾":"1f3c7-1f3fe","🏇🏽":"1f3c7-1f3fd","🏇🏼":"1f3c7-1f3fc","🏇🏻":"1f3c7-1f3fb","🏄🏿":"1f3c4-1f3ff","🏄🏾":"1f3c4-1f3fe","🏄🏽":"1f3c4-1f3fd","🏄🏼":"1f3c4-1f3fc","🏄🏻":"1f3c4-1f3fb","🏃🏿":"1f3c3-1f3ff","🏃🏾":"1f3c3-1f3fe","🏃🏽":"1f3c3-1f3fd","🏃🏼":"1f3c3-1f3fc","🏃🏻":"1f3c3-1f3fb","🎅🏿":"1f385-1f3ff","🎅🏾":"1f385-1f3fe","🎅🏽":"1f385-1f3fd","🎅🏼":"1f385-1f3fc","🎅🏻":"1f385-1f3fb","🇿🇼":"1f1ff-1f1fc","🇿🇲":"1f1ff-1f1f2","🇿🇦":"1f1ff-1f1e6","🇾🇹":"1f1fe-1f1f9","🇾🇪":"1f1fe-1f1ea","🇽🇰":"1f1fd-1f1f0","🇼🇸":"1f1fc-1f1f8","🇼🇫":"1f1fc-1f1eb","🇻🇺":"1f1fb-1f1fa","🇻🇳":"1f1fb-1f1f3","🇻🇮":"1f1fb-1f1ee","🇻🇬":"1f1fb-1f1ec","🇻🇪":"1f1fb-1f1ea","🇻🇨":"1f1fb-1f1e8","🇻🇦":"1f1fb-1f1e6","🇺🇿":"1f1fa-1f1ff","🇺🇾":"1f1fa-1f1fe","🇺🇸":"1f1fa-1f1f8","🇺🇲":"1f1fa-1f1f2","🇺🇬":"1f1fa-1f1ec","🇺🇦":"1f1fa-1f1e6","🇹🇿":"1f1f9-1f1ff","🇹🇼":"1f1f9-1f1fc","🇹🇻":"1f1f9-1f1fb","🇹🇹":"1f1f9-1f1f9","🇹🇷":"1f1f9-1f1f7","🇹🇴":"1f1f9-1f1f4","🇹🇳":"1f1f9-1f1f3","🇹🇲":"1f1f9-1f1f2","🇹🇱":"1f1f9-1f1f1","🇹🇰":"1f1f9-1f1f0","🇹🇯":"1f1f9-1f1ef","🇹🇭":"1f1f9-1f1ed","🇹🇬":"1f1f9-1f1ec","🇹🇫":"1f1f9-1f1eb","🇹🇩":"1f1f9-1f1e9","🇹🇨":"1f1f9-1f1e8","🇹🇦":"1f1f9-1f1e6","🇸🇿":"1f1f8-1f1ff","🇸🇾":"1f1f8-1f1fe","🇸🇽":"1f1f8-1f1fd","🇸🇻":"1f1f8-1f1fb","🇸🇹":"1f1f8-1f1f9","🇸🇸":"1f1f8-1f1f8","🇸🇷":"1f1f8-1f1f7","🇸🇴":"1f1f8-1f1f4","🇸🇳":"1f1f8-1f1f3","🇸🇲":"1f1f8-1f1f2","🇸🇱":"1f1f8-1f1f1","🇸🇰":"1f1f8-1f1f0","🇸🇯":"1f1f8-1f1ef","🇸🇮":"1f1f8-1f1ee","🇸🇭":"1f1f8-1f1ed","🇸🇬":"1f1f8-1f1ec","🇸🇪":"1f1f8-1f1ea","🇸🇩":"1f1f8-1f1e9","🇸🇨":"1f1f8-1f1e8","🇸🇧":"1f1f8-1f1e7","🇸🇦":"1f1f8-1f1e6","🇷🇼":"1f1f7-1f1fc","🇷🇺":"1f1f7-1f1fa","🇷🇸":"1f1f7-1f1f8","🇷🇴":"1f1f7-1f1f4","🇷🇪":"1f1f7-1f1ea","🇶🇦":"1f1f6-1f1e6","🇵🇾":"1f1f5-1f1fe","🇵🇼":"1f1f5-1f1fc","🇵🇹":"1f1f5-1f1f9","🇵🇸":"1f1f5-1f1f8","🇵🇷":"1f1f5-1f1f7","🇵🇳":"1f1f5-1f1f3","🇵🇲":"1f1f5-1f1f2","🇵🇱":"1f1f5-1f1f1","🇵🇰":"1f1f5-1f1f0","🇵🇭":"1f1f5-1f1ed","🇵🇬":"1f1f5-1f1ec","🇵🇫":"1f1f5-1f1eb","🇵🇪":"1f1f5-1f1ea","🇵🇦":"1f1f5-1f1e6","🇴🇲":"1f1f4-1f1f2","🇳🇿":"1f1f3-1f1ff","🇳🇺":"1f1f3-1f1fa","🇳🇷":"1f1f3-1f1f7","🇳🇵":"1f1f3-1f1f5","🇳🇴":"1f1f3-1f1f4","🇳🇱":"1f1f3-1f1f1","🇳🇮":"1f1f3-1f1ee","🇳🇬":"1f1f3-1f1ec","🇳🇫":"1f1f3-1f1eb","🇳🇪":"1f1f3-1f1ea","🇳🇨":"1f1f3-1f1e8","🇳🇦":"1f1f3-1f1e6","🇲🇿":"1f1f2-1f1ff","🇲🇾":"1f1f2-1f1fe","🇲🇽":"1f1f2-1f1fd","🇲🇼":"1f1f2-1f1fc","🇲🇻":"1f1f2-1f1fb","🇲🇺":"1f1f2-1f1fa","🇲🇹":"1f1f2-1f1f9","🇲🇸":"1f1f2-1f1f8","🇲🇷":"1f1f2-1f1f7","🇲🇶":"1f1f2-1f1f6","🇲🇵":"1f1f2-1f1f5","🇲🇴":"1f1f2-1f1f4","🇲🇳":"1f1f2-1f1f3","🇲🇲":"1f1f2-1f1f2","🇲🇱":"1f1f2-1f1f1","🇲🇰":"1f1f2-1f1f0","🇲🇭":"1f1f2-1f1ed","🇲🇬":"1f1f2-1f1ec","🇲🇫":"1f1f2-1f1eb","🇲🇪":"1f1f2-1f1ea","🇲🇩":"1f1f2-1f1e9","🇲🇨":"1f1f2-1f1e8","🇲🇦":"1f1f2-1f1e6","🇱🇾":"1f1f1-1f1fe","🇱🇻":"1f1f1-1f1fb","🇱🇺":"1f1f1-1f1fa","🇱🇹":"1f1f1-1f1f9","🇱🇸":"1f1f1-1f1f8","🇱🇷":"1f1f1-1f1f7","🇱🇰":"1f1f1-1f1f0","🇱🇮":"1f1f1-1f1ee","🇱🇨":"1f1f1-1f1e8","🇱🇧":"1f1f1-1f1e7","🇱🇦":"1f1f1-1f1e6","🇰🇿":"1f1f0-1f1ff","🇰🇾":"1f1f0-1f1fe","🇰🇼":"1f1f0-1f1fc","🇰🇷":"1f1f0-1f1f7","🇰🇵":"1f1f0-1f1f5","🇰🇳":"1f1f0-1f1f3","🇰🇲":"1f1f0-1f1f2","🇰🇮":"1f1f0-1f1ee","🇰🇭":"1f1f0-1f1ed","🇰🇬":"1f1f0-1f1ec","🇰🇪":"1f1f0-1f1ea","🇯🇵":"1f1ef-1f1f5","🇯🇴":"1f1ef-1f1f4","🇯🇲":"1f1ef-1f1f2","🇯🇪":"1f1ef-1f1ea","🇮🇹":"1f1ee-1f1f9","🇮🇸":"1f1ee-1f1f8","🇮🇷":"1f1ee-1f1f7","🇮🇶":"1f1ee-1f1f6","🇮🇴":"1f1ee-1f1f4","🇮🇳":"1f1ee-1f1f3","🇮🇲":"1f1ee-1f1f2","🇮🇱":"1f1ee-1f1f1","🇮🇪":"1f1ee-1f1ea","🇮🇩":"1f1ee-1f1e9","🇮🇨":"1f1ee-1f1e8","🇭🇺":"1f1ed-1f1fa","🇭🇹":"1f1ed-1f1f9","🇭🇷":"1f1ed-1f1f7","🇭🇳":"1f1ed-1f1f3","🇭🇲":"1f1ed-1f1f2","🇭🇰":"1f1ed-1f1f0","🇬🇾":"1f1ec-1f1fe","🇬🇼":"1f1ec-1f1fc","🇬🇺":"1f1ec-1f1fa","🇬🇹":"1f1ec-1f1f9","🇬🇸":"1f1ec-1f1f8","🇬🇷":"1f1ec-1f1f7","🇬🇶":"1f1ec-1f1f6","🇬🇵":"1f1ec-1f1f5","🇬🇳":"1f1ec-1f1f3","🇬🇲":"1f1ec-1f1f2","🇬🇱":"1f1ec-1f1f1","🇬🇮":"1f1ec-1f1ee","🇬🇭":"1f1ec-1f1ed","🇬🇬":"1f1ec-1f1ec","🇬🇫":"1f1ec-1f1eb","🇬🇪":"1f1ec-1f1ea","🇬🇩":"1f1ec-1f1e9","🇬🇧":"1f1ec-1f1e7","🇬🇦":"1f1ec-1f1e6","🇫🇷":"1f1eb-1f1f7","🇫🇴":"1f1eb-1f1f4","🇫🇲":"1f1eb-1f1f2","🇫🇰":"1f1eb-1f1f0","🇫🇯":"1f1eb-1f1ef","🇫🇮":"1f1eb-1f1ee","🇪🇺":"1f1ea-1f1fa","🇪🇹":"1f1ea-1f1f9","🇪🇸":"1f1ea-1f1f8","🇪🇷":"1f1ea-1f1f7","🇪🇭":"1f1ea-1f1ed","🇪🇬":"1f1ea-1f1ec","🇪🇪":"1f1ea-1f1ea","🇪🇨":"1f1ea-1f1e8","🇪🇦":"1f1ea-1f1e6","🇩🇿":"1f1e9-1f1ff","🇩🇴":"1f1e9-1f1f4","🇩🇲":"1f1e9-1f1f2","🇩🇰":"1f1e9-1f1f0","🇩🇯":"1f1e9-1f1ef","🇩🇬":"1f1e9-1f1ec","🇩🇪":"1f1e9-1f1ea","🇨🇿":"1f1e8-1f1ff","🇨🇾":"1f1e8-1f1fe","🇨🇽":"1f1e8-1f1fd","🇨🇼":"1f1e8-1f1fc","🇨🇻":"1f1e8-1f1fb","🇨🇺":"1f1e8-1f1fa","🇨🇷":"1f1e8-1f1f7","🇨🇵":"1f1e8-1f1f5","🇨🇴":"1f1e8-1f1f4","🇨🇳":"1f1e8-1f1f3","🇨🇲":"1f1e8-1f1f2","🇨🇱":"1f1e8-1f1f1","🇨🇰":"1f1e8-1f1f0","🇨🇮":"1f1e8-1f1ee","🇨🇭":"1f1e8-1f1ed","🇨🇬":"1f1e8-1f1ec","🇨🇫":"1f1e8-1f1eb","🇨🇩":"1f1e8-1f1e9","🇨🇨":"1f1e8-1f1e8","🇨🇦":"1f1e8-1f1e6","🇧🇿":"1f1e7-1f1ff","🇧🇾":"1f1e7-1f1fe","🇧🇼":"1f1e7-1f1fc","🇧🇻":"1f1e7-1f1fb","🇧🇹":"1f1e7-1f1f9","🇧🇸":"1f1e7-1f1f8","🇧🇷":"1f1e7-1f1f7","🇧🇶":"1f1e7-1f1f6","🇧🇴":"1f1e7-1f1f4","🇧🇳":"1f1e7-1f1f3","🇧🇲":"1f1e7-1f1f2","🇧🇱":"1f1e7-1f1f1","🇧🇯":"1f1e7-1f1ef","🇧🇮":"1f1e7-1f1ee","🇧🇭":"1f1e7-1f1ed","🇧🇬":"1f1e7-1f1ec","🇧🇫":"1f1e7-1f1eb","🇧🇪":"1f1e7-1f1ea","🇧🇩":"1f1e7-1f1e9","🇧🇧":"1f1e7-1f1e7","🇧🇦":"1f1e7-1f1e6","🇦🇿":"1f1e6-1f1ff","🇦🇽":"1f1e6-1f1fd","🇦🇼":"1f1e6-1f1fc","🇦🇺":"1f1e6-1f1fa","🇦🇹":"1f1e6-1f1f9","🇦🇸":"1f1e6-1f1f8","🇦🇷":"1f1e6-1f1f7","🇦🇶":"1f1e6-1f1f6","🇦🇴":"1f1e6-1f1f4","🇦🇲":"1f1e6-1f1f2","🇦🇱":"1f1e6-1f1f1","🇦🇮":"1f1e6-1f1ee","🇦🇬":"1f1e6-1f1ec","🇦🇫":"1f1e6-1f1eb","🇦🇪":"1f1e6-1f1ea","🇦🇩":"1f1e6-1f1e9","🇦🇨":"1f1e6-1f1e8","🀄":"1f004","🅿":"1f17f","🈂":"1f202","🈚":"1f21a","🈯":"1f22f","🈷":"1f237","🎞":"1f39e","🎟":"1f39f","🏋":"1f3cb","🏌":"1f3cc","🏍":"1f3cd","🏎":"1f3ce","🎖":"1f396","🎗":"1f397","🌶":"1f336","🌧":"1f327","🌨":"1f328","🌩":"1f329","🌪":"1f32a","🌫":"1f32b","🌬":"1f32c","🐿":"1f43f","🕷":"1f577","🕸":"1f578","🌡":"1f321","🎙":"1f399","🎚":"1f39a","🎛":"1f39b","🏳":"1f3f3","🏵":"1f3f5","🏷":"1f3f7","📽":"1f4fd","🕉":"1f549","🕊":"1f54a","🕯":"1f56f","🕰":"1f570","🕳":"1f573","🕶":"1f576","🕹":"1f579","🖇":"1f587","🖊":"1f58a","🖋":"1f58b","🖌":"1f58c","🖍":"1f58d","🖥":"1f5a5","🖨":"1f5a8","🖲":"1f5b2","🖼":"1f5bc","🗂":"1f5c2","🗃":"1f5c3","🗄":"1f5c4","🗑":"1f5d1","🗒":"1f5d2","🗓":"1f5d3","🗜":"1f5dc","🗝":"1f5dd","🗞":"1f5de","🗡":"1f5e1","🗣":"1f5e3","🗨":"1f5e8","🗯":"1f5ef","🗳":"1f5f3","🗺":"1f5fa","🛠":"1f6e0","🛡":"1f6e1","🛢":"1f6e2","🛰":"1f6f0","🍽":"1f37d","👁":"1f441","🕴":"1f574","🕵":"1f575","🖐":"1f590","🏔":"1f3d4","🏕":"1f3d5","🏖":"1f3d6","🏗":"1f3d7","🏘":"1f3d8","🏙":"1f3d9","🏚":"1f3da","🏛":"1f3db","🏜":"1f3dc","🏝":"1f3dd","🏞":"1f3de","🏟":"1f3df","🛋":"1f6cb","🛍":"1f6cd","🛎":"1f6ce","🛏":"1f6cf","🛣":"1f6e3","🛤":"1f6e4","🛥":"1f6e5","🛩":"1f6e9","🛳":"1f6f3","🌤":"1f324","🌥":"1f325","🌦":"1f326","🖱":"1f5b1","☝🏻":"261d-1f3fb","☝🏼":"261d-1f3fc","☝🏽":"261d-1f3fd","☝🏾":"261d-1f3fe","☝🏿":"261d-1f3ff","✌🏻":"270c-1f3fb","✌🏼":"270c-1f3fc","✌🏽":"270c-1f3fd","✌🏾":"270c-1f3fe","✌🏿":"270c-1f3ff","✊🏻":"270a-1f3fb","✊🏼":"270a-1f3fc","✊🏽":"270a-1f3fd","✊🏾":"270a-1f3fe","✊🏿":"270a-1f3ff","✋🏻":"270b-1f3fb","✋🏼":"270b-1f3fc","✋🏽":"270b-1f3fd","✋🏾":"270b-1f3fe","✋🏿":"270b-1f3ff","✍🏻":"270d-1f3fb","✍🏼":"270d-1f3fc","✍🏽":"270d-1f3fd","✍🏾":"270d-1f3fe","✍🏿":"270d-1f3ff","⛹🏻":"26f9-1f3fb","⛹🏼":"26f9-1f3fc","⛹🏽":"26f9-1f3fd","⛹🏾":"26f9-1f3fe","⛹🏿":"26f9-1f3ff","©":"00a9","®":"00ae","‼":"203c","⁉":"2049","™":"2122","ℹ":"2139","↔":"2194","↕":"2195","↖":"2196","↗":"2197","↘":"2198","↙":"2199","↩":"21a9","↪":"21aa","⌚":"231a","⌛":"231b","Ⓜ":"24c2","▪":"25aa","▫":"25ab","▶":"25b6","◀":"25c0","◻":"25fb","◼":"25fc","◽":"25fd","◾":"25fe","☀":"2600","☁":"2601","☎":"260e","☑":"2611","☔":"2614","☕":"2615","☝":"261d","☺":"263a","♈":"2648","♉":"2649","♊":"264a","♋":"264b","♌":"264c","♍":"264d","♎":"264e","♏":"264f","♐":"2650","♑":"2651","♒":"2652","♓":"2653","♠":"2660","♣":"2663","♥":"2665","♦":"2666","♨":"2668","♻":"267b","♿":"267f","⚓":"2693","⚠":"26a0","⚡":"26a1","⚪":"26aa","⚫":"26ab","⚽":"26bd","⚾":"26be","⛄":"26c4","⛅":"26c5","⛔":"26d4","⛪":"26ea","⛲":"26f2","⛳":"26f3","⛵":"26f5","⛺":"26fa","⛽":"26fd","✂":"2702","✈":"2708","✉":"2709","✌":"270c","✏":"270f","✒":"2712","✔":"2714","✖":"2716","✳":"2733","✴":"2734","❄":"2744","❇":"2747","❗":"2757","❤":"2764","➡":"27a1","⤴":"2934","⤵":"2935","⬅":"2b05","⬆":"2b06","⬇":"2b07","⬛":"2b1b","⬜":"2b1c","⭐":"2b50","⭕":"2b55","〰":"3030","〽":"303d","㊗":"3297","㊙":"3299","✝":"271d","⌨":"2328","✍":"270d","⏏":"23cf","⏭":"23ed","⏮":"23ee","⏯":"23ef","⏱":"23f1","⏲":"23f2","⏸":"23f8","⏹":"23f9","⏺":"23fa","☂":"2602","☃":"2603","☄":"2604","☘":"2618","☠":"2620","☢":"2622","☣":"2623","☦":"2626","☪":"262a","☮":"262e","☯":"262f","☸":"2638","☹":"2639","⚒":"2692","⚔":"2694","⚖":"2696","⚗":"2697","⚙":"2699","⚛":"269b","⚜":"269c","⚰":"26b0","⚱":"26b1","⛈":"26c8","⛏":"26cf","⛑":"26d1","⛓":"26d3","⛩":"26e9","⛰":"26f0","⛱":"26f1","⛴":"26f4","⛷":"26f7","⛸":"26f8","⛹":"26f9","✡":"2721","❣":"2763","🥉":"1f949","🥈":"1f948","🥇":"1f947","🤺":"1f93a","🥅":"1f945","🤾":"1f93e","🇿":"1f1ff","🤽":"1f93d","🥋":"1f94b","🥊":"1f94a","🤼":"1f93c","🤹":"1f939","🤸":"1f938","🛶":"1f6f6","🛵":"1f6f5","🛴":"1f6f4","🛒":"1f6d2","🃏":"1f0cf","🅰":"1f170","🅱":"1f171","🅾":"1f17e","🛑":"1f6d1","🆎":"1f18e","🆑":"1f191","🇾":"1f1fe","🆒":"1f192","🆓":"1f193","🆔":"1f194","🆕":"1f195","🆖":"1f196","🆗":"1f197","🆘":"1f198","🥄":"1f944","🆙":"1f199","🆚":"1f19a","🥂":"1f942","🥃":"1f943","🈁":"1f201","🥙":"1f959","🈲":"1f232","🈳":"1f233","🈴":"1f234","🈵":"1f235","🈶":"1f236","🥘":"1f958","🈸":"1f238","🈹":"1f239","🥗":"1f957","🈺":"1f23a","🉐":"1f250","🉑":"1f251","🌀":"1f300","🥖":"1f956","🌁":"1f301","🌂":"1f302","🌃":"1f303","🌄":"1f304","🌅":"1f305","🌆":"1f306","🥕":"1f955","🌇":"1f307","🌈":"1f308","🥔":"1f954","🌉":"1f309","🌊":"1f30a","🌋":"1f30b","🌌":"1f30c","🌏":"1f30f","🌑":"1f311","🥓":"1f953","🌓":"1f313","🌔":"1f314","🌕":"1f315","🌙":"1f319","🌛":"1f31b","🌟":"1f31f","🥒":"1f952","🌠":"1f320","🌰":"1f330","🥑":"1f951","🌱":"1f331","🌴":"1f334","🌵":"1f335","🌷":"1f337","🌸":"1f338","🌹":"1f339","🌺":"1f33a","🌻":"1f33b","🌼":"1f33c","🌽":"1f33d","🥐":"1f950","🌾":"1f33e","🌿":"1f33f","🍀":"1f340","🍁":"1f341","🍂":"1f342","🍃":"1f343","🍄":"1f344","🍅":"1f345","🍆":"1f346","🍇":"1f347","🍈":"1f348","🍉":"1f349","🍊":"1f34a","🥀":"1f940","🍌":"1f34c","🍍":"1f34d","🍎":"1f34e","🍏":"1f34f","🍑":"1f351","🍒":"1f352","🍓":"1f353","🦏":"1f98f","🍔":"1f354","🍕":"1f355","🍖":"1f356","🦎":"1f98e","🍗":"1f357","🍘":"1f358","🍙":"1f359","🦍":"1f98d","🍚":"1f35a","🍛":"1f35b","🦌":"1f98c","🍜":"1f35c","🍝":"1f35d","🍞":"1f35e","🍟":"1f35f","🦋":"1f98b","🍠":"1f360","🍡":"1f361","🦊":"1f98a","🍢":"1f362","🍣":"1f363","🦉":"1f989","🍤":"1f364","🍥":"1f365","🦈":"1f988","🍦":"1f366","🦇":"1f987","🍧":"1f367","🇽":"1f1fd","🍨":"1f368","🦆":"1f986","🍩":"1f369","🦅":"1f985","🍪":"1f36a","🖤":"1f5a4","🍫":"1f36b","🍬":"1f36c","🍭":"1f36d","🍮":"1f36e","🍯":"1f36f","🤞":"1f91e","🍰":"1f370","🍱":"1f371","🍲":"1f372","🤝":"1f91d","🍳":"1f373","🍴":"1f374","🍵":"1f375","🍶":"1f376","🍷":"1f377","🍸":"1f378","🍹":"1f379","🍺":"1f37a","🍻":"1f37b","🎀":"1f380","🎁":"1f381","🎂":"1f382","🎃":"1f383","🤛":"1f91b","🤜":"1f91c","🎄":"1f384","🎅":"1f385","🎆":"1f386","🤚":"1f91a","🎇":"1f387","🎈":"1f388","🎉":"1f389","🎊":"1f38a","🎋":"1f38b","🎌":"1f38c","🤙":"1f919","🎍":"1f38d","🕺":"1f57a","🎎":"1f38e","🤳":"1f933","🎏":"1f38f","🤰":"1f930","🎐":"1f390","🤦":"1f926","🤷":"1f937","🎑":"1f391","🎒":"1f392","🎓":"1f393","🎠":"1f3a0","🎡":"1f3a1","🎢":"1f3a2","🎣":"1f3a3","🎤":"1f3a4","🎥":"1f3a5","🎦":"1f3a6","🎧":"1f3a7","🤶":"1f936","🎨":"1f3a8","🤵":"1f935","🎩":"1f3a9","🎪":"1f3aa","🤴":"1f934","🎫":"1f3ab","🎬":"1f3ac","🎭":"1f3ad","🤧":"1f927","🎮":"1f3ae","🎯":"1f3af","🎰":"1f3b0","🎱":"1f3b1","🎲":"1f3b2","🎳":"1f3b3","🎴":"1f3b4","🤥":"1f925","🎵":"1f3b5","🎶":"1f3b6","🎷":"1f3b7","🤤":"1f924","🎸":"1f3b8","🎹":"1f3b9","🎺":"1f3ba","🤣":"1f923","🎻":"1f3bb","🎼":"1f3bc","🎽":"1f3bd","🤢":"1f922","🎾":"1f3be","🎿":"1f3bf","🏀":"1f3c0","🏁":"1f3c1","🤡":"1f921","🏂":"1f3c2","🏃":"1f3c3","🏄":"1f3c4","🏆":"1f3c6","🏈":"1f3c8","🏊":"1f3ca","🏠":"1f3e0","🏡":"1f3e1","🏢":"1f3e2","🏣":"1f3e3","🏥":"1f3e5","🏦":"1f3e6","🏧":"1f3e7","🏨":"1f3e8","🏩":"1f3e9","🏪":"1f3ea","🏫":"1f3eb","🏬":"1f3ec","🤠":"1f920","🏭":"1f3ed","🏮":"1f3ee","🏯":"1f3ef","🏰":"1f3f0","🐌":"1f40c","🐍":"1f40d","🐎":"1f40e","🐑":"1f411","🐒":"1f412","🐔":"1f414","🐗":"1f417","🐘":"1f418","🐙":"1f419","🐚":"1f41a","🐛":"1f41b","🐜":"1f41c","🐝":"1f41d","🐞":"1f41e","🐟":"1f41f","🐠":"1f420","🐡":"1f421","🐢":"1f422","🐣":"1f423","🐤":"1f424","🐥":"1f425","🐦":"1f426","🐧":"1f427","🐨":"1f428","🐩":"1f429","🐫":"1f42b","🐬":"1f42c","🐭":"1f42d","🐮":"1f42e","🐯":"1f42f","🐰":"1f430","🐱":"1f431","🐲":"1f432","🐳":"1f433","🐴":"1f434","🐵":"1f435","🐶":"1f436","🐷":"1f437","🐸":"1f438","🐹":"1f439","🐺":"1f43a","🐻":"1f43b","🐼":"1f43c","🐽":"1f43d","🐾":"1f43e","👀":"1f440","👂":"1f442","👃":"1f443","👄":"1f444","👅":"1f445","👆":"1f446","👇":"1f447","👈":"1f448","👉":"1f449","👊":"1f44a","👋":"1f44b","👌":"1f44c","👍":"1f44d","👎":"1f44e","👏":"1f44f","👐":"1f450","👑":"1f451","👒":"1f452","👓":"1f453","👔":"1f454","👕":"1f455","👖":"1f456","👗":"1f457","👘":"1f458","👙":"1f459","👚":"1f45a","👛":"1f45b","👜":"1f45c","👝":"1f45d","👞":"1f45e","👟":"1f45f","👠":"1f460","👡":"1f461","👢":"1f462","👣":"1f463","👤":"1f464","👦":"1f466","👧":"1f467","👨":"1f468","👩":"1f469","👪":"1f46a","👫":"1f46b","👮":"1f46e","👯":"1f46f","👰":"1f470","👱":"1f471","👲":"1f472","👳":"1f473","👴":"1f474","👵":"1f475","👶":"1f476","👷":"1f477","👸":"1f478","👹":"1f479","👺":"1f47a","👻":"1f47b","👼":"1f47c","👽":"1f47d","👾":"1f47e","👿":"1f47f","💀":"1f480","📇":"1f4c7","💁":"1f481","💂":"1f482","💃":"1f483","💄":"1f484","💅":"1f485","📒":"1f4d2","💆":"1f486","📓":"1f4d3","💇":"1f487","📔":"1f4d4","💈":"1f488","📕":"1f4d5","💉":"1f489","📖":"1f4d6","💊":"1f48a","📗":"1f4d7","💋":"1f48b","📘":"1f4d8","💌":"1f48c","📙":"1f4d9","💍":"1f48d","📚":"1f4da","💎":"1f48e","📛":"1f4db","💏":"1f48f","📜":"1f4dc","💐":"1f490","📝":"1f4dd","💑":"1f491","📞":"1f4de","💒":"1f492","📟":"1f4df","📠":"1f4e0","💓":"1f493","📡":"1f4e1","📢":"1f4e2","💔":"1f494","📣":"1f4e3","📤":"1f4e4","💕":"1f495","📥":"1f4e5","📦":"1f4e6","💖":"1f496","📧":"1f4e7","📨":"1f4e8","💗":"1f497","📩":"1f4e9","📪":"1f4ea","💘":"1f498","📫":"1f4eb","📮":"1f4ee","💙":"1f499","📰":"1f4f0","📱":"1f4f1","💚":"1f49a","📲":"1f4f2","📳":"1f4f3","💛":"1f49b","📴":"1f4f4","📶":"1f4f6","💜":"1f49c","📷":"1f4f7","📹":"1f4f9","💝":"1f49d","📺":"1f4fa","📻":"1f4fb","💞":"1f49e","📼":"1f4fc","🔃":"1f503","💟":"1f49f","🔊":"1f50a","🔋":"1f50b","💠":"1f4a0","🔌":"1f50c","🔍":"1f50d","💡":"1f4a1","🔎":"1f50e","🔏":"1f50f","💢":"1f4a2","🔐":"1f510","🔑":"1f511","💣":"1f4a3","🔒":"1f512","🔓":"1f513","💤":"1f4a4","🔔":"1f514","🔖":"1f516","💥":"1f4a5","🔗":"1f517","🔘":"1f518","💦":"1f4a6","🔙":"1f519","🔚":"1f51a","💧":"1f4a7","🔛":"1f51b","🔜":"1f51c","💨":"1f4a8","🔝":"1f51d","🔞":"1f51e","💩":"1f4a9","🔟":"1f51f","💪":"1f4aa","🔠":"1f520","🔡":"1f521","💫":"1f4ab","🔢":"1f522","🔣":"1f523","💬":"1f4ac","🔤":"1f524","🔥":"1f525","💮":"1f4ae","🔦":"1f526","🔧":"1f527","💯":"1f4af","🔨":"1f528","🔩":"1f529","💰":"1f4b0","🔪":"1f52a","🔫":"1f52b","💱":"1f4b1","🔮":"1f52e","💲":"1f4b2","🔯":"1f52f","💳":"1f4b3","🔰":"1f530","🔱":"1f531","💴":"1f4b4","🔲":"1f532","🔳":"1f533","💵":"1f4b5","🔴":"1f534","🔵":"1f535","💸":"1f4b8","🔶":"1f536","🔷":"1f537","💹":"1f4b9","🔸":"1f538","🔹":"1f539","💺":"1f4ba","🔺":"1f53a","🔻":"1f53b","💻":"1f4bb","🔼":"1f53c","💼":"1f4bc","🔽":"1f53d","🕐":"1f550","💽":"1f4bd","🕑":"1f551","💾":"1f4be","🕒":"1f552","💿":"1f4bf","🕓":"1f553","📀":"1f4c0","🕔":"1f554","🕕":"1f555","📁":"1f4c1","🕖":"1f556","🕗":"1f557","📂":"1f4c2","🕘":"1f558","🕙":"1f559","📃":"1f4c3","🕚":"1f55a","🕛":"1f55b","📄":"1f4c4","🗻":"1f5fb","🗼":"1f5fc","📅":"1f4c5","🗽":"1f5fd","🗾":"1f5fe","📆":"1f4c6","🗿":"1f5ff","😁":"1f601","😂":"1f602","😃":"1f603","📈":"1f4c8","😄":"1f604","😅":"1f605","📉":"1f4c9","😆":"1f606","😉":"1f609","📊":"1f4ca","😊":"1f60a","😋":"1f60b","📋":"1f4cb","😌":"1f60c","😍":"1f60d","📌":"1f4cc","😏":"1f60f","😒":"1f612","📍":"1f4cd","😓":"1f613","😔":"1f614","📎":"1f4ce","😖":"1f616","😘":"1f618","📏":"1f4cf","😚":"1f61a","😜":"1f61c","📐":"1f4d0","😝":"1f61d","😞":"1f61e","📑":"1f4d1","😠":"1f620","😡":"1f621","😢":"1f622","😣":"1f623","😤":"1f624","😥":"1f625","😨":"1f628","😩":"1f629","😪":"1f62a","😫":"1f62b","😭":"1f62d","😰":"1f630","😱":"1f631","😲":"1f632","😳":"1f633","😵":"1f635","😷":"1f637","😸":"1f638","😹":"1f639","😺":"1f63a","😻":"1f63b","😼":"1f63c","😽":"1f63d","😾":"1f63e","😿":"1f63f","🙀":"1f640","🙅":"1f645","🙆":"1f646","🙇":"1f647","🙈":"1f648","🙉":"1f649","🙊":"1f64a","🙋":"1f64b","🙌":"1f64c","🙍":"1f64d","🙎":"1f64e","🙏":"1f64f","🚀":"1f680","🚃":"1f683","🚄":"1f684","🚅":"1f685","🚇":"1f687","🚉":"1f689","🚌":"1f68c","🚏":"1f68f","🚑":"1f691","🚒":"1f692","🚓":"1f693","🚕":"1f695","🚗":"1f697","🚙":"1f699","🚚":"1f69a","🚢":"1f6a2","🚤":"1f6a4","🚥":"1f6a5","🚧":"1f6a7","🚨":"1f6a8","🚩":"1f6a9","🚪":"1f6aa","🚫":"1f6ab","🚬":"1f6ac","🚭":"1f6ad","🚲":"1f6b2","🚶":"1f6b6","🚹":"1f6b9","🚺":"1f6ba","🚻":"1f6bb","🚼":"1f6bc","🚽":"1f6bd","🚾":"1f6be","🛀":"1f6c0","🤘":"1f918","😀":"1f600","😇":"1f607","😈":"1f608","😎":"1f60e","😐":"1f610","😑":"1f611","😕":"1f615","😗":"1f617","😙":"1f619","😛":"1f61b","😟":"1f61f","😦":"1f626","😧":"1f627","😬":"1f62c","😮":"1f62e","😯":"1f62f","😴":"1f634","😶":"1f636","🚁":"1f681","🚂":"1f682","🚆":"1f686","🚈":"1f688","🚊":"1f68a","🚍":"1f68d","🚎":"1f68e","🚐":"1f690","🚔":"1f694","🚖":"1f696","🚘":"1f698","🚛":"1f69b","🚜":"1f69c","🚝":"1f69d","🚞":"1f69e","🚟":"1f69f","🚠":"1f6a0","🚡":"1f6a1","🚣":"1f6a3","🚦":"1f6a6","🚮":"1f6ae","🚯":"1f6af","🚰":"1f6b0","🚱":"1f6b1","🚳":"1f6b3","🚴":"1f6b4","🚵":"1f6b5","🚷":"1f6b7","🚸":"1f6b8","🚿":"1f6bf","🛁":"1f6c1","🛂":"1f6c2","🛃":"1f6c3","🛄":"1f6c4","🛅":"1f6c5","🌍":"1f30d","🌎":"1f30e","🌐":"1f310","🌒":"1f312","🌖":"1f316","🌗":"1f317","🌘":"1f318","🌚":"1f31a","🌜":"1f31c","🌝":"1f31d","🌞":"1f31e","🌲":"1f332","🌳":"1f333","🍋":"1f34b","🍐":"1f350","🍼":"1f37c","🏇":"1f3c7","🏉":"1f3c9","🏤":"1f3e4","🐀":"1f400","🐁":"1f401","🐂":"1f402","🐃":"1f403","🐄":"1f404","🐅":"1f405","🐆":"1f406","🐇":"1f407","🐈":"1f408","🐉":"1f409","🐊":"1f40a","🐋":"1f40b","🐏":"1f40f","🐐":"1f410","🐓":"1f413","🐕":"1f415","🐖":"1f416","🐪":"1f42a","👥":"1f465","👬":"1f46c","👭":"1f46d","💭":"1f4ad","💶":"1f4b6","💷":"1f4b7","📬":"1f4ec","📭":"1f4ed","📯":"1f4ef","📵":"1f4f5","🔀":"1f500","🔁":"1f501","🔂":"1f502","🔄":"1f504","🔅":"1f505","🔆":"1f506","🔇":"1f507","🔉":"1f509","🔕":"1f515","🔬":"1f52c","🔭":"1f52d","🕜":"1f55c","🕝":"1f55d","🕞":"1f55e","🕟":"1f55f","🕠":"1f560","🕡":"1f561","🕢":"1f562","🕣":"1f563","🕤":"1f564","🕥":"1f565","🕦":"1f566","🕧":"1f567","🔈":"1f508","🚋":"1f68b","🏅":"1f3c5","🏴":"1f3f4","📸":"1f4f8","🛌":"1f6cc","🖕":"1f595","🖖":"1f596","🙁":"1f641","🙂":"1f642","🛫":"1f6eb","🛬":"1f6ec","🏻":"1f3fb","🏼":"1f3fc","🏽":"1f3fd","🏾":"1f3fe","🏿":"1f3ff","🙃":"1f643","🤑":"1f911","🤓":"1f913","🤗":"1f917","🙄":"1f644","🤔":"1f914","🤐":"1f910","🤒":"1f912","🤕":"1f915","🤖":"1f916","🦁":"1f981","🦄":"1f984","🦂":"1f982","🦀":"1f980","🦃":"1f983","🧀":"1f9c0","🌭":"1f32d","🌮":"1f32e","🌯":"1f32f","🍿":"1f37f","🍾":"1f37e","🏹":"1f3f9","🏺":"1f3fa","🛐":"1f6d0","🕋":"1f54b","🕌":"1f54c","🕍":"1f54d","🕎":"1f54e","📿":"1f4ff","🏏":"1f3cf","🏐":"1f3d0","🏑":"1f3d1","🏒":"1f3d2","🏓":"1f3d3","🏸":"1f3f8","🥁":"1f941","🦐":"1f990","🦑":"1f991","🥚":"1f95a","🥛":"1f95b","🥜":"1f95c","🥝":"1f95d","🥞":"1f95e","🇼":"1f1fc","🇻":"1f1fb","🇺":"1f1fa","🇹":"1f1f9","🇸":"1f1f8","🇷":"1f1f7","🇶":"1f1f6","🇵":"1f1f5","🇴":"1f1f4","🇳":"1f1f3","🇲":"1f1f2","🇱":"1f1f1","🇰":"1f1f0","🇯":"1f1ef","🇮":"1f1ee","🇭":"1f1ed","🇬":"1f1ec","🇫":"1f1eb","🇪":"1f1ea","🇩":"1f1e9","🇨":"1f1e8","🇧":"1f1e7","🇦":"1f1e6","⏩":"23e9","⏪":"23ea","⏫":"23eb","⏬":"23ec","⏰":"23f0","⏳":"23f3","*":"002a","⛎":"26ce","✅":"2705","✊":"270a","✋":"270b","✨":"2728","❌":"274c","❎":"274e","❓":"2753","❔":"2754","❕":"2755","➕":"2795","➖":"2796","➗":"2797","➰":"27b0","#":"0023","➿":"27bf",9:"0039",8:"0038",7:"0037",6:"0036",5:"0035",4:"0034",3:"0033",2:"0032",1:"0031",0:"0030","©":"00a9","®":"00ae","‼":"203c","⁉":"2049","™":"2122","ℹ":"2139","↔":"2194","↕":"2195","↖":"2196","↗":"2197","↘":"2198","↙":"2199","↩":"21a9","↪":"21aa","⌚":"231a","⌛":"231b","Ⓜ":"24c2","▪":"25aa","▫":"25ab","▶":"25b6","◀":"25c0","◻":"25fb","◼":"25fc","◽":"25fd","◾":"25fe","☀":"2600","☁":"2601","☎":"260e","☑":"2611","☔":"2614","☕":"2615","☝":"261d","☺":"263a","♈":"2648","♉":"2649","♊":"264a","♋":"264b","♌":"264c","♍":"264d","♎":"264e","♏":"264f","♐":"2650","♑":"2651","♒":"2652","♓":"2653","♠":"2660","♣":"2663","♥":"2665","♦":"2666","♨":"2668","♻":"267b","♿":"267f","⚓":"2693","⚠":"26a0","⚡":"26a1","⚪":"26aa","⚫":"26ab","⚽":"26bd","⚾":"26be","⛄":"26c4","⛅":"26c5","⛔":"26d4","⛪":"26ea","⛲":"26f2","⛳":"26f3","⛵":"26f5","⛺":"26fa","⛽":"26fd","✂":"2702","✈":"2708","✉":"2709","✌":"270c","✏":"270f","✒":"2712","✔":"2714","✖":"2716","✳":"2733","✴":"2734","❄":"2744","❇":"2747","❗":"2757","❤":"2764","➡":"27a1","⤴":"2934","⤵":"2935","⬅":"2b05","⬆":"2b06","⬇":"2b07","⬛":"2b1b","⬜":"2b1c","⭐":"2b50","⭕":"2b55","〰":"3030","〽":"303d","㊗":"3297","㊙":"3299","🀄":"1f004","🅿":"1f17f","🈂":"1f202","🈚":"1f21a","🈯":"1f22f","🈷":"1f237","🎞":"1f39e","🎟":"1f39f","🏋":"1f3cb","🏌":"1f3cc","🏍":"1f3cd","🏎":"1f3ce","🎖":"1f396","🎗":"1f397","🌶":"1f336","🌧":"1f327","🌨":"1f328","🌩":"1f329","🌪":"1f32a","🌫":"1f32b","🌬":"1f32c","🐿":"1f43f","🕷":"1f577","🕸":"1f578","🌡":"1f321","🎙":"1f399","🎚":"1f39a","🎛":"1f39b","🏳":"1f3f3","🏵":"1f3f5","🏷":"1f3f7","📽":"1f4fd","✝":"271d","🕉":"1f549","🕊":"1f54a","🕯":"1f56f","🕰":"1f570","🕳":"1f573","🕶":"1f576","🕹":"1f579","🖇":"1f587","🖊":"1f58a","🖋":"1f58b","🖌":"1f58c","🖍":"1f58d","🖥":"1f5a5","🖨":"1f5a8","⌨":"2328","🖲":"1f5b2","🖼":"1f5bc","🗂":"1f5c2","🗃":"1f5c3","🗄":"1f5c4","🗑":"1f5d1","🗒":"1f5d2","🗓":"1f5d3","🗜":"1f5dc","🗝":"1f5dd","🗞":"1f5de","🗡":"1f5e1","🗣":"1f5e3","🗨":"1f5e8","🗯":"1f5ef","🗳":"1f5f3","🗺":"1f5fa","🛠":"1f6e0","🛡":"1f6e1","🛢":"1f6e2","🛰":"1f6f0","🍽":"1f37d","👁":"1f441","🕴":"1f574","🕵":"1f575","✍":"270d","🖐":"1f590","🏔":"1f3d4","🏕":"1f3d5","🏖":"1f3d6","🏗":"1f3d7","🏘":"1f3d8","🏙":"1f3d9","🏚":"1f3da","🏛":"1f3db","🏜":"1f3dc","🏝":"1f3dd","🏞":"1f3de","🏟":"1f3df","🛋":"1f6cb","🛍":"1f6cd","🛎":"1f6ce","🛏":"1f6cf","🛣":"1f6e3","🛤":"1f6e4","🛥":"1f6e5","🛩":"1f6e9","🛳":"1f6f3","⏏":"23cf","⏭":"23ed","⏮":"23ee","⏯":"23ef","⏱":"23f1","⏲":"23f2","⏸":"23f8","⏹":"23f9","⏺":"23fa","☂":"2602","☃":"2603","☄":"2604","☘":"2618","☠":"2620","☢":"2622","☣":"2623","☦":"2626","☪":"262a","☮":"262e","☯":"262f","☸":"2638","☹":"2639","⚒":"2692","⚔":"2694","⚖":"2696","⚗":"2697","⚙":"2699","⚛":"269b","⚜":"269c","⚰":"26b0","⚱":"26b1","⛈":"26c8","⛏":"26cf","⛑":"26d1","⛓":"26d3","⛩":"26e9","⛰":"26f0","⛱":"26f1","⛴":"26f4","⛷":"26f7","⛸":"26f8","⛹":"26f9", +"✡":"2721","❣":"2763","🌤":"1f324","🌥":"1f325","🌦":"1f326","🖱":"1f5b1"},a.imagePathPNG="//cdn.jsdelivr.net/emojione/assets/png/",a.imagePathSVG="//cdn.jsdelivr.net/emojione/assets/svg/",a.imagePathSVGSprites="./../assets/sprites/emojione.sprites.svg",a.imageType="png",a.sprites=!1,a.unicodeAlt=!0,a.ascii=!1,a.cacheBustParam="?v=2.2.6",a.regShortNames=new RegExp("]*>.*?|]*>.*?
        |<(?:object|embed|svg|img|div|span|p|a)[^>]*>|("+a.shortnames+")","gi"),a.regAscii=new RegExp("]*>.*?|]*>.*?
        |<(?:object|embed|svg|img|div|span|p|a)[^>]*>|((\\s|^)"+a.asciiRegexp+"(?=\\s|$|[!,.?]))","g"),a.regUnicode=new RegExp("]*>.*?|]*>.*?
        |<(?:object|embed|svg|img|div|span|p|a)[^>]*>|("+a.unicodeRegexp+")","gi"),a.toImage=function(b){return b=a.unicodeToImage(b),b=a.shortnameToImage(b)},a.unifyUnicode=function(b){return b=a.toShort(b),b=a.shortnameToUnicode(b)},a.shortnameToAscii=function(b){var c,d=a.objectFlip(a.asciiList);return b=b.replace(a.regShortNames,function(b){return"undefined"!=typeof b&&""!==b&&b in a.emojioneList?(c=a.emojioneList[b].unicode[a.emojioneList[b].unicode.length-1],"undefined"!=typeof d[c]?d[c]:b):b})},a.shortnameToUnicode=function(b){var c;return b=b.replace(a.regShortNames,function(b){return"undefined"!=typeof b&&""!==b&&b in a.emojioneList?(c=a.emojioneList[b].unicode[0].toUpperCase(),a.convert(c)):b}),a.ascii&&(b=b.replace(a.regAscii,function(b,d,e,f){return"undefined"!=typeof f&&""!==f&&a.unescapeHTML(f)in a.asciiList?(f=a.unescapeHTML(f),c=a.asciiList[f].toUpperCase(),e+a.convert(c)):b})),b},a.shortnameToImage=function(b){var c,d,e;return b=b.replace(a.regShortNames,function(b){return"undefined"!=typeof b&&""!==b&&b in a.emojioneList?(d=a.emojioneList[b].unicode[a.emojioneList[b].unicode.length-1],e=a.unicodeAlt?a.convert(d.toUpperCase()):b,c="png"===a.imageType?a.sprites?''+e+"":''+e+'':a.sprites?''+e+'':''+e+""):b}),a.ascii&&(b=b.replace(a.regAscii,function(b,f,g,h){return"undefined"!=typeof h&&""!==h&&a.unescapeHTML(h)in a.asciiList?(h=a.unescapeHTML(h),d=a.asciiList[h],e=a.unicodeAlt?a.convert(d.toUpperCase()):a.escapeHTML(h),c="png"===a.imageType?a.sprites?g+''+e+"":g+''+e+'':a.sprites?''+e+'':g+''+e+""):b})),b},a.unicodeToImage=function(b){var c,d,e;if(!a.unicodeAlt||a.sprites)var f=a.mapUnicodeToShort();return b=b.replace(a.regUnicode,function(b){return"undefined"!=typeof b&&""!==b&&b in a.jsEscapeMap?(d=a.jsEscapeMap[b],e=a.unicodeAlt?a.convert(d.toUpperCase()):f[d],c="png"===a.imageType?a.sprites?''+e+"":''+e+'':a.sprites?''+e+'':''+e+''):b})},a.toShort=function(b){var c=a.getUnicodeReplacementRegEx(),d=a.mapUnicodeCharactersToShort();return a.replaceAll(b,c,d)},a.convert=function(a){if(a.indexOf("-")>-1){for(var b=[],c=a.split("-"),d=0;d=65536&&1114111>=e){var f=Math.floor((e-65536)/1024)+55296,g=(e-65536)%1024+56320;e=String.fromCharCode(f)+String.fromCharCode(g)}else e=String.fromCharCode(e);b.push(e)}return b.join("")}var c=parseInt(a,16);if(c>=65536&&1114111>=c){var f=Math.floor((c-65536)/1024)+55296,g=(c-65536)%1024+56320;return String.fromCharCode(f)+String.fromCharCode(g)}return String.fromCharCode(c)},a.escapeHTML=function(a){var b={"&":"&","<":"<",">":">",'"':""","'":"'"};return a.replace(/[&<>"']/g,function(a){return b[a]})},a.unescapeHTML=function(a){var b={"&":"&","&":"&","&":"&","<":"<","<":"<","<":"<",">":">",">":">",">":">",""":'"',""":'"',""":'"',"'":"'","'":"'","'":"'"};return a.replace(/&(?:amp|#38|#x26|lt|#60|#x3C|gt|#62|#x3E|apos|#39|#x27|quot|#34|#x22);/gi,function(a){return b[a]})},a.mapEmojioneList=function(b){for(var c in a.emojioneList)if(a.emojioneList.hasOwnProperty(c))for(var d=0,e=a.emojioneList[c].unicode.length;e>d;d++){var f=a.emojioneList[c].unicode[d];b(f,c)}},a.mapUnicodeToShort=function(){return a.memMapShortToUnicode||(a.memMapShortToUnicode={},a.mapEmojioneList(function(b,c){a.memMapShortToUnicode[b]=c})),a.memMapShortToUnicode},a.memoizeReplacement=function(){if(!a.unicodeReplacementRegEx||!a.memMapShortToUnicodeCharacters){var b=[];a.memMapShortToUnicodeCharacters={},a.mapEmojioneList(function(c,d){var e=a.convert(c);a.emojioneList[d].isCanonical&&(a.memMapShortToUnicodeCharacters[e]=d),b.push(e)}),a.unicodeReplacementRegEx=b.join("|")}},a.mapUnicodeCharactersToShort=function(){return a.memoizeReplacement(),a.memMapShortToUnicodeCharacters},a.getUnicodeReplacementRegEx=function(){return a.memoizeReplacement(),a.unicodeReplacementRegEx},a.objectFlip=function(a){var b,c={};for(b in a)a.hasOwnProperty(b)&&(c[a[b]]=b);return c},a.escapeRegExp=function(a){return a.replace(/[-[\]{}()*+?.,;:&\\^$#\s]/g,"\\$&")},a.replaceAll=function(b,c,d){var e=a.escapeRegExp(c),f=new RegExp("]*>.*?|]*>.*?|<(?:object|embed|svg|img|div|span|p|a)[^>]*>|("+e+")","gi"),g=function(a,b){return"undefined"==typeof b||""===b?a:d[b]};return b.replace(f,g)}}(this.emojione=this.emojione||{}),"object"==typeof module&&(module.exports=this.emojione); \ No newline at end of file diff --git a/pagure/static/emoji/emojione.js b/pagure/static/emoji/emojione.js new file mode 120000 index 0000000..9a75d3a --- /dev/null +++ b/pagure/static/emoji/emojione.js @@ -0,0 +1 @@ +emojione-2.2.6.js \ No newline at end of file diff --git a/pagure/static/emoji/emojione.min.js b/pagure/static/emoji/emojione.min.js deleted file mode 100644 index f7c6d8c..0000000 --- a/pagure/static/emoji/emojione.min.js +++ /dev/null @@ -1,63 +0,0 @@ -/*! emojione 13-04-2015 */ -!function(a){a.emojioneList={":hash:":["0023-fe0f-20e3","0023-20e3"],":zero:":["0030-fe0f-20e3","0030-20e3"],":one:":["0031-fe0f-20e3","0031-20e3"],":two:":["0032-fe0f-20e3","0032-20e3"],":three:":["0033-fe0f-20e3","0033-20e3"],":four:":["0034-fe0f-20e3","0034-20e3"],":five:":["0035-fe0f-20e3","0035-20e3"],":six:":["0036-fe0f-20e3","0036-20e3"],":seven:":["0037-fe0f-20e3","0037-20e3"],":eight:":["0038-fe0f-20e3","0038-20e3"],":nine:":["0039-fe0f-20e3","0039-20e3"],":copyright:":["00a9"],":registered:":["00ae"],":bangbang:":["203c-fe0f","203c"],":interrobang:":["2049-fe0f","2049"],":tm:":["2122"],":information_source:":["2139-fe0f","2139"],":left_right_arrow:":["2194-fe0f","2194"],":arrow_up_down:":["2195-fe0f","2195"],":arrow_upper_left:":["2196-fe0f","2196"],":arrow_upper_right:":["2197-fe0f","2197"],":arrow_lower_right:":["2198-fe0f","2198"],":arrow_lower_left:":["2199-fe0f","2199"],":leftwards_arrow_with_hook:":["21a9-fe0f","21a9"],":arrow_right_hook:":["21aa-fe0f","21aa"],":watch:":["231a-fe0f","231a"],":hourglass:":["231b-fe0f","231b"],":fast_forward:":["23e9"],":rewind:":["23ea"],":arrow_double_up:":["23eb"],":arrow_double_down:":["23ec"],":alarm_clock:":["23f0"],":hourglass_flowing_sand:":["23f3"],":m:":["24c2-fe0f","24c2"],":black_small_square:":["25aa-fe0f","25aa"],":white_small_square:":["25ab-fe0f","25ab"],":arrow_forward:":["25b6-fe0f","25b6"],":arrow_backward:":["25c0-fe0f","25c0"],":white_medium_square:":["25fb-fe0f","25fb"],":black_medium_square:":["25fc-fe0f","25fc"],":white_medium_small_square:":["25fd-fe0f","25fd"],":black_medium_small_square:":["25fe-fe0f","25fe"],":sunny:":["2600-fe0f","2600"],":cloud:":["2601-fe0f","2601"],":telephone:":["260e-fe0f","260e"],":ballot_box_with_check:":["2611-fe0f","2611"],":umbrella:":["2614-fe0f","2614"],":coffee:":["2615-fe0f","2615"],":point_up:":["261d-fe0f","261d"],":relaxed:":["263a-fe0f","263a"],":aries:":["2648-fe0f","2648"],":taurus:":["2649-fe0f","2649"],":gemini:":["264a-fe0f","264a"],":cancer:":["264b-fe0f","264b"],":leo:":["264c-fe0f","264c"],":virgo:":["264d-fe0f","264d"],":libra:":["264e-fe0f","264e"],":scorpius:":["264f-fe0f","264f"],":sagittarius:":["2650-fe0f","2650"],":capricorn:":["2651-fe0f","2651"],":aquarius:":["2652-fe0f","2652"],":pisces:":["2653-fe0f","2653"],":spades:":["2660-fe0f","2660"],":clubs:":["2663-fe0f","2663"],":hearts:":["2665-fe0f","2665"],":diamonds:":["2666-fe0f","2666"],":hotsprings:":["2668-fe0f","2668"],":recycle:":["267b-fe0f","267b"],":wheelchair:":["267f-fe0f","267f"],":anchor:":["2693-fe0f","2693"],":warning:":["26a0-fe0f","26a0"],":zap:":["26a1-fe0f","26a1"],":white_circle:":["26aa-fe0f","26aa"],":black_circle:":["26ab-fe0f","26ab"],":soccer:":["26bd-fe0f","26bd"],":baseball:":["26be-fe0f","26be"],":snowman:":["26c4-fe0f","26c4"],":partly_sunny:":["26c5-fe0f","26c5"],":ophiuchus:":["26ce"],":no_entry:":["26d4-fe0f","26d4"],":church:":["26ea-fe0f","26ea"],":fountain:":["26f2-fe0f","26f2"],":golf:":["26f3-fe0f","26f3"],":sailboat:":["26f5-fe0f","26f5"],":tent:":["26fa-fe0f","26fa"],":fuelpump:":["26fd-fe0f","26fd"],":scissors:":["2702-fe0f","2702"],":white_check_mark:":["2705"],":airplane:":["2708-fe0f","2708"],":envelope:":["2709-fe0f","2709"],":fist:":["270a"],":raised_hand:":["270b"],":v:":["270c-fe0f","270c"],":pencil2:":["270f-fe0f","270f"],":black_nib:":["2712-fe0f","2712"],":heavy_check_mark:":["2714-fe0f","2714"],":heavy_multiplication_x:":["2716-fe0f","2716"],":sparkles:":["2728"],":eight_spoked_asterisk:":["2733-fe0f","2733"],":eight_pointed_black_star:":["2734-fe0f","2734"],":snowflake:":["2744-fe0f","2744"],":sparkle:":["2747-fe0f","2747"],":x:":["274c"],":negative_squared_cross_mark:":["274e"],":question:":["2753"],":grey_question:":["2754"],":grey_exclamation:":["2755"],":exclamation:":["2757-fe0f","2757"],":heart:":["2764-fe0f","2764"],":heavy_plus_sign:":["2795"],":heavy_minus_sign:":["2796"],":heavy_division_sign:":["2797"],":arrow_right:":["27a1-fe0f","27a1"],":curly_loop:":["27b0"],":arrow_heading_up:":["2934-fe0f","2934"],":arrow_heading_down:":["2935-fe0f","2935"],":arrow_left:":["2b05-fe0f","2b05"],":arrow_up:":["2b06-fe0f","2b06"],":arrow_down:":["2b07-fe0f","2b07"],":black_large_square:":["2b1b-fe0f","2b1b"],":white_large_square:":["2b1c-fe0f","2b1c"],":star:":["2b50-fe0f","2b50"],":o:":["2b55-fe0f","2b55"],":wavy_dash:":["3030"],":part_alternation_mark:":["303d-fe0f","303d"],":congratulations:":["3297-fe0f","3297"],":secret:":["3299-fe0f","3299"],":mahjong:":["1f004-fe0f","1f004"],":black_joker:":["1f0cf"],":a:":["1f170"],":b:":["1f171"],":o2:":["1f17e"],":parking:":["1f17f-fe0f","1f17f"],":ab:":["1f18e"],":cl:":["1f191"],":cool:":["1f192"],":free:":["1f193"],":id:":["1f194"],":new:":["1f195"],":ng:":["1f196"],":ok:":["1f197"],":sos:":["1f198"],":up:":["1f199"],":vs:":["1f19a"],":cn:":["1f1e8-1f1f3"],":de:":["1f1e9-1f1ea"],":es:":["1f1ea-1f1f8"],":fr:":["1f1eb-1f1f7"],":gb:":["1f1ec-1f1e7"],":it:":["1f1ee-1f1f9"],":jp:":["1f1ef-1f1f5"],":kr:":["1f1f0-1f1f7"],":us:":["1f1fa-1f1f8"],":ru:":["1f1f7-1f1fa"],":koko:":["1f201"],":sa:":["1f202"],":u7121:":["1f21a-fe0f","1f21a"],":u6307:":["1f22f-fe0f","1f22f"],":u7981:":["1f232"],":u7a7a:":["1f233"],":u5408:":["1f234"],":u6e80:":["1f235"],":u6709:":["1f236"],":u6708:":["1f237"],":u7533:":["1f238"],":u5272:":["1f239"],":u55b6:":["1f23a"],":ideograph_advantage:":["1f250"],":accept:":["1f251"],":cyclone:":["1f300"],":foggy:":["1f301"],":closed_umbrella:":["1f302"],":night_with_stars:":["1f303"],":sunrise_over_mountains:":["1f304"],":sunrise:":["1f305"],":city_dusk:":["1f306"],":city_sunset:":["1f307"],":city_sunrise:":["1f307"],":rainbow:":["1f308"],":bridge_at_night:":["1f309"],":ocean:":["1f30a"],":volcano:":["1f30b"],":milky_way:":["1f30c"],":earth_asia:":["1f30f"],":new_moon:":["1f311"],":first_quarter_moon:":["1f313"],":waxing_gibbous_moon:":["1f314"],":full_moon:":["1f315"],":crescent_moon:":["1f319"],":first_quarter_moon_with_face:":["1f31b"],":star2:":["1f31f"],":stars:":["1f320"],":chestnut:":["1f330"],":seedling:":["1f331"],":palm_tree:":["1f334"],":cactus:":["1f335"],":tulip:":["1f337"],":cherry_blossom:":["1f338"],":rose:":["1f339"],":hibiscus:":["1f33a"],":sunflower:":["1f33b"],":blossom:":["1f33c"],":corn:":["1f33d"],":ear_of_rice:":["1f33e"],":herb:":["1f33f"],":four_leaf_clover:":["1f340"],":maple_leaf:":["1f341"],":fallen_leaf:":["1f342"],":leaves:":["1f343"],":mushroom:":["1f344"],":tomato:":["1f345"],":eggplant:":["1f346"],":grapes:":["1f347"],":melon:":["1f348"],":watermelon:":["1f349"],":tangerine:":["1f34a"],":banana:":["1f34c"],":pineapple:":["1f34d"],":apple:":["1f34e"],":green_apple:":["1f34f"],":peach:":["1f351"],":cherries:":["1f352"],":strawberry:":["1f353"],":hamburger:":["1f354"],":pizza:":["1f355"],":meat_on_bone:":["1f356"],":poultry_leg:":["1f357"],":rice_cracker:":["1f358"],":rice_ball:":["1f359"],":rice:":["1f35a"],":curry:":["1f35b"],":ramen:":["1f35c"],":spaghetti:":["1f35d"],":bread:":["1f35e"],":fries:":["1f35f"],":sweet_potato:":["1f360"],":dango:":["1f361"],":oden:":["1f362"],":sushi:":["1f363"],":fried_shrimp:":["1f364"],":fish_cake:":["1f365"],":icecream:":["1f366"],":shaved_ice:":["1f367"],":ice_cream:":["1f368"],":doughnut:":["1f369"],":cookie:":["1f36a"],":chocolate_bar:":["1f36b"],":candy:":["1f36c"],":lollipop:":["1f36d"],":custard:":["1f36e"],":honey_pot:":["1f36f"],":cake:":["1f370"],":bento:":["1f371"],":stew:":["1f372"],":egg:":["1f373"],":fork_and_knife:":["1f374"],":tea:":["1f375"],":sake:":["1f376"],":wine_glass:":["1f377"],":cocktail:":["1f378"],":tropical_drink:":["1f379"],":beer:":["1f37a"],":beers:":["1f37b"],":ribbon:":["1f380"],":gift:":["1f381"],":birthday:":["1f382"],":jack_o_lantern:":["1f383"],":christmas_tree:":["1f384"],":santa:":["1f385"],":fireworks:":["1f386"],":sparkler:":["1f387"],":balloon:":["1f388"],":tada:":["1f389"],":confetti_ball:":["1f38a"],":tanabata_tree:":["1f38b"],":crossed_flags:":["1f38c"],":bamboo:":["1f38d"],":dolls:":["1f38e"],":flags:":["1f38f"],":wind_chime:":["1f390"],":rice_scene:":["1f391"],":school_satchel:":["1f392"],":mortar_board:":["1f393"],":carousel_horse:":["1f3a0"],":ferris_wheel:":["1f3a1"],":roller_coaster:":["1f3a2"],":fishing_pole_and_fish:":["1f3a3"],":microphone:":["1f3a4"],":movie_camera:":["1f3a5"],":cinema:":["1f3a6"],":headphones:":["1f3a7"],":art:":["1f3a8"],":tophat:":["1f3a9"],":circus_tent:":["1f3aa"],":ticket:":["1f3ab"],":clapper:":["1f3ac"],":performing_arts:":["1f3ad"],":video_game:":["1f3ae"],":dart:":["1f3af"],":slot_machine:":["1f3b0"],":8ball:":["1f3b1"],":game_die:":["1f3b2"],":bowling:":["1f3b3"],":flower_playing_cards:":["1f3b4"],":musical_note:":["1f3b5"],":notes:":["1f3b6"],":saxophone:":["1f3b7"],":guitar:":["1f3b8"],":musical_keyboard:":["1f3b9"],":trumpet:":["1f3ba"],":violin:":["1f3bb"],":musical_score:":["1f3bc"],":running_shirt_with_sash:":["1f3bd"],":tennis:":["1f3be"],":ski:":["1f3bf"],":basketball:":["1f3c0"],":checkered_flag:":["1f3c1"],":snowboarder:":["1f3c2"],":runner:":["1f3c3"],":surfer:":["1f3c4"],":trophy:":["1f3c6"],":football:":["1f3c8"],":swimmer:":["1f3ca"],":house:":["1f3e0"],":house_with_garden:":["1f3e1"],":office:":["1f3e2"],":post_office:":["1f3e3"],":hospital:":["1f3e5"],":bank:":["1f3e6"],":atm:":["1f3e7"],":hotel:":["1f3e8"],":love_hotel:":["1f3e9"],":convenience_store:":["1f3ea"],":school:":["1f3eb"],":department_store:":["1f3ec"],":factory:":["1f3ed"],":izakaya_lantern:":["1f3ee"],":japanese_castle:":["1f3ef"],":european_castle:":["1f3f0"],":snail:":["1f40c"],":snake:":["1f40d"],":racehorse:":["1f40e"],":sheep:":["1f411"],":monkey:":["1f412"],":chicken:":["1f414"],":boar:":["1f417"],":elephant:":["1f418"],":octopus:":["1f419"],":shell:":["1f41a"],":bug:":["1f41b"],":ant:":["1f41c"],":bee:":["1f41d"],":beetle:":["1f41e"],":fish:":["1f41f"],":tropical_fish:":["1f420"],":blowfish:":["1f421"],":turtle:":["1f422"],":hatching_chick:":["1f423"],":baby_chick:":["1f424"],":hatched_chick:":["1f425"],":bird:":["1f426"],":penguin:":["1f427"],":koala:":["1f428"],":poodle:":["1f429"],":camel:":["1f42b"],":dolphin:":["1f42c"],":mouse:":["1f42d"],":cow:":["1f42e"],":tiger:":["1f42f"],":rabbit:":["1f430"],":cat:":["1f431"],":dragon_face:":["1f432"],":whale:":["1f433"],":horse:":["1f434"],":monkey_face:":["1f435"],":dog:":["1f436"],":pig:":["1f437"],":frog:":["1f438"],":hamster:":["1f439"],":wolf:":["1f43a"],":bear:":["1f43b"],":panda_face:":["1f43c"],":pig_nose:":["1f43d"],":feet:":["1f43e"],":eyes:":["1f440"],":ear:":["1f442"],":nose:":["1f443"],":lips:":["1f444"],":tongue:":["1f445"],":point_up_2:":["1f446"],":point_down:":["1f447"],":point_left:":["1f448"],":point_right:":["1f449"],":punch:":["1f44a"],":wave:":["1f44b"],":ok_hand:":["1f44c"],":thumbsup:":["1f44d"],":+1:":["1f44d"],":thumbsdown:":["1f44e"],":-1:":["1f44e"],":clap:":["1f44f"],":open_hands:":["1f450"],":crown:":["1f451"],":womans_hat:":["1f452"],":eyeglasses:":["1f453"],":necktie:":["1f454"],":shirt:":["1f455"],":jeans:":["1f456"],":dress:":["1f457"],":kimono:":["1f458"],":bikini:":["1f459"],":womans_clothes:":["1f45a"],":purse:":["1f45b"],":handbag:":["1f45c"],":pouch:":["1f45d"],":mans_shoe:":["1f45e"],":athletic_shoe:":["1f45f"],":high_heel:":["1f460"],":sandal:":["1f461"],":boot:":["1f462"],":footprints:":["1f463"],":bust_in_silhouette:":["1f464"],":boy:":["1f466"],":girl:":["1f467"],":man:":["1f468"],":woman:":["1f469"],":family:":["1f46a"],":couple:":["1f46b"],":cop:":["1f46e"],":dancers:":["1f46f"],":bride_with_veil:":["1f470"],":person_with_blond_hair:":["1f471"],":man_with_gua_pi_mao:":["1f472"],":man_with_turban:":["1f473"],":older_man:":["1f474"],":older_woman:":["1f475"],":grandma:":["1f475"],":baby:":["1f476"],":construction_worker:":["1f477"],":princess:":["1f478"],":japanese_ogre:":["1f479"],":japanese_goblin:":["1f47a"],":ghost:":["1f47b"],":angel:":["1f47c"],":alien:":["1f47d"],":space_invader:":["1f47e"],":imp:":["1f47f"],":skull:":["1f480"],":skeleton:":["1f480"],":card_index:":["1f4c7"],":information_desk_person:":["1f481"],":guardsman:":["1f482"],":dancer:":["1f483"],":lipstick:":["1f484"],":nail_care:":["1f485"],":ledger:":["1f4d2"],":massage:":["1f486"],":notebook:":["1f4d3"],":haircut:":["1f487"],":notebook_with_decorative_cover:":["1f4d4"],":barber:":["1f488"],":closed_book:":["1f4d5"],":syringe:":["1f489"],":book:":["1f4d6"],":pill:":["1f48a"],":green_book:":["1f4d7"],":kiss:":["1f48b"],":blue_book:":["1f4d8"],":love_letter:":["1f48c"],":orange_book:":["1f4d9"],":ring:":["1f48d"],":books:":["1f4da"],":gem:":["1f48e"],":name_badge:":["1f4db"],":couplekiss:":["1f48f"],":scroll:":["1f4dc"],":bouquet:":["1f490"],":pencil:":["1f4dd"],":couple_with_heart:":["1f491"],":telephone_receiver:":["1f4de"],":wedding:":["1f492"],":pager:":["1f4df"],":fax:":["1f4e0"],":heartbeat:":["1f493"],":satellite:":["1f4e1"],":loudspeaker:":["1f4e2"],":broken_heart:":["1f494"],":mega:":["1f4e3"],":outbox_tray:":["1f4e4"],":two_hearts:":["1f495"],":inbox_tray:":["1f4e5"],":package:":["1f4e6"],":sparkling_heart:":["1f496"],":e-mail:":["1f4e7"],":email:":["1f4e7"],":incoming_envelope:":["1f4e8"],":heartpulse:":["1f497"],":envelope_with_arrow:":["1f4e9"],":mailbox_closed:":["1f4ea"],":cupid:":["1f498"],":mailbox:":["1f4eb"],":postbox:":["1f4ee"],":blue_heart:":["1f499"],":newspaper:":["1f4f0"],":iphone:":["1f4f1"],":green_heart:":["1f49a"],":calling:":["1f4f2"],":vibration_mode:":["1f4f3"],":yellow_heart:":["1f49b"],":mobile_phone_off:":["1f4f4"],":signal_strength:":["1f4f6"],":purple_heart:":["1f49c"],":camera:":["1f4f7"],":video_camera:":["1f4f9"],":gift_heart:":["1f49d"],":tv:":["1f4fa"],":radio:":["1f4fb"],":revolving_hearts:":["1f49e"],":vhs:":["1f4fc"],":arrows_clockwise:":["1f503"],":heart_decoration:":["1f49f"],":loud_sound:":["1f50a"],":battery:":["1f50b"],":diamond_shape_with_a_dot_inside:":["1f4a0"],":electric_plug:":["1f50c"],":mag:":["1f50d"],":bulb:":["1f4a1"],":mag_right:":["1f50e"],":lock_with_ink_pen:":["1f50f"],":anger:":["1f4a2"],":closed_lock_with_key:":["1f510"],":key:":["1f511"],":bomb:":["1f4a3"],":lock:":["1f512"],":unlock:":["1f513"],":zzz:":["1f4a4"],":bell:":["1f514"],":bookmark:":["1f516"],":boom:":["1f4a5"],":link:":["1f517"],":radio_button:":["1f518"],":sweat_drops:":["1f4a6"],":back:":["1f519"],":end:":["1f51a"],":droplet:":["1f4a7"],":on:":["1f51b"],":soon:":["1f51c"],":dash:":["1f4a8"],":top:":["1f51d"],":underage:":["1f51e"],":poop:":["1f4a9"],":shit:":["1f4a9"],":hankey:":["1f4a9"],":poo:":["1f4a9"],":keycap_ten:":["1f51f"],":muscle:":["1f4aa"],":capital_abcd:":["1f520"],":abcd:":["1f521"],":dizzy:":["1f4ab"],":1234:":["1f522"],":symbols:":["1f523"],":speech_balloon:":["1f4ac"],":abc:":["1f524"],":fire:":["1f525"],":flame:":["1f525"],":white_flower:":["1f4ae"],":flashlight:":["1f526"],":wrench:":["1f527"],":100:":["1f4af"],":hammer:":["1f528"],":nut_and_bolt:":["1f529"],":moneybag:":["1f4b0"],":knife:":["1f52a"],":gun:":["1f52b"],":currency_exchange:":["1f4b1"],":crystal_ball:":["1f52e"],":heavy_dollar_sign:":["1f4b2"],":six_pointed_star:":["1f52f"],":credit_card:":["1f4b3"],":beginner:":["1f530"],":trident:":["1f531"],":yen:":["1f4b4"],":black_square_button:":["1f532"],":white_square_button:":["1f533"],":dollar:":["1f4b5"],":red_circle:":["1f534"],":large_blue_circle:":["1f535"],":money_with_wings:":["1f4b8"],":large_orange_diamond:":["1f536"],":large_blue_diamond:":["1f537"],":chart:":["1f4b9"],":small_orange_diamond:":["1f538"],":small_blue_diamond:":["1f539"],":seat:":["1f4ba"],":small_red_triangle:":["1f53a"],":small_red_triangle_down:":["1f53b"],":computer:":["1f4bb"],":arrow_up_small:":["1f53c"],":briefcase:":["1f4bc"],":arrow_down_small:":["1f53d"],":clock1:":["1f550"],":minidisc:":["1f4bd"],":clock2:":["1f551"],":floppy_disk:":["1f4be"],":clock3:":["1f552"],":cd:":["1f4bf"],":clock4:":["1f553"],":dvd:":["1f4c0"],":clock5:":["1f554"],":clock6:":["1f555"],":file_folder:":["1f4c1"],":clock7:":["1f556"],":clock8:":["1f557"],":open_file_folder:":["1f4c2"],":clock9:":["1f558"],":clock10:":["1f559"],":page_with_curl:":["1f4c3"],":clock11:":["1f55a"],":clock12:":["1f55b"],":page_facing_up:":["1f4c4"],":mount_fuji:":["1f5fb"],":tokyo_tower:":["1f5fc"],":date:":["1f4c5"],":statue_of_liberty:":["1f5fd"],":japan:":["1f5fe"],":calendar:":["1f4c6"],":moyai:":["1f5ff"],":grin:":["1f601"],":joy:":["1f602"],":smiley:":["1f603"],":chart_with_upwards_trend:":["1f4c8"],":smile:":["1f604"],":sweat_smile:":["1f605"],":chart_with_downwards_trend:":["1f4c9"],":laughing:":["1f606"],":satisfied:":["1f606"],":wink:":["1f609"],":bar_chart:":["1f4ca"],":blush:":["1f60a"],":yum:":["1f60b"],":clipboard:":["1f4cb"],":relieved:":["1f60c"],":heart_eyes:":["1f60d"],":pushpin:":["1f4cc"],":smirk:":["1f60f"],":unamused:":["1f612"],":round_pushpin:":["1f4cd"],":sweat:":["1f613"],":pensive:":["1f614"],":paperclip:":["1f4ce"],":confounded:":["1f616"],":kissing_heart:":["1f618"],":straight_ruler:":["1f4cf"],":kissing_closed_eyes:":["1f61a"],":stuck_out_tongue_winking_eye:":["1f61c"],":triangular_ruler:":["1f4d0"],":stuck_out_tongue_closed_eyes:":["1f61d"],":disappointed:":["1f61e"],":bookmark_tabs:":["1f4d1"],":angry:":["1f620"],":rage:":["1f621"],":cry:":["1f622"],":persevere:":["1f623"],":triumph:":["1f624"],":disappointed_relieved:":["1f625"],":fearful:":["1f628"],":weary:":["1f629"],":sleepy:":["1f62a"],":tired_face:":["1f62b"],":sob:":["1f62d"],":cold_sweat:":["1f630"],":scream:":["1f631"],":astonished:":["1f632"],":flushed:":["1f633"],":dizzy_face:":["1f635"],":mask:":["1f637"],":smile_cat:":["1f638"],":joy_cat:":["1f639"],":smiley_cat:":["1f63a"],":heart_eyes_cat:":["1f63b"],":smirk_cat:":["1f63c"],":kissing_cat:":["1f63d"],":pouting_cat:":["1f63e"],":crying_cat_face:":["1f63f"],":scream_cat:":["1f640"],":no_good:":["1f645"],":ok_woman:":["1f646"],":bow:":["1f647"],":see_no_evil:":["1f648"],":hear_no_evil:":["1f649"],":speak_no_evil:":["1f64a"],":raising_hand:":["1f64b"],":raised_hands:":["1f64c"],":person_frowning:":["1f64d"],":person_with_pouting_face:":["1f64e"],":pray:":["1f64f"],":rocket:":["1f680"],":railway_car:":["1f683"],":bullettrain_side:":["1f684"],":bullettrain_front:":["1f685"],":metro:":["1f687"],":station:":["1f689"],":bus:":["1f68c"],":busstop:":["1f68f"],":ambulance:":["1f691"],":fire_engine:":["1f692"],":police_car:":["1f693"],":taxi:":["1f695"],":red_car:":["1f697"],":blue_car:":["1f699"],":truck:":["1f69a"],":ship:":["1f6a2"],":speedboat:":["1f6a4"],":traffic_light:":["1f6a5"],":construction:":["1f6a7"],":rotating_light:":["1f6a8"],":triangular_flag_on_post:":["1f6a9"],":door:":["1f6aa"],":no_entry_sign:":["1f6ab"],":smoking:":["1f6ac"],":no_smoking:":["1f6ad"],":bike:":["1f6b2"],":walking:":["1f6b6"],":mens:":["1f6b9"],":womens:":["1f6ba"],":restroom:":["1f6bb"],":baby_symbol:":["1f6bc"],":toilet:":["1f6bd"],":wc:":["1f6be"],":bath:":["1f6c0"],":grinning:":["1f600"],":innocent:":["1f607"],":smiling_imp:":["1f608"],":sunglasses:":["1f60e"],":neutral_face:":["1f610"],":expressionless:":["1f611"],":confused:":["1f615"],":kissing:":["1f617"],":kissing_smiling_eyes:":["1f619"],":stuck_out_tongue:":["1f61b"],":worried:":["1f61f"],":frowning:":["1f626"],":anguished:":["1f627"],":grimacing:":["1f62c"],":open_mouth:":["1f62e"],":hushed:":["1f62f"],":sleeping:":["1f634"],":no_mouth:":["1f636"],":helicopter:":["1f681"],":steam_locomotive:":["1f682"],":train2:":["1f686"],":light_rail:":["1f688"],":tram:":["1f68a"],":oncoming_bus:":["1f68d"],":trolleybus:":["1f68e"],":minibus:":["1f690"],":oncoming_police_car:":["1f694"],":oncoming_taxi:":["1f696"],":oncoming_automobile:":["1f698"],":articulated_lorry:":["1f69b"],":tractor:":["1f69c"],":monorail:":["1f69d"],":mountain_railway:":["1f69e"],":suspension_railway:":["1f69f"],":mountain_cableway:":["1f6a0"],":aerial_tramway:":["1f6a1"],":rowboat:":["1f6a3"],":vertical_traffic_light:":["1f6a6"],":put_litter_in_its_place:":["1f6ae"],":do_not_litter:":["1f6af"],":potable_water:":["1f6b0"],":non-potable_water:":["1f6b1"],":no_bicycles:":["1f6b3"],":bicyclist:":["1f6b4"],":mountain_bicyclist:":["1f6b5"],":no_pedestrians:":["1f6b7"],":children_crossing:":["1f6b8"],":shower:":["1f6bf"],":bathtub:":["1f6c1"],":passport_control:":["1f6c2"],":customs:":["1f6c3"],":baggage_claim:":["1f6c4"],":left_luggage:":["1f6c5"],":earth_africa:":["1f30d"],":earth_americas:":["1f30e"],":globe_with_meridians:":["1f310"],":waxing_crescent_moon:":["1f312"],":waning_gibbous_moon:":["1f316"],":last_quarter_moon:":["1f317"],":waning_crescent_moon:":["1f318"],":new_moon_with_face:":["1f31a"],":last_quarter_moon_with_face:":["1f31c"],":full_moon_with_face:":["1f31d"],":sun_with_face:":["1f31e"],":evergreen_tree:":["1f332"],":deciduous_tree:":["1f333"],":lemon:":["1f34b"],":pear:":["1f350"],":baby_bottle:":["1f37c"],":horse_racing:":["1f3c7"],":rugby_football:":["1f3c9"],":european_post_office:":["1f3e4"],":rat:":["1f400"],":mouse2:":["1f401"],":ox:":["1f402"],":water_buffalo:":["1f403"],":cow2:":["1f404"],":tiger2:":["1f405"],":leopard:":["1f406"],":rabbit2:":["1f407"],":cat2:":["1f408"],":dragon:":["1f409"],":crocodile:":["1f40a"],":whale2:":["1f40b"],":ram:":["1f40f"],":goat:":["1f410"],":rooster:":["1f413"],":dog2:":["1f415"],":pig2:":["1f416"],":dromedary_camel:":["1f42a"],":busts_in_silhouette:":["1f465"],":two_men_holding_hands:":["1f46c"],":two_women_holding_hands:":["1f46d"],":thought_balloon:":["1f4ad"],":euro:":["1f4b6"],":pound:":["1f4b7"],":mailbox_with_mail:":["1f4ec"],":mailbox_with_no_mail:":["1f4ed"],":postal_horn:":["1f4ef"],":no_mobile_phones:":["1f4f5"],":twisted_rightwards_arrows:":["1f500"],":repeat:":["1f501"],":repeat_one:":["1f502"],":arrows_counterclockwise:":["1f504"],":low_brightness:":["1f505"],":high_brightness:":["1f506"],":mute:":["1f507"],":sound:":["1f509"],":no_bell:":["1f515"],":microscope:":["1f52c"],":telescope:":["1f52d"],":clock130:":["1f55c"],":clock230:":["1f55d"],":clock330:":["1f55e"],":clock430:":["1f55f"],":clock530:":["1f560"],":clock630:":["1f561"],":clock730:":["1f562"],":clock830:":["1f563"],":clock930:":["1f564"],":clock1030:":["1f565"],":clock1130:":["1f566"],":clock1230:":["1f567"],":speaker:":["1f508"],":train:":["1f68b"],":loop:":["27bf"],":af:":["1f1e6-1f1eb"],":al:":["1f1e6-1f1f1"],":dz:":["1f1e9-1f1ff"],":ad:":["1f1e6-1f1e9"],":ao:":["1f1e6-1f1f4"],":ag:":["1f1e6-1f1ec"],":ar:":["1f1e6-1f1f7"],":am:":["1f1e6-1f1f2"],":au:":["1f1e6-1f1fa"],":at:":["1f1e6-1f1f9"],":az:":["1f1e6-1f1ff"],":bs:":["1f1e7-1f1f8"],":bh:":["1f1e7-1f1ed"],":bd:":["1f1e7-1f1e9"],":bb:":["1f1e7-1f1e7"],":by:":["1f1e7-1f1fe"],":be:":["1f1e7-1f1ea"],":bz:":["1f1e7-1f1ff"],":bj:":["1f1e7-1f1ef"],":bt:":["1f1e7-1f1f9"],":bo:":["1f1e7-1f1f4"],":ba:":["1f1e7-1f1e6"],":bw:":["1f1e7-1f1fc"],":br:":["1f1e7-1f1f7"],":bn:":["1f1e7-1f1f3"],":bg:":["1f1e7-1f1ec"],":bf:":["1f1e7-1f1eb"],":bi:":["1f1e7-1f1ee"],":kh:":["1f1f0-1f1ed"],":cm:":["1f1e8-1f1f2"],":ca:":["1f1e8-1f1e6"],":cv:":["1f1e8-1f1fb"],":cf:":["1f1e8-1f1eb"],":td:":["1f1f9-1f1e9"],":chile:":["1f1e8-1f1f1"],":co:":["1f1e8-1f1f4"],":km:":["1f1f0-1f1f2"],":cr:":["1f1e8-1f1f7"],":ci:":["1f1e8-1f1ee"],":hr:":["1f1ed-1f1f7"],":cu:":["1f1e8-1f1fa"],":cy:":["1f1e8-1f1fe"],":cz:":["1f1e8-1f1ff"],":congo:":["1f1e8-1f1e9"],":dk:":["1f1e9-1f1f0"],":dj:":["1f1e9-1f1ef"],":dm:":["1f1e9-1f1f2"],":do:":["1f1e9-1f1f4"],":tl:":["1f1f9-1f1f1"],":ec:":["1f1ea-1f1e8"],":eg:":["1f1ea-1f1ec"],":sv:":["1f1f8-1f1fb"],":gq:":["1f1ec-1f1f6"],":er:":["1f1ea-1f1f7"],":ee:":["1f1ea-1f1ea"],":et:":["1f1ea-1f1f9"],":fj:":["1f1eb-1f1ef"],":fi:":["1f1eb-1f1ee"],":ga:":["1f1ec-1f1e6"],":gm:":["1f1ec-1f1f2"],":ge:":["1f1ec-1f1ea"],":gh:":["1f1ec-1f1ed"],":gr:":["1f1ec-1f1f7"],":gd:":["1f1ec-1f1e9"],":gt:":["1f1ec-1f1f9"],":gn:":["1f1ec-1f1f3"],":gw:":["1f1ec-1f1fc"],":gy:":["1f1ec-1f1fe"],":ht:":["1f1ed-1f1f9"],":hn:":["1f1ed-1f1f3"],":hu:":["1f1ed-1f1fa"],":is:":["1f1ee-1f1f8"],":in:":["1f1ee-1f1f3"],":indonesia:":["1f1ee-1f1e9"],":ir:":["1f1ee-1f1f7"],":iq:":["1f1ee-1f1f6"],":ie:":["1f1ee-1f1ea"],":il:":["1f1ee-1f1f1"],":jm:":["1f1ef-1f1f2"],":jo:":["1f1ef-1f1f4"],":kz:":["1f1f0-1f1ff"],":ke:":["1f1f0-1f1ea"],":ki:":["1f1f0-1f1ee"],":xk:":["1f1fd-1f1f0"],":kw:":["1f1f0-1f1fc"],":kg:":["1f1f0-1f1ec"],":la:":["1f1f1-1f1e6"],":lv:":["1f1f1-1f1fb"],":lb:":["1f1f1-1f1e7"],":ls:":["1f1f1-1f1f8"],":lr:":["1f1f1-1f1f7"],":ly:":["1f1f1-1f1fe"],":li:":["1f1f1-1f1ee"],":lt:":["1f1f1-1f1f9"],":lu:":["1f1f1-1f1fa"],":mk:":["1f1f2-1f1f0"],":mg:":["1f1f2-1f1ec"],":mw:":["1f1f2-1f1fc"],":my:":["1f1f2-1f1fe"],":mv:":["1f1f2-1f1fb"],":ml:":["1f1f2-1f1f1"],":mt:":["1f1f2-1f1f9"],":mh:":["1f1f2-1f1ed"],":mr:":["1f1f2-1f1f7"],":mu:":["1f1f2-1f1fa"],":mx:":["1f1f2-1f1fd"],":fm:":["1f1eb-1f1f2"],":md:":["1f1f2-1f1e9"],":mc:":["1f1f2-1f1e8"],":mn:":["1f1f2-1f1f3"],":me:":["1f1f2-1f1ea"],":ma:":["1f1f2-1f1e6"],":mz:":["1f1f2-1f1ff"],":mm:":["1f1f2-1f1f2"],":na:":["1f1f3-1f1e6"],":nr:":["1f1f3-1f1f7"],":np:":["1f1f3-1f1f5"],":nl:":["1f1f3-1f1f1"],":nz:":["1f1f3-1f1ff"],":ni:":["1f1f3-1f1ee"],":ne:":["1f1f3-1f1ea"],":nigeria:":["1f1f3-1f1ec"],":kp:":["1f1f0-1f1f5"],":no:":["1f1f3-1f1f4"],":om:":["1f1f4-1f1f2"],":pk:":["1f1f5-1f1f0"],":pw:":["1f1f5-1f1fc"],":pa:":["1f1f5-1f1e6"],":pg:":["1f1f5-1f1ec"],":py:":["1f1f5-1f1fe"],":pe:":["1f1f5-1f1ea"],":ph:":["1f1f5-1f1ed"],":pl:":["1f1f5-1f1f1"],":pt:":["1f1f5-1f1f9"],":qa:":["1f1f6-1f1e6"],":tw:":["1f1f9-1f1fc"],":cg:":["1f1e8-1f1ec"],":ro:":["1f1f7-1f1f4"],":rw:":["1f1f7-1f1fc"],":kn:":["1f1f0-1f1f3"],":lc:":["1f1f1-1f1e8"],":vc:":["1f1fb-1f1e8"],":ws:":["1f1fc-1f1f8"],":sm:":["1f1f8-1f1f2"],":st:":["1f1f8-1f1f9"],":saudiarabia:":["1f1f8-1f1e6"],":saudi:":["1f1f8-1f1e6"],":sn:":["1f1f8-1f1f3"],":rs:":["1f1f7-1f1f8"],":sc:":["1f1f8-1f1e8"],":sl:":["1f1f8-1f1f1"],":sg:":["1f1f8-1f1ec"],":sk:":["1f1f8-1f1f0"],":si:":["1f1f8-1f1ee"],":sb:":["1f1f8-1f1e7"],":so:":["1f1f8-1f1f4"],":za:":["1f1ff-1f1e6"],":lk:":["1f1f1-1f1f0"],":sd:":["1f1f8-1f1e9"],":sr:":["1f1f8-1f1f7"],":sz:":["1f1f8-1f1ff"],":se:":["1f1f8-1f1ea"],":ch:":["1f1e8-1f1ed"],":sy:":["1f1f8-1f1fe"],":tj:":["1f1f9-1f1ef"],":tz:":["1f1f9-1f1ff"],":th:":["1f1f9-1f1ed"],":tg:":["1f1f9-1f1ec"],":to:":["1f1f9-1f1f4"],":tt:":["1f1f9-1f1f9"],":tn:":["1f1f9-1f1f3"],":tr:":["1f1f9-1f1f7"],":turkmenistan:":["1f1f9-1f1f2"],":tuvalu:":["1f1f9-1f1fb"],":ug:":["1f1fa-1f1ec"],":ua:":["1f1fa-1f1e6"],":ae:":["1f1e6-1f1ea"],":uy:":["1f1fa-1f1fe"],":uz:":["1f1fa-1f1ff"],":vu:":["1f1fb-1f1fa"],":va:":["1f1fb-1f1e6"],":ve:":["1f1fb-1f1ea"],":vn:":["1f1fb-1f1f3"],":eh:":["1f1ea-1f1ed"],":ye:":["1f1fe-1f1ea"],":zm:":["1f1ff-1f1f2"],":zw:":["1f1ff-1f1fc"],":pr:":["1f1f5-1f1f7"],":ky:":["1f1f0-1f1fe"],":bm:":["1f1e7-1f1f2"],":pf:":["1f1f5-1f1eb"],":ps:":["1f1f5-1f1f8"],":nc:":["1f1f3-1f1e8"],":sh:":["1f1f8-1f1ed"],":aw:":["1f1e6-1f1fc"],":vi:":["1f1fb-1f1ee"],":hk:":["1f1ed-1f1f0"],":ac:":["1f1e6-1f1e8"],":ms:":["1f1f2-1f1f8"],":gu:":["1f1ec-1f1fa"],":gl:":["1f1ec-1f1f1"],":nu:":["1f1f3-1f1fa"],":wf:":["1f1fc-1f1eb"],":mo:":["1f1f2-1f1f4"],":fo:":["1f1eb-1f1f4"],":fk:":["1f1eb-1f1f0"],":je:":["1f1ef-1f1ea"],":ai:":["1f1e6-1f1ee"],":gi:":["1f1ec-1f1ee"]},a.asciiList={"<3":"2764",":)":"1f606",">;)":"1f606",">:-)":"1f606",">=)":"1f606",";)":"1f609",";-)":"1f609","*-)":"1f609","*)":"1f609",";-]":"1f609",";]":"1f609",";D":"1f609",";^)":"1f609","':(":"1f613","':-(":"1f613","'=(":"1f613",":*":"1f618",":-*":"1f618","=*":"1f618",":^*":"1f618",">:P":"1f61c","X-P":"1f61c","x-p":"1f61c",">:[":"1f61e",":-(":"1f61e",":(":"1f61e",":-[":"1f61e",":[":"1f61e","=(":"1f61e",">:(":"1f620",">:-(":"1f620",":@":"1f620",":'(":"1f622",":'-(":"1f622",";(":"1f622",";-(":"1f622",">.<":"1f623",":$":"1f633","=$":"1f633","#-)":"1f635","#)":"1f635","%-)":"1f635","%)":"1f635","X)":"1f635","X-)":"1f635","*\\0/*":"1f646","\\0/":"1f646","*\\O/*":"1f646","\\O/":"1f646","O:-)":"1f607","0:-3":"1f607","0:3":"1f607","0:-)":"1f607","0:)":"1f607","0;^)":"1f607","O:)":"1f607","O;-)":"1f607","O=)":"1f607","0;-)":"1f607","O:-3":"1f607","O:3":"1f607","B-)":"1f60e","B)":"1f60e","8)":"1f60e","8-)":"1f60e","B-D":"1f60e","8-D":"1f60e","-_-":"1f611","-__-":"1f611","-___-":"1f611",">:\\":"1f615",">:/":"1f615",":-/":"1f615",":-.":"1f615",":/":"1f615",":\\":"1f615","=/":"1f615","=\\":"1f615",":L":"1f615","=L":"1f615",":P":"1f61b",":-P":"1f61b","=P":"1f61b",":-p":"1f61b",":p":"1f61b","=p":"1f61b",":-Þ":"1f61b",":Þ":"1f61b",":þ":"1f61b",":-þ":"1f61b",":-b":"1f61b",":b":"1f61b","d:":"1f61b",":-O":"1f62e",":O":"1f62e",":-o":"1f62e",":o":"1f62e",O_O:"1f62e",">:O":"1f62e",":-X":"1f636",":X":"1f636",":-#":"1f636",":#":"1f636","=X":"1f636","=x":"1f636",":x":"1f636",":-x":"1f636","=#":"1f636"},a.asciiRegexp="(\\<3|<3|\\<\\/3|<\\/3|\\:'\\)|\\:'\\-\\)|\\:D|\\:\\-D|\\=D|\\:\\)|\\:\\-\\)|\\=\\]|\\=\\)|\\:\\]|'\\:\\)|'\\:\\-\\)|'\\=\\)|'\\:D|'\\:\\-D|'\\=D|\\>\\:\\)|>\\:\\)|\\>;\\)|>;\\)|\\>\\:\\-\\)|>\\:\\-\\)|\\>\\=\\)|>\\=\\)|;\\)|;\\-\\)|\\*\\-\\)|\\*\\)|;\\-\\]|;\\]|;D|;\\^\\)|'\\:\\(|'\\:\\-\\(|'\\=\\(|\\:\\*|\\:\\-\\*|\\=\\*|\\:\\^\\*|\\>\\:P|>\\:P|X\\-P|x\\-p|\\>\\:\\[|>\\:\\[|\\:\\-\\(|\\:\\(|\\:\\-\\[|\\:\\[|\\=\\(|\\>\\:\\(|>\\:\\(|\\>\\:\\-\\(|>\\:\\-\\(|\\:@|\\:'\\(|\\:'\\-\\(|;\\(|;\\-\\(|\\>\\.\\<|>\\.<|\\:\\$|\\=\\$|#\\-\\)|#\\)|%\\-\\)|%\\)|X\\)|X\\-\\)|\\*\\\\0\\/\\*|\\\\0\\/|\\*\\\\O\\/\\*|\\\\O\\/|O\\:\\-\\)|0\\:\\-3|0\\:3|0\\:\\-\\)|0\\:\\)|0;\\^\\)|O\\:\\-\\)|O\\:\\)|O;\\-\\)|O\\=\\)|0;\\-\\)|O\\:\\-3|O\\:3|B\\-\\)|B\\)|8\\)|8\\-\\)|B\\-D|8\\-D|\\-_\\-|\\-__\\-|\\-___\\-|\\>\\:\\\\|>\\:\\\\|\\>\\:\\/|>\\:\\/|\\:\\-\\/|\\:\\-\\.|\\:\\/|\\:\\\\|\\=\\/|\\=\\\\|\\:L|\\=L|\\:P|\\:\\-P|\\=P|\\:\\-p|\\:p|\\=p|\\:\\-Þ|\\:\\-Þ|\\:Þ|\\:Þ|\\:þ|\\:þ|\\:\\-þ|\\:\\-þ|\\:\\-b|\\:b|d\\:|\\:\\-O|\\:O|\\:\\-o|\\:o|O_O|\\>\\:O|>\\:O|\\:\\-X|\\:X|\\:\\-#|\\:#|\\=X|\\=x|\\:x|\\:\\-x|\\=#)",a.unicodeRegexp="(#\\uFE0F\\u20E3|#\\u20E3|0\\uFE0F\\u20E3|0\\u20E3|1\\uFE0F\\u20E3|1\\u20E3|2\\uFE0F\\u20E3|2\\u20E3|3\\uFE0F\\u20E3|3\\u20E3|4\\uFE0F\\u20E3|4\\u20E3|5\\uFE0F\\u20E3|5\\u20E3|6\\uFE0F\\u20E3|6\\u20E3|7\\uFE0F\\u20E3|7\\u20E3|8\\uFE0F\\u20E3|8\\u20E3|9\\uFE0F\\u20E3|9\\u20E3|\\u00A9|\\u00AE|\\u203C\\uFE0F|\\u203C|\\u2049\\uFE0F|\\u2049|\\u2122|\\u2139\\uFE0F|\\u2139|\\u2194\\uFE0F|\\u2194|\\u2195\\uFE0F|\\u2195|\\u2196\\uFE0F|\\u2196|\\u2197\\uFE0F|\\u2197|\\u2198\\uFE0F|\\u2198|\\u2199\\uFE0F|\\u2199|\\u21A9\\uFE0F|\\u21A9|\\u21AA\\uFE0F|\\u21AA|\\u231A\\uFE0F|\\u231A|\\u231B\\uFE0F|\\u231B|\\u23E9|\\u23EA|\\u23EB|\\u23EC|\\u23F0|\\u23F3|\\u24C2\\uFE0F|\\u24C2|\\u25AA\\uFE0F|\\u25AA|\\u25AB\\uFE0F|\\u25AB|\\u25B6\\uFE0F|\\u25B6|\\u25C0\\uFE0F|\\u25C0|\\u25FB\\uFE0F|\\u25FB|\\u25FC\\uFE0F|\\u25FC|\\u25FD\\uFE0F|\\u25FD|\\u25FE\\uFE0F|\\u25FE|\\u2600\\uFE0F|\\u2600|\\u2601\\uFE0F|\\u2601|\\u260E\\uFE0F|\\u260E|\\u2611\\uFE0F|\\u2611|\\u2614\\uFE0F|\\u2614|\\u2615\\uFE0F|\\u2615|\\u261D\\uFE0F|\\u261D|\\u263A\\uFE0F|\\u263A|\\u2648\\uFE0F|\\u2648|\\u2649\\uFE0F|\\u2649|\\u264A\\uFE0F|\\u264A|\\u264B\\uFE0F|\\u264B|\\u264C\\uFE0F|\\u264C|\\u264D\\uFE0F|\\u264D|\\u264E\\uFE0F|\\u264E|\\u264F\\uFE0F|\\u264F|\\u2650\\uFE0F|\\u2650|\\u2651\\uFE0F|\\u2651|\\u2652\\uFE0F|\\u2652|\\u2653\\uFE0F|\\u2653|\\u2660\\uFE0F|\\u2660|\\u2663\\uFE0F|\\u2663|\\u2665\\uFE0F|\\u2665|\\u2666\\uFE0F|\\u2666|\\u2668\\uFE0F|\\u2668|\\u267B\\uFE0F|\\u267B|\\u267F\\uFE0F|\\u267F|\\u2693\\uFE0F|\\u2693|\\u26A0\\uFE0F|\\u26A0|\\u26A1\\uFE0F|\\u26A1|\\u26AA\\uFE0F|\\u26AA|\\u26AB\\uFE0F|\\u26AB|\\u26BD\\uFE0F|\\u26BD|\\u26BE\\uFE0F|\\u26BE|\\u26C4\\uFE0F|\\u26C4|\\u26C5\\uFE0F|\\u26C5|\\u26CE|\\u26D4\\uFE0F|\\u26D4|\\u26EA\\uFE0F|\\u26EA|\\u26F2\\uFE0F|\\u26F2|\\u26F3\\uFE0F|\\u26F3|\\u26F5\\uFE0F|\\u26F5|\\u26FA\\uFE0F|\\u26FA|\\u26FD\\uFE0F|\\u26FD|\\u2702\\uFE0F|\\u2702|\\u2705|\\u2708\\uFE0F|\\u2708|\\u2709\\uFE0F|\\u2709|\\u270A|\\u270B|\\u270C\\uFE0F|\\u270C|\\u270F\\uFE0F|\\u270F|\\u2712\\uFE0F|\\u2712|\\u2714\\uFE0F|\\u2714|\\u2716\\uFE0F|\\u2716|\\u2728|\\u2733\\uFE0F|\\u2733|\\u2734\\uFE0F|\\u2734|\\u2744\\uFE0F|\\u2744|\\u2747\\uFE0F|\\u2747|\\u274C|\\u274E|\\u2753|\\u2754|\\u2755|\\u2757\\uFE0F|\\u2757|\\u2764\\uFE0F|\\u2764|\\u2795|\\u2796|\\u2797|\\u27A1\\uFE0F|\\u27A1|\\u27B0|\\u2934\\uFE0F|\\u2934|\\u2935\\uFE0F|\\u2935|\\u2B05\\uFE0F|\\u2B05|\\u2B06\\uFE0F|\\u2B06|\\u2B07\\uFE0F|\\u2B07|\\u2B1B\\uFE0F|\\u2B1B|\\u2B1C\\uFE0F|\\u2B1C|\\u2B50\\uFE0F|\\u2B50|\\u2B55\\uFE0F|\\u2B55|\\u3030|\\u303D\\uFE0F|\\u303D|\\u3297\\uFE0F|\\u3297|\\u3299\\uFE0F|\\u3299|\\uD83C\\uDC04\\uFE0F|\\uD83C\\uDC04|\\uD83C\\uDCCF|\\uD83C\\uDD70|\\uD83C\\uDD71|\\uD83C\\uDD7E|\\uD83C\\uDD7F\\uFE0F|\\uD83C\\uDD7F|\\uD83C\\uDD8E|\\uD83C\\uDD91|\\uD83C\\uDD92|\\uD83C\\uDD93|\\uD83C\\uDD94|\\uD83C\\uDD95|\\uD83C\\uDD96|\\uD83C\\uDD97|\\uD83C\\uDD98|\\uD83C\\uDD99|\\uD83C\\uDD9A|\\uD83C\\uDDE8\\uD83C\\uDDF3|\\uD83C\\uDDE9\\uD83C\\uDDEA|\\uD83C\\uDDEA\\uD83C\\uDDF8|\\uD83C\\uDDEB\\uD83C\\uDDF7|\\uD83C\\uDDEC\\uD83C\\uDDE7|\\uD83C\\uDDEE\\uD83C\\uDDF9|\\uD83C\\uDDEF\\uD83C\\uDDF5|\\uD83C\\uDDF0\\uD83C\\uDDF7|\\uD83C\\uDDFA\\uD83C\\uDDF8|\\uD83C\\uDDF7\\uD83C\\uDDFA|\\uD83C\\uDE01|\\uD83C\\uDE02|\\uD83C\\uDE1A\\uFE0F|\\uD83C\\uDE1A|\\uD83C\\uDE2F\\uFE0F|\\uD83C\\uDE2F|\\uD83C\\uDE32|\\uD83C\\uDE33|\\uD83C\\uDE34|\\uD83C\\uDE35|\\uD83C\\uDE36|\\uD83C\\uDE37|\\uD83C\\uDE38|\\uD83C\\uDE39|\\uD83C\\uDE3A|\\uD83C\\uDE50|\\uD83C\\uDE51|\\uD83C\\uDF00|\\uD83C\\uDF01|\\uD83C\\uDF02|\\uD83C\\uDF03|\\uD83C\\uDF04|\\uD83C\\uDF05|\\uD83C\\uDF06|\\uD83C\\uDF07|\\uD83C\\uDF08|\\uD83C\\uDF09|\\uD83C\\uDF0A|\\uD83C\\uDF0B|\\uD83C\\uDF0C|\\uD83C\\uDF0F|\\uD83C\\uDF11|\\uD83C\\uDF13|\\uD83C\\uDF14|\\uD83C\\uDF15|\\uD83C\\uDF19|\\uD83C\\uDF1B|\\uD83C\\uDF1F|\\uD83C\\uDF20|\\uD83C\\uDF30|\\uD83C\\uDF31|\\uD83C\\uDF34|\\uD83C\\uDF35|\\uD83C\\uDF37|\\uD83C\\uDF38|\\uD83C\\uDF39|\\uD83C\\uDF3A|\\uD83C\\uDF3B|\\uD83C\\uDF3C|\\uD83C\\uDF3D|\\uD83C\\uDF3E|\\uD83C\\uDF3F|\\uD83C\\uDF40|\\uD83C\\uDF41|\\uD83C\\uDF42|\\uD83C\\uDF43|\\uD83C\\uDF44|\\uD83C\\uDF45|\\uD83C\\uDF46|\\uD83C\\uDF47|\\uD83C\\uDF48|\\uD83C\\uDF49|\\uD83C\\uDF4A|\\uD83C\\uDF4C|\\uD83C\\uDF4D|\\uD83C\\uDF4E|\\uD83C\\uDF4F|\\uD83C\\uDF51|\\uD83C\\uDF52|\\uD83C\\uDF53|\\uD83C\\uDF54|\\uD83C\\uDF55|\\uD83C\\uDF56|\\uD83C\\uDF57|\\uD83C\\uDF58|\\uD83C\\uDF59|\\uD83C\\uDF5A|\\uD83C\\uDF5B|\\uD83C\\uDF5C|\\uD83C\\uDF5D|\\uD83C\\uDF5E|\\uD83C\\uDF5F|\\uD83C\\uDF60|\\uD83C\\uDF61|\\uD83C\\uDF62|\\uD83C\\uDF63|\\uD83C\\uDF64|\\uD83C\\uDF65|\\uD83C\\uDF66|\\uD83C\\uDF67|\\uD83C\\uDF68|\\uD83C\\uDF69|\\uD83C\\uDF6A|\\uD83C\\uDF6B|\\uD83C\\uDF6C|\\uD83C\\uDF6D|\\uD83C\\uDF6E|\\uD83C\\uDF6F|\\uD83C\\uDF70|\\uD83C\\uDF71|\\uD83C\\uDF72|\\uD83C\\uDF73|\\uD83C\\uDF74|\\uD83C\\uDF75|\\uD83C\\uDF76|\\uD83C\\uDF77|\\uD83C\\uDF78|\\uD83C\\uDF79|\\uD83C\\uDF7A|\\uD83C\\uDF7B|\\uD83C\\uDF80|\\uD83C\\uDF81|\\uD83C\\uDF82|\\uD83C\\uDF83|\\uD83C\\uDF84|\\uD83C\\uDF85|\\uD83C\\uDF86|\\uD83C\\uDF87|\\uD83C\\uDF88|\\uD83C\\uDF89|\\uD83C\\uDF8A|\\uD83C\\uDF8B|\\uD83C\\uDF8C|\\uD83C\\uDF8D|\\uD83C\\uDF8E|\\uD83C\\uDF8F|\\uD83C\\uDF90|\\uD83C\\uDF91|\\uD83C\\uDF92|\\uD83C\\uDF93|\\uD83C\\uDFA0|\\uD83C\\uDFA1|\\uD83C\\uDFA2|\\uD83C\\uDFA3|\\uD83C\\uDFA4|\\uD83C\\uDFA5|\\uD83C\\uDFA6|\\uD83C\\uDFA7|\\uD83C\\uDFA8|\\uD83C\\uDFA9|\\uD83C\\uDFAA|\\uD83C\\uDFAB|\\uD83C\\uDFAC|\\uD83C\\uDFAD|\\uD83C\\uDFAE|\\uD83C\\uDFAF|\\uD83C\\uDFB0|\\uD83C\\uDFB1|\\uD83C\\uDFB2|\\uD83C\\uDFB3|\\uD83C\\uDFB4|\\uD83C\\uDFB5|\\uD83C\\uDFB6|\\uD83C\\uDFB7|\\uD83C\\uDFB8|\\uD83C\\uDFB9|\\uD83C\\uDFBA|\\uD83C\\uDFBB|\\uD83C\\uDFBC|\\uD83C\\uDFBD|\\uD83C\\uDFBE|\\uD83C\\uDFBF|\\uD83C\\uDFC0|\\uD83C\\uDFC1|\\uD83C\\uDFC2|\\uD83C\\uDFC3|\\uD83C\\uDFC4|\\uD83C\\uDFC6|\\uD83C\\uDFC8|\\uD83C\\uDFCA|\\uD83C\\uDFE0|\\uD83C\\uDFE1|\\uD83C\\uDFE2|\\uD83C\\uDFE3|\\uD83C\\uDFE5|\\uD83C\\uDFE6|\\uD83C\\uDFE7|\\uD83C\\uDFE8|\\uD83C\\uDFE9|\\uD83C\\uDFEA|\\uD83C\\uDFEB|\\uD83C\\uDFEC|\\uD83C\\uDFED|\\uD83C\\uDFEE|\\uD83C\\uDFEF|\\uD83C\\uDFF0|\\uD83D\\uDC0C|\\uD83D\\uDC0D|\\uD83D\\uDC0E|\\uD83D\\uDC11|\\uD83D\\uDC12|\\uD83D\\uDC14|\\uD83D\\uDC17|\\uD83D\\uDC18|\\uD83D\\uDC19|\\uD83D\\uDC1A|\\uD83D\\uDC1B|\\uD83D\\uDC1C|\\uD83D\\uDC1D|\\uD83D\\uDC1E|\\uD83D\\uDC1F|\\uD83D\\uDC20|\\uD83D\\uDC21|\\uD83D\\uDC22|\\uD83D\\uDC23|\\uD83D\\uDC24|\\uD83D\\uDC25|\\uD83D\\uDC26|\\uD83D\\uDC27|\\uD83D\\uDC28|\\uD83D\\uDC29|\\uD83D\\uDC2B|\\uD83D\\uDC2C|\\uD83D\\uDC2D|\\uD83D\\uDC2E|\\uD83D\\uDC2F|\\uD83D\\uDC30|\\uD83D\\uDC31|\\uD83D\\uDC32|\\uD83D\\uDC33|\\uD83D\\uDC34|\\uD83D\\uDC35|\\uD83D\\uDC36|\\uD83D\\uDC37|\\uD83D\\uDC38|\\uD83D\\uDC39|\\uD83D\\uDC3A|\\uD83D\\uDC3B|\\uD83D\\uDC3C|\\uD83D\\uDC3D|\\uD83D\\uDC3E|\\uD83D\\uDC40|\\uD83D\\uDC42|\\uD83D\\uDC43|\\uD83D\\uDC44|\\uD83D\\uDC45|\\uD83D\\uDC46|\\uD83D\\uDC47|\\uD83D\\uDC48|\\uD83D\\uDC49|\\uD83D\\uDC4A|\\uD83D\\uDC4B|\\uD83D\\uDC4C|\\uD83D\\uDC4D|\\uD83D\\uDC4E|\\uD83D\\uDC4F|\\uD83D\\uDC50|\\uD83D\\uDC51|\\uD83D\\uDC52|\\uD83D\\uDC53|\\uD83D\\uDC54|\\uD83D\\uDC55|\\uD83D\\uDC56|\\uD83D\\uDC57|\\uD83D\\uDC58|\\uD83D\\uDC59|\\uD83D\\uDC5A|\\uD83D\\uDC5B|\\uD83D\\uDC5C|\\uD83D\\uDC5D|\\uD83D\\uDC5E|\\uD83D\\uDC5F|\\uD83D\\uDC60|\\uD83D\\uDC61|\\uD83D\\uDC62|\\uD83D\\uDC63|\\uD83D\\uDC64|\\uD83D\\uDC66|\\uD83D\\uDC67|\\uD83D\\uDC68|\\uD83D\\uDC69|\\uD83D\\uDC6A|\\uD83D\\uDC6B|\\uD83D\\uDC6E|\\uD83D\\uDC6F|\\uD83D\\uDC70|\\uD83D\\uDC71|\\uD83D\\uDC72|\\uD83D\\uDC73|\\uD83D\\uDC74|\\uD83D\\uDC75|\\uD83D\\uDC76|\\uD83D\\uDC77|\\uD83D\\uDC78|\\uD83D\\uDC79|\\uD83D\\uDC7A|\\uD83D\\uDC7B|\\uD83D\\uDC7C|\\uD83D\\uDC7D|\\uD83D\\uDC7E|\\uD83D\\uDC7F|\\uD83D\\uDC80|\\uD83D\\uDCC7|\\uD83D\\uDC81|\\uD83D\\uDC82|\\uD83D\\uDC83|\\uD83D\\uDC84|\\uD83D\\uDC85|\\uD83D\\uDCD2|\\uD83D\\uDC86|\\uD83D\\uDCD3|\\uD83D\\uDC87|\\uD83D\\uDCD4|\\uD83D\\uDC88|\\uD83D\\uDCD5|\\uD83D\\uDC89|\\uD83D\\uDCD6|\\uD83D\\uDC8A|\\uD83D\\uDCD7|\\uD83D\\uDC8B|\\uD83D\\uDCD8|\\uD83D\\uDC8C|\\uD83D\\uDCD9|\\uD83D\\uDC8D|\\uD83D\\uDCDA|\\uD83D\\uDC8E|\\uD83D\\uDCDB|\\uD83D\\uDC8F|\\uD83D\\uDCDC|\\uD83D\\uDC90|\\uD83D\\uDCDD|\\uD83D\\uDC91|\\uD83D\\uDCDE|\\uD83D\\uDC92|\\uD83D\\uDCDF|\\uD83D\\uDCE0|\\uD83D\\uDC93|\\uD83D\\uDCE1|\\uD83D\\uDCE2|\\uD83D\\uDC94|\\uD83D\\uDCE3|\\uD83D\\uDCE4|\\uD83D\\uDC95|\\uD83D\\uDCE5|\\uD83D\\uDCE6|\\uD83D\\uDC96|\\uD83D\\uDCE7|\\uD83D\\uDCE8|\\uD83D\\uDC97|\\uD83D\\uDCE9|\\uD83D\\uDCEA|\\uD83D\\uDC98|\\uD83D\\uDCEB|\\uD83D\\uDCEE|\\uD83D\\uDC99|\\uD83D\\uDCF0|\\uD83D\\uDCF1|\\uD83D\\uDC9A|\\uD83D\\uDCF2|\\uD83D\\uDCF3|\\uD83D\\uDC9B|\\uD83D\\uDCF4|\\uD83D\\uDCF6|\\uD83D\\uDC9C|\\uD83D\\uDCF7|\\uD83D\\uDCF9|\\uD83D\\uDC9D|\\uD83D\\uDCFA|\\uD83D\\uDCFB|\\uD83D\\uDC9E|\\uD83D\\uDCFC|\\uD83D\\uDD03|\\uD83D\\uDC9F|\\uD83D\\uDD0A|\\uD83D\\uDD0B|\\uD83D\\uDCA0|\\uD83D\\uDD0C|\\uD83D\\uDD0D|\\uD83D\\uDCA1|\\uD83D\\uDD0E|\\uD83D\\uDD0F|\\uD83D\\uDCA2|\\uD83D\\uDD10|\\uD83D\\uDD11|\\uD83D\\uDCA3|\\uD83D\\uDD12|\\uD83D\\uDD13|\\uD83D\\uDCA4|\\uD83D\\uDD14|\\uD83D\\uDD16|\\uD83D\\uDCA5|\\uD83D\\uDD17|\\uD83D\\uDD18|\\uD83D\\uDCA6|\\uD83D\\uDD19|\\uD83D\\uDD1A|\\uD83D\\uDCA7|\\uD83D\\uDD1B|\\uD83D\\uDD1C|\\uD83D\\uDCA8|\\uD83D\\uDD1D|\\uD83D\\uDD1E|\\uD83D\\uDCA9|\\uD83D\\uDD1F|\\uD83D\\uDCAA|\\uD83D\\uDD20|\\uD83D\\uDD21|\\uD83D\\uDCAB|\\uD83D\\uDD22|\\uD83D\\uDD23|\\uD83D\\uDCAC|\\uD83D\\uDD24|\\uD83D\\uDD25|\\uD83D\\uDCAE|\\uD83D\\uDD26|\\uD83D\\uDD27|\\uD83D\\uDCAF|\\uD83D\\uDD28|\\uD83D\\uDD29|\\uD83D\\uDCB0|\\uD83D\\uDD2A|\\uD83D\\uDD2B|\\uD83D\\uDCB1|\\uD83D\\uDD2E|\\uD83D\\uDCB2|\\uD83D\\uDD2F|\\uD83D\\uDCB3|\\uD83D\\uDD30|\\uD83D\\uDD31|\\uD83D\\uDCB4|\\uD83D\\uDD32|\\uD83D\\uDD33|\\uD83D\\uDCB5|\\uD83D\\uDD34|\\uD83D\\uDD35|\\uD83D\\uDCB8|\\uD83D\\uDD36|\\uD83D\\uDD37|\\uD83D\\uDCB9|\\uD83D\\uDD38|\\uD83D\\uDD39|\\uD83D\\uDCBA|\\uD83D\\uDD3A|\\uD83D\\uDD3B|\\uD83D\\uDCBB|\\uD83D\\uDD3C|\\uD83D\\uDCBC|\\uD83D\\uDD3D|\\uD83D\\uDD50|\\uD83D\\uDCBD|\\uD83D\\uDD51|\\uD83D\\uDCBE|\\uD83D\\uDD52|\\uD83D\\uDCBF|\\uD83D\\uDD53|\\uD83D\\uDCC0|\\uD83D\\uDD54|\\uD83D\\uDD55|\\uD83D\\uDCC1|\\uD83D\\uDD56|\\uD83D\\uDD57|\\uD83D\\uDCC2|\\uD83D\\uDD58|\\uD83D\\uDD59|\\uD83D\\uDCC3|\\uD83D\\uDD5A|\\uD83D\\uDD5B|\\uD83D\\uDCC4|\\uD83D\\uDDFB|\\uD83D\\uDDFC|\\uD83D\\uDCC5|\\uD83D\\uDDFD|\\uD83D\\uDDFE|\\uD83D\\uDCC6|\\uD83D\\uDDFF|\\uD83D\\uDE01|\\uD83D\\uDE02|\\uD83D\\uDE03|\\uD83D\\uDCC8|\\uD83D\\uDE04|\\uD83D\\uDE05|\\uD83D\\uDCC9|\\uD83D\\uDE06|\\uD83D\\uDE09|\\uD83D\\uDCCA|\\uD83D\\uDE0A|\\uD83D\\uDE0B|\\uD83D\\uDCCB|\\uD83D\\uDE0C|\\uD83D\\uDE0D|\\uD83D\\uDCCC|\\uD83D\\uDE0F|\\uD83D\\uDE12|\\uD83D\\uDCCD|\\uD83D\\uDE13|\\uD83D\\uDE14|\\uD83D\\uDCCE|\\uD83D\\uDE16|\\uD83D\\uDE18|\\uD83D\\uDCCF|\\uD83D\\uDE1A|\\uD83D\\uDE1C|\\uD83D\\uDCD0|\\uD83D\\uDE1D|\\uD83D\\uDE1E|\\uD83D\\uDCD1|\\uD83D\\uDE20|\\uD83D\\uDE21|\\uD83D\\uDE22|\\uD83D\\uDE23|\\uD83D\\uDE24|\\uD83D\\uDE25|\\uD83D\\uDE28|\\uD83D\\uDE29|\\uD83D\\uDE2A|\\uD83D\\uDE2B|\\uD83D\\uDE2D|\\uD83D\\uDE30|\\uD83D\\uDE31|\\uD83D\\uDE32|\\uD83D\\uDE33|\\uD83D\\uDE35|\\uD83D\\uDE37|\\uD83D\\uDE38|\\uD83D\\uDE39|\\uD83D\\uDE3A|\\uD83D\\uDE3B|\\uD83D\\uDE3C|\\uD83D\\uDE3D|\\uD83D\\uDE3E|\\uD83D\\uDE3F|\\uD83D\\uDE40|\\uD83D\\uDE45|\\uD83D\\uDE46|\\uD83D\\uDE47|\\uD83D\\uDE48|\\uD83D\\uDE49|\\uD83D\\uDE4A|\\uD83D\\uDE4B|\\uD83D\\uDE4C|\\uD83D\\uDE4D|\\uD83D\\uDE4E|\\uD83D\\uDE4F|\\uD83D\\uDE80|\\uD83D\\uDE83|\\uD83D\\uDE84|\\uD83D\\uDE85|\\uD83D\\uDE87|\\uD83D\\uDE89|\\uD83D\\uDE8C|\\uD83D\\uDE8F|\\uD83D\\uDE91|\\uD83D\\uDE92|\\uD83D\\uDE93|\\uD83D\\uDE95|\\uD83D\\uDE97|\\uD83D\\uDE99|\\uD83D\\uDE9A|\\uD83D\\uDEA2|\\uD83D\\uDEA4|\\uD83D\\uDEA5|\\uD83D\\uDEA7|\\uD83D\\uDEA8|\\uD83D\\uDEA9|\\uD83D\\uDEAA|\\uD83D\\uDEAB|\\uD83D\\uDEAC|\\uD83D\\uDEAD|\\uD83D\\uDEB2|\\uD83D\\uDEB6|\\uD83D\\uDEB9|\\uD83D\\uDEBA|\\uD83D\\uDEBB|\\uD83D\\uDEBC|\\uD83D\\uDEBD|\\uD83D\\uDEBE|\\uD83D\\uDEC0|\\uD83D\\uDE00|\\uD83D\\uDE07|\\uD83D\\uDE08|\\uD83D\\uDE0E|\\uD83D\\uDE10|\\uD83D\\uDE11|\\uD83D\\uDE15|\\uD83D\\uDE17|\\uD83D\\uDE19|\\uD83D\\uDE1B|\\uD83D\\uDE1F|\\uD83D\\uDE26|\\uD83D\\uDE27|\\uD83D\\uDE2C|\\uD83D\\uDE2E|\\uD83D\\uDE2F|\\uD83D\\uDE34|\\uD83D\\uDE36|\\uD83D\\uDE81|\\uD83D\\uDE82|\\uD83D\\uDE86|\\uD83D\\uDE88|\\uD83D\\uDE8A|\\uD83D\\uDE8D|\\uD83D\\uDE8E|\\uD83D\\uDE90|\\uD83D\\uDE94|\\uD83D\\uDE96|\\uD83D\\uDE98|\\uD83D\\uDE9B|\\uD83D\\uDE9C|\\uD83D\\uDE9D|\\uD83D\\uDE9E|\\uD83D\\uDE9F|\\uD83D\\uDEA0|\\uD83D\\uDEA1|\\uD83D\\uDEA3|\\uD83D\\uDEA6|\\uD83D\\uDEAE|\\uD83D\\uDEAF|\\uD83D\\uDEB0|\\uD83D\\uDEB1|\\uD83D\\uDEB3|\\uD83D\\uDEB4|\\uD83D\\uDEB5|\\uD83D\\uDEB7|\\uD83D\\uDEB8|\\uD83D\\uDEBF|\\uD83D\\uDEC1|\\uD83D\\uDEC2|\\uD83D\\uDEC3|\\uD83D\\uDEC4|\\uD83D\\uDEC5|\\uD83C\\uDF0D|\\uD83C\\uDF0E|\\uD83C\\uDF10|\\uD83C\\uDF12|\\uD83C\\uDF16|\\uD83C\\uDF17|\\uD83C\\uDF18|\\uD83C\\uDF1A|\\uD83C\\uDF1C|\\uD83C\\uDF1D|\\uD83C\\uDF1E|\\uD83C\\uDF32|\\uD83C\\uDF33|\\uD83C\\uDF4B|\\uD83C\\uDF50|\\uD83C\\uDF7C|\\uD83C\\uDFC7|\\uD83C\\uDFC9|\\uD83C\\uDFE4|\\uD83D\\uDC00|\\uD83D\\uDC01|\\uD83D\\uDC02|\\uD83D\\uDC03|\\uD83D\\uDC04|\\uD83D\\uDC05|\\uD83D\\uDC06|\\uD83D\\uDC07|\\uD83D\\uDC08|\\uD83D\\uDC09|\\uD83D\\uDC0A|\\uD83D\\uDC0B|\\uD83D\\uDC0F|\\uD83D\\uDC10|\\uD83D\\uDC13|\\uD83D\\uDC15|\\uD83D\\uDC16|\\uD83D\\uDC2A|\\uD83D\\uDC65|\\uD83D\\uDC6C|\\uD83D\\uDC6D|\\uD83D\\uDCAD|\\uD83D\\uDCB6|\\uD83D\\uDCB7|\\uD83D\\uDCEC|\\uD83D\\uDCED|\\uD83D\\uDCEF|\\uD83D\\uDCF5|\\uD83D\\uDD00|\\uD83D\\uDD01|\\uD83D\\uDD02|\\uD83D\\uDD04|\\uD83D\\uDD05|\\uD83D\\uDD06|\\uD83D\\uDD07|\\uD83D\\uDD09|\\uD83D\\uDD15|\\uD83D\\uDD2C|\\uD83D\\uDD2D|\\uD83D\\uDD5C|\\uD83D\\uDD5D|\\uD83D\\uDD5E|\\uD83D\\uDD5F|\\uD83D\\uDD60|\\uD83D\\uDD61|\\uD83D\\uDD62|\\uD83D\\uDD63|\\uD83D\\uDD64|\\uD83D\\uDD65|\\uD83D\\uDD66|\\uD83D\\uDD67|\\uD83D\\uDD08|\\uD83D\\uDE8B|\\u27BF|\\uD83C\\uDDE6\\uD83C\\uDDEB|\\uD83C\\uDDE6\\uD83C\\uDDF1|\\uD83C\\uDDE9\\uD83C\\uDDFF|\\uD83C\\uDDE6\\uD83C\\uDDE9|\\uD83C\\uDDE6\\uD83C\\uDDF4|\\uD83C\\uDDE6\\uD83C\\uDDEC|\\uD83C\\uDDE6\\uD83C\\uDDF7|\\uD83C\\uDDE6\\uD83C\\uDDF2|\\uD83C\\uDDE6\\uD83C\\uDDFA|\\uD83C\\uDDE6\\uD83C\\uDDF9|\\uD83C\\uDDE6\\uD83C\\uDDFF|\\uD83C\\uDDE7\\uD83C\\uDDF8|\\uD83C\\uDDE7\\uD83C\\uDDED|\\uD83C\\uDDE7\\uD83C\\uDDE9|\\uD83C\\uDDE7\\uD83C\\uDDE7|\\uD83C\\uDDE7\\uD83C\\uDDFE|\\uD83C\\uDDE7\\uD83C\\uDDEA|\\uD83C\\uDDE7\\uD83C\\uDDFF|\\uD83C\\uDDE7\\uD83C\\uDDEF|\\uD83C\\uDDE7\\uD83C\\uDDF9|\\uD83C\\uDDE7\\uD83C\\uDDF4|\\uD83C\\uDDE7\\uD83C\\uDDE6|\\uD83C\\uDDE7\\uD83C\\uDDFC|\\uD83C\\uDDE7\\uD83C\\uDDF7|\\uD83C\\uDDE7\\uD83C\\uDDF3|\\uD83C\\uDDE7\\uD83C\\uDDEC|\\uD83C\\uDDE7\\uD83C\\uDDEB|\\uD83C\\uDDE7\\uD83C\\uDDEE|\\uD83C\\uDDF0\\uD83C\\uDDED|\\uD83C\\uDDE8\\uD83C\\uDDF2|\\uD83C\\uDDE8\\uD83C\\uDDE6|\\uD83C\\uDDE8\\uD83C\\uDDFB|\\uD83C\\uDDE8\\uD83C\\uDDEB|\\uD83C\\uDDF9\\uD83C\\uDDE9|\\uD83C\\uDDE8\\uD83C\\uDDF1|\\uD83C\\uDDE8\\uD83C\\uDDF4|\\uD83C\\uDDF0\\uD83C\\uDDF2|\\uD83C\\uDDE8\\uD83C\\uDDF7|\\uD83C\\uDDE8\\uD83C\\uDDEE|\\uD83C\\uDDED\\uD83C\\uDDF7|\\uD83C\\uDDE8\\uD83C\\uDDFA|\\uD83C\\uDDE8\\uD83C\\uDDFE|\\uD83C\\uDDE8\\uD83C\\uDDFF|\\uD83C\\uDDE8\\uD83C\\uDDE9|\\uD83C\\uDDE9\\uD83C\\uDDF0|\\uD83C\\uDDE9\\uD83C\\uDDEF|\\uD83C\\uDDE9\\uD83C\\uDDF2|\\uD83C\\uDDE9\\uD83C\\uDDF4|\\uD83C\\uDDF9\\uD83C\\uDDF1|\\uD83C\\uDDEA\\uD83C\\uDDE8|\\uD83C\\uDDEA\\uD83C\\uDDEC|\\uD83C\\uDDF8\\uD83C\\uDDFB|\\uD83C\\uDDEC\\uD83C\\uDDF6|\\uD83C\\uDDEA\\uD83C\\uDDF7|\\uD83C\\uDDEA\\uD83C\\uDDEA|\\uD83C\\uDDEA\\uD83C\\uDDF9|\\uD83C\\uDDEB\\uD83C\\uDDEF|\\uD83C\\uDDEB\\uD83C\\uDDEE|\\uD83C\\uDDEC\\uD83C\\uDDE6|\\uD83C\\uDDEC\\uD83C\\uDDF2|\\uD83C\\uDDEC\\uD83C\\uDDEA|\\uD83C\\uDDEC\\uD83C\\uDDED|\\uD83C\\uDDEC\\uD83C\\uDDF7|\\uD83C\\uDDEC\\uD83C\\uDDE9|\\uD83C\\uDDEC\\uD83C\\uDDF9|\\uD83C\\uDDEC\\uD83C\\uDDF3|\\uD83C\\uDDEC\\uD83C\\uDDFC|\\uD83C\\uDDEC\\uD83C\\uDDFE|\\uD83C\\uDDED\\uD83C\\uDDF9|\\uD83C\\uDDED\\uD83C\\uDDF3|\\uD83C\\uDDED\\uD83C\\uDDFA|\\uD83C\\uDDEE\\uD83C\\uDDF8|\\uD83C\\uDDEE\\uD83C\\uDDF3|\\uD83C\\uDDEE\\uD83C\\uDDE9|\\uD83C\\uDDEE\\uD83C\\uDDF7|\\uD83C\\uDDEE\\uD83C\\uDDF6|\\uD83C\\uDDEE\\uD83C\\uDDEA|\\uD83C\\uDDEE\\uD83C\\uDDF1|\\uD83C\\uDDEF\\uD83C\\uDDF2|\\uD83C\\uDDEF\\uD83C\\uDDF4|\\uD83C\\uDDF0\\uD83C\\uDDFF|\\uD83C\\uDDF0\\uD83C\\uDDEA|\\uD83C\\uDDF0\\uD83C\\uDDEE|\\uD83C\\uDDFD\\uD83C\\uDDF0|\\uD83C\\uDDF0\\uD83C\\uDDFC|\\uD83C\\uDDF0\\uD83C\\uDDEC|\\uD83C\\uDDF1\\uD83C\\uDDE6|\\uD83C\\uDDF1\\uD83C\\uDDFB|\\uD83C\\uDDF1\\uD83C\\uDDE7|\\uD83C\\uDDF1\\uD83C\\uDDF8|\\uD83C\\uDDF1\\uD83C\\uDDF7|\\uD83C\\uDDF1\\uD83C\\uDDFE|\\uD83C\\uDDF1\\uD83C\\uDDEE|\\uD83C\\uDDF1\\uD83C\\uDDF9|\\uD83C\\uDDF1\\uD83C\\uDDFA|\\uD83C\\uDDF2\\uD83C\\uDDF0|\\uD83C\\uDDF2\\uD83C\\uDDEC|\\uD83C\\uDDF2\\uD83C\\uDDFC|\\uD83C\\uDDF2\\uD83C\\uDDFE|\\uD83C\\uDDF2\\uD83C\\uDDFB|\\uD83C\\uDDF2\\uD83C\\uDDF1|\\uD83C\\uDDF2\\uD83C\\uDDF9|\\uD83C\\uDDF2\\uD83C\\uDDED|\\uD83C\\uDDF2\\uD83C\\uDDF7|\\uD83C\\uDDF2\\uD83C\\uDDFA|\\uD83C\\uDDF2\\uD83C\\uDDFD|\\uD83C\\uDDEB\\uD83C\\uDDF2|\\uD83C\\uDDF2\\uD83C\\uDDE9|\\uD83C\\uDDF2\\uD83C\\uDDE8|\\uD83C\\uDDF2\\uD83C\\uDDF3|\\uD83C\\uDDF2\\uD83C\\uDDEA|\\uD83C\\uDDF2\\uD83C\\uDDE6|\\uD83C\\uDDF2\\uD83C\\uDDFF|\\uD83C\\uDDF2\\uD83C\\uDDF2|\\uD83C\\uDDF3\\uD83C\\uDDE6|\\uD83C\\uDDF3\\uD83C\\uDDF7|\\uD83C\\uDDF3\\uD83C\\uDDF5|\\uD83C\\uDDF3\\uD83C\\uDDF1|\\uD83C\\uDDF3\\uD83C\\uDDFF|\\uD83C\\uDDF3\\uD83C\\uDDEE|\\uD83C\\uDDF3\\uD83C\\uDDEA|\\uD83C\\uDDF3\\uD83C\\uDDEC|\\uD83C\\uDDF0\\uD83C\\uDDF5|\\uD83C\\uDDF3\\uD83C\\uDDF4|\\uD83C\\uDDF4\\uD83C\\uDDF2|\\uD83C\\uDDF5\\uD83C\\uDDF0|\\uD83C\\uDDF5\\uD83C\\uDDFC|\\uD83C\\uDDF5\\uD83C\\uDDE6|\\uD83C\\uDDF5\\uD83C\\uDDEC|\\uD83C\\uDDF5\\uD83C\\uDDFE|\\uD83C\\uDDF5\\uD83C\\uDDEA|\\uD83C\\uDDF5\\uD83C\\uDDED|\\uD83C\\uDDF5\\uD83C\\uDDF1|\\uD83C\\uDDF5\\uD83C\\uDDF9|\\uD83C\\uDDF6\\uD83C\\uDDE6|\\uD83C\\uDDF9\\uD83C\\uDDFC|\\uD83C\\uDDE8\\uD83C\\uDDEC|\\uD83C\\uDDF7\\uD83C\\uDDF4|\\uD83C\\uDDF7\\uD83C\\uDDFC|\\uD83C\\uDDF0\\uD83C\\uDDF3|\\uD83C\\uDDF1\\uD83C\\uDDE8|\\uD83C\\uDDFB\\uD83C\\uDDE8|\\uD83C\\uDDFC\\uD83C\\uDDF8|\\uD83C\\uDDF8\\uD83C\\uDDF2|\\uD83C\\uDDF8\\uD83C\\uDDF9|\\uD83C\\uDDF8\\uD83C\\uDDE6|\\uD83C\\uDDF8\\uD83C\\uDDF3|\\uD83C\\uDDF7\\uD83C\\uDDF8|\\uD83C\\uDDF8\\uD83C\\uDDE8|\\uD83C\\uDDF8\\uD83C\\uDDF1|\\uD83C\\uDDF8\\uD83C\\uDDEC|\\uD83C\\uDDF8\\uD83C\\uDDF0|\\uD83C\\uDDF8\\uD83C\\uDDEE|\\uD83C\\uDDF8\\uD83C\\uDDE7|\\uD83C\\uDDF8\\uD83C\\uDDF4|\\uD83C\\uDDFF\\uD83C\\uDDE6|\\uD83C\\uDDF1\\uD83C\\uDDF0|\\uD83C\\uDDF8\\uD83C\\uDDE9|\\uD83C\\uDDF8\\uD83C\\uDDF7|\\uD83C\\uDDF8\\uD83C\\uDDFF|\\uD83C\\uDDF8\\uD83C\\uDDEA|\\uD83C\\uDDE8\\uD83C\\uDDED|\\uD83C\\uDDF8\\uD83C\\uDDFE|\\uD83C\\uDDF9\\uD83C\\uDDEF|\\uD83C\\uDDF9\\uD83C\\uDDFF|\\uD83C\\uDDF9\\uD83C\\uDDED|\\uD83C\\uDDF9\\uD83C\\uDDEC|\\uD83C\\uDDF9\\uD83C\\uDDF4|\\uD83C\\uDDF9\\uD83C\\uDDF9|\\uD83C\\uDDF9\\uD83C\\uDDF3|\\uD83C\\uDDF9\\uD83C\\uDDF7|\\uD83C\\uDDF9\\uD83C\\uDDF2|\\uD83C\\uDDF9\\uD83C\\uDDFB|\\uD83C\\uDDFA\\uD83C\\uDDEC|\\uD83C\\uDDFA\\uD83C\\uDDE6|\\uD83C\\uDDE6\\uD83C\\uDDEA|\\uD83C\\uDDFA\\uD83C\\uDDFE|\\uD83C\\uDDFA\\uD83C\\uDDFF|\\uD83C\\uDDFB\\uD83C\\uDDFA|\\uD83C\\uDDFB\\uD83C\\uDDE6|\\uD83C\\uDDFB\\uD83C\\uDDEA|\\uD83C\\uDDFB\\uD83C\\uDDF3|\\uD83C\\uDDEA\\uD83C\\uDDED|\\uD83C\\uDDFE\\uD83C\\uDDEA|\\uD83C\\uDDFF\\uD83C\\uDDF2|\\uD83C\\uDDFF\\uD83C\\uDDFC|\\uD83C\\uDDF5\\uD83C\\uDDF7|\\uD83C\\uDDF0\\uD83C\\uDDFE|\\uD83C\\uDDE7\\uD83C\\uDDF2|\\uD83C\\uDDF5\\uD83C\\uDDEB|\\uD83C\\uDDF5\\uD83C\\uDDF8|\\uD83C\\uDDF3\\uD83C\\uDDE8|\\uD83C\\uDDF8\\uD83C\\uDDED|\\uD83C\\uDDE6\\uD83C\\uDDFC|\\uD83C\\uDDFB\\uD83C\\uDDEE|\\uD83C\\uDDED\\uD83C\\uDDF0|\\uD83C\\uDDE6\\uD83C\\uDDE8|\\uD83C\\uDDF2\\uD83C\\uDDF8|\\uD83C\\uDDEC\\uD83C\\uDDFA|\\uD83C\\uDDEC\\uD83C\\uDDF1|\\uD83C\\uDDF3\\uD83C\\uDDFA|\\uD83C\\uDDFC\\uD83C\\uDDEB|\\uD83C\\uDDF2\\uD83C\\uDDF4|\\uD83C\\uDDEB\\uD83C\\uDDF4|\\uD83C\\uDDEB\\uD83C\\uDDF0|\\uD83C\\uDDEF\\uD83C\\uDDEA|\\uD83C\\uDDE6\\uD83C\\uDDEE|\\uD83C\\uDDEC\\uD83C\\uDDEE)", -a.jsecapeMap={"#️⃣":"0023-20E3","#⃣":"0023-20E3","0️⃣":"0030-20E3","0⃣":"0030-20E3","1️⃣":"0031-20E3","1⃣":"0031-20E3","2️⃣":"0032-20E3","2⃣":"0032-20E3","3️⃣":"0033-20E3","3⃣":"0033-20E3","4️⃣":"0034-20E3","4⃣":"0034-20E3","5️⃣":"0035-20E3","5⃣":"0035-20E3","6️⃣":"0036-20E3","6⃣":"0036-20E3","7️⃣":"0037-20E3","7⃣":"0037-20E3","8️⃣":"0038-20E3","8⃣":"0038-20E3","9️⃣":"0039-20E3","9⃣":"0039-20E3","©":"00A9","®":"00AE","‼️":"203C","‼":"203C","⁉️":"2049","⁉":"2049","™":"2122","ℹ️":"2139","ℹ":"2139","↔️":"2194","↔":"2194","↕️":"2195","↕":"2195","↖️":"2196","↖":"2196","↗️":"2197","↗":"2197","↘️":"2198","↘":"2198","↙️":"2199","↙":"2199","↩️":"21A9","↩":"21A9","↪️":"21AA","↪":"21AA","⌚️":"231A","⌚":"231A","⌛️":"231B","⌛":"231B","⏩":"23E9","⏪":"23EA","⏫":"23EB","⏬":"23EC","⏰":"23F0","⏳":"23F3","Ⓜ️":"24C2","Ⓜ":"24C2","▪️":"25AA","▪":"25AA","▫️":"25AB","▫":"25AB","▶️":"25B6","▶":"25B6","◀️":"25C0","◀":"25C0","◻️":"25FB","◻":"25FB","◼️":"25FC","◼":"25FC","◽️":"25FD","◽":"25FD","◾️":"25FE","◾":"25FE","☀️":"2600","☀":"2600","☁️":"2601","☁":"2601","☎️":"260E","☎":"260E","☑️":"2611","☑":"2611","☔️":"2614","☔":"2614","☕️":"2615","☕":"2615","☝️":"261D","☝":"261D","☺️":"263A","☺":"263A","♈️":"2648","♈":"2648","♉️":"2649","♉":"2649","♊️":"264A","♊":"264A","♋️":"264B","♋":"264B","♌️":"264C","♌":"264C","♍️":"264D","♍":"264D","♎️":"264E","♎":"264E","♏️":"264F","♏":"264F","♐️":"2650","♐":"2650","♑️":"2651","♑":"2651","♒️":"2652","♒":"2652","♓️":"2653","♓":"2653","♠️":"2660","♠":"2660","♣️":"2663","♣":"2663","♥️":"2665","♥":"2665","♦️":"2666","♦":"2666","♨️":"2668","♨":"2668","♻️":"267B","♻":"267B","♿️":"267F","♿":"267F","⚓️":"2693","⚓":"2693","⚠️":"26A0","⚠":"26A0","⚡️":"26A1","⚡":"26A1","⚪️":"26AA","⚪":"26AA","⚫️":"26AB","⚫":"26AB","⚽️":"26BD","⚽":"26BD","⚾️":"26BE","⚾":"26BE","⛄️":"26C4","⛄":"26C4","⛅️":"26C5","⛅":"26C5","⛎":"26CE","⛔️":"26D4","⛔":"26D4","⛪️":"26EA","⛪":"26EA","⛲️":"26F2","⛲":"26F2","⛳️":"26F3","⛳":"26F3","⛵️":"26F5","⛵":"26F5","⛺️":"26FA","⛺":"26FA","⛽️":"26FD","⛽":"26FD","✂️":"2702","✂":"2702","✅":"2705","✈️":"2708","✈":"2708","✉️":"2709","✉":"2709","✊":"270A","✋":"270B","✌️":"270C","✌":"270C","✏️":"270F","✏":"270F","✒️":"2712","✒":"2712","✔️":"2714","✔":"2714","✖️":"2716","✖":"2716","✨":"2728","✳️":"2733","✳":"2733","✴️":"2734","✴":"2734","❄️":"2744","❄":"2744","❇️":"2747","❇":"2747","❌":"274C","❎":"274E","❓":"2753","❔":"2754","❕":"2755","❗️":"2757","❗":"2757","❤️":"2764","❤":"2764","➕":"2795","➖":"2796","➗":"2797","➡️":"27A1","➡":"27A1","➰":"27B0","⤴️":"2934","⤴":"2934","⤵️":"2935","⤵":"2935","⬅️":"2B05","⬅":"2B05","⬆️":"2B06","⬆":"2B06","⬇️":"2B07","⬇":"2B07","⬛️":"2B1B","⬛":"2B1B","⬜️":"2B1C","⬜":"2B1C","⭐️":"2B50","⭐":"2B50","⭕️":"2B55","⭕":"2B55","〰":"3030","〽️":"303D","〽":"303D","㊗️":"3297","㊗":"3297","㊙️":"3299","㊙":"3299","🀄️":"1F004","🀄":"1F004","🃏":"1F0CF","🅰":"1F170","🅱":"1F171","🅾":"1F17E","🅿️":"1F17F","🅿":"1F17F","🆎":"1F18E","🆑":"1F191","🆒":"1F192","🆓":"1F193","🆔":"1F194","🆕":"1F195","🆖":"1F196","🆗":"1F197","🆘":"1F198","🆙":"1F199","🆚":"1F19A","🇨🇳":"1F1E8-1F1F3","🇩🇪":"1F1E9-1F1EA","🇪🇸":"1F1EA-1F1F8","🇫🇷":"1F1EB-1F1F7","🇬🇧":"1F1EC-1F1E7","🇮🇹":"1F1EE-1F1F9","🇯🇵":"1F1EF-1F1F5","🇰🇷":"1F1F0-1F1F7","🇺🇸":"1F1FA-1F1F8","🇷🇺":"1F1F7-1F1FA","🈁":"1F201","🈂":"1F202","🈚️":"1F21A","🈚":"1F21A","🈯️":"1F22F","🈯":"1F22F","🈲":"1F232","🈳":"1F233","🈴":"1F234","🈵":"1F235","🈶":"1F236","🈷":"1F237","🈸":"1F238","🈹":"1F239","🈺":"1F23A","🉐":"1F250","🉑":"1F251","🌀":"1F300","🌁":"1F301","🌂":"1F302","🌃":"1F303","🌄":"1F304","🌅":"1F305","🌆":"1F306","🌇":"1F307","🌈":"1F308","🌉":"1F309","🌊":"1F30A","🌋":"1F30B","🌌":"1F30C","🌏":"1F30F","🌑":"1F311","🌓":"1F313","🌔":"1F314","🌕":"1F315","🌙":"1F319","🌛":"1F31B","🌟":"1F31F","🌠":"1F320","🌰":"1F330","🌱":"1F331","🌴":"1F334","🌵":"1F335","🌷":"1F337","🌸":"1F338","🌹":"1F339","🌺":"1F33A","🌻":"1F33B","🌼":"1F33C","🌽":"1F33D","🌾":"1F33E","🌿":"1F33F","🍀":"1F340","🍁":"1F341","🍂":"1F342","🍃":"1F343","🍄":"1F344","🍅":"1F345","🍆":"1F346","🍇":"1F347","🍈":"1F348","🍉":"1F349","🍊":"1F34A","🍌":"1F34C","🍍":"1F34D","🍎":"1F34E","🍏":"1F34F","🍑":"1F351","🍒":"1F352","🍓":"1F353","🍔":"1F354","🍕":"1F355","🍖":"1F356","🍗":"1F357","🍘":"1F358","🍙":"1F359","🍚":"1F35A","🍛":"1F35B","🍜":"1F35C","🍝":"1F35D","🍞":"1F35E","🍟":"1F35F","🍠":"1F360","🍡":"1F361","🍢":"1F362","🍣":"1F363","🍤":"1F364","🍥":"1F365","🍦":"1F366","🍧":"1F367","🍨":"1F368","🍩":"1F369","🍪":"1F36A","🍫":"1F36B","🍬":"1F36C","🍭":"1F36D","🍮":"1F36E","🍯":"1F36F","🍰":"1F370","🍱":"1F371","🍲":"1F372","🍳":"1F373","🍴":"1F374","🍵":"1F375","🍶":"1F376","🍷":"1F377","🍸":"1F378","🍹":"1F379","🍺":"1F37A","🍻":"1F37B","🎀":"1F380","🎁":"1F381","🎂":"1F382","🎃":"1F383","🎄":"1F384","🎅":"1F385","🎆":"1F386","🎇":"1F387","🎈":"1F388","🎉":"1F389","🎊":"1F38A","🎋":"1F38B","🎌":"1F38C","🎍":"1F38D","🎎":"1F38E","🎏":"1F38F","🎐":"1F390","🎑":"1F391","🎒":"1F392","🎓":"1F393","🎠":"1F3A0","🎡":"1F3A1","🎢":"1F3A2","🎣":"1F3A3","🎤":"1F3A4","🎥":"1F3A5","🎦":"1F3A6","🎧":"1F3A7","🎨":"1F3A8","🎩":"1F3A9","🎪":"1F3AA","🎫":"1F3AB","🎬":"1F3AC","🎭":"1F3AD","🎮":"1F3AE","🎯":"1F3AF","🎰":"1F3B0","🎱":"1F3B1","🎲":"1F3B2","🎳":"1F3B3","🎴":"1F3B4","🎵":"1F3B5","🎶":"1F3B6","🎷":"1F3B7","🎸":"1F3B8","🎹":"1F3B9","🎺":"1F3BA","🎻":"1F3BB","🎼":"1F3BC","🎽":"1F3BD","🎾":"1F3BE","🎿":"1F3BF","🏀":"1F3C0","🏁":"1F3C1","🏂":"1F3C2","🏃":"1F3C3","🏄":"1F3C4","🏆":"1F3C6","🏈":"1F3C8","🏊":"1F3CA","🏠":"1F3E0","🏡":"1F3E1","🏢":"1F3E2","🏣":"1F3E3","🏥":"1F3E5","🏦":"1F3E6","🏧":"1F3E7","🏨":"1F3E8","🏩":"1F3E9","🏪":"1F3EA","🏫":"1F3EB","🏬":"1F3EC","🏭":"1F3ED","🏮":"1F3EE","🏯":"1F3EF","🏰":"1F3F0","🐌":"1F40C","🐍":"1F40D","🐎":"1F40E","🐑":"1F411","🐒":"1F412","🐔":"1F414","🐗":"1F417","🐘":"1F418","🐙":"1F419","🐚":"1F41A","🐛":"1F41B","🐜":"1F41C","🐝":"1F41D","🐞":"1F41E","🐟":"1F41F","🐠":"1F420","🐡":"1F421","🐢":"1F422","🐣":"1F423","🐤":"1F424","🐥":"1F425","🐦":"1F426","🐧":"1F427","🐨":"1F428","🐩":"1F429","🐫":"1F42B","🐬":"1F42C","🐭":"1F42D","🐮":"1F42E","🐯":"1F42F","🐰":"1F430","🐱":"1F431","🐲":"1F432","🐳":"1F433","🐴":"1F434","🐵":"1F435","🐶":"1F436","🐷":"1F437","🐸":"1F438","🐹":"1F439","🐺":"1F43A","🐻":"1F43B","🐼":"1F43C","🐽":"1F43D","🐾":"1F43E","👀":"1F440","👂":"1F442","👃":"1F443","👄":"1F444","👅":"1F445","👆":"1F446","👇":"1F447","👈":"1F448","👉":"1F449","👊":"1F44A","👋":"1F44B","👌":"1F44C","👍":"1F44D","👎":"1F44E","👏":"1F44F","👐":"1F450","👑":"1F451","👒":"1F452","👓":"1F453","👔":"1F454","👕":"1F455","👖":"1F456","👗":"1F457","👘":"1F458","👙":"1F459","👚":"1F45A","👛":"1F45B","👜":"1F45C","👝":"1F45D","👞":"1F45E","👟":"1F45F","👠":"1F460","👡":"1F461","👢":"1F462","👣":"1F463","👤":"1F464","👦":"1F466","👧":"1F467","👨":"1F468","👩":"1F469","👪":"1F46A","👫":"1F46B","👮":"1F46E","👯":"1F46F","👰":"1F470","👱":"1F471","👲":"1F472","👳":"1F473","👴":"1F474","👵":"1F475","👶":"1F476","👷":"1F477","👸":"1F478","👹":"1F479","👺":"1F47A","👻":"1F47B","👼":"1F47C","👽":"1F47D","👾":"1F47E","👿":"1F47F","💀":"1F480","📇":"1F4C7","💁":"1F481","💂":"1F482","💃":"1F483","💄":"1F484","💅":"1F485","📒":"1F4D2","💆":"1F486","📓":"1F4D3","💇":"1F487","📔":"1F4D4","💈":"1F488","📕":"1F4D5","💉":"1F489","📖":"1F4D6","💊":"1F48A","📗":"1F4D7","💋":"1F48B","📘":"1F4D8","💌":"1F48C","📙":"1F4D9","💍":"1F48D","📚":"1F4DA","💎":"1F48E","📛":"1F4DB","💏":"1F48F","📜":"1F4DC","💐":"1F490","📝":"1F4DD","💑":"1F491","📞":"1F4DE","💒":"1F492","📟":"1F4DF","📠":"1F4E0","💓":"1F493","📡":"1F4E1","📢":"1F4E2","💔":"1F494","📣":"1F4E3","📤":"1F4E4","💕":"1F495","📥":"1F4E5","📦":"1F4E6","💖":"1F496","📧":"1F4E7","📨":"1F4E8","💗":"1F497","📩":"1F4E9","📪":"1F4EA","💘":"1F498","📫":"1F4EB","📮":"1F4EE","💙":"1F499","📰":"1F4F0","📱":"1F4F1","💚":"1F49A","📲":"1F4F2","📳":"1F4F3","💛":"1F49B","📴":"1F4F4","📶":"1F4F6","💜":"1F49C","📷":"1F4F7","📹":"1F4F9","💝":"1F49D","📺":"1F4FA","📻":"1F4FB","💞":"1F49E","📼":"1F4FC","🔃":"1F503","💟":"1F49F","🔊":"1F50A","🔋":"1F50B","💠":"1F4A0","🔌":"1F50C","🔍":"1F50D","💡":"1F4A1","🔎":"1F50E","🔏":"1F50F","💢":"1F4A2","🔐":"1F510","🔑":"1F511","💣":"1F4A3","🔒":"1F512","🔓":"1F513","💤":"1F4A4","🔔":"1F514","🔖":"1F516","💥":"1F4A5","🔗":"1F517","🔘":"1F518","💦":"1F4A6","🔙":"1F519","🔚":"1F51A","💧":"1F4A7","🔛":"1F51B","🔜":"1F51C","💨":"1F4A8","🔝":"1F51D","🔞":"1F51E","💩":"1F4A9","🔟":"1F51F","💪":"1F4AA","🔠":"1F520","🔡":"1F521","💫":"1F4AB","🔢":"1F522","🔣":"1F523","💬":"1F4AC","🔤":"1F524","🔥":"1F525","💮":"1F4AE","🔦":"1F526","🔧":"1F527","💯":"1F4AF","🔨":"1F528","🔩":"1F529","💰":"1F4B0","🔪":"1F52A","🔫":"1F52B","💱":"1F4B1","🔮":"1F52E","💲":"1F4B2","🔯":"1F52F","💳":"1F4B3","🔰":"1F530","🔱":"1F531","💴":"1F4B4","🔲":"1F532","🔳":"1F533","💵":"1F4B5","🔴":"1F534","🔵":"1F535","💸":"1F4B8","🔶":"1F536","🔷":"1F537","💹":"1F4B9","🔸":"1F538","🔹":"1F539","💺":"1F4BA","🔺":"1F53A","🔻":"1F53B","💻":"1F4BB","🔼":"1F53C","💼":"1F4BC","🔽":"1F53D","🕐":"1F550","💽":"1F4BD","🕑":"1F551","💾":"1F4BE","🕒":"1F552","💿":"1F4BF","🕓":"1F553","📀":"1F4C0","🕔":"1F554","🕕":"1F555","📁":"1F4C1","🕖":"1F556","🕗":"1F557","📂":"1F4C2","🕘":"1F558","🕙":"1F559","📃":"1F4C3","🕚":"1F55A","🕛":"1F55B","📄":"1F4C4","🗻":"1F5FB","🗼":"1F5FC","📅":"1F4C5","🗽":"1F5FD","🗾":"1F5FE","📆":"1F4C6","🗿":"1F5FF","😁":"1F601","😂":"1F602","😃":"1F603","📈":"1F4C8","😄":"1F604","😅":"1F605","📉":"1F4C9","😆":"1F606","😉":"1F609","📊":"1F4CA","😊":"1F60A","😋":"1F60B","📋":"1F4CB","😌":"1F60C","😍":"1F60D","📌":"1F4CC","😏":"1F60F","😒":"1F612","📍":"1F4CD","😓":"1F613","😔":"1F614","📎":"1F4CE","😖":"1F616","😘":"1F618","📏":"1F4CF","😚":"1F61A","😜":"1F61C","📐":"1F4D0","😝":"1F61D","😞":"1F61E","📑":"1F4D1","😠":"1F620","😡":"1F621","😢":"1F622","😣":"1F623","😤":"1F624","😥":"1F625","😨":"1F628","😩":"1F629","😪":"1F62A","😫":"1F62B","😭":"1F62D","😰":"1F630","😱":"1F631","😲":"1F632","😳":"1F633","😵":"1F635","😷":"1F637","😸":"1F638","😹":"1F639","😺":"1F63A","😻":"1F63B","😼":"1F63C","😽":"1F63D","😾":"1F63E","😿":"1F63F","🙀":"1F640","🙅":"1F645","🙆":"1F646","🙇":"1F647","🙈":"1F648","🙉":"1F649","🙊":"1F64A","🙋":"1F64B","🙌":"1F64C","🙍":"1F64D","🙎":"1F64E","🙏":"1F64F","🚀":"1F680","🚃":"1F683","🚄":"1F684","🚅":"1F685","🚇":"1F687","🚉":"1F689","🚌":"1F68C","🚏":"1F68F","🚑":"1F691","🚒":"1F692","🚓":"1F693","🚕":"1F695","🚗":"1F697","🚙":"1F699","🚚":"1F69A","🚢":"1F6A2","🚤":"1F6A4","🚥":"1F6A5","🚧":"1F6A7","🚨":"1F6A8","🚩":"1F6A9","🚪":"1F6AA","🚫":"1F6AB","🚬":"1F6AC","🚭":"1F6AD","🚲":"1F6B2","🚶":"1F6B6","🚹":"1F6B9","🚺":"1F6BA","🚻":"1F6BB","🚼":"1F6BC","🚽":"1F6BD","🚾":"1F6BE","🛀":"1F6C0","😀":"1F600","😇":"1F607","😈":"1F608","😎":"1F60E","😐":"1F610","😑":"1F611","😕":"1F615","😗":"1F617","😙":"1F619","😛":"1F61B","😟":"1F61F","😦":"1F626","😧":"1F627","😬":"1F62C","😮":"1F62E","😯":"1F62F","😴":"1F634","😶":"1F636","🚁":"1F681","🚂":"1F682","🚆":"1F686","🚈":"1F688","🚊":"1F68A","🚍":"1F68D","🚎":"1F68E","🚐":"1F690","🚔":"1F694","🚖":"1F696","🚘":"1F698","🚛":"1F69B","🚜":"1F69C","🚝":"1F69D","🚞":"1F69E","🚟":"1F69F","🚠":"1F6A0","🚡":"1F6A1","🚣":"1F6A3","🚦":"1F6A6","🚮":"1F6AE","🚯":"1F6AF","🚰":"1F6B0","🚱":"1F6B1","🚳":"1F6B3","🚴":"1F6B4","🚵":"1F6B5","🚷":"1F6B7","🚸":"1F6B8","🚿":"1F6BF","🛁":"1F6C1","🛂":"1F6C2","🛃":"1F6C3","🛄":"1F6C4","🛅":"1F6C5","🌍":"1F30D","🌎":"1F30E","🌐":"1F310","🌒":"1F312","🌖":"1F316","🌗":"1F317","🌘":"1F318","🌚":"1F31A","🌜":"1F31C","🌝":"1F31D","🌞":"1F31E","🌲":"1F332","🌳":"1F333","🍋":"1F34B","🍐":"1F350","🍼":"1F37C","🏇":"1F3C7","🏉":"1F3C9","🏤":"1F3E4","🐀":"1F400","🐁":"1F401","🐂":"1F402","🐃":"1F403","🐄":"1F404","🐅":"1F405","🐆":"1F406","🐇":"1F407","🐈":"1F408","🐉":"1F409","🐊":"1F40A","🐋":"1F40B","🐏":"1F40F","🐐":"1F410","🐓":"1F413","🐕":"1F415","🐖":"1F416","🐪":"1F42A","👥":"1F465","👬":"1F46C","👭":"1F46D","💭":"1F4AD","💶":"1F4B6","💷":"1F4B7","📬":"1F4EC","📭":"1F4ED","📯":"1F4EF","📵":"1F4F5","🔀":"1F500","🔁":"1F501","🔂":"1F502","🔄":"1F504","🔅":"1F505","🔆":"1F506","🔇":"1F507","🔉":"1F509","🔕":"1F515","🔬":"1F52C","🔭":"1F52D","🕜":"1F55C","🕝":"1F55D","🕞":"1F55E","🕟":"1F55F","🕠":"1F560","🕡":"1F561","🕢":"1F562","🕣":"1F563","🕤":"1F564","🕥":"1F565","🕦":"1F566","🕧":"1F567","🔈":"1F508","🚋":"1F68B","➿":"27BF","🇦🇫":"1F1E6-1F1EB","🇦🇱":"1F1E6-1F1F1","🇩🇿":"1F1E9-1F1FF","🇦🇩":"1F1E6-1F1E9","🇦🇴":"1F1E6-1F1F4","🇦🇬":"1F1E6-1F1EC","🇦🇷":"1F1E6-1F1F7","🇦🇲":"1F1E6-1F1F2","🇦🇺":"1F1E6-1F1FA","🇦🇹":"1F1E6-1F1F9","🇦🇿":"1F1E6-1F1FF","🇧🇸":"1F1E7-1F1F8","🇧🇭":"1F1E7-1F1ED","🇧🇩":"1F1E7-1F1E9","🇧🇧":"1F1E7-1F1E7","🇧🇾":"1F1E7-1F1FE","🇧🇪":"1F1E7-1F1EA","🇧🇿":"1F1E7-1F1FF","🇧🇯":"1F1E7-1F1EF","🇧🇹":"1F1E7-1F1F9","🇧🇴":"1F1E7-1F1F4","🇧🇦":"1F1E7-1F1E6","🇧🇼":"1F1E7-1F1FC","🇧🇷":"1F1E7-1F1F7","🇧🇳":"1F1E7-1F1F3","🇧🇬":"1F1E7-1F1EC","🇧🇫":"1F1E7-1F1EB","🇧🇮":"1F1E7-1F1EE","🇰🇭":"1F1F0-1F1ED","🇨🇲":"1F1E8-1F1F2","🇨🇦":"1F1E8-1F1E6","🇨🇻":"1F1E8-1F1FB","🇨🇫":"1F1E8-1F1EB","🇹🇩":"1F1F9-1F1E9","🇨🇱":"1F1E8-1F1F1","🇨🇴":"1F1E8-1F1F4","🇰🇲":"1F1F0-1F1F2","🇨🇷":"1F1E8-1F1F7","🇨🇮":"1F1E8-1F1EE","🇭🇷":"1F1ED-1F1F7","🇨🇺":"1F1E8-1F1FA","🇨🇾":"1F1E8-1F1FE","🇨🇿":"1F1E8-1F1FF","🇨🇩":"1F1E8-1F1E9","🇩🇰":"1F1E9-1F1F0","🇩🇯":"1F1E9-1F1EF","🇩🇲":"1F1E9-1F1F2","🇩🇴":"1F1E9-1F1F4","🇹🇱":"1F1F9-1F1F1","🇪🇨":"1F1EA-1F1E8","🇪🇬":"1F1EA-1F1EC","🇸🇻":"1F1F8-1F1FB","🇬🇶":"1F1EC-1F1F6","🇪🇷":"1F1EA-1F1F7","🇪🇪":"1F1EA-1F1EA","🇪🇹":"1F1EA-1F1F9","🇫🇯":"1F1EB-1F1EF","🇫🇮":"1F1EB-1F1EE","🇬🇦":"1F1EC-1F1E6","🇬🇲":"1F1EC-1F1F2","🇬🇪":"1F1EC-1F1EA","🇬🇭":"1F1EC-1F1ED","🇬🇷":"1F1EC-1F1F7","🇬🇩":"1F1EC-1F1E9","🇬🇹":"1F1EC-1F1F9","🇬🇳":"1F1EC-1F1F3","🇬🇼":"1F1EC-1F1FC","🇬🇾":"1F1EC-1F1FE","🇭🇹":"1F1ED-1F1F9","🇭🇳":"1F1ED-1F1F3","🇭🇺":"1F1ED-1F1FA","🇮🇸":"1F1EE-1F1F8","🇮🇳":"1F1EE-1F1F3","🇮🇩":"1F1EE-1F1E9","🇮🇷":"1F1EE-1F1F7","🇮🇶":"1F1EE-1F1F6","🇮🇪":"1F1EE-1F1EA","🇮🇱":"1F1EE-1F1F1","🇯🇲":"1F1EF-1F1F2","🇯🇴":"1F1EF-1F1F4","🇰🇿":"1F1F0-1F1FF","🇰🇪":"1F1F0-1F1EA","🇰🇮":"1F1F0-1F1EE","🇽🇰":"1F1FD-1F1F0","🇰🇼":"1F1F0-1F1FC","🇰🇬":"1F1F0-1F1EC","🇱🇦":"1F1F1-1F1E6","🇱🇻":"1F1F1-1F1FB","🇱🇧":"1F1F1-1F1E7","🇱🇸":"1F1F1-1F1F8","🇱🇷":"1F1F1-1F1F7","🇱🇾":"1F1F1-1F1FE","🇱🇮":"1F1F1-1F1EE","🇱🇹":"1F1F1-1F1F9","🇱🇺":"1F1F1-1F1FA","🇲🇰":"1F1F2-1F1F0","🇲🇬":"1F1F2-1F1EC","🇲🇼":"1F1F2-1F1FC","🇲🇾":"1F1F2-1F1FE","🇲🇻":"1F1F2-1F1FB","🇲🇱":"1F1F2-1F1F1","🇲🇹":"1F1F2-1F1F9","🇲🇭":"1F1F2-1F1ED","🇲🇷":"1F1F2-1F1F7","🇲🇺":"1F1F2-1F1FA","🇲🇽":"1F1F2-1F1FD","🇫🇲":"1F1EB-1F1F2","🇲🇩":"1F1F2-1F1E9","🇲🇨":"1F1F2-1F1E8","🇲🇳":"1F1F2-1F1F3","🇲🇪":"1F1F2-1F1EA","🇲🇦":"1F1F2-1F1E6","🇲🇿":"1F1F2-1F1FF","🇲🇲":"1F1F2-1F1F2","🇳🇦":"1F1F3-1F1E6","🇳🇷":"1F1F3-1F1F7","🇳🇵":"1F1F3-1F1F5","🇳🇱":"1F1F3-1F1F1","🇳🇿":"1F1F3-1F1FF","🇳🇮":"1F1F3-1F1EE","🇳🇪":"1F1F3-1F1EA","🇳🇬":"1F1F3-1F1EC","🇰🇵":"1F1F0-1F1F5","🇳🇴":"1F1F3-1F1F4","🇴🇲":"1F1F4-1F1F2","🇵🇰":"1F1F5-1F1F0","🇵🇼":"1F1F5-1F1FC","🇵🇦":"1F1F5-1F1E6","🇵🇬":"1F1F5-1F1EC","🇵🇾":"1F1F5-1F1FE","🇵🇪":"1F1F5-1F1EA","🇵🇭":"1F1F5-1F1ED","🇵🇱":"1F1F5-1F1F1","🇵🇹":"1F1F5-1F1F9","🇶🇦":"1F1F6-1F1E6","🇹🇼":"1F1F9-1F1FC","🇨🇬":"1F1E8-1F1EC","🇷🇴":"1F1F7-1F1F4","🇷🇼":"1F1F7-1F1FC","🇰🇳":"1F1F0-1F1F3","🇱🇨":"1F1F1-1F1E8","🇻🇨":"1F1FB-1F1E8","🇼🇸":"1F1FC-1F1F8","🇸🇲":"1F1F8-1F1F2","🇸🇹":"1F1F8-1F1F9","🇸🇦":"1F1F8-1F1E6","🇸🇳":"1F1F8-1F1F3","🇷🇸":"1F1F7-1F1F8","🇸🇨":"1F1F8-1F1E8","🇸🇱":"1F1F8-1F1F1","🇸🇬":"1F1F8-1F1EC","🇸🇰":"1F1F8-1F1F0","🇸🇮":"1F1F8-1F1EE","🇸🇧":"1F1F8-1F1E7","🇸🇴":"1F1F8-1F1F4","🇿🇦":"1F1FF-1F1E6","🇱🇰":"1F1F1-1F1F0","🇸🇩":"1F1F8-1F1E9","🇸🇷":"1F1F8-1F1F7","🇸🇿":"1F1F8-1F1FF","🇸🇪":"1F1F8-1F1EA","🇨🇭":"1F1E8-1F1ED","🇸🇾":"1F1F8-1F1FE","🇹🇯":"1F1F9-1F1EF","🇹🇿":"1F1F9-1F1FF","🇹🇭":"1F1F9-1F1ED","🇹🇬":"1F1F9-1F1EC","🇹🇴":"1F1F9-1F1F4","🇹🇹":"1F1F9-1F1F9","🇹🇳":"1F1F9-1F1F3","🇹🇷":"1F1F9-1F1F7","🇹🇲":"1F1F9-1F1F2","🇹🇻":"1F1F9-1F1FB","🇺🇬":"1F1FA-1F1EC","🇺🇦":"1F1FA-1F1E6","🇦🇪":"1F1E6-1F1EA","🇺🇾":"1F1FA-1F1FE","🇺🇿":"1F1FA-1F1FF","🇻🇺":"1F1FB-1F1FA","🇻🇦":"1F1FB-1F1E6","🇻🇪":"1F1FB-1F1EA","🇻🇳":"1F1FB-1F1F3","🇪🇭":"1F1EA-1F1ED","🇾🇪":"1F1FE-1F1EA","🇿🇲":"1F1FF-1F1F2","🇿🇼":"1F1FF-1F1FC","🇵🇷":"1F1F5-1F1F7","🇰🇾":"1F1F0-1F1FE","🇧🇲":"1F1E7-1F1F2","🇵🇫":"1F1F5-1F1EB","🇵🇸":"1F1F5-1F1F8","🇳🇨":"1F1F3-1F1E8","🇸🇭":"1F1F8-1F1ED","🇦🇼":"1F1E6-1F1FC","🇻🇮":"1F1FB-1F1EE","🇭🇰":"1F1ED-1F1F0","🇦🇨":"1F1E6-1F1E8","🇲🇸":"1F1F2-1F1F8","🇬🇺":"1F1EC-1F1FA","🇬🇱":"1F1EC-1F1F1","🇳🇺":"1F1F3-1F1FA","🇼🇫":"1F1FC-1F1EB","🇲🇴":"1F1F2-1F1F4","🇫🇴":"1F1EB-1F1F4","🇫🇰":"1F1EB-1F1F0","🇯🇪":"1F1EF-1F1EA","🇦🇮":"1F1E6-1F1EE","🇬🇮":"1F1EC-1F1EE"},a.shortnameRegexp=":([-+\\w]+):",a.imagePathPNG="//cdn.jsdelivr.net/emojione/assets/png/",a.imagePathSVG="//cdn.jsdelivr.net/emojione/assets/svg/",a.imagePathSVGSprites="./../assets/sprites/emojione.sprites.svg",a.imageType="png",a.sprites=!1,a.unicodeAlt=!0,a.ascii=!1,a.cacheBustParam="?v=1.2.4",a.toImage=function(b){return b=a.unicodeToImage(b),b=a.shortnameToImage(b)},a.unifyUnicode=function(b){return b=a.toShort(b),b=a.shortnameToUnicode(b)},a.shortnameToAscii=function(b){var c,d=a.objectFlip(a.asciiList);return b=b.replace(new RegExp("]*>.*?|]*>.*?|<(?:object|embed|svg|img|div|span|p|a)[^>]*>|("+a.shortnameRegexp+")","gi"),function(b){return"undefined"!=typeof b&&""!==b&&b in a.emojioneList?(c=a.emojioneList[b][a.emojioneList[b].length-1].toLowerCase(),"undefined"!=typeof d[c]?d[c]:b):b})},a.shortnameToUnicode=function(b){var c;return b=b.replace(new RegExp("]*>.*?|]*>.*?|<(?:object|embed|svg|img|div|span|p|a)[^>]*>|("+a.shortnameRegexp+")","gi"),function(b){return"undefined"!=typeof b&&""!==b&&b in a.emojioneList?(c=a.emojioneList[b][a.emojioneList[b].length-1].toUpperCase(),a.convert(c)):b}),a.ascii&&(b=b.replace(new RegExp("]*>.*?|]*>.*?|<(?:object|embed|svg|img|div|span|p|a)[^>]*>|((\\s|^)"+a.asciiRegexp+"(?=\\s|$|[!,.]))","g"),function(b,d,e,f){return"undefined"!=typeof f&&""!==f&&a.unescapeHTML(f)in a.asciiList?(f=a.unescapeHTML(f),c=a.asciiList[f].toUpperCase(),e+a.convert(c)):b})),b},a.shortnameToImage=function(b){var c,d,e;return b=b.replace(new RegExp("]*>.*?|]*>.*?|<(?:object|embed|svg|img|div|span|p|a)[^>]*>|("+a.shortnameRegexp+")","gi"),function(b){return"undefined"!=typeof b&&""!==b&&b in a.emojioneList?(d=a.emojioneList[b][a.emojioneList[b].length-1].toUpperCase(),e=a.unicodeAlt?a.convert(d):b,c="png"===a.imageType?a.sprites?''+e+"":''+e+'':a.sprites?''+e+'':''+e+""):b}),a.ascii&&(b=b.replace(new RegExp("]*>.*?|]*>.*?|<(?:object|embed|svg|img|div|span|p|a)[^>]*>|((\\s|^)"+a.asciiRegexp+"(?=\\s|$|[!,.]))","g"),function(b,f,g,h){return"undefined"!=typeof h&&""!==h&&a.unescapeHTML(h)in a.asciiList?(h=a.unescapeHTML(h),d=a.asciiList[h].toUpperCase(),e=a.unicodeAlt?a.convert(d):a.escapeHTML(h),c="png"===a.imageType?a.sprites?g+''+e+"":g+''+e+'':a.sprites?''+e+'':g+''+e+""):b})),b},a.unicodeToImage=function(b){var c,d,e;if(!a.unicodeAlt||a.sprites)var f=a.mapShortToUnicode();return b=b.replace(new RegExp("]*>.*?|]*>.*?|<(?:object|embed|svg|img|div|span|p|a)[^>]*>|("+a.unicodeRegexp+")","gi"),function(b){return"undefined"!=typeof b&&""!==b&&b in a.jsecapeMap?(d=a.jsecapeMap[b],e=a.unicodeAlt?a.convert(d):f[d],c="png"===a.imageType?a.sprites?''+e+"":''+e+'':a.sprites?''+e+'':''+e+''):b})},a.toShort=function(b){for(var c in a.emojioneList)if(a.emojioneList.hasOwnProperty(c))for(var d in a.emojioneList[c])if(a.emojioneList[c].hasOwnProperty(d)){var e=a.emojioneList[c][d].toUpperCase();b=a.replaceAll(b,a.convert(e),c)}return b},a.convert=function(a){if(a.indexOf("-")>-1){for(var b=[],c=a.split("-"),d=0;d=65536&&1114111>=e){var f=Math.floor((e-65536)/1024)+55296,g=(e-65536)%1024+56320;e=String.fromCharCode(f)+String.fromCharCode(g)}else e=String.fromCharCode(e);b.push(e)}return b.join("")}var c=parseInt(a,16);if(c>=65536&&1114111>=c){var f=Math.floor((c-65536)/1024)+55296,g=(c-65536)%1024+56320;return String.fromCharCode(f)+String.fromCharCode(g)}return String.fromCharCode(c)},a.escapeHTML=function(a){var b={"&":"&","<":"<",">":">",'"':""","'":"'"};return a.replace(/[&<>"']/g,function(a){return b[a]})},a.unescapeHTML=function(a){var b={"&":"&","&":"&","&":"&","<":"<","<":"<","<":"<",">":">",">":">",">":">",""":'"',""":'"',""":'"',"'":"'","'":"'","'":"'"};return a.replace(/&(?:amp|#38|#x26|lt|#60|#x3C|gt|#62|#x3E|apos|#39|#x27|quot|#34|#x22);/gi,function(a){return b[a]})},a.mapShortToUnicode=function(){var b={};for(var c in a.emojioneList)if(a.emojioneList.hasOwnProperty(c))for(var d in a.emojioneList[c])a.emojioneList[c].hasOwnProperty(d)&&(b[a.emojioneList[c][d].toUpperCase()]=c);return b},a.objectFlip=function(a){var b,c={};for(b in a)a.hasOwnProperty(b)&&(c[a[b]]=b);return c},a.escapeRegExp=function(a){return a.replace(/[-[\]{}()*+?.,;:&\\^$|#\s]/g,"\\$&")},a.replaceAll=function(a,b,c){var d=new RegExp("]*>.*?|]*>.*?|<(?:object|embed|svg|img|div|span|p|a)[^>]*>|("+b+")","gi"),e=function(a,b){return"undefined"==typeof b||""===b?a:c};return a.replace(d,e)}}(this.emojione=this.emojione||{}),"object"==typeof module&&(module.exports=this.emojione); - - - -emoji_complete = function(json_url, folder) { - - emojione.imagePathPNG = folder; - emojione.imageType = 'png'; - emojione.sprites = true; - - var emojiStrategy; - if (!emojiStrategy) { - $.getJSON( - json_url, - function( data ) { - emojiStrategy = data; - } - ); - } - - $("textarea").textcomplete([ { - match: /\B:([\-+\w]*)$/, - search: function (term, callback) { - var results = []; - var results2 = []; - var results3 = []; - console.log(emojiStrategy); - $.each(emojiStrategy,function(shortname,data) { - if(shortname.indexOf(term) > -1) { results.push(shortname); } - else { - if((data.aliases !== null) && (data.aliases.indexOf(term) > -1)) { - results2.push(shortname); - } - else if((data.keywords !== null) && (data.keywords.indexOf(term) > -1)) { - results3.push(shortname); - } - } - }); - - if(term.length >= 3) { - results.sort(function(a,b) { return (a.length > b.length); }); - results2.sort(function(a,b) { return (a.length > b.length); }); - results3.sort(); - } - var newResults = results.concat(results2).concat(results3); - - callback(newResults); - }, - template: function (shortname) { - return ':'+shortname+':'; - }, - replace: function (shortname) { - return ':'+shortname+': '; - }, - index: 1, - maxCount: 10 - } - ],{ - footer: 'Browse All»' - }); -}; diff --git a/pagure/static/emoji/emojione.min.js b/pagure/static/emoji/emojione.min.js new file mode 120000 index 0000000..5af8e38 --- /dev/null +++ b/pagure/static/emoji/emojione.min.js @@ -0,0 +1 @@ +emojione-2.2.6.min.js \ No newline at end of file diff --git a/pagure/static/emoji/emojione.sprites-2.2.6.css b/pagure/static/emoji/emojione.sprites-2.2.6.css new file mode 100644 index 0000000..ea9c5e2 --- /dev/null +++ b/pagure/static/emoji/emojione.sprites-2.2.6.css @@ -0,0 +1 @@ +.emojione{text-indent:-9999em;image-rendering:optimizeQuality;font-size:inherit;height:64px;width:64px;top:-3px;position:relative;display:inline-block;margin:0 .15em;line-height:normal;vertical-align:middle;background-image:url(emojione.sprites.png);background-repeat:no-repeat}.emojione-0023-20e3{background-position:-65px 0}.emojione-0023{background-position:-1365px -1820px}.emojione-002a-20e3{background-position:0 -65px}.emojione-002a{background-position:-65px -65px}.emojione-0030-20e3{background-position:-130px 0}.emojione-0030{background-position:-130px -65px}.emojione-0031-20e3{background-position:0 -130px}.emojione-0031{background-position:-65px -130px}.emojione-0032-20e3{background-position:-130px -130px}.emojione-0032{background-position:-195px 0}.emojione-0033-20e3{background-position:-195px -65px}.emojione-0033{background-position:-195px -130px}.emojione-0034-20e3{background-position:0 -195px}.emojione-0034{background-position:-65px -195px}.emojione-0035-20e3{background-position:-130px -195px}.emojione-0035{background-position:-195px -195px}.emojione-0036-20e3{background-position:-260px 0}.emojione-0036{background-position:-260px -65px}.emojione-0037-20e3{background-position:-260px -130px}.emojione-0037{background-position:-260px -195px}.emojione-0038-20e3{background-position:0 -260px}.emojione-0038{background-position:-65px -260px}.emojione-0039-20e3{background-position:-130px -260px}.emojione-0039{background-position:-195px -260px}.emojione-00a9{background-position:-260px -260px}.emojione-00ae{background-position:-325px 0}.emojione-1f004{background-position:-325px -65px}.emojione-1f0cf{background-position:-325px -130px}.emojione-1f170{background-position:-325px -195px}.emojione-1f171{background-position:-325px -260px}.emojione-1f17e{background-position:0 -325px}.emojione-1f17f{background-position:-65px -325px}.emojione-1f18e{background-position:-130px -325px}.emojione-1f191{background-position:-195px -325px}.emojione-1f192{background-position:-260px -325px}.emojione-1f193{background-position:-325px -325px}.emojione-1f194{background-position:-390px 0}.emojione-1f195{background-position:-390px -65px}.emojione-1f196{background-position:-390px -130px}.emojione-1f197{background-position:-390px -195px}.emojione-1f198{background-position:-390px -260px}.emojione-1f199{background-position:-390px -325px}.emojione-1f19a{background-position:0 -390px}.emojione-1f1e6-1f1e8{background-position:-65px -390px}.emojione-1f1e6-1f1e9{background-position:-130px -390px}.emojione-1f1e6-1f1ea{background-position:-195px -390px}.emojione-1f1e6-1f1eb{background-position:-260px -390px}.emojione-1f1e6-1f1ec{background-position:-325px -390px}.emojione-1f1e6-1f1ee{background-position:-390px -390px}.emojione-1f1e6-1f1f1{background-position:-455px 0}.emojione-1f1e6-1f1f2{background-position:-455px -65px}.emojione-1f1e6-1f1f4{background-position:-455px -130px}.emojione-1f1e6-1f1f6{background-position:-455px -195px}.emojione-1f1e6-1f1f7{background-position:-455px -260px}.emojione-1f1e6-1f1f8{background-position:-455px -325px}.emojione-1f1e6-1f1f9{background-position:-455px -390px}.emojione-1f1e6-1f1fa{background-position:0 -455px}.emojione-1f1e6-1f1fc{background-position:-65px -455px}.emojione-1f1e6-1f1fd{background-position:-130px -455px}.emojione-1f1e6-1f1ff{background-position:-195px -455px}.emojione-1f1e6{background-position:-260px -455px}.emojione-1f1e7-1f1e6{background-position:-325px -455px}.emojione-1f1e7-1f1e7{background-position:-390px -455px}.emojione-1f1e7-1f1e9{background-position:-455px -455px}.emojione-1f1e7-1f1ea{background-position:-520px 0}.emojione-1f1e7-1f1eb{background-position:-520px -65px}.emojione-1f1e7-1f1ec{background-position:-520px -130px}.emojione-1f1e7-1f1ed{background-position:-520px -195px}.emojione-1f1e7-1f1ee{background-position:-520px -260px}.emojione-1f1e7-1f1ef{background-position:-520px -325px}.emojione-1f1e7-1f1f1{background-position:-520px -390px}.emojione-1f1e7-1f1f2{background-position:-520px -455px}.emojione-1f1e7-1f1f3{background-position:0 -520px}.emojione-1f1e7-1f1f4{background-position:-65px -520px}.emojione-1f1e7-1f1f6{background-position:-130px -520px}.emojione-1f1e7-1f1f7{background-position:-195px -520px}.emojione-1f1e7-1f1f8{background-position:-260px -520px}.emojione-1f1e7-1f1f9{background-position:-325px -520px}.emojione-1f1e7-1f1fb{background-position:-390px -520px}.emojione-1f1e7-1f1fc{background-position:-455px -520px}.emojione-1f1e7-1f1fe{background-position:-520px -520px}.emojione-1f1e7-1f1ff{background-position:-585px 0}.emojione-1f1e7{background-position:-585px -65px}.emojione-1f1e8-1f1e6{background-position:-585px -130px}.emojione-1f1e8-1f1e8{background-position:-585px -195px}.emojione-1f1e8-1f1e9{background-position:-585px -260px}.emojione-1f1e8-1f1eb{background-position:-585px -325px}.emojione-1f1e8-1f1ec{background-position:-585px -390px}.emojione-1f1e8-1f1ed{background-position:-585px -455px}.emojione-1f1e8-1f1ee{background-position:-585px -520px}.emojione-1f1e8-1f1f0{background-position:0 -585px}.emojione-1f1e8-1f1f1{background-position:-65px -585px}.emojione-1f1e8-1f1f2{background-position:-130px -585px}.emojione-1f1e8-1f1f3{background-position:-195px -585px}.emojione-1f1e8-1f1f4{background-position:-260px -585px}.emojione-1f1e8-1f1f5{background-position:-325px -585px}.emojione-1f1e8-1f1f7{background-position:-390px -585px}.emojione-1f1e8-1f1fa{background-position:-455px -585px}.emojione-1f1e8-1f1fb{background-position:-520px -585px}.emojione-1f1e8-1f1fc{background-position:-585px -585px}.emojione-1f1e8-1f1fd{background-position:-650px 0}.emojione-1f1e8-1f1fe{background-position:-650px -65px}.emojione-1f1e8-1f1ff{background-position:-650px -130px}.emojione-1f1e8{background-position:-650px -195px}.emojione-1f1e9-1f1ea{background-position:-650px -260px}.emojione-1f1e9-1f1ec{background-position:-650px -325px}.emojione-1f1e9-1f1ef{background-position:-650px -390px}.emojione-1f1e9-1f1f0{background-position:-650px -455px}.emojione-1f1e9-1f1f2{background-position:-650px -520px}.emojione-1f1e9-1f1f4{background-position:-650px -585px}.emojione-1f1e9-1f1ff{background-position:0 -650px}.emojione-1f1e9{background-position:-65px -650px}.emojione-1f1ea-1f1e6{background-position:-130px -650px}.emojione-1f1ea-1f1e8{background-position:-195px -650px}.emojione-1f1ea-1f1ea{background-position:-260px -650px}.emojione-1f1ea-1f1ec{background-position:-325px -650px}.emojione-1f1ea-1f1ed{background-position:-390px -650px}.emojione-1f1ea-1f1f7{background-position:-455px -650px}.emojione-1f1ea-1f1f8{background-position:-520px -650px}.emojione-1f1ea-1f1f9{background-position:-585px -650px}.emojione-1f1ea-1f1fa{background-position:-650px -650px}.emojione-1f1ea{background-position:-715px 0}.emojione-1f1eb-1f1ee{background-position:-715px -65px}.emojione-1f1eb-1f1ef{background-position:-715px -130px}.emojione-1f1eb-1f1f0{background-position:-715px -195px}.emojione-1f1eb-1f1f2{background-position:-715px -260px}.emojione-1f1eb-1f1f4{background-position:-715px -325px}.emojione-1f1eb-1f1f7{background-position:-715px -390px}.emojione-1f1eb{background-position:-715px -455px}.emojione-1f1ec-1f1e6{background-position:-715px -520px}.emojione-1f1ec-1f1e7{background-position:-715px -585px}.emojione-1f1ec-1f1e9{background-position:-715px -650px}.emojione-1f1ec-1f1ea{background-position:0 -715px}.emojione-1f1ec-1f1eb{background-position:-65px -715px}.emojione-1f1ec-1f1ec{background-position:-130px -715px}.emojione-1f1ec-1f1ed{background-position:-195px -715px}.emojione-1f1ec-1f1ee{background-position:-260px -715px}.emojione-1f1ec-1f1f1{background-position:-325px -715px}.emojione-1f1ec-1f1f2{background-position:-390px -715px}.emojione-1f1ec-1f1f3{background-position:-455px -715px}.emojione-1f1ec-1f1f5{background-position:-520px -715px}.emojione-1f1ec-1f1f6{background-position:-585px -715px}.emojione-1f1ec-1f1f7{background-position:-650px -715px}.emojione-1f1ec-1f1f8{background-position:-715px -715px}.emojione-1f1ec-1f1f9{background-position:-780px 0}.emojione-1f1ec-1f1fa{background-position:-780px -65px}.emojione-1f1ec-1f1fc{background-position:-780px -130px}.emojione-1f1ec-1f1fe{background-position:-780px -195px}.emojione-1f1ec{background-position:-780px -260px}.emojione-1f1ed-1f1f0{background-position:-780px -325px}.emojione-1f1ed-1f1f2{background-position:-780px -390px}.emojione-1f1ed-1f1f3{background-position:-780px -455px}.emojione-1f1ed-1f1f7{background-position:-780px -520px}.emojione-1f1ed-1f1f9{background-position:-780px -585px}.emojione-1f1ed-1f1fa{background-position:-780px -650px}.emojione-1f1ed{background-position:-780px -715px}.emojione-1f1ee-1f1e8{background-position:0 -780px}.emojione-1f1ee-1f1e9{background-position:-65px -780px}.emojione-1f1ee-1f1ea{background-position:-130px -780px}.emojione-1f1ee-1f1f1{background-position:-195px -780px}.emojione-1f1ee-1f1f2{background-position:-260px -780px}.emojione-1f1ee-1f1f3{background-position:-325px -780px}.emojione-1f1ee-1f1f4{background-position:-390px -780px}.emojione-1f1ee-1f1f6{background-position:-455px -780px}.emojione-1f1ee-1f1f7{background-position:-520px -780px}.emojione-1f1ee-1f1f8{background-position:-585px -780px}.emojione-1f1ee-1f1f9{background-position:-650px -780px}.emojione-1f1ee{background-position:-715px -780px}.emojione-1f1ef-1f1ea{background-position:-780px -780px}.emojione-1f1ef-1f1f2{background-position:-845px 0}.emojione-1f1ef-1f1f4{background-position:-845px -65px}.emojione-1f1ef-1f1f5{background-position:-845px -130px}.emojione-1f1ef{background-position:-845px -195px}.emojione-1f1f0-1f1ea{background-position:-845px -260px}.emojione-1f1f0-1f1ec{background-position:-845px -325px}.emojione-1f1f0-1f1ed{background-position:-845px -390px}.emojione-1f1f0-1f1ee{background-position:-845px -455px}.emojione-1f1f0-1f1f2{background-position:-845px -520px}.emojione-1f1f0-1f1f3{background-position:-845px -585px}.emojione-1f1f0-1f1f5{background-position:-845px -650px}.emojione-1f1f0-1f1f7{background-position:-845px -715px}.emojione-1f1f0-1f1fc{background-position:-845px -780px}.emojione-1f1f0-1f1fe{background-position:0 -845px}.emojione-1f1f0-1f1ff{background-position:-65px -845px}.emojione-1f1f0{background-position:-130px -845px}.emojione-1f1f1-1f1e6{background-position:-195px -845px}.emojione-1f1f1-1f1e7{background-position:-260px -845px}.emojione-1f1f1-1f1e8{background-position:-325px -845px}.emojione-1f1f1-1f1ee{background-position:-390px -845px}.emojione-1f1f1-1f1f0{background-position:-455px -845px}.emojione-1f1f1-1f1f7{background-position:-520px -845px}.emojione-1f1f1-1f1f8{background-position:-585px -845px}.emojione-1f1f1-1f1f9{background-position:-650px -845px}.emojione-1f1f1-1f1fa{background-position:-715px -845px}.emojione-1f1f1-1f1fb{background-position:-780px -845px}.emojione-1f1f1-1f1fe{background-position:-845px -845px}.emojione-1f1f1{background-position:-910px 0}.emojione-1f1f2-1f1e6{background-position:-910px -65px}.emojione-1f1f2-1f1e8{background-position:-910px -130px}.emojione-1f1f2-1f1e9{background-position:-910px -195px}.emojione-1f1f2-1f1ea{background-position:-910px -260px}.emojione-1f1f2-1f1eb{background-position:-910px -325px}.emojione-1f1f2-1f1ec{background-position:-910px -390px}.emojione-1f1f2-1f1ed{background-position:-910px -455px}.emojione-1f1f2-1f1f0{background-position:-910px -520px}.emojione-1f1f2-1f1f1{background-position:-910px -585px}.emojione-1f1f2-1f1f2{background-position:-910px -650px}.emojione-1f1f2-1f1f3{background-position:-910px -715px}.emojione-1f1f2-1f1f4{background-position:-910px -780px}.emojione-1f1f2-1f1f5{background-position:-910px -845px}.emojione-1f1f2-1f1f6{background-position:0 -910px}.emojione-1f1f2-1f1f7{background-position:-65px -910px}.emojione-1f1f2-1f1f8{background-position:-130px -910px}.emojione-1f1f2-1f1f9{background-position:-195px -910px}.emojione-1f1f2-1f1fa{background-position:-260px -910px}.emojione-1f1f2-1f1fb{background-position:-325px -910px}.emojione-1f1f2-1f1fc{background-position:-390px -910px}.emojione-1f1f2-1f1fd{background-position:-455px -910px}.emojione-1f1f2-1f1fe{background-position:-520px -910px}.emojione-1f1f2-1f1ff{background-position:-585px -910px}.emojione-1f1f2{background-position:-650px -910px}.emojione-1f1f3-1f1e6{background-position:-715px -910px}.emojione-1f1f3-1f1e8{background-position:-780px -910px}.emojione-1f1f3-1f1ea{background-position:-845px -910px}.emojione-1f1f3-1f1eb{background-position:-910px -910px}.emojione-1f1f3-1f1ec{background-position:-975px 0}.emojione-1f1f3-1f1ee{background-position:-975px -65px}.emojione-1f1f3-1f1f1{background-position:-975px -130px}.emojione-1f1f3-1f1f4{background-position:-975px -195px}.emojione-1f1f3-1f1f5{background-position:-975px -260px}.emojione-1f1f3-1f1f7{background-position:-975px -325px}.emojione-1f1f3-1f1fa{background-position:-975px -390px}.emojione-1f1f3-1f1ff{background-position:-975px -455px}.emojione-1f1f3{background-position:-975px -520px}.emojione-1f1f4-1f1f2{background-position:-975px -585px}.emojione-1f1f4{background-position:-975px -650px}.emojione-1f1f5-1f1e6{background-position:-975px -715px}.emojione-1f1f5-1f1ea{background-position:-975px -780px}.emojione-1f1f5-1f1eb{background-position:-975px -845px}.emojione-1f1f5-1f1ec{background-position:-975px -910px}.emojione-1f1f5-1f1ed{background-position:0 -975px}.emojione-1f1f5-1f1f0{background-position:-65px -975px}.emojione-1f1f5-1f1f1{background-position:-130px -975px}.emojione-1f1f5-1f1f2{background-position:-195px -975px}.emojione-1f1f5-1f1f3{background-position:-260px -975px}.emojione-1f1f5-1f1f7{background-position:-325px -975px}.emojione-1f1f5-1f1f8{background-position:-390px -975px}.emojione-1f1f5-1f1f9{background-position:-455px -975px}.emojione-1f1f5-1f1fc{background-position:-520px -975px}.emojione-1f1f5-1f1fe{background-position:-585px -975px}.emojione-1f1f5{background-position:-650px -975px}.emojione-1f1f6-1f1e6{background-position:-715px -975px}.emojione-1f1f6{background-position:-780px -975px}.emojione-1f1f7-1f1ea{background-position:-845px -975px}.emojione-1f1f7-1f1f4{background-position:-910px -975px}.emojione-1f1f7-1f1f8{background-position:-975px -975px}.emojione-1f1f7-1f1fa{background-position:-1040px 0}.emojione-1f1f7-1f1fc{background-position:-1040px -65px}.emojione-1f1f7{background-position:-1040px -130px}.emojione-1f1f8-1f1e6{background-position:-1040px -195px}.emojione-1f1f8-1f1e7{background-position:-1040px -260px}.emojione-1f1f8-1f1e8{background-position:-1040px -325px}.emojione-1f1f8-1f1e9{background-position:-1040px -390px}.emojione-1f1f8-1f1ea{background-position:-1040px -455px}.emojione-1f1f8-1f1ec{background-position:-1040px -520px}.emojione-1f1f8-1f1ed{background-position:-1040px -585px}.emojione-1f1f8-1f1ee{background-position:-1040px -650px}.emojione-1f1f8-1f1ef{background-position:-1040px -715px}.emojione-1f1f8-1f1f0{background-position:-1040px -780px}.emojione-1f1f8-1f1f1{background-position:-1040px -845px}.emojione-1f1f8-1f1f2{background-position:-1040px -910px}.emojione-1f1f8-1f1f3{background-position:-1040px -975px}.emojione-1f1f8-1f1f4{background-position:0 -1040px}.emojione-1f1f8-1f1f7{background-position:-65px -1040px}.emojione-1f1f8-1f1f8{background-position:-130px -1040px}.emojione-1f1f8-1f1f9{background-position:-195px -1040px}.emojione-1f1f8-1f1fb{background-position:-260px -1040px}.emojione-1f1f8-1f1fd{background-position:-325px -1040px}.emojione-1f1f8-1f1fe{background-position:-390px -1040px}.emojione-1f1f8-1f1ff{background-position:-455px -1040px}.emojione-1f1f8{background-position:-520px -1040px}.emojione-1f1f9-1f1e6{background-position:-585px -1040px}.emojione-1f1f9-1f1e8{background-position:-650px -1040px}.emojione-1f1f9-1f1e9{background-position:-715px -1040px}.emojione-1f1f9-1f1eb{background-position:-780px -1040px}.emojione-1f1f9-1f1ec{background-position:-845px -1040px}.emojione-1f1f9-1f1ed{background-position:-910px -1040px}.emojione-1f1f9-1f1ef{background-position:-975px -1040px}.emojione-1f1f9-1f1f0{background-position:-1040px -1040px}.emojione-1f1f9-1f1f1{background-position:-1105px 0}.emojione-1f1f9-1f1f2{background-position:-1105px -65px}.emojione-1f1f9-1f1f3{background-position:-1105px -130px}.emojione-1f1f9-1f1f4{background-position:-1105px -195px}.emojione-1f1f9-1f1f7{background-position:-1105px -260px}.emojione-1f1f9-1f1f9{background-position:-1105px -325px}.emojione-1f1f9-1f1fb{background-position:-1105px -390px}.emojione-1f1f9-1f1fc{background-position:-1105px -455px}.emojione-1f1f9-1f1ff{background-position:-1105px -520px}.emojione-1f1f9{background-position:-1105px -585px}.emojione-1f1fa-1f1e6{background-position:-1105px -650px}.emojione-1f1fa-1f1ec{background-position:-1105px -715px}.emojione-1f1fa-1f1f2{background-position:-1105px -780px}.emojione-1f1fa-1f1f8{background-position:-1105px -845px}.emojione-1f1fa-1f1fe{background-position:-1105px -910px}.emojione-1f1fa-1f1ff{background-position:-1105px -975px}.emojione-1f1fa{background-position:-1105px -1040px}.emojione-1f1fb-1f1e6{background-position:0 -1105px}.emojione-1f1fb-1f1e8{background-position:-65px -1105px}.emojione-1f1fb-1f1ea{background-position:-130px -1105px}.emojione-1f1fb-1f1ec{background-position:-195px -1105px}.emojione-1f1fb-1f1ee{background-position:-260px -1105px}.emojione-1f1fb-1f1f3{background-position:-325px -1105px}.emojione-1f1fb-1f1fa{background-position:-390px -1105px}.emojione-1f1fb{background-position:-455px -1105px}.emojione-1f1fc-1f1eb{background-position:-520px -1105px}.emojione-1f1fc-1f1f8{background-position:-585px -1105px}.emojione-1f1fc{background-position:-650px -1105px}.emojione-1f1fd-1f1f0{background-position:-715px -1105px}.emojione-1f1fd{background-position:-780px -1105px}.emojione-1f1fe-1f1ea{background-position:-845px -1105px}.emojione-1f1fe-1f1f9{background-position:-910px -1105px}.emojione-1f1fe{background-position:-975px -1105px}.emojione-1f1ff-1f1e6{background-position:-1040px -1105px}.emojione-1f1ff-1f1f2{background-position:-1105px -1105px}.emojione-1f1ff-1f1fc{background-position:-1170px 0}.emojione-1f1ff{background-position:-1170px -65px}.emojione-1f201{background-position:-1170px -130px}.emojione-1f202{background-position:-1170px -195px}.emojione-1f21a{background-position:-1170px -260px}.emojione-1f22f{background-position:-1170px -325px}.emojione-1f232{background-position:-1170px -390px}.emojione-1f233{background-position:-1170px -455px}.emojione-1f234{background-position:-1170px -520px}.emojione-1f235{background-position:-1170px -585px}.emojione-1f236{background-position:-1170px -650px}.emojione-1f237{background-position:-1170px -715px}.emojione-1f238{background-position:-1170px -780px}.emojione-1f239{background-position:-1170px -845px}.emojione-1f23a{background-position:-1170px -910px}.emojione-1f250{background-position:-1170px -975px}.emojione-1f251{background-position:-1170px -1040px}.emojione-1f300{background-position:-1170px -1105px}.emojione-1f301{background-position:0 -1170px}.emojione-1f302{background-position:-65px -1170px}.emojione-1f303{background-position:-130px -1170px}.emojione-1f304{background-position:-195px -1170px}.emojione-1f305{background-position:-260px -1170px}.emojione-1f306{background-position:-325px -1170px}.emojione-1f307{background-position:-390px -1170px}.emojione-1f308{background-position:-455px -1170px}.emojione-1f309{background-position:-520px -1170px}.emojione-1f30a{background-position:-585px -1170px}.emojione-1f30b{background-position:-650px -1170px}.emojione-1f30c{background-position:-715px -1170px}.emojione-1f30d{background-position:-780px -1170px}.emojione-1f30e{background-position:-845px -1170px}.emojione-1f30f{background-position:-910px -1170px}.emojione-1f310{background-position:-975px -1170px}.emojione-1f311{background-position:-1040px -1170px}.emojione-1f312{background-position:-1105px -1170px}.emojione-1f313{background-position:-1170px -1170px}.emojione-1f314{background-position:-1235px 0}.emojione-1f315{background-position:-1235px -65px}.emojione-1f316{background-position:-1235px -130px}.emojione-1f317{background-position:-1235px -195px}.emojione-1f318{background-position:-1235px -260px}.emojione-1f319{background-position:-1235px -325px}.emojione-1f31a{background-position:-1235px -390px}.emojione-1f31b{background-position:-1235px -455px}.emojione-1f31c{background-position:-1235px -520px}.emojione-1f31d{background-position:-1235px -585px}.emojione-1f31e{background-position:-1235px -650px}.emojione-1f31f{background-position:-1235px -715px}.emojione-1f320{background-position:-1235px -780px}.emojione-1f321{background-position:-1235px -845px}.emojione-1f324{background-position:-1235px -910px}.emojione-1f325{background-position:-1235px -975px}.emojione-1f326{background-position:-1235px -1040px}.emojione-1f327{background-position:-1235px -1105px}.emojione-1f328{background-position:-1235px -1170px}.emojione-1f329{background-position:0 -1235px}.emojione-1f32a{background-position:-65px -1235px}.emojione-1f32b{background-position:-130px -1235px}.emojione-1f32c{background-position:-195px -1235px}.emojione-1f32d{background-position:-260px -1235px}.emojione-1f32e{background-position:-325px -1235px}.emojione-1f32f{background-position:-390px -1235px}.emojione-1f330{background-position:-455px -1235px}.emojione-1f331{background-position:-520px -1235px}.emojione-1f332{background-position:-585px -1235px}.emojione-1f333{background-position:-650px -1235px}.emojione-1f334{background-position:-715px -1235px}.emojione-1f335{background-position:-780px -1235px}.emojione-1f336{background-position:-845px -1235px}.emojione-1f337{background-position:-910px -1235px}.emojione-1f338{background-position:-975px -1235px}.emojione-1f339{background-position:-1040px -1235px}.emojione-1f33a{background-position:-1105px -1235px}.emojione-1f33b{background-position:-1170px -1235px}.emojione-1f33c{background-position:-1235px -1235px}.emojione-1f33d{background-position:-1300px 0}.emojione-1f33e{background-position:-1300px -65px}.emojione-1f33f{background-position:-1300px -130px}.emojione-1f340{background-position:-1300px -195px}.emojione-1f341{background-position:-1300px -260px}.emojione-1f342{background-position:-1300px -325px}.emojione-1f343{background-position:-1300px -390px}.emojione-1f344{background-position:-1300px -455px}.emojione-1f345{background-position:-1300px -520px}.emojione-1f346{background-position:-1300px -585px}.emojione-1f347{background-position:-1300px -650px}.emojione-1f348{background-position:-1300px -715px}.emojione-1f349{background-position:-1300px -780px}.emojione-1f34a{background-position:-1300px -845px}.emojione-1f34b{background-position:-1300px -910px}.emojione-1f34c{background-position:-1300px -975px}.emojione-1f34d{background-position:-1300px -1040px}.emojione-1f34e{background-position:-1300px -1105px}.emojione-1f34f{background-position:-1300px -1170px}.emojione-1f350{background-position:-1300px -1235px}.emojione-1f351{background-position:0 -1300px}.emojione-1f352{background-position:-65px -1300px}.emojione-1f353{background-position:-130px -1300px}.emojione-1f354{background-position:-195px -1300px}.emojione-1f355{background-position:-260px -1300px}.emojione-1f356{background-position:-325px -1300px}.emojione-1f357{background-position:-390px -1300px}.emojione-1f358{background-position:-455px -1300px}.emojione-1f359{background-position:-520px -1300px}.emojione-1f35a{background-position:-585px -1300px}.emojione-1f35b{background-position:-650px -1300px}.emojione-1f35c{background-position:-715px -1300px}.emojione-1f35d{background-position:-780px -1300px}.emojione-1f35e{background-position:-845px -1300px}.emojione-1f35f{background-position:-910px -1300px}.emojione-1f360{background-position:-975px -1300px}.emojione-1f361{background-position:-1040px -1300px}.emojione-1f362{background-position:-1105px -1300px}.emojione-1f363{background-position:-1170px -1300px}.emojione-1f364{background-position:-1235px -1300px}.emojione-1f365{background-position:-1300px -1300px}.emojione-1f366{background-position:-1365px 0}.emojione-1f367{background-position:-1365px -65px}.emojione-1f368{background-position:-1365px -130px}.emojione-1f369{background-position:-1365px -195px}.emojione-1f36a{background-position:-1365px -260px}.emojione-1f36b{background-position:-1365px -325px}.emojione-1f36c{background-position:-1365px -390px}.emojione-1f36d{background-position:-1365px -455px}.emojione-1f36e{background-position:-1365px -520px}.emojione-1f36f{background-position:-1365px -585px}.emojione-1f370{background-position:-1365px -650px}.emojione-1f371{background-position:-1365px -715px}.emojione-1f372{background-position:-1365px -780px}.emojione-1f373{background-position:-1365px -845px}.emojione-1f374{background-position:-1365px -910px}.emojione-1f375{background-position:-1365px -975px}.emojione-1f376{background-position:-1365px -1040px}.emojione-1f377{background-position:-1365px -1105px}.emojione-1f378{background-position:-1365px -1170px}.emojione-1f379{background-position:-1365px -1235px}.emojione-1f37a{background-position:-1365px -1300px}.emojione-1f37b{background-position:0 -1365px}.emojione-1f37c{background-position:-65px -1365px}.emojione-1f37d{background-position:-130px -1365px}.emojione-1f37e{background-position:-195px -1365px}.emojione-1f37f{background-position:-260px -1365px}.emojione-1f380{background-position:-325px -1365px}.emojione-1f381{background-position:-390px -1365px}.emojione-1f382{background-position:-455px -1365px}.emojione-1f383{background-position:-520px -1365px}.emojione-1f384{background-position:-585px -1365px}.emojione-1f385-1f3fb{background-position:-650px -1365px}.emojione-1f385-1f3fc{background-position:-715px -1365px}.emojione-1f385-1f3fd{background-position:-780px -1365px}.emojione-1f385-1f3fe{background-position:-845px -1365px}.emojione-1f385-1f3ff{background-position:-910px -1365px}.emojione-1f385{background-position:-975px -1365px}.emojione-1f386{background-position:-1040px -1365px}.emojione-1f387{background-position:-1105px -1365px}.emojione-1f388{background-position:-1170px -1365px}.emojione-1f389{background-position:-1235px -1365px}.emojione-1f38a{background-position:-1300px -1365px}.emojione-1f38b{background-position:-1365px -1365px}.emojione-1f38c{background-position:-1430px 0}.emojione-1f38d{background-position:-1430px -65px}.emojione-1f38e{background-position:-1430px -130px}.emojione-1f38f{background-position:-1430px -195px}.emojione-1f390{background-position:-1430px -260px}.emojione-1f391{background-position:-1430px -325px}.emojione-1f392{background-position:-1430px -390px}.emojione-1f393{background-position:-1430px -455px}.emojione-1f396{background-position:-1430px -520px}.emojione-1f397{background-position:-1430px -585px}.emojione-1f399{background-position:-1430px -650px}.emojione-1f39a{background-position:-1430px -715px}.emojione-1f39b{background-position:-1430px -780px}.emojione-1f39e{background-position:-1430px -845px}.emojione-1f39f{background-position:-1430px -910px}.emojione-1f3a0{background-position:-1430px -975px}.emojione-1f3a1{background-position:-1430px -1040px}.emojione-1f3a2{background-position:-1430px -1105px}.emojione-1f3a3{background-position:-1430px -1170px}.emojione-1f3a4{background-position:-1430px -1235px}.emojione-1f3a5{background-position:-1430px -1300px}.emojione-1f3a6{background-position:-1430px -1365px}.emojione-1f3a7{background-position:0 -1430px}.emojione-1f3a8{background-position:-65px -1430px}.emojione-1f3a9{background-position:-130px -1430px}.emojione-1f3aa{background-position:-195px -1430px}.emojione-1f3ab{background-position:-260px -1430px}.emojione-1f3ac{background-position:-325px -1430px}.emojione-1f3ad{background-position:-390px -1430px}.emojione-1f3ae{background-position:-455px -1430px}.emojione-1f3af{background-position:-520px -1430px}.emojione-1f3b0{background-position:-585px -1430px}.emojione-1f3b1{background-position:-650px -1430px}.emojione-1f3b2{background-position:-715px -1430px}.emojione-1f3b3{background-position:-780px -1430px}.emojione-1f3b4{background-position:-845px -1430px}.emojione-1f3b5{background-position:-910px -1430px}.emojione-1f3b6{background-position:-975px -1430px}.emojione-1f3b7{background-position:-1040px -1430px}.emojione-1f3b8{background-position:-1105px -1430px}.emojione-1f3b9{background-position:-1170px -1430px}.emojione-1f3ba{background-position:-1235px -1430px}.emojione-1f3bb{background-position:-1300px -1430px}.emojione-1f3bc{background-position:-1365px -1430px}.emojione-1f3bd{background-position:-1430px -1430px}.emojione-1f3be{background-position:-1495px 0}.emojione-1f3bf{background-position:-1495px -65px}.emojione-1f3c0{background-position:-1495px -130px}.emojione-1f3c1{background-position:-1495px -195px}.emojione-1f3c2{background-position:-1495px -260px}.emojione-1f3c3-1f3fb{background-position:-1495px -325px}.emojione-1f3c3-1f3fc{background-position:-1495px -390px}.emojione-1f3c3-1f3fd{background-position:-1495px -455px}.emojione-1f3c3-1f3fe{background-position:-1495px -520px}.emojione-1f3c3-1f3ff{background-position:-1495px -585px}.emojione-1f3c3{background-position:-1495px -650px}.emojione-1f3c4-1f3fb{background-position:-1495px -715px}.emojione-1f3c4-1f3fc{background-position:-1495px -780px}.emojione-1f3c4-1f3fd{background-position:-1495px -845px}.emojione-1f3c4-1f3fe{background-position:-1495px -910px}.emojione-1f3c4-1f3ff{background-position:-1495px -975px}.emojione-1f3c4{background-position:-1495px -1040px}.emojione-1f3c5{background-position:-1495px -1105px}.emojione-1f3c6{background-position:-1495px -1170px}.emojione-1f3c7-1f3fb{background-position:-1495px -1235px}.emojione-1f3c7-1f3fc{background-position:-1495px -1300px}.emojione-1f3c7-1f3fd{background-position:-1495px -1365px}.emojione-1f3c7-1f3fe{background-position:-1495px -1430px}.emojione-1f3c7-1f3ff{background-position:0 -1495px}.emojione-1f3c7{background-position:-65px -1495px}.emojione-1f3c8{background-position:-130px -1495px}.emojione-1f3c9{background-position:-195px -1495px}.emojione-1f3ca-1f3fb{background-position:-260px -1495px}.emojione-1f3ca-1f3fc{background-position:-325px -1495px}.emojione-1f3ca-1f3fd{background-position:-390px -1495px}.emojione-1f3ca-1f3fe{background-position:-455px -1495px}.emojione-1f3ca-1f3ff{background-position:-520px -1495px}.emojione-1f3ca{background-position:-585px -1495px}.emojione-1f3cb-1f3fb{background-position:-650px -1495px}.emojione-1f3cb-1f3fc{background-position:-715px -1495px}.emojione-1f3cb-1f3fd{background-position:-780px -1495px}.emojione-1f3cb-1f3fe{background-position:-845px -1495px}.emojione-1f3cb-1f3ff{background-position:-910px -1495px}.emojione-1f3cb{background-position:-975px -1495px}.emojione-1f3cc{background-position:-1040px -1495px}.emojione-1f3cd{background-position:-1105px -1495px}.emojione-1f3ce{background-position:-1170px -1495px}.emojione-1f3cf{background-position:-1235px -1495px}.emojione-1f3d0{background-position:-1300px -1495px}.emojione-1f3d1{background-position:-1365px -1495px}.emojione-1f3d2{background-position:-1430px -1495px}.emojione-1f3d3{background-position:-1495px -1495px}.emojione-1f3d4{background-position:-1560px 0}.emojione-1f3d5{background-position:-1560px -65px}.emojione-1f3d6{background-position:-1560px -130px}.emojione-1f3d7{background-position:-1560px -195px}.emojione-1f3d8{background-position:-1560px -260px}.emojione-1f3d9{background-position:-1560px -325px}.emojione-1f3da{background-position:-1560px -390px}.emojione-1f3db{background-position:-1560px -455px}.emojione-1f3dc{background-position:-1560px -520px}.emojione-1f3dd{background-position:-1560px -585px}.emojione-1f3de{background-position:-1560px -650px}.emojione-1f3df{background-position:-1560px -715px}.emojione-1f3e0{background-position:-1560px -780px}.emojione-1f3e1{background-position:-1560px -845px}.emojione-1f3e2{background-position:-1560px -910px}.emojione-1f3e3{background-position:-1560px -975px}.emojione-1f3e4{background-position:-1560px -1040px}.emojione-1f3e5{background-position:-1560px -1105px}.emojione-1f3e6{background-position:-1560px -1170px}.emojione-1f3e7{background-position:-1560px -1235px}.emojione-1f3e8{background-position:-1560px -1300px}.emojione-1f3e9{background-position:-1560px -1365px}.emojione-1f3ea{background-position:-1560px -1430px}.emojione-1f3eb{background-position:-1560px -1495px}.emojione-1f3ec{background-position:0 -1560px}.emojione-1f3ed{background-position:-65px -1560px}.emojione-1f3ee{background-position:-130px -1560px}.emojione-1f3ef{background-position:-195px -1560px}.emojione-1f3f0{background-position:-260px -1560px}.emojione-1f3f3-1f308{background-position:-325px -1560px}.emojione-1f3f3{background-position:-390px -1560px}.emojione-1f3f4{background-position:-455px -1560px}.emojione-1f3f5{background-position:-520px -1560px}.emojione-1f3f7{background-position:-585px -1560px}.emojione-1f3f8{background-position:-650px -1560px}.emojione-1f3f9{background-position:-715px -1560px}.emojione-1f3fa{background-position:-780px -1560px}.emojione-1f3fb{background-position:-845px -1560px}.emojione-1f3fc{background-position:-910px -1560px}.emojione-1f3fd{background-position:-975px -1560px}.emojione-1f3fe{background-position:-1040px -1560px}.emojione-1f3ff{background-position:-1105px -1560px}.emojione-1f400{background-position:-1170px -1560px}.emojione-1f401{background-position:-1235px -1560px}.emojione-1f402{background-position:-1300px -1560px}.emojione-1f403{background-position:-1365px -1560px}.emojione-1f404{background-position:-1430px -1560px}.emojione-1f405{background-position:-1495px -1560px}.emojione-1f406{background-position:-1560px -1560px}.emojione-1f407{background-position:-1625px 0}.emojione-1f408{background-position:-1625px -65px}.emojione-1f409{background-position:-1625px -130px}.emojione-1f40a{background-position:-1625px -195px}.emojione-1f40b{background-position:-1625px -260px}.emojione-1f40c{background-position:-1625px -325px}.emojione-1f40d{background-position:-1625px -390px}.emojione-1f40e{background-position:-1625px -455px}.emojione-1f40f{background-position:-1625px -520px}.emojione-1f410{background-position:-1625px -585px}.emojione-1f411{background-position:-1625px -650px}.emojione-1f412{background-position:-1625px -715px}.emojione-1f413{background-position:-1625px -780px}.emojione-1f414{background-position:-1625px -845px}.emojione-1f415{background-position:-1625px -910px}.emojione-1f416{background-position:-1625px -975px}.emojione-1f417{background-position:-1625px -1040px}.emojione-1f418{background-position:-1625px -1105px}.emojione-1f419{background-position:-1625px -1170px}.emojione-1f41a{background-position:-1625px -1235px}.emojione-1f41b{background-position:-1625px -1300px}.emojione-1f41c{background-position:-1625px -1365px}.emojione-1f41d{background-position:-1625px -1430px}.emojione-1f41e{background-position:-1625px -1495px}.emojione-1f41f{background-position:-1625px -1560px}.emojione-1f420{background-position:0 -1625px}.emojione-1f421{background-position:-65px -1625px}.emojione-1f422{background-position:-130px -1625px}.emojione-1f423{background-position:-195px -1625px}.emojione-1f424{background-position:-260px -1625px}.emojione-1f425{background-position:-325px -1625px}.emojione-1f426{background-position:-390px -1625px}.emojione-1f427{background-position:-455px -1625px}.emojione-1f428{background-position:-520px -1625px}.emojione-1f429{background-position:-585px -1625px}.emojione-1f42a{background-position:-650px -1625px}.emojione-1f42b{background-position:-715px -1625px}.emojione-1f42c{background-position:-780px -1625px}.emojione-1f42d{background-position:-845px -1625px}.emojione-1f42e{background-position:-910px -1625px}.emojione-1f42f{background-position:-975px -1625px}.emojione-1f430{background-position:-1040px -1625px}.emojione-1f431{background-position:-1105px -1625px}.emojione-1f432{background-position:-1170px -1625px}.emojione-1f433{background-position:-1235px -1625px}.emojione-1f434{background-position:-1300px -1625px}.emojione-1f435{background-position:-1365px -1625px}.emojione-1f436{background-position:-1430px -1625px}.emojione-1f437{background-position:-1495px -1625px}.emojione-1f438{background-position:-1560px -1625px}.emojione-1f439{background-position:-1625px -1625px}.emojione-1f43a{background-position:-1690px 0}.emojione-1f43b{background-position:-1690px -65px}.emojione-1f43c{background-position:-1690px -130px}.emojione-1f43d{background-position:-1690px -195px}.emojione-1f43e{background-position:-1690px -260px}.emojione-1f43f{background-position:-1690px -325px}.emojione-1f440{background-position:-1690px -390px}.emojione-1f441-1f5e8{background-position:-1690px -455px}.emojione-1f441{background-position:-1690px -520px}.emojione-1f442-1f3fb{background-position:-1690px -585px}.emojione-1f442-1f3fc{background-position:-1690px -650px}.emojione-1f442-1f3fd{background-position:-1690px -715px}.emojione-1f442-1f3fe{background-position:-1690px -780px}.emojione-1f442-1f3ff{background-position:-1690px -845px}.emojione-1f442{background-position:-1690px -910px}.emojione-1f443-1f3fb{background-position:-1690px -975px}.emojione-1f443-1f3fc{background-position:-1690px -1040px}.emojione-1f443-1f3fd{background-position:-1690px -1105px}.emojione-1f443-1f3fe{background-position:-1690px -1170px}.emojione-1f443-1f3ff{background-position:-1690px -1235px}.emojione-1f443{background-position:-1690px -1300px}.emojione-1f444{background-position:-1690px -1365px}.emojione-1f445{background-position:-1690px -1430px}.emojione-1f446-1f3fb{background-position:-1690px -1495px}.emojione-1f446-1f3fc{background-position:-1690px -1560px}.emojione-1f446-1f3fd{background-position:-1690px -1625px}.emojione-1f446-1f3fe{background-position:0 -1690px}.emojione-1f446-1f3ff{background-position:-65px -1690px}.emojione-1f446{background-position:-130px -1690px}.emojione-1f447-1f3fb{background-position:-195px -1690px}.emojione-1f447-1f3fc{background-position:-260px -1690px}.emojione-1f447-1f3fd{background-position:-325px -1690px}.emojione-1f447-1f3fe{background-position:-390px -1690px}.emojione-1f447-1f3ff{background-position:-455px -1690px}.emojione-1f447{background-position:-520px -1690px}.emojione-1f448-1f3fb{background-position:-585px -1690px}.emojione-1f448-1f3fc{background-position:-650px -1690px}.emojione-1f448-1f3fd{background-position:-715px -1690px}.emojione-1f448-1f3fe{background-position:-780px -1690px}.emojione-1f448-1f3ff{background-position:-845px -1690px}.emojione-1f448{background-position:-910px -1690px}.emojione-1f449-1f3fb{background-position:-975px -1690px}.emojione-1f449-1f3fc{background-position:-1040px -1690px}.emojione-1f449-1f3fd{background-position:-1105px -1690px}.emojione-1f449-1f3fe{background-position:-1170px -1690px}.emojione-1f449-1f3ff{background-position:-1235px -1690px}.emojione-1f449{background-position:-1300px -1690px}.emojione-1f44a-1f3fb{background-position:-1365px -1690px}.emojione-1f44a-1f3fc{background-position:-1430px -1690px}.emojione-1f44a-1f3fd{background-position:-1495px -1690px}.emojione-1f44a-1f3fe{background-position:-1560px -1690px}.emojione-1f44a-1f3ff{background-position:-1625px -1690px}.emojione-1f44a{background-position:-1690px -1690px}.emojione-1f44b-1f3fb{background-position:-1755px 0}.emojione-1f44b-1f3fc{background-position:-1755px -65px}.emojione-1f44b-1f3fd{background-position:-1755px -130px}.emojione-1f44b-1f3fe{background-position:-1755px -195px}.emojione-1f44b-1f3ff{background-position:-1755px -260px}.emojione-1f44b{background-position:-1755px -325px}.emojione-1f44c-1f3fb{background-position:-1755px -390px}.emojione-1f44c-1f3fc{background-position:-1755px -455px}.emojione-1f44c-1f3fd{background-position:-1755px -520px}.emojione-1f44c-1f3fe{background-position:-1755px -585px}.emojione-1f44c-1f3ff{background-position:-1755px -650px}.emojione-1f44c{background-position:-1755px -715px}.emojione-1f44d-1f3fb{background-position:-1755px -780px}.emojione-1f44d-1f3fc{background-position:-1755px -845px}.emojione-1f44d-1f3fd{background-position:-1755px -910px}.emojione-1f44d-1f3fe{background-position:-1755px -975px}.emojione-1f44d-1f3ff{background-position:-1755px -1040px}.emojione-1f44d{background-position:-1755px -1105px}.emojione-1f44e-1f3fb{background-position:-1755px -1170px}.emojione-1f44e-1f3fc{background-position:-1755px -1235px}.emojione-1f44e-1f3fd{background-position:-1755px -1300px}.emojione-1f44e-1f3fe{background-position:-1755px -1365px}.emojione-1f44e-1f3ff{background-position:-1755px -1430px}.emojione-1f44e{background-position:-1755px -1495px}.emojione-1f44f-1f3fb{background-position:-1755px -1560px}.emojione-1f44f-1f3fc{background-position:-1755px -1625px}.emojione-1f44f-1f3fd{background-position:-1755px -1690px}.emojione-1f44f-1f3fe{background-position:0 -1755px}.emojione-1f44f-1f3ff{background-position:-65px -1755px}.emojione-1f44f{background-position:-130px -1755px}.emojione-1f450-1f3fb{background-position:-195px -1755px}.emojione-1f450-1f3fc{background-position:-260px -1755px}.emojione-1f450-1f3fd{background-position:-325px -1755px}.emojione-1f450-1f3fe{background-position:-390px -1755px}.emojione-1f450-1f3ff{background-position:-455px -1755px}.emojione-1f450{background-position:-520px -1755px}.emojione-1f451{background-position:-585px -1755px}.emojione-1f452{background-position:-650px -1755px}.emojione-1f453{background-position:-715px -1755px}.emojione-1f454{background-position:-780px -1755px}.emojione-1f455{background-position:-845px -1755px}.emojione-1f456{background-position:-910px -1755px}.emojione-1f457{background-position:-975px -1755px}.emojione-1f458{background-position:-1040px -1755px}.emojione-1f459{background-position:-1105px -1755px}.emojione-1f45a{background-position:-1170px -1755px}.emojione-1f45b{background-position:-1235px -1755px}.emojione-1f45c{background-position:-1300px -1755px}.emojione-1f45d{background-position:-1365px -1755px}.emojione-1f45e{background-position:-1430px -1755px}.emojione-1f45f{background-position:-1495px -1755px}.emojione-1f460{background-position:-1560px -1755px}.emojione-1f461{background-position:-1625px -1755px}.emojione-1f462{background-position:-1690px -1755px}.emojione-1f463{background-position:-1755px -1755px}.emojione-1f464{background-position:-1820px 0}.emojione-1f465{background-position:-1820px -65px}.emojione-1f466-1f3fb{background-position:-1820px -130px}.emojione-1f466-1f3fc{background-position:-1820px -195px}.emojione-1f466-1f3fd{background-position:-1820px -260px}.emojione-1f466-1f3fe{background-position:-1820px -325px}.emojione-1f466-1f3ff{background-position:-1820px -390px}.emojione-1f466{background-position:-1820px -455px}.emojione-1f467-1f3fb{background-position:-1820px -520px}.emojione-1f467-1f3fc{background-position:-1820px -585px}.emojione-1f467-1f3fd{background-position:-1820px -650px}.emojione-1f467-1f3fe{background-position:-1820px -715px}.emojione-1f467-1f3ff{background-position:-1820px -780px}.emojione-1f467{background-position:-1820px -845px}.emojione-1f468-1f3fb{background-position:-1820px -910px}.emojione-1f468-1f3fc{background-position:-1820px -975px}.emojione-1f468-1f3fd{background-position:-1820px -1040px}.emojione-1f468-1f3fe{background-position:-1820px -1105px}.emojione-1f468-1f3ff{background-position:-1820px -1170px}.emojione-1f468-1f468-1f466-1f466{background-position:-1820px -1235px}.emojione-1f468-1f468-1f466{background-position:-1820px -1300px}.emojione-1f468-1f468-1f467-1f466{background-position:-1820px -1365px}.emojione-1f468-1f468-1f467-1f467{background-position:-1820px -1430px}.emojione-1f468-1f468-1f467{background-position:-1820px -1495px}.emojione-1f468-1f469-1f466-1f466{background-position:-1820px -1560px}.emojione-1f468-1f469-1f467-1f466{background-position:-1820px -1625px}.emojione-1f468-1f469-1f467-1f467{background-position:-1820px -1690px}.emojione-1f468-1f469-1f467{background-position:-1820px -1755px}.emojione-1f468-2764-1f468{background-position:0 -1820px}.emojione-1f468-2764-1f48b-1f468{background-position:-65px -1820px}.emojione-1f468{background-position:-130px -1820px}.emojione-1f469-1f3fb{background-position:-195px -1820px}.emojione-1f469-1f3fc{background-position:-260px -1820px}.emojione-1f469-1f3fd{background-position:-325px -1820px}.emojione-1f469-1f3fe{background-position:-390px -1820px}.emojione-1f469-1f3ff{background-position:-455px -1820px}.emojione-1f469-1f469-1f466-1f466{background-position:-520px -1820px}.emojione-1f469-1f469-1f466{background-position:-585px -1820px}.emojione-1f469-1f469-1f467-1f466{background-position:-650px -1820px}.emojione-1f469-1f469-1f467-1f467{background-position:-715px -1820px}.emojione-1f469-1f469-1f467{background-position:-780px -1820px}.emojione-1f469-2764-1f469{background-position:-845px -1820px}.emojione-1f469-2764-1f48b-1f469{background-position:-910px -1820px}.emojione-1f469{background-position:-975px -1820px}.emojione-1f46a{background-position:-1040px -1820px}.emojione-1f46b{background-position:-1105px -1820px}.emojione-1f46c{background-position:-1170px -1820px}.emojione-1f46d{background-position:-1235px -1820px}.emojione-1f46e-1f3fb{background-position:-1300px -1820px}.emojione-1f46e-1f3fc{background-position:0 0}.emojione-1f46e-1f3fd{background-position:-1430px -1820px}.emojione-1f46e-1f3fe{background-position:-1495px -1820px}.emojione-1f46e-1f3ff{background-position:-1560px -1820px}.emojione-1f46e{background-position:-1625px -1820px}.emojione-1f46f{background-position:-1690px -1820px}.emojione-1f470-1f3fb{background-position:-1755px -1820px}.emojione-1f470-1f3fc{background-position:-1820px -1820px}.emojione-1f470-1f3fd{background-position:-1885px 0}.emojione-1f470-1f3fe{background-position:-1885px -65px}.emojione-1f470-1f3ff{background-position:-1885px -130px}.emojione-1f470{background-position:-1885px -195px}.emojione-1f471-1f3fb{background-position:-1885px -260px}.emojione-1f471-1f3fc{background-position:-1885px -325px}.emojione-1f471-1f3fd{background-position:-1885px -390px}.emojione-1f471-1f3fe{background-position:-1885px -455px}.emojione-1f471-1f3ff{background-position:-1885px -520px}.emojione-1f471{background-position:-1885px -585px}.emojione-1f472-1f3fb{background-position:-1885px -650px}.emojione-1f472-1f3fc{background-position:-1885px -715px}.emojione-1f472-1f3fd{background-position:-1885px -780px}.emojione-1f472-1f3fe{background-position:-1885px -845px}.emojione-1f472-1f3ff{background-position:-1885px -910px}.emojione-1f472{background-position:-1885px -975px}.emojione-1f473-1f3fb{background-position:-1885px -1040px}.emojione-1f473-1f3fc{background-position:-1885px -1105px}.emojione-1f473-1f3fd{background-position:-1885px -1170px}.emojione-1f473-1f3fe{background-position:-1885px -1235px}.emojione-1f473-1f3ff{background-position:-1885px -1300px}.emojione-1f473{background-position:-1885px -1365px}.emojione-1f474-1f3fb{background-position:-1885px -1430px}.emojione-1f474-1f3fc{background-position:-1885px -1495px}.emojione-1f474-1f3fd{background-position:-1885px -1560px}.emojione-1f474-1f3fe{background-position:-1885px -1625px}.emojione-1f474-1f3ff{background-position:-1885px -1690px}.emojione-1f474{background-position:-1885px -1755px}.emojione-1f475-1f3fb{background-position:-1885px -1820px}.emojione-1f475-1f3fc{background-position:0 -1885px}.emojione-1f475-1f3fd{background-position:-65px -1885px}.emojione-1f475-1f3fe{background-position:-130px -1885px}.emojione-1f475-1f3ff{background-position:-195px -1885px}.emojione-1f475{background-position:-260px -1885px}.emojione-1f476-1f3fb{background-position:-325px -1885px}.emojione-1f476-1f3fc{background-position:-390px -1885px}.emojione-1f476-1f3fd{background-position:-455px -1885px}.emojione-1f476-1f3fe{background-position:-520px -1885px}.emojione-1f476-1f3ff{background-position:-585px -1885px}.emojione-1f476{background-position:-650px -1885px}.emojione-1f477-1f3fb{background-position:-715px -1885px}.emojione-1f477-1f3fc{background-position:-780px -1885px}.emojione-1f477-1f3fd{background-position:-845px -1885px}.emojione-1f477-1f3fe{background-position:-910px -1885px}.emojione-1f477-1f3ff{background-position:-975px -1885px}.emojione-1f477{background-position:-1040px -1885px}.emojione-1f478-1f3fb{background-position:-1105px -1885px}.emojione-1f478-1f3fc{background-position:-1170px -1885px}.emojione-1f478-1f3fd{background-position:-1235px -1885px}.emojione-1f478-1f3fe{background-position:-1300px -1885px}.emojione-1f478-1f3ff{background-position:-1365px -1885px}.emojione-1f478{background-position:-1430px -1885px}.emojione-1f479{background-position:-1495px -1885px}.emojione-1f47a{background-position:-1560px -1885px}.emojione-1f47b{background-position:-1625px -1885px}.emojione-1f47c-1f3fb{background-position:-1690px -1885px}.emojione-1f47c-1f3fc{background-position:-1755px -1885px}.emojione-1f47c-1f3fd{background-position:-1820px -1885px}.emojione-1f47c-1f3fe{background-position:-1885px -1885px}.emojione-1f47c-1f3ff{background-position:-1950px 0}.emojione-1f47c{background-position:-1950px -65px}.emojione-1f47d{background-position:-1950px -130px}.emojione-1f47e{background-position:-1950px -195px}.emojione-1f47f{background-position:-1950px -260px}.emojione-1f480{background-position:-1950px -325px}.emojione-1f481-1f3fb{background-position:-1950px -390px}.emojione-1f481-1f3fc{background-position:-1950px -455px}.emojione-1f481-1f3fd{background-position:-1950px -520px}.emojione-1f481-1f3fe{background-position:-1950px -585px}.emojione-1f481-1f3ff{background-position:-1950px -650px}.emojione-1f481{background-position:-1950px -715px}.emojione-1f482-1f3fb{background-position:-1950px -780px}.emojione-1f482-1f3fc{background-position:-1950px -845px}.emojione-1f482-1f3fd{background-position:-1950px -910px}.emojione-1f482-1f3fe{background-position:-1950px -975px}.emojione-1f482-1f3ff{background-position:-1950px -1040px}.emojione-1f482{background-position:-1950px -1105px}.emojione-1f483-1f3fb{background-position:-1950px -1170px}.emojione-1f483-1f3fc{background-position:-1950px -1235px}.emojione-1f483-1f3fd{background-position:-1950px -1300px}.emojione-1f483-1f3fe{background-position:-1950px -1365px}.emojione-1f483-1f3ff{background-position:-1950px -1430px}.emojione-1f483{background-position:-1950px -1495px}.emojione-1f484{background-position:-1950px -1560px}.emojione-1f485-1f3fb{background-position:-1950px -1625px}.emojione-1f485-1f3fc{background-position:-1950px -1690px}.emojione-1f485-1f3fd{background-position:-1950px -1755px}.emojione-1f485-1f3fe{background-position:-1950px -1820px}.emojione-1f485-1f3ff{background-position:-1950px -1885px}.emojione-1f485{background-position:0 -1950px}.emojione-1f486-1f3fb{background-position:-65px -1950px}.emojione-1f486-1f3fc{background-position:-130px -1950px}.emojione-1f486-1f3fd{background-position:-195px -1950px}.emojione-1f486-1f3fe{background-position:-260px -1950px}.emojione-1f486-1f3ff{background-position:-325px -1950px}.emojione-1f486{background-position:-390px -1950px}.emojione-1f487-1f3fb{background-position:-455px -1950px}.emojione-1f487-1f3fc{background-position:-520px -1950px}.emojione-1f487-1f3fd{background-position:-585px -1950px}.emojione-1f487-1f3fe{background-position:-650px -1950px}.emojione-1f487-1f3ff{background-position:-715px -1950px}.emojione-1f487{background-position:-780px -1950px}.emojione-1f488{background-position:-845px -1950px}.emojione-1f489{background-position:-910px -1950px}.emojione-1f48a{background-position:-975px -1950px}.emojione-1f48b{background-position:-1040px -1950px}.emojione-1f48c{background-position:-1105px -1950px}.emojione-1f48d{background-position:-1170px -1950px}.emojione-1f48e{background-position:-1235px -1950px}.emojione-1f48f{background-position:-1300px -1950px}.emojione-1f490{background-position:-1365px -1950px}.emojione-1f491{background-position:-1430px -1950px}.emojione-1f492{background-position:-1495px -1950px}.emojione-1f493{background-position:-1560px -1950px}.emojione-1f494{background-position:-1625px -1950px}.emojione-1f495{background-position:-1690px -1950px}.emojione-1f496{background-position:-1755px -1950px}.emojione-1f497{background-position:-1820px -1950px}.emojione-1f498{background-position:-1885px -1950px}.emojione-1f499{background-position:-1950px -1950px}.emojione-1f49a{background-position:-2015px 0}.emojione-1f49b{background-position:-2015px -65px}.emojione-1f49c{background-position:-2015px -130px}.emojione-1f49d{background-position:-2015px -195px}.emojione-1f49e{background-position:-2015px -260px}.emojione-1f49f{background-position:-2015px -325px}.emojione-1f4a0{background-position:-2015px -390px}.emojione-1f4a1{background-position:-2015px -455px}.emojione-1f4a2{background-position:-2015px -520px}.emojione-1f4a3{background-position:-2015px -585px}.emojione-1f4a4{background-position:-2015px -650px}.emojione-1f4a5{background-position:-2015px -715px}.emojione-1f4a6{background-position:-2015px -780px}.emojione-1f4a7{background-position:-2015px -845px}.emojione-1f4a8{background-position:-2015px -910px}.emojione-1f4a9{background-position:-2015px -975px}.emojione-1f4aa-1f3fb{background-position:-2015px -1040px}.emojione-1f4aa-1f3fc{background-position:-2015px -1105px}.emojione-1f4aa-1f3fd{background-position:-2015px -1170px}.emojione-1f4aa-1f3fe{background-position:-2015px -1235px}.emojione-1f4aa-1f3ff{background-position:-2015px -1300px}.emojione-1f4aa{background-position:-2015px -1365px}.emojione-1f4ab{background-position:-2015px -1430px}.emojione-1f4ac{background-position:-2015px -1495px}.emojione-1f4ad{background-position:-2015px -1560px}.emojione-1f4ae{background-position:-2015px -1625px}.emojione-1f4af{background-position:-2015px -1690px}.emojione-1f4b0{background-position:-2015px -1755px}.emojione-1f4b1{background-position:-2015px -1820px}.emojione-1f4b2{background-position:-2015px -1885px}.emojione-1f4b3{background-position:-2015px -1950px}.emojione-1f4b4{background-position:0 -2015px}.emojione-1f4b5{background-position:-65px -2015px}.emojione-1f4b6{background-position:-130px -2015px}.emojione-1f4b7{background-position:-195px -2015px}.emojione-1f4b8{background-position:-260px -2015px}.emojione-1f4b9{background-position:-325px -2015px}.emojione-1f4ba{background-position:-390px -2015px}.emojione-1f4bb{background-position:-455px -2015px}.emojione-1f4bc{background-position:-520px -2015px}.emojione-1f4bd{background-position:-585px -2015px}.emojione-1f4be{background-position:-650px -2015px}.emojione-1f4bf{background-position:-715px -2015px}.emojione-1f4c0{background-position:-780px -2015px}.emojione-1f4c1{background-position:-845px -2015px}.emojione-1f4c2{background-position:-910px -2015px}.emojione-1f4c3{background-position:-975px -2015px}.emojione-1f4c4{background-position:-1040px -2015px}.emojione-1f4c5{background-position:-1105px -2015px}.emojione-1f4c6{background-position:-1170px -2015px}.emojione-1f4c7{background-position:-1235px -2015px}.emojione-1f4c8{background-position:-1300px -2015px}.emojione-1f4c9{background-position:-1365px -2015px}.emojione-1f4ca{background-position:-1430px -2015px}.emojione-1f4cb{background-position:-1495px -2015px}.emojione-1f4cc{background-position:-1560px -2015px}.emojione-1f4cd{background-position:-1625px -2015px}.emojione-1f4ce{background-position:-1690px -2015px}.emojione-1f4cf{background-position:-1755px -2015px}.emojione-1f4d0{background-position:-1820px -2015px}.emojione-1f4d1{background-position:-1885px -2015px}.emojione-1f4d2{background-position:-1950px -2015px}.emojione-1f4d3{background-position:-2015px -2015px}.emojione-1f4d4{background-position:-2080px 0}.emojione-1f4d5{background-position:-2080px -65px}.emojione-1f4d6{background-position:-2080px -130px}.emojione-1f4d7{background-position:-2080px -195px}.emojione-1f4d8{background-position:-2080px -260px}.emojione-1f4d9{background-position:-2080px -325px}.emojione-1f4da{background-position:-2080px -390px}.emojione-1f4db{background-position:-2080px -455px}.emojione-1f4dc{background-position:-2080px -520px}.emojione-1f4dd{background-position:-2080px -585px}.emojione-1f4de{background-position:-2080px -650px}.emojione-1f4df{background-position:-2080px -715px}.emojione-1f4e0{background-position:-2080px -780px}.emojione-1f4e1{background-position:-2080px -845px}.emojione-1f4e2{background-position:-2080px -910px}.emojione-1f4e3{background-position:-2080px -975px}.emojione-1f4e4{background-position:-2080px -1040px}.emojione-1f4e5{background-position:-2080px -1105px}.emojione-1f4e6{background-position:-2080px -1170px}.emojione-1f4e7{background-position:-2080px -1235px}.emojione-1f4e8{background-position:-2080px -1300px}.emojione-1f4e9{background-position:-2080px -1365px}.emojione-1f4ea{background-position:-2080px -1430px}.emojione-1f4eb{background-position:-2080px -1495px}.emojione-1f4ec{background-position:-2080px -1560px}.emojione-1f4ed{background-position:-2080px -1625px}.emojione-1f4ee{background-position:-2080px -1690px}.emojione-1f4ef{background-position:-2080px -1755px}.emojione-1f4f0{background-position:-2080px -1820px}.emojione-1f4f1{background-position:-2080px -1885px}.emojione-1f4f2{background-position:-2080px -1950px}.emojione-1f4f3{background-position:-2080px -2015px}.emojione-1f4f4{background-position:0 -2080px}.emojione-1f4f5{background-position:-65px -2080px}.emojione-1f4f6{background-position:-130px -2080px}.emojione-1f4f7{background-position:-195px -2080px}.emojione-1f4f8{background-position:-260px -2080px}.emojione-1f4f9{background-position:-325px -2080px}.emojione-1f4fa{background-position:-390px -2080px}.emojione-1f4fb{background-position:-455px -2080px}.emojione-1f4fc{background-position:-520px -2080px}.emojione-1f4fd{background-position:-585px -2080px}.emojione-1f4ff{background-position:-650px -2080px}.emojione-1f500{background-position:-715px -2080px}.emojione-1f501{background-position:-780px -2080px}.emojione-1f502{background-position:-845px -2080px}.emojione-1f503{background-position:-910px -2080px}.emojione-1f504{background-position:-975px -2080px}.emojione-1f505{background-position:-1040px -2080px}.emojione-1f506{background-position:-1105px -2080px}.emojione-1f507{background-position:-1170px -2080px}.emojione-1f508{background-position:-1235px -2080px}.emojione-1f509{background-position:-1300px -2080px}.emojione-1f50a{background-position:-1365px -2080px}.emojione-1f50b{background-position:-1430px -2080px}.emojione-1f50c{background-position:-1495px -2080px}.emojione-1f50d{background-position:-1560px -2080px}.emojione-1f50e{background-position:-1625px -2080px}.emojione-1f50f{background-position:-1690px -2080px}.emojione-1f510{background-position:-1755px -2080px}.emojione-1f511{background-position:-1820px -2080px}.emojione-1f512{background-position:-1885px -2080px}.emojione-1f513{background-position:-1950px -2080px}.emojione-1f514{background-position:-2015px -2080px}.emojione-1f515{background-position:-2080px -2080px}.emojione-1f516{background-position:-2145px 0}.emojione-1f517{background-position:-2145px -65px}.emojione-1f518{background-position:-2145px -130px}.emojione-1f519{background-position:-2145px -195px}.emojione-1f51a{background-position:-2145px -260px}.emojione-1f51b{background-position:-2145px -325px}.emojione-1f51c{background-position:-2145px -390px}.emojione-1f51d{background-position:-2145px -455px}.emojione-1f51e{background-position:-2145px -520px}.emojione-1f51f{background-position:-2145px -585px}.emojione-1f520{background-position:-2145px -650px}.emojione-1f521{background-position:-2145px -715px}.emojione-1f522{background-position:-2145px -780px}.emojione-1f523{background-position:-2145px -845px}.emojione-1f524{background-position:-2145px -910px}.emojione-1f525{background-position:-2145px -975px}.emojione-1f526{background-position:-2145px -1040px}.emojione-1f527{background-position:-2145px -1105px}.emojione-1f528{background-position:-2145px -1170px}.emojione-1f529{background-position:-2145px -1235px}.emojione-1f52a{background-position:-2145px -1300px}.emojione-1f52b{background-position:-2145px -1365px}.emojione-1f52c{background-position:-2145px -1430px}.emojione-1f52d{background-position:-2145px -1495px}.emojione-1f52e{background-position:-2145px -1560px}.emojione-1f52f{background-position:-2145px -1625px}.emojione-1f530{background-position:-2145px -1690px}.emojione-1f531{background-position:-2145px -1755px}.emojione-1f532{background-position:-2145px -1820px}.emojione-1f533{background-position:-2145px -1885px}.emojione-1f534{background-position:-2145px -1950px}.emojione-1f535{background-position:-2145px -2015px}.emojione-1f536{background-position:-2145px -2080px}.emojione-1f537{background-position:0 -2145px}.emojione-1f538{background-position:-65px -2145px}.emojione-1f539{background-position:-130px -2145px}.emojione-1f53a{background-position:-195px -2145px}.emojione-1f53b{background-position:-260px -2145px}.emojione-1f53c{background-position:-325px -2145px}.emojione-1f53d{background-position:-390px -2145px}.emojione-1f549{background-position:-455px -2145px}.emojione-1f54a{background-position:-520px -2145px}.emojione-1f54b{background-position:-585px -2145px}.emojione-1f54c{background-position:-650px -2145px}.emojione-1f54d{background-position:-715px -2145px}.emojione-1f54e{background-position:-780px -2145px}.emojione-1f550{background-position:-845px -2145px}.emojione-1f551{background-position:-910px -2145px}.emojione-1f552{background-position:-975px -2145px}.emojione-1f553{background-position:-1040px -2145px}.emojione-1f554{background-position:-1105px -2145px}.emojione-1f555{background-position:-1170px -2145px}.emojione-1f556{background-position:-1235px -2145px}.emojione-1f557{background-position:-1300px -2145px}.emojione-1f558{background-position:-1365px -2145px}.emojione-1f559{background-position:-1430px -2145px}.emojione-1f55a{background-position:-1495px -2145px}.emojione-1f55b{background-position:-1560px -2145px}.emojione-1f55c{background-position:-1625px -2145px}.emojione-1f55d{background-position:-1690px -2145px}.emojione-1f55e{background-position:-1755px -2145px}.emojione-1f55f{background-position:-1820px -2145px}.emojione-1f560{background-position:-1885px -2145px}.emojione-1f561{background-position:-1950px -2145px}.emojione-1f562{background-position:-2015px -2145px}.emojione-1f563{background-position:-2080px -2145px}.emojione-1f564{background-position:-2145px -2145px}.emojione-1f565{background-position:-2210px 0}.emojione-1f566{background-position:-2210px -65px}.emojione-1f567{background-position:-2210px -130px}.emojione-1f56f{background-position:-2210px -195px}.emojione-1f570{background-position:-2210px -260px}.emojione-1f573{background-position:-2210px -325px}.emojione-1f574{background-position:-2210px -390px}.emojione-1f575-1f3fb{background-position:-2210px -455px}.emojione-1f575-1f3fc{background-position:-2210px -520px}.emojione-1f575-1f3fd{background-position:-2210px -585px}.emojione-1f575-1f3fe{background-position:-2210px -650px}.emojione-1f575-1f3ff{background-position:-2210px -715px}.emojione-1f575{background-position:-2210px -780px}.emojione-1f576{background-position:-2210px -845px}.emojione-1f577{background-position:-2210px -910px}.emojione-1f578{background-position:-2210px -975px}.emojione-1f579{background-position:-2210px -1040px}.emojione-1f57a-1f3fb{background-position:-2210px -1105px}.emojione-1f57a-1f3fc{background-position:-2210px -1170px}.emojione-1f57a-1f3fd{background-position:-2210px -1235px}.emojione-1f57a-1f3fe{background-position:-2210px -1300px}.emojione-1f57a-1f3ff{background-position:-2210px -1365px}.emojione-1f57a{background-position:-2210px -1430px}.emojione-1f587{background-position:-2210px -1495px}.emojione-1f58a{background-position:-2210px -1560px}.emojione-1f58b{background-position:-2210px -1625px}.emojione-1f58c{background-position:-2210px -1690px}.emojione-1f58d{background-position:-2210px -1755px}.emojione-1f590-1f3fb{background-position:-2210px -1820px}.emojione-1f590-1f3fc{background-position:-2210px -1885px}.emojione-1f590-1f3fd{background-position:-2210px -1950px}.emojione-1f590-1f3fe{background-position:-2210px -2015px}.emojione-1f590-1f3ff{background-position:-2210px -2080px}.emojione-1f590{background-position:-2210px -2145px}.emojione-1f595-1f3fb{background-position:0 -2210px}.emojione-1f595-1f3fc{background-position:-65px -2210px}.emojione-1f595-1f3fd{background-position:-130px -2210px}.emojione-1f595-1f3fe{background-position:-195px -2210px}.emojione-1f595-1f3ff{background-position:-260px -2210px}.emojione-1f595{background-position:-325px -2210px}.emojione-1f596-1f3fb{background-position:-390px -2210px}.emojione-1f596-1f3fc{background-position:-455px -2210px}.emojione-1f596-1f3fd{background-position:-520px -2210px}.emojione-1f596-1f3fe{background-position:-585px -2210px}.emojione-1f596-1f3ff{background-position:-650px -2210px}.emojione-1f596{background-position:-715px -2210px}.emojione-1f5a4{background-position:-780px -2210px}.emojione-1f5a5{background-position:-845px -2210px}.emojione-1f5a8{background-position:-910px -2210px}.emojione-1f5b1{background-position:-975px -2210px}.emojione-1f5b2{background-position:-1040px -2210px}.emojione-1f5bc{background-position:-1105px -2210px}.emojione-1f5c2{background-position:-1170px -2210px}.emojione-1f5c3{background-position:-1235px -2210px}.emojione-1f5c4{background-position:-1300px -2210px}.emojione-1f5d1{background-position:-1365px -2210px}.emojione-1f5d2{background-position:-1430px -2210px}.emojione-1f5d3{background-position:-1495px -2210px}.emojione-1f5dc{background-position:-1560px -2210px}.emojione-1f5dd{background-position:-1625px -2210px}.emojione-1f5de{background-position:-1690px -2210px}.emojione-1f5e1{background-position:-1755px -2210px}.emojione-1f5e3{background-position:-1820px -2210px}.emojione-1f5e8{background-position:-1885px -2210px}.emojione-1f5ef{background-position:-1950px -2210px}.emojione-1f5f3{background-position:-2015px -2210px}.emojione-1f5fa{background-position:-2080px -2210px}.emojione-1f5fb{background-position:-2145px -2210px}.emojione-1f5fc{background-position:-2210px -2210px}.emojione-1f5fd{background-position:-2275px 0}.emojione-1f5fe{background-position:-2275px -65px}.emojione-1f5ff{background-position:-2275px -130px}.emojione-1f600{background-position:-2275px -195px}.emojione-1f601{background-position:-2275px -260px}.emojione-1f602{background-position:-2275px -325px}.emojione-1f603{background-position:-2275px -390px}.emojione-1f604{background-position:-2275px -455px}.emojione-1f605{background-position:-2275px -520px}.emojione-1f606{background-position:-2275px -585px}.emojione-1f607{background-position:-2275px -650px}.emojione-1f608{background-position:-2275px -715px}.emojione-1f609{background-position:-2275px -780px}.emojione-1f60a{background-position:-2275px -845px}.emojione-1f60b{background-position:-2275px -910px}.emojione-1f60c{background-position:-2275px -975px}.emojione-1f60d{background-position:-2275px -1040px}.emojione-1f60e{background-position:-2275px -1105px}.emojione-1f60f{background-position:-2275px -1170px}.emojione-1f610{background-position:-2275px -1235px}.emojione-1f611{background-position:-2275px -1300px}.emojione-1f612{background-position:-2275px -1365px}.emojione-1f613{background-position:-2275px -1430px}.emojione-1f614{background-position:-2275px -1495px}.emojione-1f615{background-position:-2275px -1560px}.emojione-1f616{background-position:-2275px -1625px}.emojione-1f617{background-position:-2275px -1690px}.emojione-1f618{background-position:-2275px -1755px}.emojione-1f619{background-position:-2275px -1820px}.emojione-1f61a{background-position:-2275px -1885px}.emojione-1f61b{background-position:-2275px -1950px}.emojione-1f61c{background-position:-2275px -2015px}.emojione-1f61d{background-position:-2275px -2080px}.emojione-1f61e{background-position:-2275px -2145px}.emojione-1f61f{background-position:-2275px -2210px}.emojione-1f620{background-position:0 -2275px}.emojione-1f621{background-position:-65px -2275px}.emojione-1f622{background-position:-130px -2275px}.emojione-1f623{background-position:-195px -2275px}.emojione-1f624{background-position:-260px -2275px}.emojione-1f625{background-position:-325px -2275px}.emojione-1f626{background-position:-390px -2275px}.emojione-1f627{background-position:-455px -2275px}.emojione-1f628{background-position:-520px -2275px}.emojione-1f629{background-position:-585px -2275px}.emojione-1f62a{background-position:-650px -2275px}.emojione-1f62b{background-position:-715px -2275px}.emojione-1f62c{background-position:-780px -2275px}.emojione-1f62d{background-position:-845px -2275px}.emojione-1f62e{background-position:-910px -2275px}.emojione-1f62f{background-position:-975px -2275px}.emojione-1f630{background-position:-1040px -2275px}.emojione-1f631{background-position:-1105px -2275px}.emojione-1f632{background-position:-1170px -2275px}.emojione-1f633{background-position:-1235px -2275px}.emojione-1f634{background-position:-1300px -2275px}.emojione-1f635{background-position:-1365px -2275px}.emojione-1f636{background-position:-1430px -2275px}.emojione-1f637{background-position:-1495px -2275px}.emojione-1f638{background-position:-1560px -2275px}.emojione-1f639{background-position:-1625px -2275px}.emojione-1f63a{background-position:-1690px -2275px}.emojione-1f63b{background-position:-1755px -2275px}.emojione-1f63c{background-position:-1820px -2275px}.emojione-1f63d{background-position:-1885px -2275px}.emojione-1f63e{background-position:-1950px -2275px}.emojione-1f63f{background-position:-2015px -2275px}.emojione-1f640{background-position:-2080px -2275px}.emojione-1f641{background-position:-2145px -2275px}.emojione-1f642{background-position:-2210px -2275px}.emojione-1f643{background-position:-2275px -2275px}.emojione-1f644{background-position:-2340px 0}.emojione-1f645-1f3fb{background-position:-2340px -65px}.emojione-1f645-1f3fc{background-position:-2340px -130px}.emojione-1f645-1f3fd{background-position:-2340px -195px}.emojione-1f645-1f3fe{background-position:-2340px -260px}.emojione-1f645-1f3ff{background-position:-2340px -325px}.emojione-1f645{background-position:-2340px -390px}.emojione-1f646-1f3fb{background-position:-2340px -455px}.emojione-1f646-1f3fc{background-position:-2340px -520px}.emojione-1f646-1f3fd{background-position:-2340px -585px}.emojione-1f646-1f3fe{background-position:-2340px -650px}.emojione-1f646-1f3ff{background-position:-2340px -715px}.emojione-1f646{background-position:-2340px -780px}.emojione-1f647-1f3fb{background-position:-2340px -845px}.emojione-1f647-1f3fc{background-position:-2340px -910px}.emojione-1f647-1f3fd{background-position:-2340px -975px}.emojione-1f647-1f3fe{background-position:-2340px -1040px}.emojione-1f647-1f3ff{background-position:-2340px -1105px}.emojione-1f647{background-position:-2340px -1170px}.emojione-1f648{background-position:-2340px -1235px}.emojione-1f649{background-position:-2340px -1300px}.emojione-1f64a{background-position:-2340px -1365px}.emojione-1f64b-1f3fb{background-position:-2340px -1430px}.emojione-1f64b-1f3fc{background-position:-2340px -1495px}.emojione-1f64b-1f3fd{background-position:-2340px -1560px}.emojione-1f64b-1f3fe{background-position:-2340px -1625px}.emojione-1f64b-1f3ff{background-position:-2340px -1690px}.emojione-1f64b{background-position:-2340px -1755px}.emojione-1f64c-1f3fb{background-position:-2340px -1820px}.emojione-1f64c-1f3fc{background-position:-2340px -1885px}.emojione-1f64c-1f3fd{background-position:-2340px -1950px}.emojione-1f64c-1f3fe{background-position:-2340px -2015px}.emojione-1f64c-1f3ff{background-position:-2340px -2080px}.emojione-1f64c{background-position:-2340px -2145px}.emojione-1f64d-1f3fb{background-position:-2340px -2210px}.emojione-1f64d-1f3fc{background-position:-2340px -2275px}.emojione-1f64d-1f3fd{background-position:0 -2340px}.emojione-1f64d-1f3fe{background-position:-65px -2340px}.emojione-1f64d-1f3ff{background-position:-130px -2340px}.emojione-1f64d{background-position:-195px -2340px}.emojione-1f64e-1f3fb{background-position:-260px -2340px}.emojione-1f64e-1f3fc{background-position:-325px -2340px}.emojione-1f64e-1f3fd{background-position:-390px -2340px}.emojione-1f64e-1f3fe{background-position:-455px -2340px}.emojione-1f64e-1f3ff{background-position:-520px -2340px}.emojione-1f64e{background-position:-585px -2340px}.emojione-1f64f-1f3fb{background-position:-650px -2340px}.emojione-1f64f-1f3fc{background-position:-715px -2340px}.emojione-1f64f-1f3fd{background-position:-780px -2340px}.emojione-1f64f-1f3fe{background-position:-845px -2340px}.emojione-1f64f-1f3ff{background-position:-910px -2340px}.emojione-1f64f{background-position:-975px -2340px}.emojione-1f680{background-position:-1040px -2340px}.emojione-1f681{background-position:-1105px -2340px}.emojione-1f682{background-position:-1170px -2340px}.emojione-1f683{background-position:-1235px -2340px}.emojione-1f684{background-position:-1300px -2340px}.emojione-1f685{background-position:-1365px -2340px}.emojione-1f686{background-position:-1430px -2340px}.emojione-1f687{background-position:-1495px -2340px}.emojione-1f688{background-position:-1560px -2340px}.emojione-1f689{background-position:-1625px -2340px}.emojione-1f68a{background-position:-1690px -2340px}.emojione-1f68b{background-position:-1755px -2340px}.emojione-1f68c{background-position:-1820px -2340px}.emojione-1f68d{background-position:-1885px -2340px}.emojione-1f68e{background-position:-1950px -2340px}.emojione-1f68f{background-position:-2015px -2340px}.emojione-1f690{background-position:-2080px -2340px}.emojione-1f691{background-position:-2145px -2340px}.emojione-1f692{background-position:-2210px -2340px}.emojione-1f693{background-position:-2275px -2340px}.emojione-1f694{background-position:-2340px -2340px}.emojione-1f695{background-position:-2405px 0}.emojione-1f696{background-position:-2405px -65px}.emojione-1f697{background-position:-2405px -130px}.emojione-1f698{background-position:-2405px -195px}.emojione-1f699{background-position:-2405px -260px}.emojione-1f69a{background-position:-2405px -325px}.emojione-1f69b{background-position:-2405px -390px}.emojione-1f69c{background-position:-2405px -455px}.emojione-1f69d{background-position:-2405px -520px}.emojione-1f69e{background-position:-2405px -585px}.emojione-1f69f{background-position:-2405px -650px}.emojione-1f6a0{background-position:-2405px -715px}.emojione-1f6a1{background-position:-2405px -780px}.emojione-1f6a2{background-position:-2405px -845px}.emojione-1f6a3-1f3fb{background-position:-2405px -910px}.emojione-1f6a3-1f3fc{background-position:-2405px -975px}.emojione-1f6a3-1f3fd{background-position:-2405px -1040px}.emojione-1f6a3-1f3fe{background-position:-2405px -1105px}.emojione-1f6a3-1f3ff{background-position:-2405px -1170px}.emojione-1f6a3{background-position:-2405px -1235px}.emojione-1f6a4{background-position:-2405px -1300px}.emojione-1f6a5{background-position:-2405px -1365px}.emojione-1f6a6{background-position:-2405px -1430px}.emojione-1f6a7{background-position:-2405px -1495px}.emojione-1f6a8{background-position:-2405px -1560px}.emojione-1f6a9{background-position:-2405px -1625px}.emojione-1f6aa{background-position:-2405px -1690px}.emojione-1f6ab{background-position:-2405px -1755px}.emojione-1f6ac{background-position:-2405px -1820px}.emojione-1f6ad{background-position:-2405px -1885px}.emojione-1f6ae{background-position:-2405px -1950px}.emojione-1f6af{background-position:-2405px -2015px}.emojione-1f6b0{background-position:-2405px -2080px}.emojione-1f6b1{background-position:-2405px -2145px}.emojione-1f6b2{background-position:-2405px -2210px}.emojione-1f6b3{background-position:-2405px -2275px}.emojione-1f6b4-1f3fb{background-position:-2405px -2340px}.emojione-1f6b4-1f3fc{background-position:0 -2405px}.emojione-1f6b4-1f3fd{background-position:-65px -2405px}.emojione-1f6b4-1f3fe{background-position:-130px -2405px}.emojione-1f6b4-1f3ff{background-position:-195px -2405px}.emojione-1f6b4{background-position:-260px -2405px}.emojione-1f6b5-1f3fb{background-position:-325px -2405px}.emojione-1f6b5-1f3fc{background-position:-390px -2405px}.emojione-1f6b5-1f3fd{background-position:-455px -2405px}.emojione-1f6b5-1f3fe{background-position:-520px -2405px}.emojione-1f6b5-1f3ff{background-position:-585px -2405px}.emojione-1f6b5{background-position:-650px -2405px}.emojione-1f6b6-1f3fb{background-position:-715px -2405px}.emojione-1f6b6-1f3fc{background-position:-780px -2405px}.emojione-1f6b6-1f3fd{background-position:-845px -2405px}.emojione-1f6b6-1f3fe{background-position:-910px -2405px}.emojione-1f6b6-1f3ff{background-position:-975px -2405px}.emojione-1f6b6{background-position:-1040px -2405px}.emojione-1f6b7{background-position:-1105px -2405px}.emojione-1f6b8{background-position:-1170px -2405px}.emojione-1f6b9{background-position:-1235px -2405px}.emojione-1f6ba{background-position:-1300px -2405px}.emojione-1f6bb{background-position:-1365px -2405px}.emojione-1f6bc{background-position:-1430px -2405px}.emojione-1f6bd{background-position:-1495px -2405px}.emojione-1f6be{background-position:-1560px -2405px}.emojione-1f6bf{background-position:-1625px -2405px}.emojione-1f6c0-1f3fb{background-position:-1690px -2405px}.emojione-1f6c0-1f3fc{background-position:-1755px -2405px}.emojione-1f6c0-1f3fd{background-position:-1820px -2405px}.emojione-1f6c0-1f3fe{background-position:-1885px -2405px}.emojione-1f6c0-1f3ff{background-position:-1950px -2405px}.emojione-1f6c0{background-position:-2015px -2405px}.emojione-1f6c1{background-position:-2080px -2405px}.emojione-1f6c2{background-position:-2145px -2405px}.emojione-1f6c3{background-position:-2210px -2405px}.emojione-1f6c4{background-position:-2275px -2405px}.emojione-1f6c5{background-position:-2340px -2405px}.emojione-1f6cb{background-position:-2405px -2405px}.emojione-1f6cc{background-position:-2470px 0}.emojione-1f6cd{background-position:-2470px -65px}.emojione-1f6ce{background-position:-2470px -130px}.emojione-1f6cf{background-position:-2470px -195px}.emojione-1f6d0{background-position:-2470px -260px}.emojione-1f6d1{background-position:-2470px -325px}.emojione-1f6d2{background-position:-2470px -390px}.emojione-1f6e0{background-position:-2470px -455px}.emojione-1f6e1{background-position:-2470px -520px}.emojione-1f6e2{background-position:-2470px -585px}.emojione-1f6e3{background-position:-2470px -650px}.emojione-1f6e4{background-position:-2470px -715px}.emojione-1f6e5{background-position:-2470px -780px}.emojione-1f6e9{background-position:-2470px -845px}.emojione-1f6eb{background-position:-2470px -910px}.emojione-1f6ec{background-position:-2470px -975px}.emojione-1f6f0{background-position:-2470px -1040px}.emojione-1f6f3{background-position:-2470px -1105px}.emojione-1f6f4{background-position:-2470px -1170px}.emojione-1f6f5{background-position:-2470px -1235px}.emojione-1f6f6{background-position:-2470px -1300px}.emojione-1f910{background-position:-2470px -1365px}.emojione-1f911{background-position:-2470px -1430px}.emojione-1f912{background-position:-2470px -1495px}.emojione-1f913{background-position:-2470px -1560px}.emojione-1f914{background-position:-2470px -1625px}.emojione-1f915{background-position:-2470px -1690px}.emojione-1f916{background-position:-2470px -1755px}.emojione-1f917{background-position:-2470px -1820px}.emojione-1f918-1f3fb{background-position:-2470px -1885px}.emojione-1f918-1f3fc{background-position:-2470px -1950px}.emojione-1f918-1f3fd{background-position:-2470px -2015px}.emojione-1f918-1f3fe{background-position:-2470px -2080px}.emojione-1f918-1f3ff{background-position:-2470px -2145px}.emojione-1f918{background-position:-2470px -2210px}.emojione-1f919-1f3fb{background-position:-2470px -2275px}.emojione-1f919-1f3fc{background-position:-2470px -2340px}.emojione-1f919-1f3fd{background-position:-2470px -2405px}.emojione-1f919-1f3fe{background-position:0 -2470px}.emojione-1f919-1f3ff{background-position:-65px -2470px}.emojione-1f919{background-position:-130px -2470px}.emojione-1f91a-1f3fb{background-position:-195px -2470px}.emojione-1f91a-1f3fc{background-position:-260px -2470px}.emojione-1f91a-1f3fd{background-position:-325px -2470px}.emojione-1f91a-1f3fe{background-position:-390px -2470px}.emojione-1f91a-1f3ff{background-position:-455px -2470px}.emojione-1f91a{background-position:-520px -2470px}.emojione-1f91b-1f3fb{background-position:-585px -2470px}.emojione-1f91b-1f3fc{background-position:-650px -2470px}.emojione-1f91b-1f3fd{background-position:-715px -2470px}.emojione-1f91b-1f3fe{background-position:-780px -2470px}.emojione-1f91b-1f3ff{background-position:-845px -2470px}.emojione-1f91b{background-position:-910px -2470px}.emojione-1f91c-1f3fb{background-position:-975px -2470px}.emojione-1f91c-1f3fc{background-position:-1040px -2470px}.emojione-1f91c-1f3fd{background-position:-1105px -2470px}.emojione-1f91c-1f3fe{background-position:-1170px -2470px}.emojione-1f91c-1f3ff{background-position:-1235px -2470px}.emojione-1f91c{background-position:-1300px -2470px}.emojione-1f91d-1f3fb{background-position:-1365px -2470px}.emojione-1f91d-1f3fc{background-position:-1430px -2470px}.emojione-1f91d-1f3fd{background-position:-1495px -2470px}.emojione-1f91d-1f3fe{background-position:-1560px -2470px}.emojione-1f91d-1f3ff{background-position:-1625px -2470px}.emojione-1f91d{background-position:-1690px -2470px}.emojione-1f91e-1f3fb{background-position:-1755px -2470px}.emojione-1f91e-1f3fc{background-position:-1820px -2470px}.emojione-1f91e-1f3fd{background-position:-1885px -2470px}.emojione-1f91e-1f3fe{background-position:-1950px -2470px}.emojione-1f91e-1f3ff{background-position:-2015px -2470px}.emojione-1f91e{background-position:-2080px -2470px}.emojione-1f920{background-position:-2145px -2470px}.emojione-1f921{background-position:-2210px -2470px}.emojione-1f922{background-position:-2275px -2470px}.emojione-1f923{background-position:-2340px -2470px}.emojione-1f924{background-position:-2405px -2470px}.emojione-1f925{background-position:-2470px -2470px}.emojione-1f926-1f3fb{background-position:-2535px 0}.emojione-1f926-1f3fc{background-position:-2535px -65px}.emojione-1f926-1f3fd{background-position:-2535px -130px}.emojione-1f926-1f3fe{background-position:-2535px -195px}.emojione-1f926-1f3ff{background-position:-2535px -260px}.emojione-1f926{background-position:-2535px -325px}.emojione-1f927{background-position:-2535px -390px}.emojione-1f930-1f3fb{background-position:-2535px -455px}.emojione-1f930-1f3fc{background-position:-2535px -520px}.emojione-1f930-1f3fd{background-position:-2535px -585px}.emojione-1f930-1f3fe{background-position:-2535px -650px}.emojione-1f930-1f3ff{background-position:-2535px -715px}.emojione-1f930{background-position:-2535px -780px}.emojione-1f933-1f3fb{background-position:-2535px -845px}.emojione-1f933-1f3fc{background-position:-2535px -910px}.emojione-1f933-1f3fd{background-position:-2535px -975px}.emojione-1f933-1f3fe{background-position:-2535px -1040px}.emojione-1f933-1f3ff{background-position:-2535px -1105px}.emojione-1f933{background-position:-2535px -1170px}.emojione-1f934-1f3fb{background-position:-2535px -1235px}.emojione-1f934-1f3fc{background-position:-2535px -1300px}.emojione-1f934-1f3fd{background-position:-2535px -1365px}.emojione-1f934-1f3fe{background-position:-2535px -1430px}.emojione-1f934-1f3ff{background-position:-2535px -1495px}.emojione-1f934{background-position:-2535px -1560px}.emojione-1f935-1f3fb{background-position:-2535px -1625px}.emojione-1f935-1f3fc{background-position:-2535px -1690px}.emojione-1f935-1f3fd{background-position:-2535px -1755px}.emojione-1f935-1f3fe{background-position:-2535px -1820px}.emojione-1f935-1f3ff{background-position:-2535px -1885px}.emojione-1f935{background-position:-2535px -1950px}.emojione-1f936-1f3fb{background-position:-2535px -2015px}.emojione-1f936-1f3fc{background-position:-2535px -2080px}.emojione-1f936-1f3fd{background-position:-2535px -2145px}.emojione-1f936-1f3fe{background-position:-2535px -2210px}.emojione-1f936-1f3ff{background-position:-2535px -2275px}.emojione-1f936{background-position:-2535px -2340px}.emojione-1f937-1f3fb{background-position:-2535px -2405px}.emojione-1f937-1f3fc{background-position:-2535px -2470px}.emojione-1f937-1f3fd{background-position:0 -2535px}.emojione-1f937-1f3fe{background-position:-65px -2535px}.emojione-1f937-1f3ff{background-position:-130px -2535px}.emojione-1f937{background-position:-195px -2535px}.emojione-1f938-1f3fb{background-position:-260px -2535px}.emojione-1f938-1f3fc{background-position:-325px -2535px}.emojione-1f938-1f3fd{background-position:-390px -2535px}.emojione-1f938-1f3fe{background-position:-455px -2535px}.emojione-1f938-1f3ff{background-position:-520px -2535px}.emojione-1f938{background-position:-585px -2535px}.emojione-1f939-1f3fb{background-position:-650px -2535px}.emojione-1f939-1f3fc{background-position:-715px -2535px}.emojione-1f939-1f3fd{background-position:-780px -2535px}.emojione-1f939-1f3fe{background-position:-845px -2535px}.emojione-1f939-1f3ff{background-position:-910px -2535px}.emojione-1f939{background-position:-975px -2535px}.emojione-1f93a{background-position:-1040px -2535px}.emojione-1f93c-1f3fb{background-position:-1105px -2535px}.emojione-1f93c-1f3fc{background-position:-1170px -2535px}.emojione-1f93c-1f3fd{background-position:-1235px -2535px}.emojione-1f93c-1f3fe{background-position:-1300px -2535px}.emojione-1f93c-1f3ff{background-position:-1365px -2535px}.emojione-1f93c{background-position:-1430px -2535px}.emojione-1f93d-1f3fb{background-position:-1495px -2535px}.emojione-1f93d-1f3fc{background-position:-1560px -2535px}.emojione-1f93d-1f3fd{background-position:-1625px -2535px}.emojione-1f93d-1f3fe{background-position:-1690px -2535px}.emojione-1f93d-1f3ff{background-position:-1755px -2535px}.emojione-1f93d{background-position:-1820px -2535px}.emojione-1f93e-1f3fb{background-position:-1885px -2535px}.emojione-1f93e-1f3fc{background-position:-1950px -2535px}.emojione-1f93e-1f3fd{background-position:-2015px -2535px}.emojione-1f93e-1f3fe{background-position:-2080px -2535px}.emojione-1f93e-1f3ff{background-position:-2145px -2535px}.emojione-1f93e{background-position:-2210px -2535px}.emojione-1f940{background-position:-2275px -2535px}.emojione-1f941{background-position:-2340px -2535px}.emojione-1f942{background-position:-2405px -2535px}.emojione-1f943{background-position:-2470px -2535px}.emojione-1f944{background-position:-2535px -2535px}.emojione-1f945{background-position:-2600px 0}.emojione-1f947{background-position:-2600px -65px}.emojione-1f948{background-position:-2600px -130px}.emojione-1f949{background-position:-2600px -195px}.emojione-1f94a{background-position:-2600px -260px}.emojione-1f94b{background-position:-2600px -325px}.emojione-1f950{background-position:-2600px -390px}.emojione-1f951{background-position:-2600px -455px}.emojione-1f952{background-position:-2600px -520px}.emojione-1f953{background-position:-2600px -585px}.emojione-1f954{background-position:-2600px -650px}.emojione-1f955{background-position:-2600px -715px}.emojione-1f956{background-position:-2600px -780px}.emojione-1f957{background-position:-2600px -845px}.emojione-1f958{background-position:-2600px -910px}.emojione-1f959{background-position:-2600px -975px}.emojione-1f95a{background-position:-2600px -1040px}.emojione-1f95b{background-position:-2600px -1105px}.emojione-1f95c{background-position:-2600px -1170px}.emojione-1f95d{background-position:-2600px -1235px}.emojione-1f95e{background-position:-2600px -1300px}.emojione-1f980{background-position:-2600px -1365px}.emojione-1f981{background-position:-2600px -1430px}.emojione-1f982{background-position:-2600px -1495px}.emojione-1f983{background-position:-2600px -1560px}.emojione-1f984{background-position:-2600px -1625px}.emojione-1f985{background-position:-2600px -1690px}.emojione-1f986{background-position:-2600px -1755px}.emojione-1f987{background-position:-2600px -1820px}.emojione-1f988{background-position:-2600px -1885px}.emojione-1f989{background-position:-2600px -1950px}.emojione-1f98a{background-position:-2600px -2015px}.emojione-1f98b{background-position:-2600px -2080px}.emojione-1f98c{background-position:-2600px -2145px}.emojione-1f98d{background-position:-2600px -2210px}.emojione-1f98e{background-position:-2600px -2275px}.emojione-1f98f{background-position:-2600px -2340px}.emojione-1f990{background-position:-2600px -2405px}.emojione-1f991{background-position:-2600px -2470px}.emojione-1f9c0{background-position:-2600px -2535px}.emojione-203c{background-position:0 -2600px}.emojione-2049{background-position:-65px -2600px}.emojione-2122{background-position:-130px -2600px}.emojione-2139{background-position:-195px -2600px}.emojione-2194{background-position:-260px -2600px}.emojione-2195{background-position:-325px -2600px}.emojione-2196{background-position:-390px -2600px}.emojione-2197{background-position:-455px -2600px}.emojione-2198{background-position:-520px -2600px}.emojione-2199{background-position:-585px -2600px}.emojione-21a9{background-position:-650px -2600px}.emojione-21aa{background-position:-715px -2600px}.emojione-231a{background-position:-780px -2600px}.emojione-231b{background-position:-845px -2600px}.emojione-2328{background-position:-910px -2600px}.emojione-23cf{background-position:-975px -2600px}.emojione-23e9{background-position:-1040px -2600px}.emojione-23ea{background-position:-1105px -2600px}.emojione-23eb{background-position:-1170px -2600px}.emojione-23ec{background-position:-1235px -2600px}.emojione-23ed{background-position:-1300px -2600px}.emojione-23ee{background-position:-1365px -2600px}.emojione-23ef{background-position:-1430px -2600px}.emojione-23f0{background-position:-1495px -2600px}.emojione-23f1{background-position:-1560px -2600px}.emojione-23f2{background-position:-1625px -2600px}.emojione-23f3{background-position:-1690px -2600px}.emojione-23f8{background-position:-1755px -2600px}.emojione-23f9{background-position:-1820px -2600px}.emojione-23fa{background-position:-1885px -2600px}.emojione-24c2{background-position:-1950px -2600px}.emojione-25aa{background-position:-2015px -2600px}.emojione-25ab{background-position:-2080px -2600px}.emojione-25b6{background-position:-2145px -2600px}.emojione-25c0{background-position:-2210px -2600px}.emojione-25fb{background-position:-2275px -2600px}.emojione-25fc{background-position:-2340px -2600px}.emojione-25fd{background-position:-2405px -2600px}.emojione-25fe{background-position:-2470px -2600px}.emojione-2600{background-position:-2535px -2600px}.emojione-2601{background-position:-2600px -2600px}.emojione-2602{background-position:-2665px 0}.emojione-2603{background-position:-2665px -65px}.emojione-2604{background-position:-2665px -130px}.emojione-260e{background-position:-2665px -195px}.emojione-2611{background-position:-2665px -260px}.emojione-2614{background-position:-2665px -325px}.emojione-2615{background-position:-2665px -390px}.emojione-2618{background-position:-2665px -455px}.emojione-261d-1f3fb{background-position:-2665px -520px}.emojione-261d-1f3fc{background-position:-2665px -585px}.emojione-261d-1f3fd{background-position:-2665px -650px}.emojione-261d-1f3fe{background-position:-2665px -715px}.emojione-261d-1f3ff{background-position:-2665px -780px}.emojione-261d{background-position:-2665px -845px}.emojione-2620{background-position:-2665px -910px}.emojione-2622{background-position:-2665px -975px}.emojione-2623{background-position:-2665px -1040px}.emojione-2626{background-position:-2665px -1105px}.emojione-262a{background-position:-2665px -1170px}.emojione-262e{background-position:-2665px -1235px}.emojione-262f{background-position:-2665px -1300px}.emojione-2638{background-position:-2665px -1365px}.emojione-2639{background-position:-2665px -1430px}.emojione-263a{background-position:-2665px -1495px}.emojione-2648{background-position:-2665px -1560px}.emojione-2649{background-position:-2665px -1625px}.emojione-264a{background-position:-2665px -1690px}.emojione-264b{background-position:-2665px -1755px}.emojione-264c{background-position:-2665px -1820px}.emojione-264d{background-position:-2665px -1885px}.emojione-264e{background-position:-2665px -1950px}.emojione-264f{background-position:-2665px -2015px}.emojione-2650{background-position:-2665px -2080px}.emojione-2651{background-position:-2665px -2145px}.emojione-2652{background-position:-2665px -2210px}.emojione-2653{background-position:-2665px -2275px}.emojione-2660{background-position:-2665px -2340px}.emojione-2663{background-position:-2665px -2405px}.emojione-2665{background-position:-2665px -2470px}.emojione-2666{background-position:-2665px -2535px}.emojione-2668{background-position:-2665px -2600px}.emojione-267b{background-position:0 -2665px}.emojione-267f{background-position:-65px -2665px}.emojione-2692{background-position:-130px -2665px}.emojione-2693{background-position:-195px -2665px}.emojione-2694{background-position:-260px -2665px}.emojione-2696{background-position:-325px -2665px}.emojione-2697{background-position:-390px -2665px}.emojione-2699{background-position:-455px -2665px}.emojione-269b{background-position:-520px -2665px}.emojione-269c{background-position:-585px -2665px}.emojione-26a0{background-position:-650px -2665px}.emojione-26a1{background-position:-715px -2665px}.emojione-26aa{background-position:-780px -2665px}.emojione-26ab{background-position:-845px -2665px}.emojione-26b0{background-position:-910px -2665px}.emojione-26b1{background-position:-975px -2665px}.emojione-26bd{background-position:-1040px -2665px}.emojione-26be{background-position:-1105px -2665px}.emojione-26c4{background-position:-1170px -2665px}.emojione-26c5{background-position:-1235px -2665px}.emojione-26c8{background-position:-1300px -2665px}.emojione-26ce{background-position:-1365px -2665px}.emojione-26cf{background-position:-1430px -2665px}.emojione-26d1{background-position:-1495px -2665px}.emojione-26d3{background-position:-1560px -2665px}.emojione-26d4{background-position:-1625px -2665px}.emojione-26e9{background-position:-1690px -2665px}.emojione-26ea{background-position:-1755px -2665px}.emojione-26f0{background-position:-1820px -2665px}.emojione-26f1{background-position:-1885px -2665px}.emojione-26f2{background-position:-1950px -2665px}.emojione-26f3{background-position:-2015px -2665px}.emojione-26f4{background-position:-2080px -2665px}.emojione-26f5{background-position:-2145px -2665px}.emojione-26f7{background-position:-2210px -2665px}.emojione-26f8{background-position:-2275px -2665px}.emojione-26f9-1f3fb{background-position:-2340px -2665px}.emojione-26f9-1f3fc{background-position:-2405px -2665px}.emojione-26f9-1f3fd{background-position:-2470px -2665px}.emojione-26f9-1f3fe{background-position:-2535px -2665px}.emojione-26f9-1f3ff{background-position:-2600px -2665px}.emojione-26f9{background-position:-2665px -2665px}.emojione-26fa{background-position:-2730px 0}.emojione-26fd{background-position:-2730px -65px}.emojione-2702{background-position:-2730px -130px}.emojione-2705{background-position:-2730px -195px}.emojione-2708{background-position:-2730px -260px}.emojione-2709{background-position:-2730px -325px}.emojione-270a-1f3fb{background-position:-2730px -390px}.emojione-270a-1f3fc{background-position:-2730px -455px}.emojione-270a-1f3fd{background-position:-2730px -520px}.emojione-270a-1f3fe{background-position:-2730px -585px}.emojione-270a-1f3ff{background-position:-2730px -650px}.emojione-270a{background-position:-2730px -715px}.emojione-270b-1f3fb{background-position:-2730px -780px}.emojione-270b-1f3fc{background-position:-2730px -845px}.emojione-270b-1f3fd{background-position:-2730px -910px}.emojione-270b-1f3fe{background-position:-2730px -975px}.emojione-270b-1f3ff{background-position:-2730px -1040px}.emojione-270b{background-position:-2730px -1105px}.emojione-270c-1f3fb{background-position:-2730px -1170px}.emojione-270c-1f3fc{background-position:-2730px -1235px}.emojione-270c-1f3fd{background-position:-2730px -1300px}.emojione-270c-1f3fe{background-position:-2730px -1365px}.emojione-270c-1f3ff{background-position:-2730px -1430px}.emojione-270c{background-position:-2730px -1495px}.emojione-270d-1f3fb{background-position:-2730px -1560px}.emojione-270d-1f3fc{background-position:-2730px -1625px}.emojione-270d-1f3fd{background-position:-2730px -1690px}.emojione-270d-1f3fe{background-position:-2730px -1755px}.emojione-270d-1f3ff{background-position:-2730px -1820px}.emojione-270d{background-position:-2730px -1885px}.emojione-270f{background-position:-2730px -1950px}.emojione-2712{background-position:-2730px -2015px}.emojione-2714{background-position:-2730px -2080px}.emojione-2716{background-position:-2730px -2145px}.emojione-271d{background-position:-2730px -2210px}.emojione-2721{background-position:-2730px -2275px}.emojione-2728{background-position:-2730px -2340px}.emojione-2733{background-position:-2730px -2405px}.emojione-2734{background-position:-2730px -2470px}.emojione-2744{background-position:-2730px -2535px}.emojione-2747{background-position:-2730px -2600px}.emojione-274c{background-position:-2730px -2665px}.emojione-274e{background-position:0 -2730px}.emojione-2753{background-position:-65px -2730px}.emojione-2754{background-position:-130px -2730px}.emojione-2755{background-position:-195px -2730px}.emojione-2757{background-position:-260px -2730px}.emojione-2763{background-position:-325px -2730px}.emojione-2764{background-position:-390px -2730px}.emojione-2795{background-position:-455px -2730px}.emojione-2796{background-position:-520px -2730px}.emojione-2797{background-position:-585px -2730px}.emojione-27a1{background-position:-650px -2730px}.emojione-27b0{background-position:-715px -2730px}.emojione-27bf{background-position:-780px -2730px}.emojione-2934{background-position:-845px -2730px}.emojione-2935{background-position:-910px -2730px}.emojione-2b05{background-position:-975px -2730px}.emojione-2b06{background-position:-1040px -2730px}.emojione-2b07{background-position:-1105px -2730px}.emojione-2b1b{background-position:-1170px -2730px}.emojione-2b1c{background-position:-1235px -2730px}.emojione-2b50{background-position:-1300px -2730px}.emojione-2b55{background-position:-1365px -2730px}.emojione-3030{background-position:-1430px -2730px}.emojione-303d{background-position:-1495px -2730px}.emojione-3297{background-position:-1560px -2730px}.emojione-3299{background-position:-1625px -2730px} \ No newline at end of file diff --git a/pagure/static/emoji/emojione.sprites-2.2.6.png b/pagure/static/emoji/emojione.sprites-2.2.6.png new file mode 100644 index 0000000..c80cded Binary files /dev/null and b/pagure/static/emoji/emojione.sprites-2.2.6.png differ diff --git a/pagure/static/emoji/emojione.sprites.css b/pagure/static/emoji/emojione.sprites.css deleted file mode 100755 index bc53f87..0000000 --- a/pagure/static/emoji/emojione.sprites.css +++ /dev/null @@ -1,72 +0,0 @@ -[class*=emojione-]{text-indent:-9999em;image-rendering:optimizeQuality;font-size:inherit;height:1.3em;width:1.3em;top:-3px;position:relative;display:inline-block;margin:0 .15em;line-height:normal;vertical-align:middle;background-image:url("emojione.sprites.png");background-size:3300%;background-repeat:no-repeat}.emojione-0023-20E3{background-position:3.125% 0%}.emojione-0030-20E3{background-position:21.875% 64.51613%}.emojione-0031-20E3{background-position:0% 3.22581%}.emojione-0032-20E3{background-position:3.125% 3.22581%}.emojione-0033-20E3{background-position:6.25% 0%}.emojione-0034-20E3{background-position:6.25% 3.22581%}.emojione-0035-20E3{background-position:0% 6.45161%}.emojione-0036-20E3{background-position:3.125% 6.45161%}.emojione-0037-20E3{background-position:6.25% 6.45161%}.emojione-0038-20E3{background-position:9.375% 0%}.emojione-0039-20E3{background-position:9.375% 3.22581%}.emojione-00A9{background-position:9.375% 6.45161%}.emojione-00AE{background-position:0% 9.67742%}.emojione-1F004{background-position:3.125% 9.67742%}.emojione-1F0CF{background-position:6.25% 9.67742%}.emojione-1F170{background-position:9.375% 9.67742%}.emojione-1F171{background-position:12.5% 0%}.emojione-1F17E{background-position:12.5% 3.22581%}.emojione-1F17F{background-position:12.5% 6.45161%}.emojione-1F18E{background-position:12.5% 9.67742%}.emojione-1F191{background-position:0% 12.90323%}.emojione-1F192{background-position:3.125% 12.90323%}.emojione-1F193{background-position:6.25% 12.90323%}.emojione-1F194{background-position:9.375% 12.90323%}.emojione-1F195{background-position:12.5% 12.90323%}.emojione-1F196{background-position:15.625% 0%}.emojione-1F197{background-position:15.625% 3.22581%}.emojione-1F198{background-position:15.625% 6.45161%}.emojione-1F199{background-position:15.625% 9.67742%}.emojione-1F19A{background-position:15.625% 12.90323%}.emojione-1F1E6-1F1E8{background-position:0% 16.12903%}.emojione-1F1E6-1F1E9{background-position:3.125% 16.12903%}.emojione-1F1E6-1F1EA{background-position:6.25% 16.12903%}.emojione-1F1E6-1F1EB{background-position:9.375% 16.12903%}.emojione-1F1E6-1F1EC{background-position:12.5% 16.12903%}.emojione-1F1E6-1F1EE{background-position:15.625% 16.12903%}.emojione-1F1E6-1F1F1{background-position:18.75% 0%}.emojione-1F1E6-1F1F2{background-position:18.75% 3.22581%}.emojione-1F1E6-1F1F4{background-position:18.75% 6.45161%}.emojione-1F1E6-1F1F7{background-position:18.75% 9.67742%}.emojione-1F1E6-1F1F9{background-position:18.75% 12.90323%}.emojione-1F1E6-1F1FA{background-position:18.75% 16.12903%}.emojione-1F1E6-1F1FC{background-position:0% 19.35484%}.emojione-1F1E6-1F1FF{background-position:3.125% 19.35484%}.emojione-1F1E7-1F1E6{background-position:6.25% 19.35484%}.emojione-1F1E7-1F1E7{background-position:9.375% 19.35484%}.emojione-1F1E7-1F1E9{background-position:12.5% 19.35484%}.emojione-1F1E7-1F1EA{background-position:15.625% 19.35484%}.emojione-1F1E7-1F1EB{background-position:18.75% 19.35484%}.emojione-1F1E7-1F1EC{background-position:21.875% 0%}.emojione-1F1E7-1F1ED{background-position:21.875% 3.22581%}.emojione-1F1E7-1F1EE{background-position:21.875% 6.45161%}.emojione-1F1E7-1F1EF{background-position:21.875% 9.67742%}.emojione-1F1E7-1F1F2{background-position:21.875% 12.90323%}.emojione-1F1E7-1F1F3{background-position:21.875% 16.12903%}.emojione-1F1E7-1F1F4{background-position:21.875% 19.35484%}.emojione-1F1E7-1F1F7{background-position:0% 22.58065%}.emojione-1F1E7-1F1F8{background-position:3.125% 22.58065%}.emojione-1F1E7-1F1F9{background-position:6.25% 22.58065%}.emojione-1F1E7-1F1FC{background-position:9.375% 22.58065%}.emojione-1F1E7-1F1FE{background-position:12.5% 22.58065%}.emojione-1F1E7-1F1FF{background-position:15.625% 22.58065%}.emojione-1F1E8-1F1E6{background-position:18.75% 22.58065%}.emojione-1F1E8-1F1E9{background-position:21.875% 22.58065%}.emojione-1F1E8-1F1EB{background-position:25% 0%}.emojione-1F1E8-1F1EC{background-position:25% 3.22581%}.emojione-1F1E8-1F1ED{background-position:25% 6.45161%}.emojione-1F1E8-1F1EE{background-position:25% 9.67742%}.emojione-1F1E8-1F1F1{background-position:25% 12.90323%}.emojione-1F1E8-1F1F2{background-position:25% 16.12903%}.emojione-1F1E8-1F1F3{background-position:25% 19.35484%}.emojione-1F1E8-1F1F4{background-position:25% 22.58065%}.emojione-1F1E8-1F1F7{background-position:0% 25.80645%}.emojione-1F1E8-1F1FA{background-position:3.125% 25.80645%}.emojione-1F1E8-1F1FB{background-position:6.25% 25.80645%}.emojione-1F1E8-1F1FE{background-position:9.375% 25.80645%}.emojione-1F1E8-1F1FF{background-position:12.5% 25.80645%}.emojione-1F1E9-1F1EA{background-position:15.625% 25.80645%}.emojione-1F1E9-1F1EF{background-position:18.75% 25.80645%}.emojione-1F1E9-1F1F0{background-position:21.875% 25.80645%}.emojione-1F1E9-1F1F2{background-position:25% 25.80645%}.emojione-1F1E9-1F1F4{background-position:28.125% 0%}.emojione-1F1E9-1F1FF{background-position:28.125% 3.22581%}.emojione-1F1EA-1F1E8{background-position:28.125% 6.45161%}.emojione-1F1EA-1F1EA{background-position:28.125% 9.67742%}.emojione-1F1EA-1F1EC{background-position:28.125% 12.90323%}.emojione-1F1EA-1F1ED{background-position:28.125% 16.12903%}.emojione-1F1EA-1F1F7{background-position:28.125% 19.35484%}.emojione-1F1EA-1F1F8{background-position:28.125% 22.58065%}.emojione-1F1EA-1F1F9{background-position:28.125% 25.80645%}.emojione-1F1EB-1F1EE{background-position:0% 29.03226%}.emojione-1F1EB-1F1EF{background-position:3.125% 29.03226%}.emojione-1F1EB-1F1F0{background-position:6.25% 29.03226%}.emojione-1F1EB-1F1F2{background-position:9.375% 29.03226%}.emojione-1F1EB-1F1F4{background-position:12.5% 29.03226%}.emojione-1F1EB-1F1F7{background-position:15.625% 29.03226%}.emojione-1F1EC-1F1E6{background-position:18.75% 29.03226%}.emojione-1F1EC-1F1E7{background-position:21.875% 29.03226%}.emojione-1F1EC-1F1E9{background-position:25% 29.03226%}.emojione-1F1EC-1F1EA{background-position:28.125% 29.03226%}.emojione-1F1EC-1F1ED{background-position:31.25% 0%}.emojione-1F1EC-1F1EE{background-position:31.25% 3.22581%}.emojione-1F1EC-1F1F1{background-position:31.25% 6.45161%}.emojione-1F1EC-1F1F2{background-position:31.25% 9.67742%}.emojione-1F1EC-1F1F3{background-position:31.25% 12.90323%}.emojione-1F1EC-1F1F6{background-position:31.25% 16.12903%}.emojione-1F1EC-1F1F7{background-position:31.25% 19.35484%}.emojione-1F1EC-1F1F9{background-position:31.25% 22.58065%}.emojione-1F1EC-1F1FA{background-position:31.25% 25.80645%}.emojione-1F1EC-1F1FC{background-position:31.25% 29.03226%}.emojione-1F1EC-1F1FE{background-position:0% 32.25806%}.emojione-1F1ED-1F1F0{background-position:3.125% 32.25806%}.emojione-1F1ED-1F1F3{background-position:6.25% 32.25806%}.emojione-1F1ED-1F1F7{background-position:9.375% 32.25806%}.emojione-1F1ED-1F1F9{background-position:12.5% 32.25806%}.emojione-1F1ED-1F1FA{background-position:15.625% 32.25806%}.emojione-1F1EE-1F1E9{background-position:18.75% 32.25806%}.emojione-1F1EE-1F1EA{background-position:21.875% 32.25806%}.emojione-1F1EE-1F1F1{background-position:25% 32.25806%}.emojione-1F1EE-1F1F3{background-position:28.125% 32.25806%}.emojione-1F1EE-1F1F6{background-position:31.25% 32.25806%}.emojione-1F1EE-1F1F7{background-position:34.375% 0%}.emojione-1F1EE-1F1F8{background-position:34.375% 3.22581%}.emojione-1F1EE-1F1F9{background-position:34.375% 6.45161%}.emojione-1F1EF-1F1EA{background-position:34.375% 9.67742%}.emojione-1F1EF-1F1F2{background-position:34.375% 12.90323%}.emojione-1F1EF-1F1F4{background-position:34.375% 16.12903%}.emojione-1F1EF-1F1F5{background-position:34.375% 19.35484%}.emojione-1F1F0-1F1EA{background-position:34.375% 22.58065%}.emojione-1F1F0-1F1EC{background-position:34.375% 25.80645%}.emojione-1F1F0-1F1ED{background-position:34.375% 29.03226%}.emojione-1F1F0-1F1EE{background-position:34.375% 32.25806%}.emojione-1F1F0-1F1F2{background-position:0% 35.48387%}.emojione-1F1F0-1F1F3{background-position:3.125% 35.48387%}.emojione-1F1F0-1F1F5{background-position:6.25% 35.48387%}.emojione-1F1F0-1F1F7{background-position:9.375% 35.48387%}.emojione-1F1F0-1F1FC{background-position:12.5% 35.48387%}.emojione-1F1F0-1F1FE{background-position:15.625% 35.48387%}.emojione-1F1F0-1F1FF{background-position:18.75% 35.48387%}.emojione-1F1F1-1F1E6{background-position:21.875% 35.48387%}.emojione-1F1F1-1F1E7{background-position:25% 35.48387%}.emojione-1F1F1-1F1E8{background-position:28.125% 35.48387%}.emojione-1F1F1-1F1EE{background-position:31.25% 35.48387%}.emojione-1F1F1-1F1F0{background-position:34.375% 35.48387%}.emojione-1F1F1-1F1F7{background-position:37.5% 0%}.emojione-1F1F1-1F1F8{background-position:37.5% 3.22581%}.emojione-1F1F1-1F1F9{background-position:37.5% 6.45161%}.emojione-1F1F1-1F1FA{background-position:37.5% 9.67742%}.emojione-1F1F1-1F1FB{background-position:37.5% 12.90323%}.emojione-1F1F1-1F1FE{background-position:37.5% 16.12903%}.emojione-1F1F2-1F1E6{background-position:37.5% 19.35484%}.emojione-1F1F2-1F1E8{background-position:37.5% 22.58065%}.emojione-1F1F2-1F1E9{background-position:37.5% 25.80645%}.emojione-1F1F2-1F1EA{background-position:37.5% 29.03226%}.emojione-1F1F2-1F1EC{background-position:37.5% 32.25806%}.emojione-1F1F2-1F1ED{background-position:37.5% 35.48387%}.emojione-1F1F2-1F1F0{background-position:0% 38.70968%}.emojione-1F1F2-1F1F1{background-position:3.125% 38.70968%}.emojione-1F1F2-1F1F2{background-position:6.25% 38.70968%}.emojione-1F1F2-1F1F3{background-position:9.375% 38.70968%}.emojione-1F1F2-1F1F4{background-position:12.5% 38.70968%}.emojione-1F1F2-1F1F7{background-position:15.625% 38.70968%}.emojione-1F1F2-1F1F8{background-position:18.75% 38.70968%}.emojione-1F1F2-1F1F9{background-position:21.875% 38.70968%}.emojione-1F1F2-1F1FA{background-position:25% 38.70968%}.emojione-1F1F2-1F1FB{background-position:28.125% 38.70968%}.emojione-1F1F2-1F1FC{background-position:31.25% 38.70968%}.emojione-1F1F2-1F1FD{background-position:34.375% 38.70968%}.emojione-1F1F2-1F1FE{background-position:37.5% 38.70968%}.emojione-1F1F2-1F1FF{background-position:40.625% 0%}.emojione-1F1F3-1F1E6{background-position:40.625% 3.22581%}.emojione-1F1F3-1F1E8{background-position:40.625% 6.45161%}.emojione-1F1F3-1F1EA{background-position:40.625% 9.67742%}.emojione-1F1F3-1F1EC{background-position:40.625% 12.90323%}.emojione-1F1F3-1F1EE{background-position:40.625% 16.12903%}.emojione-1F1F3-1F1F1{background-position:40.625% 19.35484%}.emojione-1F1F3-1F1F4{background-position:40.625% 22.58065%}.emojione-1F1F3-1F1F5{background-position:40.625% 25.80645%}.emojione-1F1F3-1F1F7{background-position:40.625% 29.03226%}.emojione-1F1F3-1F1FA{background-position:40.625% 32.25806%}.emojione-1F1F3-1F1FF{background-position:40.625% 35.48387%}.emojione-1F1F4-1F1F2{background-position:40.625% 38.70968%}.emojione-1F1F5-1F1E6{background-position:0% 41.93548%}.emojione-1F1F5-1F1EA{background-position:3.125% 41.93548%}.emojione-1F1F5-1F1EB{background-position:6.25% 41.93548%}.emojione-1F1F5-1F1EC{background-position:9.375% 41.93548%}.emojione-1F1F5-1F1ED{background-position:12.5% 41.93548%}.emojione-1F1F5-1F1F0{background-position:15.625% 41.93548%}.emojione-1F1F5-1F1F1{background-position:18.75% 41.93548%}.emojione-1F1F5-1F1F7{background-position:21.875% 41.93548%}.emojione-1F1F5-1F1F8{background-position:25% 41.93548%}.emojione-1F1F5-1F1F9{background-position:28.125% 41.93548%}.emojione-1F1F5-1F1FC{background-position:31.25% 41.93548%}.emojione-1F1F5-1F1FE{background-position:34.375% 41.93548%}.emojione-1F1F6-1F1E6{background-position:37.5% 41.93548%}.emojione-1F1F7-1F1F4{background-position:40.625% 41.93548%}.emojione-1F1F7-1F1F8{background-position:43.75% 0%}.emojione-1F1F7-1F1FA{background-position:43.75% 3.22581%}.emojione-1F1F7-1F1FC{background-position:43.75% 6.45161%}.emojione-1F1F8-1F1E6{background-position:43.75% 9.67742%}.emojione-1F1F8-1F1E7{background-position:43.75% 12.90323%}.emojione-1F1F8-1F1E8{background-position:43.75% 16.12903%}.emojione-1F1F8-1F1E9{background-position:43.75% 19.35484%}.emojione-1F1F8-1F1EA{background-position:43.75% 22.58065%}.emojione-1F1F8-1F1EC{background-position:43.75% 25.80645%}.emojione-1F1F8-1F1ED{background-position:43.75% 29.03226%}.emojione-1F1F8-1F1EE{background-position:43.75% 32.25806%}.emojione-1F1F8-1F1F0{background-position:43.75% 35.48387%}.emojione-1F1F8-1F1F1{background-position:43.75% 38.70968%}.emojione-1F1F8-1F1F2{background-position:43.75% 41.93548%}.emojione-1F1F8-1F1F3{background-position:0% 45.16129%}.emojione-1F1F8-1F1F4{background-position:3.125% 45.16129%}.emojione-1F1F8-1F1F7{background-position:6.25% 45.16129%}.emojione-1F1F8-1F1F9{background-position:9.375% 45.16129%}.emojione-1F1F8-1F1FB{background-position:12.5% 45.16129%}.emojione-1F1F8-1F1FE{background-position:15.625% 45.16129%}.emojione-1F1F8-1F1FF{background-position:18.75% 45.16129%}.emojione-1F1F9-1F1E9{background-position:21.875% 45.16129%}.emojione-1F1F9-1F1EC{background-position:25% 45.16129%}.emojione-1F1F9-1F1ED{background-position:28.125% 45.16129%}.emojione-1F1F9-1F1EF{background-position:31.25% 45.16129%}.emojione-1F1F9-1F1F1{background-position:34.375% 45.16129%}.emojione-1F1F9-1F1F2{background-position:37.5% 45.16129%}.emojione-1F1F9-1F1F3{background-position:40.625% 45.16129%}.emojione-1F1F9-1F1F4{background-position:43.75% 45.16129%}.emojione-1F1F9-1F1F7{background-position:46.875% 0%}.emojione-1F1F9-1F1F9{background-position:46.875% 3.22581%}.emojione-1F1F9-1F1FB{background-position:46.875% 6.45161%}.emojione-1F1F9-1F1FC{background-position:46.875% 9.67742%}.emojione-1F1F9-1F1FF{background-position:46.875% 12.90323%}.emojione-1F1FA-1F1E6{background-position:46.875% 16.12903%}.emojione-1F1FA-1F1EC{background-position:46.875% 19.35484%}.emojione-1F1FA-1F1F8{background-position:46.875% 22.58065%}.emojione-1F1FA-1F1FE{background-position:46.875% 25.80645%}.emojione-1F1FA-1F1FF{background-position:46.875% 29.03226%}.emojione-1F1FB-1F1E6{background-position:46.875% 32.25806%}.emojione-1F1FB-1F1E8{background-position:46.875% 35.48387%}.emojione-1F1FB-1F1EA{background-position:46.875% 38.70968%}.emojione-1F1FB-1F1EE{background-position:46.875% 41.93548%}.emojione-1F1FB-1F1F3{background-position:46.875% 45.16129%}.emojione-1F1FB-1F1FA{background-position:0% 48.3871%}.emojione-1F1FC-1F1EB{background-position:3.125% 48.3871%}.emojione-1F1FC-1F1F8{background-position:6.25% 48.3871%}.emojione-1F1FD-1F1F0{background-position:9.375% 48.3871%}.emojione-1F1FE-1F1EA{background-position:12.5% 48.3871%}.emojione-1F1FF-1F1E6{background-position:15.625% 48.3871%}.emojione-1F1FF-1F1F2{background-position:18.75% 48.3871%}.emojione-1F1FF-1F1FC{background-position:21.875% 48.3871%}.emojione-1F201{background-position:25% 48.3871%}.emojione-1F202{background-position:28.125% 48.3871%}.emojione-1F21A{background-position:31.25% 48.3871%}.emojione-1F22F{background-position:34.375% 48.3871%}.emojione-1F232{background-position:37.5% 48.3871%}.emojione-1F233{background-position:40.625% 48.3871%}.emojione-1F234{background-position:43.75% 48.3871%}.emojione-1F235{background-position:46.875% 48.3871%}.emojione-1F236{background-position:50% 0%}.emojione-1F237{background-position:50% 3.22581%}.emojione-1F238{background-position:50% 6.45161%}.emojione-1F239{background-position:50% 9.67742%}.emojione-1F23A{background-position:50% 12.90323%}.emojione-1F250{background-position:50% 16.12903%}.emojione-1F251{background-position:50% 19.35484%}.emojione-1F300{background-position:50% 22.58065%}.emojione-1F301{background-position:50% 25.80645%}.emojione-1F302{background-position:50% 29.03226%}.emojione-1F303{background-position:50% 32.25806%}.emojione-1F304{background-position:50% 35.48387%}.emojione-1F305{background-position:50% 38.70968%}.emojione-1F306{background-position:50% 41.93548%}.emojione-1F307{background-position:50% 45.16129%}.emojione-1F308{background-position:50% 48.3871%}.emojione-1F309{background-position:0% 51.6129%}.emojione-1F30A{background-position:3.125% 51.6129%}.emojione-1F30B{background-position:6.25% 51.6129%}.emojione-1F30C{background-position:9.375% 51.6129%}.emojione-1F30D{background-position:12.5% 51.6129%}.emojione-1F30E{background-position:15.625% 51.6129%}.emojione-1F30F{background-position:18.75% 51.6129%}.emojione-1F310{background-position:21.875% 51.6129%}.emojione-1F311{background-position:25% 51.6129%}.emojione-1F312{background-position:28.125% 51.6129%}.emojione-1F313{background-position:31.25% 51.6129%}.emojione-1F314{background-position:34.375% 51.6129%}.emojione-1F315{background-position:37.5% 51.6129%}.emojione-1F316{background-position:40.625% 51.6129%}.emojione-1F317{background-position:43.75% 51.6129%}.emojione-1F318{background-position:46.875% 51.6129%}.emojione-1F319{background-position:50% 51.6129%}.emojione-1F31A{background-position:53.125% 0%}.emojione-1F31B{background-position:53.125% 3.22581%}.emojione-1F31C{background-position:53.125% 6.45161%}.emojione-1F31D{background-position:53.125% 9.67742%}.emojione-1F31E{background-position:53.125% 12.90323%}.emojione-1F31F{background-position:53.125% 16.12903%}.emojione-1F320{background-position:53.125% 19.35484%}.emojione-1F330{background-position:53.125% 22.58065%}.emojione-1F331{background-position:53.125% 25.80645%}.emojione-1F332{background-position:53.125% 29.03226%}.emojione-1F333{background-position:53.125% 32.25806%}.emojione-1F334{background-position:53.125% 35.48387%}.emojione-1F335{background-position:53.125% 38.70968%}.emojione-1F337{background-position:53.125% 41.93548%}.emojione-1F338{background-position:53.125% 45.16129%}.emojione-1F339{background-position:53.125% 48.3871%}.emojione-1F33A{background-position:53.125% 51.6129%}.emojione-1F33B{background-position:0% 54.83871%}.emojione-1F33C{background-position:3.125% 54.83871%}.emojione-1F33D{background-position:6.25% 54.83871%}.emojione-1F33E{background-position:9.375% 54.83871%}.emojione-1F33F{background-position:12.5% 54.83871%}.emojione-1F340{background-position:15.625% 54.83871%}.emojione-1F341{background-position:18.75% 54.83871%}.emojione-1F342{background-position:21.875% 54.83871%}.emojione-1F343{background-position:25% 54.83871%}.emojione-1F344{background-position:28.125% 54.83871%}.emojione-1F345{background-position:31.25% 54.83871%}.emojione-1F346{background-position:34.375% 54.83871%}.emojione-1F347{background-position:37.5% 54.83871%}.emojione-1F348{background-position:40.625% 54.83871%}.emojione-1F349{background-position:43.75% 54.83871%}.emojione-1F34A{background-position:46.875% 54.83871%}.emojione-1F34B{background-position:50% 54.83871%}.emojione-1F34C{background-position:53.125% 54.83871%}.emojione-1F34D{background-position:56.25% 0%}.emojione-1F34E{background-position:56.25% 3.22581%}.emojione-1F34F{background-position:56.25% 6.45161%}.emojione-1F350{background-position:56.25% 9.67742%}.emojione-1F351{background-position:56.25% 12.90323%}.emojione-1F352{background-position:56.25% 16.12903%}.emojione-1F353{background-position:56.25% 19.35484%}.emojione-1F354{background-position:56.25% 22.58065%}.emojione-1F355{background-position:56.25% 25.80645%}.emojione-1F356{background-position:56.25% 29.03226%}.emojione-1F357{background-position:56.25% 32.25806%}.emojione-1F358{background-position:56.25% 35.48387%}.emojione-1F359{background-position:56.25% 38.70968%}.emojione-1F35A{background-position:56.25% 41.93548%}.emojione-1F35B{background-position:56.25% 45.16129%}.emojione-1F35C{background-position:56.25% 48.3871%}.emojione-1F35D{background-position:56.25% 51.6129%}.emojione-1F35E{background-position:56.25% 54.83871%}.emojione-1F35F{background-position:0% 58.06452%}.emojione-1F360{background-position:3.125% 58.06452%}.emojione-1F361{background-position:6.25% 58.06452%}.emojione-1F362{background-position:9.375% 58.06452%}.emojione-1F363{background-position:12.5% 58.06452%}.emojione-1F364{background-position:15.625% 58.06452%}.emojione-1F365{background-position:18.75% 58.06452%}.emojione-1F366{background-position:21.875% 58.06452%}.emojione-1F367{background-position:25% 58.06452%}.emojione-1F368{background-position:28.125% 58.06452%}.emojione-1F369{background-position:31.25% 58.06452%}.emojione-1F36A{background-position:34.375% 58.06452%}.emojione-1F36B{background-position:37.5% 58.06452%}.emojione-1F36C{background-position:40.625% 58.06452%}.emojione-1F36D{background-position:43.75% 58.06452%}.emojione-1F36E{background-position:46.875% 58.06452%}.emojione-1F36F{background-position:50% 58.06452%}.emojione-1F370{background-position:53.125% 58.06452%}.emojione-1F371{background-position:56.25% 58.06452%}.emojione-1F372{background-position:59.375% 0%}.emojione-1F373{background-position:59.375% 3.22581%}.emojione-1F374{background-position:59.375% 6.45161%}.emojione-1F375{background-position:59.375% 9.67742%}.emojione-1F376{background-position:59.375% 12.90323%}.emojione-1F377{background-position:59.375% 16.12903%}.emojione-1F378{background-position:59.375% 19.35484%}.emojione-1F379{background-position:59.375% 22.58065%}.emojione-1F37A{background-position:59.375% 25.80645%}.emojione-1F37B{background-position:59.375% 29.03226%}.emojione-1F37C{background-position:59.375% 32.25806%}.emojione-1F380{background-position:59.375% 35.48387%}.emojione-1F381{background-position:59.375% 38.70968%}.emojione-1F382{background-position:59.375% 41.93548%}.emojione-1F383{background-position:59.375% 45.16129%}.emojione-1F384{background-position:59.375% 48.3871%}.emojione-1F385{background-position:59.375% 51.6129%}.emojione-1F386{background-position:59.375% 54.83871%}.emojione-1F387{background-position:59.375% 58.06452%}.emojione-1F388{background-position:0% 61.29032%}.emojione-1F389{background-position:3.125% 61.29032%}.emojione-1F38A{background-position:6.25% 61.29032%}.emojione-1F38B{background-position:9.375% 61.29032%}.emojione-1F38C{background-position:12.5% 61.29032%}.emojione-1F38D{background-position:15.625% 61.29032%}.emojione-1F38E{background-position:18.75% 61.29032%}.emojione-1F38F{background-position:21.875% 61.29032%}.emojione-1F390{background-position:25% 61.29032%}.emojione-1F391{background-position:28.125% 61.29032%}.emojione-1F392{background-position:31.25% 61.29032%}.emojione-1F393{background-position:34.375% 61.29032%}.emojione-1F3A0{background-position:37.5% 61.29032%}.emojione-1F3A1{background-position:40.625% 61.29032%}.emojione-1F3A2{background-position:43.75% 61.29032%}.emojione-1F3A3{background-position:46.875% 61.29032%}.emojione-1F3A4{background-position:50% 61.29032%}.emojione-1F3A5{background-position:53.125% 61.29032%}.emojione-1F3A6{background-position:56.25% 61.29032%}.emojione-1F3A7{background-position:59.375% 61.29032%}.emojione-1F3A8{background-position:62.5% 0%}.emojione-1F3A9{background-position:62.5% 3.22581%}.emojione-1F3AA{background-position:62.5% 6.45161%}.emojione-1F3AB{background-position:62.5% 9.67742%}.emojione-1F3AC{background-position:62.5% 12.90323%}.emojione-1F3AD{background-position:62.5% 16.12903%}.emojione-1F3AE{background-position:62.5% 19.35484%}.emojione-1F3AF{background-position:62.5% 22.58065%}.emojione-1F3B0{background-position:62.5% 25.80645%}.emojione-1F3B1{background-position:62.5% 29.03226%}.emojione-1F3B2{background-position:62.5% 32.25806%}.emojione-1F3B3{background-position:62.5% 35.48387%}.emojione-1F3B4{background-position:62.5% 38.70968%}.emojione-1F3B5{background-position:62.5% 41.93548%}.emojione-1F3B6{background-position:62.5% 45.16129%}.emojione-1F3B7{background-position:62.5% 48.3871%}.emojione-1F3B8{background-position:62.5% 51.6129%}.emojione-1F3B9{background-position:62.5% 54.83871%}.emojione-1F3BA{background-position:62.5% 58.06452%}.emojione-1F3BB{background-position:62.5% 61.29032%}.emojione-1F3BC{background-position:0% 64.51613%}.emojione-1F3BD{background-position:3.125% 64.51613%}.emojione-1F3BE{background-position:6.25% 64.51613%}.emojione-1F3BF{background-position:9.375% 64.51613%}.emojione-1F3C0{background-position:12.5% 64.51613%}.emojione-1F3C1{background-position:15.625% 64.51613%}.emojione-1F3C2{background-position:18.75% 64.51613%}.emojione-1F3C3{background-position:0% 0%}.emojione-1F3C4{background-position:25% 64.51613%}.emojione-1F3C6{background-position:28.125% 64.51613%}.emojione-1F3C7{background-position:31.25% 64.51613%}.emojione-1F3C8{background-position:34.375% 64.51613%}.emojione-1F3C9{background-position:37.5% 64.51613%}.emojione-1F3CA{background-position:40.625% 64.51613%}.emojione-1F3E0{background-position:43.75% 64.51613%}.emojione-1F3E1{background-position:46.875% 64.51613%}.emojione-1F3E2{background-position:50% 64.51613%}.emojione-1F3E3{background-position:53.125% 64.51613%}.emojione-1F3E4{background-position:56.25% 64.51613%}.emojione-1F3E5{background-position:59.375% 64.51613%}.emojione-1F3E6{background-position:62.5% 64.51613%}.emojione-1F3E7{background-position:65.625% 0%}.emojione-1F3E8{background-position:65.625% 3.22581%}.emojione-1F3E9{background-position:65.625% 6.45161%}.emojione-1F3EA{background-position:65.625% 9.67742%}.emojione-1F3EB{background-position:65.625% 12.90323%}.emojione-1F3EC{background-position:65.625% 16.12903%}.emojione-1F3ED{background-position:65.625% 19.35484%}.emojione-1F3EE{background-position:65.625% 22.58065%}.emojione-1F3EF{background-position:65.625% 25.80645%}.emojione-1F3F0{background-position:65.625% 29.03226%}.emojione-1F400{background-position:65.625% 32.25806%}.emojione-1F401{background-position:65.625% 35.48387%}.emojione-1F402{background-position:65.625% 38.70968%}.emojione-1F403{background-position:65.625% 41.93548%}.emojione-1F404{background-position:65.625% 45.16129%}.emojione-1F405{background-position:65.625% 48.3871%}.emojione-1F406{background-position:65.625% 51.6129%}.emojione-1F407{background-position:65.625% 54.83871%}.emojione-1F408{background-position:65.625% 58.06452%}.emojione-1F409{background-position:65.625% 61.29032%}.emojione-1F40A{background-position:65.625% 64.51613%}.emojione-1F40B{background-position:0% 67.74194%}.emojione-1F40C{background-position:3.125% 67.74194%}.emojione-1F40D{background-position:6.25% 67.74194%}.emojione-1F40E{background-position:9.375% 67.74194%}.emojione-1F40F{background-position:12.5% 67.74194%}.emojione-1F410{background-position:15.625% 67.74194%}.emojione-1F411{background-position:18.75% 67.74194%}.emojione-1F412{background-position:21.875% 67.74194%}.emojione-1F413{background-position:25% 67.74194%}.emojione-1F414{background-position:28.125% 67.74194%}.emojione-1F415{background-position:31.25% 67.74194%}.emojione-1F416{background-position:34.375% 67.74194%}.emojione-1F417{background-position:37.5% 67.74194%}.emojione-1F418{background-position:40.625% 67.74194%}.emojione-1F419{background-position:43.75% 67.74194%}.emojione-1F41A{background-position:46.875% 67.74194%}.emojione-1F41B{background-position:50% 67.74194%}.emojione-1F41C{background-position:53.125% 67.74194%}.emojione-1F41D{background-position:56.25% 67.74194%}.emojione-1F41E{background-position:59.375% 67.74194%}.emojione-1F41F{background-position:62.5% 67.74194%}.emojione-1F420{background-position:65.625% 67.74194%}.emojione-1F421{background-position:68.75% 0%}.emojione-1F422{background-position:68.75% 3.22581%}.emojione-1F423{background-position:68.75% 6.45161%}.emojione-1F424{background-position:68.75% 9.67742%}.emojione-1F425{background-position:68.75% 12.90323%}.emojione-1F426{background-position:68.75% 16.12903%}.emojione-1F427{background-position:68.75% 19.35484%}.emojione-1F428{background-position:68.75% 22.58065%}.emojione-1F429{background-position:68.75% 25.80645%}.emojione-1F42A{background-position:68.75% 29.03226%}.emojione-1F42B{background-position:68.75% 32.25806%}.emojione-1F42C{background-position:68.75% 35.48387%}.emojione-1F42D{background-position:68.75% 38.70968%}.emojione-1F42E{background-position:68.75% 41.93548%}.emojione-1F42F{background-position:68.75% 45.16129%}.emojione-1F430{background-position:68.75% 48.3871%}.emojione-1F431{background-position:68.75% 51.6129%}.emojione-1F432{background-position:68.75% 54.83871%}.emojione-1F433{background-position:68.75% 58.06452%}.emojione-1F434{background-position:68.75% 61.29032%}.emojione-1F435{background-position:68.75% 64.51613%}.emojione-1F436{background-position:68.75% 67.74194%}.emojione-1F437{background-position:0% 70.96774%}.emojione-1F438{background-position:3.125% 70.96774%}.emojione-1F439{background-position:6.25% 70.96774%}.emojione-1F43A{background-position:9.375% 70.96774%}.emojione-1F43B{background-position:12.5% 70.96774%}.emojione-1F43C{background-position:15.625% 70.96774%}.emojione-1F43D{background-position:18.75% 70.96774%}.emojione-1F43E{background-position:21.875% 70.96774%}.emojione-1F440{background-position:25% 70.96774%}.emojione-1F442{background-position:28.125% 70.96774%}.emojione-1F443{background-position:31.25% 70.96774%}.emojione-1F444{background-position:34.375% 70.96774%}.emojione-1F445{background-position:37.5% 70.96774%}.emojione-1F446{background-position:40.625% 70.96774%}.emojione-1F447{background-position:43.75% 70.96774%}.emojione-1F448{background-position:46.875% 70.96774%}.emojione-1F449{background-position:50% 70.96774%}.emojione-1F44A{background-position:53.125% 70.96774%}.emojione-1F44B{background-position:56.25% 70.96774%}.emojione-1F44C{background-position:59.375% 70.96774%}.emojione-1F44D{background-position:62.5% 70.96774%}.emojione-1F44E{background-position:65.625% 70.96774%}.emojione-1F44F{background-position:68.75% 70.96774%}.emojione-1F450{background-position:71.875% 0%}.emojione-1F451{background-position:71.875% 3.22581%}.emojione-1F452{background-position:71.875% 6.45161%}.emojione-1F453{background-position:71.875% 9.67742%}.emojione-1F454{background-position:71.875% 12.90323%}.emojione-1F455{background-position:71.875% 16.12903%}.emojione-1F456{background-position:71.875% 19.35484%}.emojione-1F457{background-position:71.875% 22.58065%}.emojione-1F458{background-position:71.875% 25.80645%}.emojione-1F459{background-position:71.875% 29.03226%}.emojione-1F45A{background-position:71.875% 32.25806%}.emojione-1F45B{background-position:71.875% 35.48387%}.emojione-1F45C{background-position:71.875% 38.70968%}.emojione-1F45D{background-position:71.875% 41.93548%}.emojione-1F45E{background-position:71.875% 45.16129%}.emojione-1F45F{background-position:71.875% 48.3871%}.emojione-1F460{background-position:71.875% 51.6129%}.emojione-1F461{background-position:71.875% 54.83871%}.emojione-1F462{background-position:71.875% 58.06452%}.emojione-1F463{background-position:71.875% 61.29032%}.emojione-1F464{background-position:71.875% 64.51613%}.emojione-1F465{background-position:71.875% 67.74194%}.emojione-1F466{background-position:71.875% 70.96774%}.emojione-1F467{background-position:0% 74.19355%}.emojione-1F468{background-position:3.125% 74.19355%}.emojione-1F469{background-position:6.25% 74.19355%}.emojione-1F46A{background-position:9.375% 74.19355%}.emojione-1F46B{background-position:12.5% 74.19355%}.emojione-1F46C{background-position:15.625% 74.19355%}.emojione-1F46D{background-position:18.75% 74.19355%}.emojione-1F46E{background-position:21.875% 74.19355%}.emojione-1F46F{background-position:25% 74.19355%}.emojione-1F470{background-position:28.125% 74.19355%}.emojione-1F471{background-position:31.25% 74.19355%}.emojione-1F472{background-position:34.375% 74.19355%}.emojione-1F473{background-position:37.5% 74.19355%}.emojione-1F474{background-position:40.625% 74.19355%}.emojione-1F475{background-position:43.75% 74.19355%}.emojione-1F476{background-position:46.875% 74.19355%}.emojione-1F477{background-position:50% 74.19355%}.emojione-1F478{background-position:53.125% 74.19355%}.emojione-1F479{background-position:56.25% 74.19355%}.emojione-1F47A{background-position:59.375% 74.19355%}.emojione-1F47B{background-position:62.5% 74.19355%}.emojione-1F47C{background-position:65.625% 74.19355%}.emojione-1F47D{background-position:68.75% 74.19355%}.emojione-1F47E{background-position:71.875% 74.19355%}.emojione-1F47F{background-position:75% 0%}.emojione-1F480{background-position:75% 3.22581%}.emojione-1F481{background-position:75% 6.45161%}.emojione-1F482{background-position:75% 9.67742%}.emojione-1F483{background-position:75% 12.90323%}.emojione-1F484{background-position:75% 16.12903%}.emojione-1F485{background-position:75% 19.35484%}.emojione-1F486{background-position:75% 22.58065%}.emojione-1F487{background-position:75% 25.80645%}.emojione-1F488{background-position:75% 29.03226%}.emojione-1F489{background-position:75% 32.25806%}.emojione-1F48A{background-position:75% 35.48387%}.emojione-1F48B{background-position:75% 38.70968%}.emojione-1F48C{background-position:75% 41.93548%}.emojione-1F48D{background-position:75% 45.16129%}.emojione-1F48E{background-position:75% 48.3871%}.emojione-1F48F{background-position:75% 51.6129%}.emojione-1F490{background-position:75% 54.83871%}.emojione-1F491{background-position:75% 58.06452%}.emojione-1F492{background-position:75% 61.29032%}.emojione-1F493{background-position:75% 64.51613%}.emojione-1F494{background-position:75% 67.74194%}.emojione-1F495{background-position:75% 70.96774%}.emojione-1F496{background-position:75% 74.19355%}.emojione-1F497{background-position:0% 77.41935%}.emojione-1F498{background-position:3.125% 77.41935%}.emojione-1F499{background-position:6.25% 77.41935%}.emojione-1F49A{background-position:9.375% 77.41935%}.emojione-1F49B{background-position:12.5% 77.41935%}.emojione-1F49C{background-position:15.625% 77.41935%}.emojione-1F49D{background-position:18.75% 77.41935%}.emojione-1F49E{background-position:21.875% 77.41935%}.emojione-1F49F{background-position:25% 77.41935%}.emojione-1F4A0{background-position:28.125% 77.41935%}.emojione-1F4A1{background-position:31.25% 77.41935%}.emojione-1F4A2{background-position:34.375% 77.41935%}.emojione-1F4A3{background-position:37.5% 77.41935%}.emojione-1F4A4{background-position:40.625% 77.41935%}.emojione-1F4A5{background-position:43.75% 77.41935%}.emojione-1F4A6{background-position:46.875% 77.41935%}.emojione-1F4A7{background-position:50% 77.41935%}.emojione-1F4A8{background-position:53.125% 77.41935%}.emojione-1F4A9{background-position:56.25% 77.41935%}.emojione-1F4AA{background-position:59.375% 77.41935%}.emojione-1F4AB{background-position:62.5% 77.41935%}.emojione-1F4AC{background-position:65.625% 77.41935%}.emojione-1F4AD{background-position:68.75% 77.41935%}.emojione-1F4AE{background-position:71.875% 77.41935%}.emojione-1F4AF{background-position:75% 77.41935%}.emojione-1F4B0{background-position:78.125% 0%}.emojione-1F4B1{background-position:78.125% 3.22581%}.emojione-1F4B2{background-position:78.125% 6.45161%}.emojione-1F4B3{background-position:78.125% 9.67742%}.emojione-1F4B4{background-position:78.125% 12.90323%}.emojione-1F4B5{background-position:78.125% 16.12903%}.emojione-1F4B6{background-position:78.125% 19.35484%}.emojione-1F4B7{background-position:78.125% 22.58065%}.emojione-1F4B8{background-position:78.125% 25.80645%}.emojione-1F4B9{background-position:78.125% 29.03226%}.emojione-1F4BA{background-position:78.125% 32.25806%}.emojione-1F4BB{background-position:78.125% 35.48387%}.emojione-1F4BC{background-position:78.125% 38.70968%}.emojione-1F4BD{background-position:78.125% 41.93548%}.emojione-1F4BE{background-position:78.125% 45.16129%}.emojione-1F4BF{background-position:78.125% 48.3871%}.emojione-1F4C0{background-position:78.125% 51.6129%}.emojione-1F4C1{background-position:78.125% 54.83871%}.emojione-1F4C2{background-position:78.125% 58.06452%}.emojione-1F4C3{background-position:78.125% 61.29032%}.emojione-1F4C4{background-position:78.125% 64.51613%}.emojione-1F4C5{background-position:78.125% 67.74194%}.emojione-1F4C6{background-position:78.125% 70.96774%}.emojione-1F4C7{background-position:78.125% 74.19355%}.emojione-1F4C8{background-position:78.125% 77.41935%}.emojione-1F4C9{background-position:0% 80.64516%}.emojione-1F4CA{background-position:3.125% 80.64516%}.emojione-1F4CB{background-position:6.25% 80.64516%}.emojione-1F4CC{background-position:9.375% 80.64516%}.emojione-1F4CD{background-position:12.5% 80.64516%}.emojione-1F4CE{background-position:15.625% 80.64516%}.emojione-1F4CF{background-position:18.75% 80.64516%}.emojione-1F4D0{background-position:21.875% 80.64516%}.emojione-1F4D1{background-position:25% 80.64516%}.emojione-1F4D2{background-position:28.125% 80.64516%}.emojione-1F4D3{background-position:31.25% 80.64516%}.emojione-1F4D4{background-position:34.375% 80.64516%}.emojione-1F4D5{background-position:37.5% 80.64516%}.emojione-1F4D6{background-position:40.625% 80.64516%}.emojione-1F4D7{background-position:43.75% 80.64516%}.emojione-1F4D8{background-position:46.875% 80.64516%}.emojione-1F4D9{background-position:50% 80.64516%}.emojione-1F4DA{background-position:53.125% 80.64516%}.emojione-1F4DB{background-position:56.25% 80.64516%}.emojione-1F4DC{background-position:59.375% 80.64516%}.emojione-1F4DD{background-position:62.5% 80.64516%}.emojione-1F4DE{background-position:65.625% 80.64516%}.emojione-1F4DF{background-position:68.75% 80.64516%}.emojione-1F4E0{background-position:71.875% 80.64516%}.emojione-1F4E1{background-position:75% 80.64516%}.emojione-1F4E2{background-position:78.125% 80.64516%}.emojione-1F4E3{background-position:81.25% 0%}.emojione-1F4E4{background-position:81.25% 3.22581%}.emojione-1F4E5{background-position:81.25% 6.45161%}.emojione-1F4E6{background-position:81.25% 9.67742%}.emojione-1F4E7{background-position:81.25% 12.90323%}.emojione-1F4E8{background-position:81.25% 16.12903%}.emojione-1F4E9{background-position:81.25% 19.35484%}.emojione-1F4EA{background-position:81.25% 22.58065%}.emojione-1F4EB{background-position:81.25% 25.80645%}.emojione-1F4EC{background-position:81.25% 29.03226%}.emojione-1F4ED{background-position:81.25% 32.25806%}.emojione-1F4EE{background-position:81.25% 35.48387%}.emojione-1F4EF{background-position:81.25% 38.70968%}.emojione-1F4F0{background-position:81.25% 41.93548%}.emojione-1F4F1{background-position:81.25% 45.16129%}.emojione-1F4F2{background-position:81.25% 48.3871%}.emojione-1F4F3{background-position:81.25% 51.6129%}.emojione-1F4F4{background-position:81.25% 54.83871%}.emojione-1F4F5{background-position:81.25% 58.06452%}.emojione-1F4F6{background-position:81.25% 61.29032%}.emojione-1F4F7{background-position:81.25% 64.51613%}.emojione-1F4F9{background-position:81.25% 67.74194%}.emojione-1F4FA{background-position:81.25% 70.96774%}.emojione-1F4FB{background-position:81.25% 74.19355%}.emojione-1F4FC{background-position:81.25% 77.41935%}.emojione-1F500{background-position:81.25% 80.64516%}.emojione-1F501{background-position:0% 83.87097%}.emojione-1F502{background-position:3.125% 83.87097%}.emojione-1F503{background-position:6.25% 83.87097%}.emojione-1F504{background-position:9.375% 83.87097%}.emojione-1F505{background-position:12.5% 83.87097%}.emojione-1F506{background-position:15.625% 83.87097%}.emojione-1F507{background-position:18.75% 83.87097%}.emojione-1F508{background-position:21.875% 83.87097%}.emojione-1F509{background-position:25% 83.87097%}.emojione-1F50A{background-position:28.125% 83.87097%}.emojione-1F50B{background-position:31.25% 83.87097%}.emojione-1F50C{background-position:34.375% 83.87097%}.emojione-1F50D{background-position:37.5% 83.87097%}.emojione-1F50E{background-position:40.625% 83.87097%}.emojione-1F50F{background-position:43.75% 83.87097%}.emojione-1F510{background-position:46.875% 83.87097%}.emojione-1F511{background-position:50% 83.87097%}.emojione-1F512{background-position:53.125% 83.87097%}.emojione-1F513{background-position:56.25% 83.87097%}.emojione-1F514{background-position:59.375% 83.87097%}.emojione-1F515{background-position:62.5% 83.87097%}.emojione-1F516{background-position:65.625% 83.87097%}.emojione-1F517{background-position:68.75% 83.87097%}.emojione-1F518{background-position:71.875% 83.87097%}.emojione-1F519{background-position:75% 83.87097%}.emojione-1F51A{background-position:78.125% 83.87097%}.emojione-1F51B{background-position:81.25% 83.87097%}.emojione-1F51C{background-position:84.375% 0%}.emojione-1F51D{background-position:84.375% 3.22581%}.emojione-1F51E{background-position:84.375% 6.45161%}.emojione-1F51F{background-position:84.375% 9.67742%}.emojione-1F520{background-position:84.375% 12.90323%}.emojione-1F521{background-position:84.375% 16.12903%}.emojione-1F522{background-position:84.375% 19.35484%}.emojione-1F523{background-position:84.375% 22.58065%}.emojione-1F524{background-position:84.375% 25.80645%}.emojione-1F525{background-position:84.375% 29.03226%}.emojione-1F526{background-position:84.375% 32.25806%}.emojione-1F527{background-position:84.375% 35.48387%}.emojione-1F528{background-position:84.375% 38.70968%}.emojione-1F529{background-position:84.375% 41.93548%}.emojione-1F52A{background-position:84.375% 45.16129%}.emojione-1F52B{background-position:84.375% 48.3871%}.emojione-1F52C{background-position:84.375% 51.6129%}.emojione-1F52D{background-position:84.375% 54.83871%}.emojione-1F52E{background-position:84.375% 58.06452%}.emojione-1F52F{background-position:84.375% 61.29032%}.emojione-1F530{background-position:84.375% 64.51613%}.emojione-1F531{background-position:84.375% 67.74194%}.emojione-1F532{background-position:84.375% 70.96774%}.emojione-1F533{background-position:84.375% 74.19355%}.emojione-1F534{background-position:84.375% 77.41935%}.emojione-1F535{background-position:84.375% 80.64516%}.emojione-1F536{background-position:84.375% 83.87097%}.emojione-1F537{background-position:0% 87.09677%}.emojione-1F538{background-position:3.125% 87.09677%}.emojione-1F539{background-position:6.25% 87.09677%}.emojione-1F53A{background-position:9.375% 87.09677%}.emojione-1F53B{background-position:12.5% 87.09677%}.emojione-1F53C{background-position:15.625% 87.09677%}.emojione-1F53D{background-position:18.75% 87.09677%}.emojione-1F550{background-position:21.875% 87.09677%}.emojione-1F551{background-position:25% 87.09677%}.emojione-1F552{background-position:28.125% 87.09677%}.emojione-1F553{background-position:31.25% 87.09677%}.emojione-1F554{background-position:34.375% 87.09677%}.emojione-1F555{background-position:37.5% 87.09677%}.emojione-1F556{background-position:40.625% 87.09677%}.emojione-1F557{background-position:43.75% 87.09677%}.emojione-1F558{background-position:46.875% 87.09677%}.emojione-1F559{background-position:50% 87.09677%}.emojione-1F55A{background-position:53.125% 87.09677%}.emojione-1F55B{background-position:56.25% 87.09677%}.emojione-1F55C{background-position:59.375% 87.09677%}.emojione-1F55D{background-position:62.5% 87.09677%}.emojione-1F55E{background-position:65.625% 87.09677%}.emojione-1F55F{background-position:68.75% 87.09677%}.emojione-1F560{background-position:71.875% 87.09677%}.emojione-1F561{background-position:75% 87.09677%}.emojione-1F562{background-position:78.125% 87.09677%}.emojione-1F563{background-position:81.25% 87.09677%}.emojione-1F564{background-position:84.375% 87.09677%}.emojione-1F565{background-position:87.5% 0%}.emojione-1F566{background-position:87.5% 3.22581%}.emojione-1F567{background-position:87.5% 6.45161%}.emojione-1F5FB{background-position:87.5% 9.67742%}.emojione-1F5FC{background-position:87.5% 12.90323%}.emojione-1F5FD{background-position:87.5% 16.12903%}.emojione-1F5FE{background-position:87.5% 19.35484%}.emojione-1F5FF{background-position:87.5% 22.58065%}.emojione-1F600{background-position:87.5% 25.80645%}.emojione-1F601{background-position:87.5% 29.03226%}.emojione-1F602{background-position:87.5% 32.25806%}.emojione-1F603{background-position:87.5% 35.48387%}.emojione-1F604{background-position:87.5% 38.70968%}.emojione-1F605{background-position:87.5% 41.93548%}.emojione-1F606{background-position:87.5% 45.16129%}.emojione-1F607{background-position:87.5% 48.3871%}.emojione-1F608{background-position:87.5% 51.6129%}.emojione-1F609{background-position:87.5% 54.83871%}.emojione-1F60A{background-position:87.5% 58.06452%}.emojione-1F60B{background-position:87.5% 61.29032%}.emojione-1F60C{background-position:87.5% 64.51613%}.emojione-1F60D{background-position:87.5% 67.74194%}.emojione-1F60E{background-position:87.5% 70.96774%}.emojione-1F60F{background-position:87.5% 74.19355%}.emojione-1F610{background-position:87.5% 77.41935%}.emojione-1F611{background-position:87.5% 80.64516%}.emojione-1F612{background-position:87.5% 83.87097%}.emojione-1F613{background-position:87.5% 87.09677%}.emojione-1F614{background-position:0% 90.32258%}.emojione-1F615{background-position:3.125% 90.32258%}.emojione-1F616{background-position:6.25% 90.32258%}.emojione-1F617{background-position:9.375% 90.32258%}.emojione-1F618{background-position:12.5% 90.32258%}.emojione-1F619{background-position:15.625% 90.32258%}.emojione-1F61A{background-position:18.75% 90.32258%}.emojione-1F61B{background-position:21.875% 90.32258%}.emojione-1F61C{background-position:25% 90.32258%}.emojione-1F61D{background-position:28.125% 90.32258%}.emojione-1F61E{background-position:31.25% 90.32258%}.emojione-1F61F{background-position:34.375% 90.32258%}.emojione-1F620{background-position:37.5% 90.32258%}.emojione-1F621{background-position:40.625% 90.32258%}.emojione-1F622{background-position:43.75% 90.32258%}.emojione-1F623{background-position:46.875% 90.32258%}.emojione-1F624{background-position:50% 90.32258%}.emojione-1F625{background-position:53.125% 90.32258%}.emojione-1F626{background-position:56.25% 90.32258%}.emojione-1F627{background-position:59.375% 90.32258%}.emojione-1F628{background-position:62.5% 90.32258%}.emojione-1F629{background-position:65.625% 90.32258%}.emojione-1F62A{background-position:68.75% 90.32258%}.emojione-1F62B{background-position:71.875% 90.32258%}.emojione-1F62C{background-position:75% 90.32258%}.emojione-1F62D{background-position:78.125% 90.32258%}.emojione-1F62E{background-position:81.25% 90.32258%}.emojione-1F62F{background-position:84.375% 90.32258%}.emojione-1F630{background-position:87.5% 90.32258%}.emojione-1F631{background-position:90.625% 0%}.emojione-1F632{background-position:90.625% 3.22581%}.emojione-1F633{background-position:90.625% 6.45161%}.emojione-1F634{background-position:90.625% 9.67742%}.emojione-1F635{background-position:90.625% 12.90323%}.emojione-1F636{background-position:90.625% 16.12903%}.emojione-1F637{background-position:90.625% 19.35484%}.emojione-1F638{background-position:90.625% 22.58065%}.emojione-1F639{background-position:90.625% 25.80645%}.emojione-1F63A{background-position:90.625% 29.03226%}.emojione-1F63B{background-position:90.625% 32.25806%}.emojione-1F63C{background-position:90.625% 35.48387%}.emojione-1F63D{background-position:90.625% 38.70968%}.emojione-1F63E{background-position:90.625% 41.93548%}.emojione-1F63F{background-position:90.625% 45.16129%}.emojione-1F640{background-position:90.625% 48.3871%}.emojione-1F645{background-position:90.625% 51.6129%}.emojione-1F646{background-position:90.625% 54.83871%}.emojione-1F647{background-position:90.625% 58.06452%}.emojione-1F648{background-position:90.625% 61.29032%}.emojione-1F649{background-position:90.625% 64.51613%}.emojione-1F64A{background-position:90.625% 67.74194%}.emojione-1F64B{background-position:90.625% 70.96774%}.emojione-1F64C{background-position:90.625% 74.19355%}.emojione-1F64D{background-position:90.625% 77.41935%}.emojione-1F64E{background-position:90.625% 80.64516%}.emojione-1F64F{background-position:90.625% 83.87097%}.emojione-1F680{background-position:90.625% 87.09677%}.emojione-1F681{background-position:90.625% 90.32258%}.emojione-1F682{background-position:0% 93.54839%}.emojione-1F683{background-position:3.125% 93.54839%}.emojione-1F684{background-position:6.25% 93.54839%}.emojione-1F685{background-position:9.375% 93.54839%}.emojione-1F686{background-position:12.5% 93.54839%}.emojione-1F687{background-position:15.625% 93.54839%}.emojione-1F688{background-position:18.75% 93.54839%}.emojione-1F689{background-position:21.875% 93.54839%}.emojione-1F68A{background-position:25% 93.54839%}.emojione-1F68B{background-position:28.125% 93.54839%}.emojione-1F68C{background-position:31.25% 93.54839%}.emojione-1F68D{background-position:34.375% 93.54839%}.emojione-1F68E{background-position:37.5% 93.54839%}.emojione-1F68F{background-position:40.625% 93.54839%}.emojione-1F690{background-position:43.75% 93.54839%}.emojione-1F691{background-position:46.875% 93.54839%}.emojione-1F692{background-position:50% 93.54839%}.emojione-1F693{background-position:53.125% 93.54839%}.emojione-1F694{background-position:56.25% 93.54839%}.emojione-1F695{background-position:59.375% 93.54839%}.emojione-1F696{background-position:62.5% 93.54839%}.emojione-1F697{background-position:65.625% 93.54839%}.emojione-1F698{background-position:68.75% 93.54839%}.emojione-1F699{background-position:71.875% 93.54839%}.emojione-1F69A{background-position:75% 93.54839%}.emojione-1F69B{background-position:78.125% 93.54839%}.emojione-1F69C{background-position:81.25% 93.54839%}.emojione-1F69D{background-position:84.375% 93.54839%}.emojione-1F69E{background-position:87.5% 93.54839%}.emojione-1F69F{background-position:90.625% 93.54839%}.emojione-1F6A0{background-position:93.75% 0%}.emojione-1F6A1{background-position:93.75% 3.22581%}.emojione-1F6A2{background-position:93.75% 6.45161%}.emojione-1F6A3{background-position:93.75% 9.67742%}.emojione-1F6A4{background-position:93.75% 12.90323%}.emojione-1F6A5{background-position:93.75% 16.12903%}.emojione-1F6A6{background-position:93.75% 19.35484%}.emojione-1F6A7{background-position:93.75% 22.58065%}.emojione-1F6A8{background-position:93.75% 25.80645%}.emojione-1F6A9{background-position:93.75% 29.03226%}.emojione-1F6AA{background-position:93.75% 32.25806%}.emojione-1F6AB{background-position:93.75% 35.48387%}.emojione-1F6AC{background-position:93.75% 38.70968%}.emojione-1F6AD{background-position:93.75% 41.93548%}.emojione-1F6AE{background-position:93.75% 45.16129%}.emojione-1F6AF{background-position:93.75% 48.3871%}.emojione-1F6B0{background-position:93.75% 51.6129%}.emojione-1F6B1{background-position:93.75% 54.83871%}.emojione-1F6B2{background-position:93.75% 58.06452%}.emojione-1F6B3{background-position:93.75% 61.29032%}.emojione-1F6B4{background-position:93.75% 64.51613%}.emojione-1F6B5{background-position:93.75% 67.74194%}.emojione-1F6B6{background-position:93.75% 70.96774%}.emojione-1F6B7{background-position:93.75% 74.19355%}.emojione-1F6B8{background-position:93.75% 77.41935%}.emojione-1F6B9{background-position:93.75% 80.64516%}.emojione-1F6BA{background-position:93.75% 83.87097%}.emojione-1F6BB{background-position:93.75% 87.09677%}.emojione-1F6BC{background-position:93.75% 90.32258%}.emojione-1F6BD{background-position:93.75% 93.54839%}.emojione-1F6BE{background-position:0% 96.77419%}.emojione-1F6BF{background-position:3.125% 96.77419%}.emojione-1F6C0{background-position:6.25% 96.77419%}.emojione-1F6C1{background-position:9.375% 96.77419%}.emojione-1F6C2{background-position:12.5% 96.77419%}.emojione-1F6C3{background-position:15.625% 96.77419%}.emojione-1F6C4{background-position:18.75% 96.77419%}.emojione-1F6C5{background-position:21.875% 96.77419%}.emojione-203C{background-position:25% 96.77419%}.emojione-2049{background-position:28.125% 96.77419%}.emojione-2122{background-position:31.25% 96.77419%}.emojione-2139{background-position:34.375% 96.77419%}.emojione-2194{background-position:37.5% 96.77419%}.emojione-2195{background-position:40.625% 96.77419%}.emojione-2196{background-position:43.75% 96.77419%}.emojione-2197{background-position:46.875% 96.77419%}.emojione-2198{background-position:50% 96.77419%}.emojione-2199{background-position:53.125% 96.77419%}.emojione-21A9{background-position:56.25% 96.77419%}.emojione-21AA{background-position:59.375% 96.77419%}.emojione-231A{background-position:62.5% 96.77419%}.emojione-231B{background-position:65.625% 96.77419%}.emojione-23E9{background-position:68.75% 96.77419%}.emojione-23EA{background-position:71.875% 96.77419%}.emojione-23EB{background-position:75% 96.77419%}.emojione-23EC{background-position:78.125% 96.77419%}.emojione-23F0{background-position:81.25% 96.77419%}.emojione-23F3{background-position:84.375% 96.77419%}.emojione-24C2{background-position:87.5% 96.77419%}.emojione-25AA{background-position:90.625% 96.77419%}.emojione-25AB{background-position:93.75% 96.77419%}.emojione-25B6{background-position:96.875% 0%}.emojione-25C0{background-position:96.875% 3.22581%}.emojione-25FB{background-position:96.875% 6.45161%}.emojione-25FC{background-position:96.875% 9.67742%}.emojione-25FD{background-position:96.875% 12.90323%}.emojione-25FE{background-position:96.875% 16.12903%}.emojione-2600{background-position:96.875% 19.35484%}.emojione-2601{background-position:96.875% 22.58065%}.emojione-260E{background-position:96.875% 25.80645%}.emojione-2611{background-position:96.875% 29.03226%}.emojione-2614{background-position:96.875% 32.25806%}.emojione-2615{background-position:96.875% 35.48387%}.emojione-261D{background-position:96.875% 38.70968%}.emojione-263A{background-position:96.875% 41.93548%}.emojione-2648{background-position:96.875% 45.16129%}.emojione-2649{background-position:96.875% 48.3871%}.emojione-264A{background-position:96.875% 51.6129%}.emojione-264B{background-position:96.875% 54.83871%}.emojione-264C{background-position:96.875% 58.06452%}.emojione-264D{background-position:96.875% 61.29032%}.emojione-264E{background-position:96.875% 64.51613%}.emojione-264F{background-position:96.875% 67.74194%}.emojione-2650{background-position:96.875% 70.96774%}.emojione-2651{background-position:96.875% 74.19355%}.emojione-2652{background-position:96.875% 77.41935%}.emojione-2653{background-position:96.875% 80.64516%}.emojione-2660{background-position:96.875% 83.87097%}.emojione-2663{background-position:96.875% 87.09677%}.emojione-2665{background-position:96.875% 90.32258%}.emojione-2666{background-position:96.875% 93.54839%}.emojione-2668{background-position:96.875% 96.77419%}.emojione-267B{background-position:0% 100%}.emojione-267F{background-position:3.125% 100%}.emojione-2693{background-position:6.25% 100%}.emojione-26A0{background-position:9.375% 100%}.emojione-26A1{background-position:12.5% 100%}.emojione-26AA{background-position:15.625% 100%}.emojione-26AB{background-position:18.75% 100%}.emojione-26BD{background-position:21.875% 100%}.emojione-26BE{background-position:25% 100%}.emojione-26C4{background-position:28.125% 100%}.emojione-26C5{background-position:31.25% 100%}.emojione-26CE{background-position:34.375% 100%}.emojione-26D4{background-position:37.5% 100%}.emojione-26EA{background-position:40.625% 100%}.emojione-26F2{background-position:43.75% 100%}.emojione-26F3{background-position:46.875% 100%}.emojione-26F5{background-position:50% 100%}.emojione-26FA{background-position:53.125% 100%}.emojione-26FD{background-position:56.25% 100%}.emojione-2702{background-position:59.375% 100%}.emojione-2705{background-position:62.5% 100%}.emojione-2708{background-position:65.625% 100%}.emojione-2709{background-position:68.75% 100%}.emojione-270A{background-position:71.875% 100%}.emojione-270B{background-position:75% 100%}.emojione-270C{background-position:78.125% 100%}.emojione-270F{background-position:81.25% 100%}.emojione-2712{background-position:84.375% 100%}.emojione-2714{background-position:87.5% 100%}.emojione-2716{background-position:90.625% 100%}.emojione-2728{background-position:93.75% 100%}.emojione-2733{background-position:96.875% 100%}.emojione-2734{background-position:100% 0%}.emojione-2744{background-position:100% 3.22581%}.emojione-2747{background-position:100% 6.45161%}.emojione-274C{background-position:100% 9.67742%}.emojione-274E{background-position:100% 12.90323%}.emojione-2753{background-position:100% 16.12903%}.emojione-2754{background-position:100% 19.35484%}.emojione-2755{background-position:100% 22.58065%}.emojione-2757{background-position:100% 25.80645%}.emojione-2764{background-position:100% 29.03226%}.emojione-2795{background-position:100% 32.25806%}.emojione-2796{background-position:100% 35.48387%}.emojione-2797{background-position:100% 38.70968%}.emojione-27A1{background-position:100% 41.93548%}.emojione-27B0{background-position:100% 45.16129%}.emojione-27BF{background-position:100% 48.3871%}.emojione-2934{background-position:100% 51.6129%}.emojione-2935{background-position:100% 54.83871%}.emojione-2B05{background-position:100% 58.06452%}.emojione-2B06{background-position:100% 61.29032%}.emojione-2B07{background-position:100% 64.51613%}.emojione-2B1B{background-position:100% 67.74194%}.emojione-2B1C{background-position:100% 70.96774%}.emojione-2B50{background-position:100% 74.19355%}.emojione-2B55{background-position:100% 77.41935%}.emojione-3030{background-position:100% 80.64516%}.emojione-303D{background-position:100% 83.87097%}.emojione-3297{background-position:100% 87.09677%}.emojione-3299{background-position:100% 90.32258%} - - -/* AutoComplete styles for Emoji One */ - -.dropdown-menu { - list-style: none; - padding: .3em 0 0; - margin: 0; - border: 1px solid #6E6E6E; - background-color: white; - border-radius: 5px; - overflow: hidden; - font-size: inherit; - letter-spacing: .025em; - box-shadow: 3px 3px 3px rgba(0,0,0,.2); -} -.dropdown-menu a:hover { - cursor: pointer; -} -.dropdown-menu li { - letter-spacing: 0; - display: block; - float: none; - margin: 0; - padding: 0; - border:none; -} -.dropdown-menu li:before { - display: none; -} -.dropdown-menu .textcomplete-footer { - margin-top: .3em; - background: #e6e6e6; -} -.dropdown-menu .textcomplete-footer a { - color: #999999; - text-decoration: none; - text-transform: uppercase; - letter-spacing: .05em; - line-height: 2.1818em; - padding-left: 1.8181em; - font-size: .84em; -} -.dropdown-menu .textcomplete-footer .arrow { - margin-left: .8em; - font-size: 1.3em; -} -.dropdown-menu li .emojione { - vertical-align: middle; - font-size: 1.23em; - width: 1em; - height: 1em; - top: -1px; - margin: 0 .3em 0 0; -} -.dropdown-menu li a { - display: block; - height: 100%; - line-height: 1.8em; - padding: 0 1.54em 0 .615em; - color: #4f4f4f; -} -.dropdown-menu .active, -.dropdown-menu li:hover { - background: #6E6E6E; - color: white; -} -.dropdown-menu .active a, -.dropdown-menu li:hover a { - color: inherit; -} diff --git a/pagure/static/emoji/emojione.sprites.css b/pagure/static/emoji/emojione.sprites.css new file mode 120000 index 0000000..57ad187 --- /dev/null +++ b/pagure/static/emoji/emojione.sprites.css @@ -0,0 +1 @@ +emojione.sprites-2.2.6.css \ No newline at end of file diff --git a/pagure/static/emoji/emojione.sprites.png b/pagure/static/emoji/emojione.sprites.png deleted file mode 100644 index 1f2aecc..0000000 Binary files a/pagure/static/emoji/emojione.sprites.png and /dev/null differ diff --git a/pagure/static/emoji/emojione.sprites.png b/pagure/static/emoji/emojione.sprites.png new file mode 120000 index 0000000..4235a37 --- /dev/null +++ b/pagure/static/emoji/emojione.sprites.png @@ -0,0 +1 @@ +emojione.sprites-2.2.6.png \ No newline at end of file diff --git a/pagure/static/emoji/jquery.textcomplete-1.7.1.js b/pagure/static/emoji/jquery.textcomplete-1.7.1.js new file mode 100644 index 0000000..87463c4 --- /dev/null +++ b/pagure/static/emoji/jquery.textcomplete-1.7.1.js @@ -0,0 +1,1482 @@ +(function (factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define(['jquery'], factory); + } else if (typeof module === "object" && module.exports) { + var $ = require('jquery'); + module.exports = factory($); + } else { + // Browser globals + factory(jQuery); + } +}(function (jQuery) { + +/*! + * jQuery.textcomplete + * + * Repository: https://github.com/yuku-t/jquery-textcomplete + * License: MIT (https://github.com/yuku-t/jquery-textcomplete/blob/master/LICENSE) + * Author: Yuku Takahashi + */ + +if (typeof jQuery === 'undefined') { + throw new Error('jQuery.textcomplete requires jQuery'); +} + ++function ($) { + 'use strict'; + + var warn = function (message) { + if (console.warn) { console.warn(message); } + }; + + var id = 1; + + $.fn.textcomplete = function (strategies, option) { + var args = Array.prototype.slice.call(arguments); + return this.each(function () { + var self = this; + var $this = $(this); + var completer = $this.data('textComplete'); + if (!completer) { + option || (option = {}); + option._oid = id++; // unique object id + completer = new $.fn.textcomplete.Completer(this, option); + $this.data('textComplete', completer); + } + if (typeof strategies === 'string') { + if (!completer) return; + args.shift() + completer[strategies].apply(completer, args); + if (strategies === 'destroy') { + $this.removeData('textComplete'); + } + } else { + // For backward compatibility. + // TODO: Remove at v0.4 + $.each(strategies, function (obj) { + $.each(['header', 'footer', 'placement', 'maxCount'], function (name) { + if (obj[name]) { + completer.option[name] = obj[name]; + warn(name + 'as a strategy param is deprecated. Use option.'); + delete obj[name]; + } + }); + }); + completer.register($.fn.textcomplete.Strategy.parse(strategies, { + el: self, + $el: $this + })); + } + }); + }; + +}(jQuery); + ++function ($) { + 'use strict'; + + // Exclusive execution control utility. + // + // func - The function to be locked. It is executed with a function named + // `free` as the first argument. Once it is called, additional + // execution are ignored until the free is invoked. Then the last + // ignored execution will be replayed immediately. + // + // Examples + // + // var lockedFunc = lock(function (free) { + // setTimeout(function { free(); }, 1000); // It will be free in 1 sec. + // console.log('Hello, world'); + // }); + // lockedFunc(); // => 'Hello, world' + // lockedFunc(); // none + // lockedFunc(); // none + // // 1 sec past then + // // => 'Hello, world' + // lockedFunc(); // => 'Hello, world' + // lockedFunc(); // none + // + // Returns a wrapped function. + var lock = function (func) { + var locked, queuedArgsToReplay; + + return function () { + // Convert arguments into a real array. + var args = Array.prototype.slice.call(arguments); + if (locked) { + // Keep a copy of this argument list to replay later. + // OK to overwrite a previous value because we only replay + // the last one. + queuedArgsToReplay = args; + return; + } + locked = true; + var self = this; + args.unshift(function replayOrFree() { + if (queuedArgsToReplay) { + // Other request(s) arrived while we were locked. + // Now that the lock is becoming available, replay + // the latest such request, then call back here to + // unlock (or replay another request that arrived + // while this one was in flight). + var replayArgs = queuedArgsToReplay; + queuedArgsToReplay = undefined; + replayArgs.unshift(replayOrFree); + func.apply(self, replayArgs); + } else { + locked = false; + } + }); + func.apply(this, args); + }; + }; + + var isString = function (obj) { + return Object.prototype.toString.call(obj) === '[object String]'; + }; + + var uniqueId = 0; + + function Completer(element, option) { + this.$el = $(element); + this.id = 'textcomplete' + uniqueId++; + this.strategies = []; + this.views = []; + this.option = $.extend({}, Completer.defaults, option); + + if (!this.$el.is('input[type=text]') && !this.$el.is('input[type=search]') && !this.$el.is('textarea') && !element.isContentEditable && element.contentEditable != 'true') { + throw new Error('textcomplete must be called on a Textarea or a ContentEditable.'); + } + + // use ownerDocument to fix iframe / IE issues + if (element === element.ownerDocument.activeElement) { + // element has already been focused. Initialize view objects immediately. + this.initialize() + } else { + // Initialize view objects lazily. + var self = this; + this.$el.one('focus.' + this.id, function () { self.initialize(); }); + + // Special handling for CKEditor: lazy init on instance load + if ((!this.option.adapter || this.option.adapter == 'CKEditor') && typeof CKEDITOR != 'undefined' && (this.$el.is('textarea'))) { + CKEDITOR.on("instanceReady", function(event) { + event.editor.once("focus", function(event2) { + // replace the element with the Iframe element and flag it as CKEditor + self.$el = $(event.editor.editable().$); + if (!self.option.adapter) { + self.option.adapter = $.fn.textcomplete['CKEditor']; + } + self.initialize(); + }); + }); + } + } + } + + Completer.defaults = { + appendTo: 'body', + className: '', // deprecated option + dropdownClassName: 'dropdown-menu textcomplete-dropdown', + maxCount: 10, + zIndex: '100', + rightEdgeOffset: 30 + }; + + $.extend(Completer.prototype, { + // Public properties + // ----------------- + + id: null, + option: null, + strategies: null, + adapter: null, + dropdown: null, + $el: null, + $iframe: null, + + // Public methods + // -------------- + + initialize: function () { + var element = this.$el.get(0); + + // check if we are in an iframe + // we need to alter positioning logic if using an iframe + if (this.$el.prop('ownerDocument') !== document && window.frames.length) { + for (var iframeIndex = 0; iframeIndex < window.frames.length; iframeIndex++) { + if (this.$el.prop('ownerDocument') === window.frames[iframeIndex].document) { + this.$iframe = $(window.frames[iframeIndex].frameElement); + break; + } + } + } + + + // Initialize view objects. + this.dropdown = new $.fn.textcomplete.Dropdown(element, this, this.option); + var Adapter, viewName; + if (this.option.adapter) { + Adapter = this.option.adapter; + } else { + if (this.$el.is('textarea') || this.$el.is('input[type=text]') || this.$el.is('input[type=search]')) { + viewName = typeof element.selectionEnd === 'number' ? 'Textarea' : 'IETextarea'; + } else { + viewName = 'ContentEditable'; + } + Adapter = $.fn.textcomplete[viewName]; + } + this.adapter = new Adapter(element, this, this.option); + }, + + destroy: function () { + this.$el.off('.' + this.id); + if (this.adapter) { + this.adapter.destroy(); + } + if (this.dropdown) { + this.dropdown.destroy(); + } + this.$el = this.adapter = this.dropdown = null; + }, + + deactivate: function () { + if (this.dropdown) { + this.dropdown.deactivate(); + } + }, + + // Invoke textcomplete. + trigger: function (text, skipUnchangedTerm) { + if (!this.dropdown) { this.initialize(); } + text != null || (text = this.adapter.getTextFromHeadToCaret()); + var searchQuery = this._extractSearchQuery(text); + if (searchQuery.length) { + var term = searchQuery[1]; + // Ignore shift-key, ctrl-key and so on. + if (skipUnchangedTerm && this._term === term && term !== "") { return; } + this._term = term; + this._search.apply(this, searchQuery); + } else { + this._term = null; + this.dropdown.deactivate(); + } + }, + + fire: function (eventName) { + var args = Array.prototype.slice.call(arguments, 1); + this.$el.trigger(eventName, args); + return this; + }, + + register: function (strategies) { + Array.prototype.push.apply(this.strategies, strategies); + }, + + // Insert the value into adapter view. It is called when the dropdown is clicked + // or selected. + // + // value - The selected element of the array callbacked from search func. + // strategy - The Strategy object. + // e - Click or keydown event object. + select: function (value, strategy, e) { + this._term = null; + this.adapter.select(value, strategy, e); + this.fire('change').fire('textComplete:select', value, strategy); + this.adapter.focus(); + }, + + // Private properties + // ------------------ + + _clearAtNext: true, + _term: null, + + // Private methods + // --------------- + + // Parse the given text and extract the first matching strategy. + // + // Returns an array including the strategy, the query term and the match + // object if the text matches an strategy; otherwise returns an empty array. + _extractSearchQuery: function (text) { + for (var i = 0; i < this.strategies.length; i++) { + var strategy = this.strategies[i]; + var context = strategy.context(text); + if (context || context === '') { + var matchRegexp = $.isFunction(strategy.match) ? strategy.match(text) : strategy.match; + if (isString(context)) { text = context; } + var match = text.match(matchRegexp); + if (match) { return [strategy, match[strategy.index], match]; } + } + } + return [] + }, + + // Call the search method of selected strategy.. + _search: lock(function (free, strategy, term, match) { + var self = this; + strategy.search(term, function (data, stillSearching) { + if (!self.dropdown.shown) { + self.dropdown.activate(); + } + if (self._clearAtNext) { + // The first callback in the current lock. + self.dropdown.clear(); + self._clearAtNext = false; + } + self.dropdown.setPosition(self.adapter.getCaretPosition()); + self.dropdown.render(self._zip(data, strategy, term)); + if (!stillSearching) { + // The last callback in the current lock. + free(); + self._clearAtNext = true; // Call dropdown.clear at the next time. + } + }, match); + }), + + // Build a parameter for Dropdown#render. + // + // Examples + // + // this._zip(['a', 'b'], 's'); + // //=> [{ value: 'a', strategy: 's' }, { value: 'b', strategy: 's' }] + _zip: function (data, strategy, term) { + return $.map(data, function (value) { + return { value: value, strategy: strategy, term: term }; + }); + } + }); + + $.fn.textcomplete.Completer = Completer; +}(jQuery); + ++function ($) { + 'use strict'; + + var $window = $(window); + + var include = function (zippedData, datum) { + var i, elem; + var idProperty = datum.strategy.idProperty + for (i = 0; i < zippedData.length; i++) { + elem = zippedData[i]; + if (elem.strategy !== datum.strategy) continue; + if (idProperty) { + if (elem.value[idProperty] === datum.value[idProperty]) return true; + } else { + if (elem.value === datum.value) return true; + } + } + return false; + }; + + var dropdownViews = {}; + $(document).on('click', function (e) { + var id = e.originalEvent && e.originalEvent.keepTextCompleteDropdown; + $.each(dropdownViews, function (key, view) { + if (key !== id) { view.deactivate(); } + }); + }); + + var commands = { + SKIP_DEFAULT: 0, + KEY_UP: 1, + KEY_DOWN: 2, + KEY_ENTER: 3, + KEY_PAGEUP: 4, + KEY_PAGEDOWN: 5, + KEY_ESCAPE: 6 + }; + + // Dropdown view + // ============= + + // Construct Dropdown object. + // + // element - Textarea or contenteditable element. + function Dropdown(element, completer, option) { + this.$el = Dropdown.createElement(option); + this.completer = completer; + this.id = completer.id + 'dropdown'; + this._data = []; // zipped data. + this.$inputEl = $(element); + this.option = option; + + // Override setPosition method. + if (option.listPosition) { this.setPosition = option.listPosition; } + if (option.height) { this.$el.height(option.height); } + var self = this; + $.each(['maxCount', 'placement', 'footer', 'header', 'noResultsMessage', 'className'], function (_i, name) { + if (option[name] != null) { self[name] = option[name]; } + }); + this._bindEvents(element); + dropdownViews[this.id] = this; + } + + $.extend(Dropdown, { + // Class methods + // ------------- + + createElement: function (option) { + var $parent = option.appendTo; + if (!($parent instanceof $)) { $parent = $($parent); } + var $el = $('
          ') + .addClass(option.dropdownClassName) + .attr('id', 'textcomplete-dropdown-' + option._oid) + .css({ + display: 'none', + left: 0, + position: 'absolute', + zIndex: option.zIndex + }) + .appendTo($parent); + return $el; + } + }); + + $.extend(Dropdown.prototype, { + // Public properties + // ----------------- + + $el: null, // jQuery object of ul.dropdown-menu element. + $inputEl: null, // jQuery object of target textarea. + completer: null, + footer: null, + header: null, + id: null, + maxCount: null, + placement: '', + shown: false, + data: [], // Shown zipped data. + className: '', + + // Public methods + // -------------- + + destroy: function () { + // Don't remove $el because it may be shared by several textcompletes. + this.deactivate(); + + this.$el.off('.' + this.id); + this.$inputEl.off('.' + this.id); + this.clear(); + this.$el.remove(); + this.$el = this.$inputEl = this.completer = null; + delete dropdownViews[this.id] + }, + + render: function (zippedData) { + var contentsHtml = this._buildContents(zippedData); + var unzippedData = $.map(this.data, function (d) { return d.value; }); + if (this.data.length) { + var strategy = zippedData[0].strategy; + if (strategy.id) { + this.$el.attr('data-strategy', strategy.id); + } else { + this.$el.removeAttr('data-strategy'); + } + this._renderHeader(unzippedData); + this._renderFooter(unzippedData); + if (contentsHtml) { + this._renderContents(contentsHtml); + this._fitToBottom(); + this._fitToRight(); + this._activateIndexedItem(); + } + this._setScroll(); + } else if (this.noResultsMessage) { + this._renderNoResultsMessage(unzippedData); + } else if (this.shown) { + this.deactivate(); + } + }, + + setPosition: function (pos) { + // Make the dropdown fixed if the input is also fixed + // This can't be done during init, as textcomplete may be used on multiple elements on the same page + // Because the same dropdown is reused behind the scenes, we need to recheck every time the dropdown is showed + var position = 'absolute'; + // Check if input or one of its parents has positioning we need to care about + this.$inputEl.add(this.$inputEl.parents()).each(function() { + if($(this).css('position') === 'absolute') // The element has absolute positioning, so it's all OK + return false; + if($(this).css('position') === 'fixed') { + pos.top -= $window.scrollTop(); + pos.left -= $window.scrollLeft(); + position = 'fixed'; + return false; + } + }); + this.$el.css(this._applyPlacement(pos)); + this.$el.css({ position: position }); // Update positioning + + return this; + }, + + clear: function () { + this.$el.html(''); + this.data = []; + this._index = 0; + this._$header = this._$footer = this._$noResultsMessage = null; + }, + + activate: function () { + if (!this.shown) { + this.clear(); + this.$el.show(); + if (this.className) { this.$el.addClass(this.className); } + this.completer.fire('textComplete:show'); + this.shown = true; + } + return this; + }, + + deactivate: function () { + if (this.shown) { + this.$el.hide(); + if (this.className) { this.$el.removeClass(this.className); } + this.completer.fire('textComplete:hide'); + this.shown = false; + } + return this; + }, + + isUp: function (e) { + return e.keyCode === 38 || (e.ctrlKey && e.keyCode === 80); // UP, Ctrl-P + }, + + isDown: function (e) { + return e.keyCode === 40 || (e.ctrlKey && e.keyCode === 78); // DOWN, Ctrl-N + }, + + isEnter: function (e) { + var modifiers = e.ctrlKey || e.altKey || e.metaKey || e.shiftKey; + return !modifiers && (e.keyCode === 13 || e.keyCode === 9 || (this.option.completeOnSpace === true && e.keyCode === 32)) // ENTER, TAB + }, + + isPageup: function (e) { + return e.keyCode === 33; // PAGEUP + }, + + isPagedown: function (e) { + return e.keyCode === 34; // PAGEDOWN + }, + + isEscape: function (e) { + return e.keyCode === 27; // ESCAPE + }, + + // Private properties + // ------------------ + + _data: null, // Currently shown zipped data. + _index: null, + _$header: null, + _$noResultsMessage: null, + _$footer: null, + + // Private methods + // --------------- + + _bindEvents: function () { + this.$el.on('mousedown.' + this.id, '.textcomplete-item', $.proxy(this._onClick, this)); + this.$el.on('touchstart.' + this.id, '.textcomplete-item', $.proxy(this._onClick, this)); + this.$el.on('mouseover.' + this.id, '.textcomplete-item', $.proxy(this._onMouseover, this)); + this.$inputEl.on('keydown.' + this.id, $.proxy(this._onKeydown, this)); + }, + + _onClick: function (e) { + var $el = $(e.target); + e.preventDefault(); + e.originalEvent.keepTextCompleteDropdown = this.id; + if (!$el.hasClass('textcomplete-item')) { + $el = $el.closest('.textcomplete-item'); + } + var datum = this.data[parseInt($el.data('index'), 10)]; + this.completer.select(datum.value, datum.strategy, e); + var self = this; + // Deactive at next tick to allow other event handlers to know whether + // the dropdown has been shown or not. + setTimeout(function () { + self.deactivate(); + if (e.type === 'touchstart') { + self.$inputEl.focus(); + } + }, 0); + }, + + // Activate hovered item. + _onMouseover: function (e) { + var $el = $(e.target); + e.preventDefault(); + if (!$el.hasClass('textcomplete-item')) { + $el = $el.closest('.textcomplete-item'); + } + this._index = parseInt($el.data('index'), 10); + this._activateIndexedItem(); + }, + + _onKeydown: function (e) { + if (!this.shown) { return; } + + var command; + + if ($.isFunction(this.option.onKeydown)) { + command = this.option.onKeydown(e, commands); + } + + if (command == null) { + command = this._defaultKeydown(e); + } + + switch (command) { + case commands.KEY_UP: + e.preventDefault(); + this._up(); + break; + case commands.KEY_DOWN: + e.preventDefault(); + this._down(); + break; + case commands.KEY_ENTER: + e.preventDefault(); + this._enter(e); + break; + case commands.KEY_PAGEUP: + e.preventDefault(); + this._pageup(); + break; + case commands.KEY_PAGEDOWN: + e.preventDefault(); + this._pagedown(); + break; + case commands.KEY_ESCAPE: + e.preventDefault(); + this.deactivate(); + break; + } + }, + + _defaultKeydown: function (e) { + if (this.isUp(e)) { + return commands.KEY_UP; + } else if (this.isDown(e)) { + return commands.KEY_DOWN; + } else if (this.isEnter(e)) { + return commands.KEY_ENTER; + } else if (this.isPageup(e)) { + return commands.KEY_PAGEUP; + } else if (this.isPagedown(e)) { + return commands.KEY_PAGEDOWN; + } else if (this.isEscape(e)) { + return commands.KEY_ESCAPE; + } + }, + + _up: function () { + if (this._index === 0) { + this._index = this.data.length - 1; + } else { + this._index -= 1; + } + this._activateIndexedItem(); + this._setScroll(); + }, + + _down: function () { + if (this._index === this.data.length - 1) { + this._index = 0; + } else { + this._index += 1; + } + this._activateIndexedItem(); + this._setScroll(); + }, + + _enter: function (e) { + var datum = this.data[parseInt(this._getActiveElement().data('index'), 10)]; + this.completer.select(datum.value, datum.strategy, e); + this.deactivate(); + }, + + _pageup: function () { + var target = 0; + var threshold = this._getActiveElement().position().top - this.$el.innerHeight(); + this.$el.children().each(function (i) { + if ($(this).position().top + $(this).outerHeight() > threshold) { + target = i; + return false; + } + }); + this._index = target; + this._activateIndexedItem(); + this._setScroll(); + }, + + _pagedown: function () { + var target = this.data.length - 1; + var threshold = this._getActiveElement().position().top + this.$el.innerHeight(); + this.$el.children().each(function (i) { + if ($(this).position().top > threshold) { + target = i; + return false + } + }); + this._index = target; + this._activateIndexedItem(); + this._setScroll(); + }, + + _activateIndexedItem: function () { + this.$el.find('.textcomplete-item.active').removeClass('active'); + this._getActiveElement().addClass('active'); + }, + + _getActiveElement: function () { + return this.$el.children('.textcomplete-item:nth(' + this._index + ')'); + }, + + _setScroll: function () { + var $activeEl = this._getActiveElement(); + var itemTop = $activeEl.position().top; + var itemHeight = $activeEl.outerHeight(); + var visibleHeight = this.$el.innerHeight(); + var visibleTop = this.$el.scrollTop(); + if (this._index === 0 || this._index == this.data.length - 1 || itemTop < 0) { + this.$el.scrollTop(itemTop + visibleTop); + } else if (itemTop + itemHeight > visibleHeight) { + this.$el.scrollTop(itemTop + itemHeight + visibleTop - visibleHeight); + } + }, + + _buildContents: function (zippedData) { + var datum, i, index; + var html = ''; + for (i = 0; i < zippedData.length; i++) { + if (this.data.length === this.maxCount) break; + datum = zippedData[i]; + if (include(this.data, datum)) { continue; } + index = this.data.length; + this.data.push(datum); + html += '
        • '; + html += datum.strategy.template(datum.value, datum.term); + html += '
        • '; + } + return html; + }, + + _renderHeader: function (unzippedData) { + if (this.header) { + if (!this._$header) { + this._$header = $('
        • ').prependTo(this.$el); + } + var html = $.isFunction(this.header) ? this.header(unzippedData) : this.header; + this._$header.html(html); + } + }, + + _renderFooter: function (unzippedData) { + if (this.footer) { + if (!this._$footer) { + this._$footer = $('').appendTo(this.$el); + } + var html = $.isFunction(this.footer) ? this.footer(unzippedData) : this.footer; + this._$footer.html(html); + } + }, + + _renderNoResultsMessage: function (unzippedData) { + if (this.noResultsMessage) { + if (!this._$noResultsMessage) { + this._$noResultsMessage = $('
        • ').appendTo(this.$el); + } + var html = $.isFunction(this.noResultsMessage) ? this.noResultsMessage(unzippedData) : this.noResultsMessage; + this._$noResultsMessage.html(html); + } + }, + + _renderContents: function (html) { + if (this._$footer) { + this._$footer.before(html); + } else { + this.$el.append(html); + } + }, + + _fitToBottom: function() { + var windowScrollBottom = $window.scrollTop() + $window.height(); + var height = this.$el.height(); + if ((this.$el.position().top + height) > windowScrollBottom) { + // only do this if we are not in an iframe + if (!this.completer.$iframe) { + this.$el.offset({top: windowScrollBottom - height}); + } + } + }, + + _fitToRight: function() { + // We don't know how wide our content is until the browser positions us, and at that point it clips us + // to the document width so we don't know if we would have overrun it. As a heuristic to avoid that clipping + // (which makes our elements wrap onto the next line and corrupt the next item), if we're close to the right + // edge, move left. We don't know how far to move left, so just keep nudging a bit. + var tolerance = this.option.rightEdgeOffset; // pixels. Make wider than vertical scrollbar because we might not be able to use that space. + var lastOffset = this.$el.offset().left, offset; + var width = this.$el.width(); + var maxLeft = $window.width() - tolerance; + while (lastOffset + width > maxLeft) { + this.$el.offset({left: lastOffset - tolerance}); + offset = this.$el.offset().left; + if (offset >= lastOffset) { break; } + lastOffset = offset; + } + }, + + _applyPlacement: function (position) { + // If the 'placement' option set to 'top', move the position above the element. + if (this.placement.indexOf('top') !== -1) { + // Overwrite the position object to set the 'bottom' property instead of the top. + position = { + top: 'auto', + bottom: this.$el.parent().height() - position.top + position.lineHeight, + left: position.left + }; + } else { + position.bottom = 'auto'; + delete position.lineHeight; + } + if (this.placement.indexOf('absleft') !== -1) { + position.left = 0; + } else if (this.placement.indexOf('absright') !== -1) { + position.right = 0; + position.left = 'auto'; + } + return position; + } + }); + + $.fn.textcomplete.Dropdown = Dropdown; + $.extend($.fn.textcomplete, commands); +}(jQuery); + ++function ($) { + 'use strict'; + + // Memoize a search function. + var memoize = function (func) { + var memo = {}; + return function (term, callback) { + if (memo[term]) { + callback(memo[term]); + } else { + func.call(this, term, function (data) { + memo[term] = (memo[term] || []).concat(data); + callback.apply(null, arguments); + }); + } + }; + }; + + function Strategy(options) { + $.extend(this, options); + if (this.cache) { this.search = memoize(this.search); } + } + + Strategy.parse = function (strategiesArray, params) { + return $.map(strategiesArray, function (strategy) { + var strategyObj = new Strategy(strategy); + strategyObj.el = params.el; + strategyObj.$el = params.$el; + return strategyObj; + }); + }; + + $.extend(Strategy.prototype, { + // Public properties + // ----------------- + + // Required + match: null, + replace: null, + search: null, + + // Optional + id: null, + cache: false, + context: function () { return true; }, + index: 2, + template: function (obj) { return obj; }, + idProperty: null + }); + + $.fn.textcomplete.Strategy = Strategy; + +}(jQuery); + ++function ($) { + 'use strict'; + + var now = Date.now || function () { return new Date().getTime(); }; + + // Returns a function, that, as long as it continues to be invoked, will not + // be triggered. The function will be called after it stops being called for + // `wait` msec. + // + // This utility function was originally implemented at Underscore.js. + var debounce = function (func, wait) { + var timeout, args, context, timestamp, result; + var later = function () { + var last = now() - timestamp; + if (last < wait) { + timeout = setTimeout(later, wait - last); + } else { + timeout = null; + result = func.apply(context, args); + context = args = null; + } + }; + + return function () { + context = this; + args = arguments; + timestamp = now(); + if (!timeout) { + timeout = setTimeout(later, wait); + } + return result; + }; + }; + + function Adapter () {} + + $.extend(Adapter.prototype, { + // Public properties + // ----------------- + + id: null, // Identity. + completer: null, // Completer object which creates it. + el: null, // Textarea element. + $el: null, // jQuery object of the textarea. + option: null, + + // Public methods + // -------------- + + initialize: function (element, completer, option) { + this.el = element; + this.$el = $(element); + this.id = completer.id + this.constructor.name; + this.completer = completer; + this.option = option; + + if (this.option.debounce) { + this._onKeyup = debounce(this._onKeyup, this.option.debounce); + } + + this._bindEvents(); + }, + + destroy: function () { + this.$el.off('.' + this.id); // Remove all event handlers. + this.$el = this.el = this.completer = null; + }, + + // Update the element with the given value and strategy. + // + // value - The selected object. It is one of the item of the array + // which was callbacked from the search function. + // strategy - The Strategy associated with the selected value. + select: function (/* value, strategy */) { + throw new Error('Not implemented'); + }, + + // Returns the caret's relative coordinates from body's left top corner. + getCaretPosition: function () { + var position = this._getCaretRelativePosition(); + var offset = this.$el.offset(); + + // Calculate the left top corner of `this.option.appendTo` element. + var $parent = this.option.appendTo; + if ($parent) { + if (!($parent instanceof $)) { $parent = $($parent); } + var parentOffset = $parent.offsetParent().offset(); + offset.top -= parentOffset.top; + offset.left -= parentOffset.left; + } + + position.top += offset.top; + position.left += offset.left; + return position; + }, + + // Focus on the element. + focus: function () { + this.$el.focus(); + }, + + // Private methods + // --------------- + + _bindEvents: function () { + this.$el.on('keyup.' + this.id, $.proxy(this._onKeyup, this)); + }, + + _onKeyup: function (e) { + if (this._skipSearch(e)) { return; } + this.completer.trigger(this.getTextFromHeadToCaret(), true); + }, + + // Suppress searching if it returns true. + _skipSearch: function (clickEvent) { + switch (clickEvent.keyCode) { + case 9: // TAB + case 13: // ENTER + case 40: // DOWN + case 38: // UP + case 27: // ESC + return true; + } + if (clickEvent.ctrlKey) switch (clickEvent.keyCode) { + case 78: // Ctrl-N + case 80: // Ctrl-P + return true; + } + } + }); + + $.fn.textcomplete.Adapter = Adapter; +}(jQuery); + ++function ($) { + 'use strict'; + + // Textarea adapter + // ================ + // + // Managing a textarea. It doesn't know a Dropdown. + function Textarea(element, completer, option) { + this.initialize(element, completer, option); + } + + $.extend(Textarea.prototype, $.fn.textcomplete.Adapter.prototype, { + // Public methods + // -------------- + + // Update the textarea with the given value and strategy. + select: function (value, strategy, e) { + var pre = this.getTextFromHeadToCaret(); + var post = this.el.value.substring(this.el.selectionEnd); + var newSubstr = strategy.replace(value, e); + var regExp; + if (typeof newSubstr !== 'undefined') { + if ($.isArray(newSubstr)) { + post = newSubstr[1] + post; + newSubstr = newSubstr[0]; + } + regExp = $.isFunction(strategy.match) ? strategy.match(pre) : strategy.match; + pre = pre.replace(regExp, newSubstr); + this.$el.val(pre + post); + this.el.selectionStart = this.el.selectionEnd = pre.length; + } + }, + + getTextFromHeadToCaret: function () { + return this.el.value.substring(0, this.el.selectionEnd); + }, + + // Private methods + // --------------- + + _getCaretRelativePosition: function () { + var p = $.fn.textcomplete.getCaretCoordinates(this.el, this.el.selectionStart); + return { + top: p.top + this._calculateLineHeight() - this.$el.scrollTop(), + left: p.left - this.$el.scrollLeft(), + lineHeight: this._calculateLineHeight() + }; + }, + + _calculateLineHeight: function () { + var lineHeight = parseInt(this.$el.css('line-height'), 10); + if (isNaN(lineHeight)) { + // http://stackoverflow.com/a/4515470/1297336 + var parentNode = this.el.parentNode; + var temp = document.createElement(this.el.nodeName); + var style = this.el.style; + temp.setAttribute( + 'style', + 'margin:0px;padding:0px;font-family:' + style.fontFamily + ';font-size:' + style.fontSize + ); + temp.innerHTML = 'test'; + parentNode.appendChild(temp); + lineHeight = temp.clientHeight; + parentNode.removeChild(temp); + } + return lineHeight; + } + }); + + $.fn.textcomplete.Textarea = Textarea; +}(jQuery); + ++function ($) { + 'use strict'; + + var sentinelChar = '吶'; + + function IETextarea(element, completer, option) { + this.initialize(element, completer, option); + $('' + sentinelChar + '').css({ + position: 'absolute', + top: -9999, + left: -9999 + }).insertBefore(element); + } + + $.extend(IETextarea.prototype, $.fn.textcomplete.Textarea.prototype, { + // Public methods + // -------------- + + select: function (value, strategy, e) { + var pre = this.getTextFromHeadToCaret(); + var post = this.el.value.substring(pre.length); + var newSubstr = strategy.replace(value, e); + var regExp; + if (typeof newSubstr !== 'undefined') { + if ($.isArray(newSubstr)) { + post = newSubstr[1] + post; + newSubstr = newSubstr[0]; + } + regExp = $.isFunction(strategy.match) ? strategy.match(pre) : strategy.match; + pre = pre.replace(regExp, newSubstr); + this.$el.val(pre + post); + this.el.focus(); + var range = this.el.createTextRange(); + range.collapse(true); + range.moveEnd('character', pre.length); + range.moveStart('character', pre.length); + range.select(); + } + }, + + getTextFromHeadToCaret: function () { + this.el.focus(); + var range = document.selection.createRange(); + range.moveStart('character', -this.el.value.length); + var arr = range.text.split(sentinelChar) + return arr.length === 1 ? arr[0] : arr[1]; + } + }); + + $.fn.textcomplete.IETextarea = IETextarea; +}(jQuery); + +// NOTE: TextComplete plugin has contenteditable support but it does not work +// fine especially on old IEs. +// Any pull requests are REALLY welcome. + ++function ($) { + 'use strict'; + + // ContentEditable adapter + // ======================= + // + // Adapter for contenteditable elements. + function ContentEditable (element, completer, option) { + this.initialize(element, completer, option); + } + + $.extend(ContentEditable.prototype, $.fn.textcomplete.Adapter.prototype, { + // Public methods + // -------------- + + // Update the content with the given value and strategy. + // When an dropdown item is selected, it is executed. + select: function (value, strategy, e) { + var pre = this.getTextFromHeadToCaret(); + // use ownerDocument instead of window to support iframes + var sel = this.el.ownerDocument.getSelection(); + + var range = sel.getRangeAt(0); + var selection = range.cloneRange(); + selection.selectNodeContents(range.startContainer); + var content = selection.toString(); + var post = content.substring(range.startOffset); + var newSubstr = strategy.replace(value, e); + var regExp; + if (typeof newSubstr !== 'undefined') { + if ($.isArray(newSubstr)) { + post = newSubstr[1] + post; + newSubstr = newSubstr[0]; + } + regExp = $.isFunction(strategy.match) ? strategy.match(pre) : strategy.match; + pre = pre.replace(regExp, newSubstr) + .replace(/ $/, " "); //   necessary at least for CKeditor to not eat spaces + range.selectNodeContents(range.startContainer); + range.deleteContents(); + + // create temporary elements + var preWrapper = this.el.ownerDocument.createElement("div"); + preWrapper.innerHTML = pre; + var postWrapper = this.el.ownerDocument.createElement("div"); + postWrapper.innerHTML = post; + + // create the fragment thats inserted + var fragment = this.el.ownerDocument.createDocumentFragment(); + var childNode; + var lastOfPre; + while (childNode = preWrapper.firstChild) { + lastOfPre = fragment.appendChild(childNode); + } + while (childNode = postWrapper.firstChild) { + fragment.appendChild(childNode); + } + + // insert the fragment & jump behind the last node in "pre" + range.insertNode(fragment); + range.setStartAfter(lastOfPre); + + range.collapse(true); + sel.removeAllRanges(); + sel.addRange(range); + } + }, + + // Private methods + // --------------- + + // Returns the caret's relative position from the contenteditable's + // left top corner. + // + // Examples + // + // this._getCaretRelativePosition() + // //=> { top: 18, left: 200, lineHeight: 16 } + // + // Dropdown's position will be decided using the result. + _getCaretRelativePosition: function () { + var range = this.el.ownerDocument.getSelection().getRangeAt(0).cloneRange(); + var node = this.el.ownerDocument.createElement('span'); + range.insertNode(node); + range.selectNodeContents(node); + range.deleteContents(); + var $node = $(node); + var position = $node.offset(); + position.left -= this.$el.offset().left; + position.top += $node.height() - this.$el.offset().top; + position.lineHeight = $node.height(); + + // special positioning logic for iframes + // this is typically used for contenteditables such as tinymce or ckeditor + if (this.completer.$iframe) { + var iframePosition = this.completer.$iframe.offset(); + position.top += iframePosition.top; + position.left += iframePosition.left; + //subtract scrollTop from element in iframe + position.top -= this.$el.scrollTop(); + } + + $node.remove(); + return position; + }, + + // Returns the string between the first character and the caret. + // Completer will be triggered with the result for start autocompleting. + // + // Example + // + // // Suppose the html is 'hello wor|ld' and | is the caret. + // this.getTextFromHeadToCaret() + // // => ' wor' // not 'hello wor' + getTextFromHeadToCaret: function () { + var range = this.el.ownerDocument.getSelection().getRangeAt(0); + var selection = range.cloneRange(); + selection.selectNodeContents(range.startContainer); + return selection.toString().substring(0, range.startOffset); + } + }); + + $.fn.textcomplete.ContentEditable = ContentEditable; +}(jQuery); + +// NOTE: TextComplete plugin has contenteditable support but it does not work +// fine especially on old IEs. +// Any pull requests are REALLY welcome. + ++function ($) { + 'use strict'; + + // CKEditor adapter + // ======================= + // + // Adapter for CKEditor, based on contenteditable elements. + function CKEditor (element, completer, option) { + this.initialize(element, completer, option); + } + + $.extend(CKEditor.prototype, $.fn.textcomplete.ContentEditable.prototype, { + _bindEvents: function () { + var $this = this; + CKEDITOR.instances["issue_notes"].on('key', function(event) { + var domEvent = event.data; + $this._onKeyup(domEvent); + if ($this.completer.dropdown.shown && $this._skipSearch(domEvent)) { + return false; + } + }, null, null, 1); // 1 = Priority = Important! + // we actually also need the native event, as the CKEditor one is happening to late + this.$el.on('keyup.' + this.id, $.proxy(this._onKeyup, this)); + }, +}); + + $.fn.textcomplete.CKEditor = CKEditor; +}(jQuery); + +// The MIT License (MIT) +// +// Copyright (c) 2015 Jonathan Ong me@jongleberry.com +// +// 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. +// +// https://github.com/component/textarea-caret-position + +(function ($) { + +// The properties that we copy into a mirrored div. +// Note that some browsers, such as Firefox, +// do not concatenate properties, i.e. padding-top, bottom etc. -> padding, +// so we have to do every single property specifically. +var properties = [ + 'direction', // RTL support + 'boxSizing', + 'width', // on Chrome and IE, exclude the scrollbar, so the mirror div wraps exactly as the textarea does + 'height', + 'overflowX', + 'overflowY', // copy the scrollbar for IE + + 'borderTopWidth', + 'borderRightWidth', + 'borderBottomWidth', + 'borderLeftWidth', + 'borderStyle', + + 'paddingTop', + 'paddingRight', + 'paddingBottom', + 'paddingLeft', + + // https://developer.mozilla.org/en-US/docs/Web/CSS/font + 'fontStyle', + 'fontVariant', + 'fontWeight', + 'fontStretch', + 'fontSize', + 'fontSizeAdjust', + 'lineHeight', + 'fontFamily', + + 'textAlign', + 'textTransform', + 'textIndent', + 'textDecoration', // might not make a difference, but better be safe + + 'letterSpacing', + 'wordSpacing', + + 'tabSize', + 'MozTabSize' + +]; + +var isBrowser = (typeof window !== 'undefined'); +var isFirefox = (isBrowser && window.mozInnerScreenX != null); + +function getCaretCoordinates(element, position, options) { + if(!isBrowser) { + throw new Error('textarea-caret-position#getCaretCoordinates should only be called in a browser'); + } + + var debug = options && options.debug || false; + if (debug) { + var el = document.querySelector('#input-textarea-caret-position-mirror-div'); + if ( el ) { el.parentNode.removeChild(el); } + } + + // mirrored div + var div = document.createElement('div'); + div.id = 'input-textarea-caret-position-mirror-div'; + document.body.appendChild(div); + + var style = div.style; + var computed = window.getComputedStyle? getComputedStyle(element) : element.currentStyle; // currentStyle for IE < 9 + + // default textarea styles + style.whiteSpace = 'pre-wrap'; + if (element.nodeName !== 'INPUT') + style.wordWrap = 'break-word'; // only for textarea-s + + // position off-screen + style.position = 'absolute'; // required to return coordinates properly + if (!debug) + style.visibility = 'hidden'; // not 'display: none' because we want rendering + + // transfer the element's properties to the div + properties.forEach(function (prop) { + style[prop] = computed[prop]; + }); + + if (isFirefox) { + // Firefox lies about the overflow property for textareas: https://bugzilla.mozilla.org/show_bug.cgi?id=984275 + if (element.scrollHeight > parseInt(computed.height)) + style.overflowY = 'scroll'; + } else { + style.overflow = 'hidden'; // for Chrome to not render a scrollbar; IE keeps overflowY = 'scroll' + } + + div.textContent = element.value.substring(0, position); + // the second special handling for input type="text" vs textarea: spaces need to be replaced with non-breaking spaces - http://stackoverflow.com/a/13402035/1269037 + if (element.nodeName === 'INPUT') + div.textContent = div.textContent.replace(/\s/g, '\u00a0'); + + var span = document.createElement('span'); + // Wrapping must be replicated *exactly*, including when a long word gets + // onto the next line, with whitespace at the end of the line before (#7). + // The *only* reliable way to do that is to copy the *entire* rest of the + // textarea's content into the created at the caret position. + // for inputs, just '.' would be enough, but why bother? + span.textContent = element.value.substring(position) || '.'; // || because a completely empty faux span doesn't render at all + div.appendChild(span); + + var coordinates = { + top: span.offsetTop + parseInt(computed['borderTopWidth']), + left: span.offsetLeft + parseInt(computed['borderLeftWidth']) + }; + + if (debug) { + span.style.backgroundColor = '#aaa'; + } else { + document.body.removeChild(div); + } + + return coordinates; +} + +$.fn.textcomplete.getCaretCoordinates = getCaretCoordinates; + +}(jQuery)); + +return jQuery; +})); diff --git a/pagure/static/emoji/jquery.textcomplete-1.7.1.min.js b/pagure/static/emoji/jquery.textcomplete-1.7.1.min.js new file mode 100644 index 0000000..32f6414 --- /dev/null +++ b/pagure/static/emoji/jquery.textcomplete-1.7.1.min.js @@ -0,0 +1,3 @@ +/*! jquery-textcomplete - v1.7.1 - 2016-08-29 */ +!function(a){if("function"==typeof define&&define.amd)define(["jquery"],a);else if("object"==typeof module&&module.exports){var b=require("jquery");module.exports=a(b)}else a(jQuery)}(function(a){if("undefined"==typeof a)throw new Error("jQuery.textcomplete requires jQuery");return+function(a){"use strict";var b=function(a){console.warn&&console.warn(a)},c=1;a.fn.textcomplete=function(d,e){var f=Array.prototype.slice.call(arguments);return this.each(function(){var g=this,h=a(this),i=h.data("textComplete");if(i||(e||(e={}),e._oid=c++,i=new a.fn.textcomplete.Completer(this,e),h.data("textComplete",i)),"string"==typeof d){if(!i)return;f.shift(),i[d].apply(i,f),"destroy"===d&&h.removeData("textComplete")}else a.each(d,function(c){a.each(["header","footer","placement","maxCount"],function(a){c[a]&&(i.option[a]=c[a],b(a+"as a strategy param is deprecated. Use option."),delete c[a])})}),i.register(a.fn.textcomplete.Strategy.parse(d,{el:g,$el:h}))})}}(a),+function(a){"use strict";function b(c,d){if(this.$el=a(c),this.id="textcomplete"+e++,this.strategies=[],this.views=[],this.option=a.extend({},b.defaults,d),!(this.$el.is("input[type=text]")||this.$el.is("input[type=search]")||this.$el.is("textarea")||c.isContentEditable||"true"==c.contentEditable))throw new Error("textcomplete must be called on a Textarea or a ContentEditable.");if(c===c.ownerDocument.activeElement)this.initialize();else{var f=this;this.$el.one("focus."+this.id,function(){f.initialize()}),this.option.adapter&&"CKEditor"!=this.option.adapter||"undefined"==typeof CKEDITOR||!this.$el.is("textarea")||CKEDITOR.on("instanceReady",function(b){b.editor.once("focus",function(c){f.$el=a(b.editor.editable().$),f.option.adapter||(f.option.adapter=a.fn.textcomplete.CKEditor),f.initialize()})})}}var c=function(a){var b,c;return function(){var d=Array.prototype.slice.call(arguments);if(b)return void(c=d);b=!0;var e=this;d.unshift(function f(){if(c){var d=c;c=void 0,d.unshift(f),a.apply(e,d)}else b=!1}),a.apply(this,d)}},d=function(a){return"[object String]"===Object.prototype.toString.call(a)},e=0;b.defaults={appendTo:"body",className:"",dropdownClassName:"dropdown-menu textcomplete-dropdown",maxCount:10,zIndex:"100",rightEdgeOffset:30},a.extend(b.prototype,{id:null,option:null,strategies:null,adapter:null,dropdown:null,$el:null,$iframe:null,initialize:function(){var b=this.$el.get(0);if(this.$el.prop("ownerDocument")!==document&&window.frames.length)for(var c=0;c").addClass(b.dropdownClassName).attr("id","textcomplete-dropdown-"+b._oid).css({display:"none",left:0,position:"absolute",zIndex:b.zIndex}).appendTo(c);return d}}),a.extend(b.prototype,{$el:null,$inputEl:null,completer:null,footer:null,header:null,id:null,maxCount:null,placement:"",shown:!1,data:[],className:"",destroy:function(){this.deactivate(),this.$el.off("."+this.id),this.$inputEl.off("."+this.id),this.clear(),this.$el.remove(),this.$el=this.$inputEl=this.completer=null,delete e[this.id]},render:function(b){var c=this._buildContents(b),d=a.map(this.data,function(a){return a.value});if(this.data.length){var e=b[0].strategy;e.id?this.$el.attr("data-strategy",e.id):this.$el.removeAttr("data-strategy"),this._renderHeader(d),this._renderFooter(d),c&&(this._renderContents(c),this._fitToBottom(),this._fitToRight(),this._activateIndexedItem()),this._setScroll()}else this.noResultsMessage?this._renderNoResultsMessage(d):this.shown&&this.deactivate()},setPosition:function(b){var d="absolute";return this.$inputEl.add(this.$inputEl.parents()).each(function(){return"absolute"===a(this).css("position")?!1:"fixed"===a(this).css("position")?(b.top-=c.scrollTop(),b.left-=c.scrollLeft(),d="fixed",!1):void 0}),this.$el.css(this._applyPlacement(b)),this.$el.css({position:d}),this},clear:function(){this.$el.html(""),this.data=[],this._index=0,this._$header=this._$footer=this._$noResultsMessage=null},activate:function(){return this.shown||(this.clear(),this.$el.show(),this.className&&this.$el.addClass(this.className),this.completer.fire("textComplete:show"),this.shown=!0),this},deactivate:function(){return this.shown&&(this.$el.hide(),this.className&&this.$el.removeClass(this.className),this.completer.fire("textComplete:hide"),this.shown=!1),this},isUp:function(a){return 38===a.keyCode||a.ctrlKey&&80===a.keyCode},isDown:function(a){return 40===a.keyCode||a.ctrlKey&&78===a.keyCode},isEnter:function(a){var b=a.ctrlKey||a.altKey||a.metaKey||a.shiftKey;return!b&&(13===a.keyCode||9===a.keyCode||this.option.completeOnSpace===!0&&32===a.keyCode)},isPageup:function(a){return 33===a.keyCode},isPagedown:function(a){return 34===a.keyCode},isEscape:function(a){return 27===a.keyCode},_data:null,_index:null,_$header:null,_$noResultsMessage:null,_$footer:null,_bindEvents:function(){this.$el.on("mousedown."+this.id,".textcomplete-item",a.proxy(this._onClick,this)),this.$el.on("touchstart."+this.id,".textcomplete-item",a.proxy(this._onClick,this)),this.$el.on("mouseover."+this.id,".textcomplete-item",a.proxy(this._onMouseover,this)),this.$inputEl.on("keydown."+this.id,a.proxy(this._onKeydown,this))},_onClick:function(b){var c=a(b.target);b.preventDefault(),b.originalEvent.keepTextCompleteDropdown=this.id,c.hasClass("textcomplete-item")||(c=c.closest(".textcomplete-item"));var d=this.data[parseInt(c.data("index"),10)];this.completer.select(d.value,d.strategy,b);var e=this;setTimeout(function(){e.deactivate(),"touchstart"===b.type&&e.$inputEl.focus()},0)},_onMouseover:function(b){var c=a(b.target);b.preventDefault(),c.hasClass("textcomplete-item")||(c=c.closest(".textcomplete-item")),this._index=parseInt(c.data("index"),10),this._activateIndexedItem()},_onKeydown:function(b){if(this.shown){var c;switch(a.isFunction(this.option.onKeydown)&&(c=this.option.onKeydown(b,f)),null==c&&(c=this._defaultKeydown(b)),c){case f.KEY_UP:b.preventDefault(),this._up();break;case f.KEY_DOWN:b.preventDefault(),this._down();break;case f.KEY_ENTER:b.preventDefault(),this._enter(b);break;case f.KEY_PAGEUP:b.preventDefault(),this._pageup();break;case f.KEY_PAGEDOWN:b.preventDefault(),this._pagedown();break;case f.KEY_ESCAPE:b.preventDefault(),this.deactivate()}}},_defaultKeydown:function(a){return this.isUp(a)?f.KEY_UP:this.isDown(a)?f.KEY_DOWN:this.isEnter(a)?f.KEY_ENTER:this.isPageup(a)?f.KEY_PAGEUP:this.isPagedown(a)?f.KEY_PAGEDOWN:this.isEscape(a)?f.KEY_ESCAPE:void 0},_up:function(){0===this._index?this._index=this.data.length-1:this._index-=1,this._activateIndexedItem(),this._setScroll()},_down:function(){this._index===this.data.length-1?this._index=0:this._index+=1,this._activateIndexedItem(),this._setScroll()},_enter:function(a){var b=this.data[parseInt(this._getActiveElement().data("index"),10)];this.completer.select(b.value,b.strategy,a),this.deactivate()},_pageup:function(){var b=0,c=this._getActiveElement().position().top-this.$el.innerHeight();this.$el.children().each(function(d){return a(this).position().top+a(this).outerHeight()>c?(b=d,!1):void 0}),this._index=b,this._activateIndexedItem(),this._setScroll()},_pagedown:function(){var b=this.data.length-1,c=this._getActiveElement().position().top+this.$el.innerHeight();this.$el.children().each(function(d){return a(this).position().top>c?(b=d,!1):void 0}),this._index=b,this._activateIndexedItem(),this._setScroll()},_activateIndexedItem:function(){this.$el.find(".textcomplete-item.active").removeClass("active"),this._getActiveElement().addClass("active")},_getActiveElement:function(){return this.$el.children(".textcomplete-item:nth("+this._index+")")},_setScroll:function(){var a=this._getActiveElement(),b=a.position().top,c=a.outerHeight(),d=this.$el.innerHeight(),e=this.$el.scrollTop();0===this._index||this._index==this.data.length-1||0>b?this.$el.scrollTop(b+e):b+c>d&&this.$el.scrollTop(b+c+e-d)},_buildContents:function(a){var b,c,e,f="";for(c=0;c',f+=b.strategy.template(b.value,b.term),f+="");return f},_renderHeader:function(b){if(this.header){this._$header||(this._$header=a('
        • ').prependTo(this.$el));var c=a.isFunction(this.header)?this.header(b):this.header;this._$header.html(c)}},_renderFooter:function(b){if(this.footer){this._$footer||(this._$footer=a('').appendTo(this.$el));var c=a.isFunction(this.footer)?this.footer(b):this.footer;this._$footer.html(c)}},_renderNoResultsMessage:function(b){if(this.noResultsMessage){this._$noResultsMessage||(this._$noResultsMessage=a('
        • ').appendTo(this.$el));var c=a.isFunction(this.noResultsMessage)?this.noResultsMessage(b):this.noResultsMessage;this._$noResultsMessage.html(c)}},_renderContents:function(a){this._$footer?this._$footer.before(a):this.$el.append(a)},_fitToBottom:function(){var a=c.scrollTop()+c.height(),b=this.$el.height();this.$el.position().top+b>a&&(this.completer.$iframe||this.$el.offset({top:a-b}))},_fitToRight:function(){for(var a,b=this.option.rightEdgeOffset,d=this.$el.offset().left,e=this.$el.width(),f=c.width()-b;d+e>f&&(this.$el.offset({left:d-b}),a=this.$el.offset().left,!(a>=d));)d=a},_applyPlacement:function(a){return-1!==this.placement.indexOf("top")?a={top:"auto",bottom:this.$el.parent().height()-a.top+a.lineHeight,left:a.left}:(a.bottom="auto",delete a.lineHeight),-1!==this.placement.indexOf("absleft")?a.left=0:-1!==this.placement.indexOf("absright")&&(a.right=0,a.left="auto"),a}}),a.fn.textcomplete.Dropdown=b,a.extend(a.fn.textcomplete,f)}(a),+function(a){"use strict";function b(b){a.extend(this,b),this.cache&&(this.search=c(this.search))}var c=function(a){var b={};return function(c,d){b[c]?d(b[c]):a.call(this,c,function(a){b[c]=(b[c]||[]).concat(a),d.apply(null,arguments)})}};b.parse=function(c,d){return a.map(c,function(a){var c=new b(a);return c.el=d.el,c.$el=d.$el,c})},a.extend(b.prototype,{match:null,replace:null,search:null,id:null,cache:!1,context:function(){return!0},index:2,template:function(a){return a},idProperty:null}),a.fn.textcomplete.Strategy=b}(a),+function(a){"use strict";function b(){}var c=Date.now||function(){return(new Date).getTime()},d=function(a,b){var d,e,f,g,h,i=function(){var j=c()-g;b>j?d=setTimeout(i,b-j):(d=null,h=a.apply(f,e),f=e=null)};return function(){return f=this,e=arguments,g=c(),d||(d=setTimeout(i,b)),h}};a.extend(b.prototype,{id:null,completer:null,el:null,$el:null,option:null,initialize:function(b,c,e){this.el=b,this.$el=a(b),this.id=c.id+this.constructor.name,this.completer=c,this.option=e,this.option.debounce&&(this._onKeyup=d(this._onKeyup,this.option.debounce)),this._bindEvents()},destroy:function(){this.$el.off("."+this.id),this.$el=this.el=this.completer=null},select:function(){throw new Error("Not implemented")},getCaretPosition:function(){var b=this._getCaretRelativePosition(),c=this.$el.offset(),d=this.option.appendTo;if(d){d instanceof a||(d=a(d));var e=d.offsetParent().offset();c.top-=e.top,c.left-=e.left}return b.top+=c.top,b.left+=c.left,b},focus:function(){this.$el.focus()},_bindEvents:function(){this.$el.on("keyup."+this.id,a.proxy(this._onKeyup,this))},_onKeyup:function(a){this._skipSearch(a)||this.completer.trigger(this.getTextFromHeadToCaret(),!0)},_skipSearch:function(a){switch(a.keyCode){case 9:case 13:case 40:case 38:case 27:return!0}if(a.ctrlKey)switch(a.keyCode){case 78:case 80:return!0}}}),a.fn.textcomplete.Adapter=b}(a),+function(a){"use strict";function b(a,b,c){this.initialize(a,b,c)}a.extend(b.prototype,a.fn.textcomplete.Adapter.prototype,{select:function(b,c,d){var e,f=this.getTextFromHeadToCaret(),g=this.el.value.substring(this.el.selectionEnd),h=c.replace(b,d);"undefined"!=typeof h&&(a.isArray(h)&&(g=h[1]+g,h=h[0]),e=a.isFunction(c.match)?c.match(f):c.match,f=f.replace(e,h),this.$el.val(f+g),this.el.selectionStart=this.el.selectionEnd=f.length)},getTextFromHeadToCaret:function(){return this.el.value.substring(0,this.el.selectionEnd)},_getCaretRelativePosition:function(){var b=a.fn.textcomplete.getCaretCoordinates(this.el,this.el.selectionStart);return{top:b.top+this._calculateLineHeight()-this.$el.scrollTop(),left:b.left-this.$el.scrollLeft(),lineHeight:this._calculateLineHeight()}},_calculateLineHeight:function(){var a=parseInt(this.$el.css("line-height"),10);if(isNaN(a)){var b=this.el.parentNode,c=document.createElement(this.el.nodeName),d=this.el.style;c.setAttribute("style","margin:0px;padding:0px;font-family:"+d.fontFamily+";font-size:"+d.fontSize),c.innerHTML="test",b.appendChild(c),a=c.clientHeight,b.removeChild(c)}return a}}),a.fn.textcomplete.Textarea=b}(a),+function(a){"use strict";function b(b,d,e){this.initialize(b,d,e),a(""+c+"").css({position:"absolute",top:-9999,left:-9999}).insertBefore(b)}var c="吶";a.extend(b.prototype,a.fn.textcomplete.Textarea.prototype,{select:function(b,c,d){var e,f=this.getTextFromHeadToCaret(),g=this.el.value.substring(f.length),h=c.replace(b,d);if("undefined"!=typeof h){a.isArray(h)&&(g=h[1]+g,h=h[0]),e=a.isFunction(c.match)?c.match(f):c.match,f=f.replace(e,h),this.$el.val(f+g),this.el.focus();var i=this.el.createTextRange();i.collapse(!0),i.moveEnd("character",f.length),i.moveStart("character",f.length),i.select()}},getTextFromHeadToCaret:function(){this.el.focus();var a=document.selection.createRange();a.moveStart("character",-this.el.value.length);var b=a.text.split(c);return 1===b.length?b[0]:b[1]}}),a.fn.textcomplete.IETextarea=b}(a),+function(a){"use strict";function b(a,b,c){this.initialize(a,b,c)}a.extend(b.prototype,a.fn.textcomplete.Adapter.prototype,{select:function(b,c,d){var e=this.getTextFromHeadToCaret(),f=this.el.ownerDocument.getSelection(),g=f.getRangeAt(0),h=g.cloneRange();h.selectNodeContents(g.startContainer);var i,j=h.toString(),k=j.substring(g.startOffset),l=c.replace(b,d);if("undefined"!=typeof l){a.isArray(l)&&(k=l[1]+k,l=l[0]),i=a.isFunction(c.match)?c.match(e):c.match,e=e.replace(i,l).replace(/ $/," "),g.selectNodeContents(g.startContainer),g.deleteContents();var m=this.el.ownerDocument.createElement("div");m.innerHTML=e;var n=this.el.ownerDocument.createElement("div");n.innerHTML=k;for(var o,p,q=this.el.ownerDocument.createDocumentFragment();o=m.firstChild;)p=q.appendChild(o);for(;o=n.firstChild;)q.appendChild(o);g.insertNode(q),g.setStartAfter(p),g.collapse(!0),f.removeAllRanges(),f.addRange(g)}},_getCaretRelativePosition:function(){var b=this.el.ownerDocument.getSelection().getRangeAt(0).cloneRange(),c=this.el.ownerDocument.createElement("span");b.insertNode(c),b.selectNodeContents(c),b.deleteContents();var d=a(c),e=d.offset();if(e.left-=this.$el.offset().left,e.top+=d.height()-this.$el.offset().top,e.lineHeight=d.height(),this.completer.$iframe){var f=this.completer.$iframe.offset();e.top+=f.top,e.left+=f.left,e.top-=this.$el.scrollTop()}return d.remove(),e},getTextFromHeadToCaret:function(){var a=this.el.ownerDocument.getSelection().getRangeAt(0),b=a.cloneRange();return b.selectNodeContents(a.startContainer),b.toString().substring(0,a.startOffset)}}),a.fn.textcomplete.ContentEditable=b}(a),+function(a){"use strict";function b(a,b,c){this.initialize(a,b,c)}a.extend(b.prototype,a.fn.textcomplete.ContentEditable.prototype,{_bindEvents:function(){var b=this;CKEDITOR.instances.issue_notes.on("key",function(a){var c=a.data;return b._onKeyup(c),b.completer.dropdown.shown&&b._skipSearch(c)?!1:void 0},null,null,1),this.$el.on("keyup."+this.id,a.proxy(this._onKeyup,this))}}),a.fn.textcomplete.CKEditor=b}(a),function(a){function b(a,b,f){if(!d)throw new Error("textarea-caret-position#getCaretCoordinates should only be called in a browser");var g=f&&f.debug||!1;if(g){var h=document.querySelector("#input-textarea-caret-position-mirror-div");h&&h.parentNode.removeChild(h)}var i=document.createElement("div");i.id="input-textarea-caret-position-mirror-div",document.body.appendChild(i);var j=i.style,k=window.getComputedStyle?getComputedStyle(a):a.currentStyle;j.whiteSpace="pre-wrap","INPUT"!==a.nodeName&&(j.wordWrap="break-word"),j.position="absolute",g||(j.visibility="hidden"),c.forEach(function(a){j[a]=k[a]}),e?a.scrollHeight>parseInt(k.height)&&(j.overflowY="scroll"):j.overflow="hidden",i.textContent=a.value.substring(0,b),"INPUT"===a.nodeName&&(i.textContent=i.textContent.replace(/\s/g," "));var l=document.createElement("span");l.textContent=a.value.substring(b)||".",i.appendChild(l);var m={top:l.offsetTop+parseInt(k.borderTopWidth),left:l.offsetLeft+parseInt(k.borderLeftWidth)};return g?l.style.backgroundColor="#aaa":document.body.removeChild(i),m}var c=["direction","boxSizing","width","height","overflowX","overflowY","borderTopWidth","borderRightWidth","borderBottomWidth","borderLeftWidth","borderStyle","paddingTop","paddingRight","paddingBottom","paddingLeft","fontStyle","fontVariant","fontWeight","fontStretch","fontSize","fontSizeAdjust","lineHeight","fontFamily","textAlign","textTransform","textIndent","textDecoration","letterSpacing","wordSpacing","tabSize","MozTabSize"],d="undefined"!=typeof window,e=d&&null!=window.mozInnerScreenX;a.fn.textcomplete.getCaretCoordinates=b}(a),a}); +//# sourceMappingURL=dist/jquery.textcomplete.min.map \ No newline at end of file diff --git a/pagure/static/emoji/jquery.textcomplete.js b/pagure/static/emoji/jquery.textcomplete.js new file mode 120000 index 0000000..a2bee68 --- /dev/null +++ b/pagure/static/emoji/jquery.textcomplete.js @@ -0,0 +1 @@ +jquery.textcomplete-1.7.1.js \ No newline at end of file diff --git a/pagure/static/emoji/jquery.textcomplete.min.js b/pagure/static/emoji/jquery.textcomplete.min.js deleted file mode 100644 index d7aed69..0000000 --- a/pagure/static/emoji/jquery.textcomplete.min.js +++ /dev/null @@ -1,4 +0,0 @@ -/*! jquery-textcomplete - v0.3.2 - 2014-09-16 */if("undefined"==typeof jQuery)throw new Error("jQuery.textcomplete requires jQuery");+function(a){"use strict";var b=function(a){console.warn&&console.warn(a)};a.fn.textcomplete=function(c,d){var e=Array.prototype.slice.call(arguments);return this.each(function(){var f=a(this),g=f.data("textComplete");g||(g=new a.fn.textcomplete.Completer(this,d||{}),f.data("textComplete",g)),"string"==typeof c?(e.shift(),g[c].apply(g,e)):(a.each(c,function(c){a.each(["header","footer","placement","maxCount"],function(a){c[a]&&(g.option[a]=c[a],b(a+"as a strategy param is deplicated. Use option."),delete c[a])})}),g.register(a.fn.textcomplete.Strategy.parse(c)))})}}(jQuery),+function(a){"use strict";function b(c,d){if(this.$el=a(c),this.id="textcomplete"+e++,this.strategies=[],this.views=[],this.option=a.extend({},b.DEFAULTS,d),!this.$el.is("textarea")&&!c.isContentEditable)throw new Error("textcomplete must be called to a Textarea or a ContentEditable.");if(c===document.activeElement)this.initialize();else{var f=this;this.$el.one("focus."+this.id,function(){f.initialize()})}}var c=function(a){var b,c;return function(){var d=Array.prototype.slice.call(arguments);if(b)return c=d,void 0;b=!0;var e=this;d.unshift(function f(){if(c){var d=c;c=void 0,d.unshift(f),a.apply(e,d)}else b=!1}),a.apply(this,d)}},d=function(a){return"[object String]"===Object.prototype.toString.call(a)},e=0;b.DEFAULTS={appendTo:a("body"),zIndex:"100"},a.extend(b.prototype,{id:null,option:null,strategies:null,adapter:null,dropdown:null,$el:null,initialize:function(){var b=this.$el.get(0);this.dropdown=new a.fn.textcomplete.Dropdown(b,this,this.option);var c,d;this.option.adapter?c=this.option.adapter:(d=this.$el.is("textarea")?"number"==typeof b.selectionEnd?"Textarea":"IETextarea":"ContentEditable",c=a.fn.textcomplete[d]),this.adapter=new c(b,this,this.option)},destroy:function(){this.$el.off("."+this.id),this.adapter.destroy(),this.dropdown.destroy(),this.$el=this.adapter=this.dropdown=null},trigger:function(a,b){this.dropdown||this.initialize();var c=this._extractSearchQuery(a);if(c.length){var d=c[1];if(b&&this._term===d)return;this._term=d,this._search.apply(this,c)}else this._term=null,this.dropdown.deactivate()},fire:function(a){return this.$el.trigger(a),this},register:function(a){Array.prototype.push.apply(this.strategies,a)},select:function(a,b){this.adapter.select(a,b),this.fire("change").fire("textComplete:select",a,b),this.adapter.focus()},_clearAtNext:!0,_term:null,_extractSearchQuery:function(a){for(var b=0;b').css({display:"none",left:0,position:"absolute",zIndex:b.zIndex}).appendTo(c)),d}}),a.extend(b.prototype,{$el:null,$inputEl:null,completer:null,footer:null,header:null,id:null,maxCount:10,placement:"",shown:!1,data:[],destroy:function(){this.$el.off("."+this.id),this.$inputEl.off("."+this.id),this.clear(),this.$el=this.$inputEl=this.completer=null,delete d[this.id]},render:function(b){var c=this._buildContents(b),d=a.map(this.data,function(a){return a.value});this.data.length?(this._renderHeader(d),this._renderFooter(d),c&&(this._renderContents(c),this._activateIndexedItem()),this._setScroll()):this.shown&&this.deactivate()},setPosition:function(a){return this.$el.css(this._applyPlacement(a)),this},clear:function(){this.$el.html(""),this.data=[],this._index=0,this._$header=this._$footer=null},activate:function(){return this.shown||(this.clear(),this.$el.show(),this.completer.fire("textComplete:show"),this.shown=!0),this},deactivate:function(){return this.shown&&(this.$el.hide(),this.completer.fire("textComplete:hide"),this.shown=!1),this},isUp:function(a){return 38===a.keyCode||a.ctrlKey&&80===a.keyCode},isDown:function(a){return 40===a.keyCode||a.ctrlKey&&78===a.keyCode},isEnter:function(a){var b=a.ctrlKey||a.altKey||a.metaKey||a.shiftKey;return!b&&(13===a.keyCode||9===a.keyCode)},isPageup:function(a){return 33===a.keyCode},isPagedown:function(a){return 34===a.keyCode},_data:null,_index:null,_$header:null,_$footer:null,_bindEvents:function(){this.$el.on("mousedown."+this.id,".textcomplete-item",a.proxy(this._onClick,this)),this.$el.on("mouseover."+this.id,".textcomplete-item",a.proxy(this._onMouseover,this)),this.$inputEl.on("keydown."+this.id,a.proxy(this._onKeydown,this))},_onClick:function(b){var c=a(b.target);b.preventDefault(),b.originalEvent.keepTextCompleteDropdown=this.id,c.hasClass("textcomplete-item")||(c=c.closest(".textcomplete-item"));var d=this.data[parseInt(c.data("index"),10)];this.completer.select(d.value,d.strategy);var e=this;setTimeout(function(){e.deactivate()},0)},_onMouseover:function(b){var c=a(b.target);b.preventDefault(),c.hasClass("textcomplete-item")||(c=c.closest(".textcomplete-item")),this._index=parseInt(c.data("index"),10),this._activateIndexedItem()},_onKeydown:function(a){this.shown&&(this.isUp(a)?(a.preventDefault(),this._up()):this.isDown(a)?(a.preventDefault(),this._down()):this.isEnter(a)?(a.preventDefault(),this._enter()):this.isPageup(a)?(a.preventDefault(),this._pageup()):this.isPagedown(a)&&(a.preventDefault(),this._pagedown()))},_up:function(){0===this._index?this._index=this.data.length-1:this._index-=1,this._activateIndexedItem(),this._setScroll()},_down:function(){this._index===this.data.length-1?this._index=0:this._index+=1,this._activateIndexedItem(),this._setScroll()},_enter:function(){var a=this.data[parseInt(this._getActiveElement().data("index"),10)];this.completer.select(a.value,a.strategy),this._setScroll()},_pageup:function(){var b=0,c=this._getActiveElement().position().top-this.$el.innerHeight();this.$el.children().each(function(d){return a(this).position().top+a(this).outerHeight()>c?(b=d,!1):void 0}),this._index=b,this._activateIndexedItem(),this._setScroll()},_pagedown:function(){var b=this.data.length-1,c=this._getActiveElement().position().top+this.$el.innerHeight();this.$el.children().each(function(d){return a(this).position().top>c?(b=d,!1):void 0}),this._index=b,this._activateIndexedItem(),this._setScroll()},_activateIndexedItem:function(){this.$el.find(".textcomplete-item.active").removeClass("active"),this._getActiveElement().addClass("active")},_getActiveElement:function(){return this.$el.children(".textcomplete-item:nth("+this._index+")")},_setScroll:function(){var a=this._getActiveElement(),b=a.position().top,c=a.outerHeight(),d=this.$el.innerHeight(),e=this.$el.scrollTop();0===this._index||this._index==this.data.length-1||0>b?this.$el.scrollTop(b+e):b+c>d&&this.$el.scrollTop(b+c+e-d)},_buildContents:function(a){var b,d,e,f="";for(d=0;d',f+=b.strategy.template(b.value),f+="");return f},_renderHeader:function(b){if(this.header){this._$header||(this._$header=a('
        • ').prependTo(this.$el));var c=a.isFunction(this.header)?this.header(b):this.header;this._$header.html(c)}},_renderFooter:function(b){if(this.footer){this._$footer||(this._$footer=a('').appendTo(this.$el));var c=a.isFunction(this.footer)?this.footer(b):this.footer;this._$footer.html(c)}},_renderContents:function(a){this._$footer?this._$footer.before(a):this.$el.append(a)},_applyPlacement:function(a){return-1!==this.placement.indexOf("top")?a={top:"auto",bottom:this.$el.parent().height()-a.top+a.lineHeight,left:a.left}:(a.bottom="auto",delete a.lineHeight),-1!==this.placement.indexOf("absleft")?a.left=0:-1!==this.placement.indexOf("absright")&&(a.right=0,a.left="auto"),a}}),a.fn.textcomplete.Dropdown=b}(jQuery),+function(a){"use strict";function b(b){a.extend(this,b),this.cache&&(this.search=c(this.search))}var c=function(a){var b={};return function(c,d){b[c]?d(b[c]):a.call(this,c,function(a){b[c]=(b[c]||[]).concat(a),d.apply(null,arguments)})}};b.parse=function(c){return a.map(c,function(a){return new b(a)})},a.extend(b.prototype,{match:null,replace:null,search:null,cache:!1,context:function(){return!0},index:2,template:function(a){return a},idProperty:null}),a.fn.textcomplete.Strategy=b}(jQuery),+function(a){"use strict";function b(){}var c=Date.now||function(){return(new Date).getTime()},d=function(a,b){var d,e,f,g,h,i=function(){var j=c()-g;b>j?d=setTimeout(i,b-j):(d=null,h=a.apply(f,e),f=e=null)};return function(){return f=this,e=arguments,g=c(),d||(d=setTimeout(i,b)),h}};a.extend(b.prototype,{id:null,completer:null,el:null,$el:null,option:null,initialize:function(b,c,e){this.el=b,this.$el=a(b),this.id=c.id+this.constructor.name,this.completer=c,this.option=e,this.option.debounce&&(this._onKeyup=d(this._onKeyup,this.option.debounce)),this._bindEvents()},destroy:function(){this.$el.off("."+this.id),this.$el=this.el=this.completer=null},select:function(){throw new Error("Not implemented")},getCaretPosition:function(){var a=this._getCaretRelativePosition(),b=this.$el.offset();return a.top+=b.top,a.left+=b.left,a},focus:function(){this.$el.focus()},_bindEvents:function(){this.$el.on("keyup."+this.id,a.proxy(this._onKeyup,this))},_onKeyup:function(a){this._skipSearch(a)||this.completer.trigger(this._getTextFromHeadToCaret(),!0)},_skipSearch:function(a){switch(a.keyCode){case 40:case 38:return!0}if(a.ctrlKey)switch(a.keyCode){case 78:case 80:return!0}}}),a.fn.textcomplete.Adapter=b}(jQuery),+function(a){"use strict";function b(a,b,c){this.initialize(a,b,c)}b.DIV_PROPERTIES={left:-9999,position:"absolute",top:0,whiteSpace:"pre-wrap"},b.COPY_PROPERTIES=["border-width","font-family","font-size","font-style","font-variant","font-weight","height","letter-spacing","word-spacing","line-height","text-decoration","text-align","width","padding-top","padding-right","padding-bottom","padding-left","margin-top","margin-right","margin-bottom","margin-left","border-style","box-sizing","tab-size"],a.extend(b.prototype,a.fn.textcomplete.Adapter.prototype,{select:function(b,c){var d=this._getTextFromHeadToCaret(),e=this.el.value.substring(this.el.selectionEnd),f=c.replace(b);a.isArray(f)&&(e=f[1]+e,f=f[0]),d=d.replace(c.match,f),this.$el.val(d+e),this.el.selectionStart=this.el.selectionEnd=d.length},_getCaretRelativePosition:function(){var b=a("
          ").css(this._copyCss()).text(this._getTextFromHeadToCaret()),c=a("").text(".").appendTo(b);this.$el.before(b);var d=c.position();return d.top+=c.height()-this.$el.scrollTop(),d.lineHeight=c.height(),b.remove(),d},_copyCss:function(){return a.extend({overflow:this.el.scrollHeight>this.el.offsetHeight?"scroll":"auto"},b.DIV_PROPERTIES,this._getStyles())},_getStyles:function(a){var c=a("
          ").css(["color"]).color;return"undefined"!=typeof c?function(){return this.$el.css(b.COPY_PROPERTIES)}:function(){var c=this.$el,d={};return a.each(b.COPY_PROPERTIES,function(a,b){d[b]=c.css(b)}),d}}(a),_getTextFromHeadToCaret:function(){return this.el.value.substring(0,this.el.selectionEnd)}}),a.fn.textcomplete.Textarea=b}(jQuery),+function(a){"use strict";function b(b,d,e){this.initialize(b,d,e),a(""+c+"").css({position:"absolute",top:-9999,left:-9999}).insertBefore(b)}var c="吶";a.extend(b.prototype,a.fn.textcomplete.Textarea.prototype,{select:function(b,c){var d=this._getTextFromHeadToCaret(),e=this.el.value.substring(d.length),f=c.replace(b);a.isArray(f)&&(e=f[1]+e,f=f[0]),d=d.replace(c.match,f),this.$el.val(d+e),this.el.focus();var g=this.el.createTextRange();g.collapse(!0),g.moveEnd("character",d.length),g.moveStart("character",d.length),g.select()},_getTextFromHeadToCaret:function(){this.el.focus();var a=document.selection.createRange();a.moveStart("character",-this.el.value.length);var b=a.text.split(c);return 1===b.length?b[0]:b[1]}}),a.fn.textcomplete.IETextarea=b}(jQuery),+function(a){"use strict";function b(a,b,c){this.initialize(a,b,c)}a.extend(b.prototype,a.fn.textcomplete.Adapter.prototype,{select:function(b,c){var d=this._getTextFromHeadToCaret(),e=window.getSelection(),f=e.getRangeAt(0),g=f.cloneRange();g.selectNodeContents(f.startContainer);var h=g.toString(),i=h.substring(f.startOffset),j=c.replace(b);a.isArray(j)&&(i=j[1]+i,j=j[0]),d=d.replace(c.match,j),f.selectNodeContents(f.startContainer),f.deleteContents();var k=document.createTextNode(d+i);f.insertNode(k),f.setStart(k,d.length),f.collapse(!0),e.removeAllRanges(),e.addRange(f)},_getCaretRelativePosition:function(){var b=window.getSelection().getRangeAt(0).cloneRange(),c=document.createElement("span");b.insertNode(c),b.selectNodeContents(c),b.deleteContents();var d=a(c),e=d.offset();e.left-=this.$el.offset().left,e.top+=d.height()-this.$el.offset().top,e.lineHeight=d.height();var f=this.$el.attr("dir")||this.$el.css("direction");return"rtl"===f&&(e.left-=this.listView.$el.width()),e},_getTextFromHeadToCaret:function(){var a=window.getSelection().getRangeAt(0),b=a.cloneRange();return b.selectNodeContents(a.startContainer),b.toString().substring(0,a.startOffset)}}),a.fn.textcomplete.ContentEditable=b}(jQuery); -/* - //@ sourceMappingURL=dist/jquery.textcomplete.min.map - */ \ No newline at end of file diff --git a/pagure/static/emoji/jquery.textcomplete.min.js b/pagure/static/emoji/jquery.textcomplete.min.js new file mode 120000 index 0000000..8406123 --- /dev/null +++ b/pagure/static/emoji/jquery.textcomplete.min.js @@ -0,0 +1 @@ +jquery.textcomplete-1.7.1.min.js \ No newline at end of file diff --git a/pagure/static/hack_fonts/css/hack-extended-2.020.css b/pagure/static/hack_fonts/css/hack-extended-2.020.css new file mode 100644 index 0000000..0f98461 --- /dev/null +++ b/pagure/static/hack_fonts/css/hack-extended-2.020.css @@ -0,0 +1,38 @@ +/*! + * Hack v2.020 - https://sourcefoundry.org/hack/ + * Licenses - Fonts: Hack Open Font License + Bitstream Vera license, CSS: MIT License + */ +/* FONT PATHS + * -------------------------- */ +@font-face { + font-family: 'Hack'; + src: url('../fonts/eot/hack-regular-webfont.eot?v=2.020'); + src: url('../fonts/eot/hack-regular-webfont.eot?#iefix&v=2.020') format('embedded-opentype'), url('../fonts/woff2/hack-regular-webfont.woff2?v=2.020') format('woff2'), url('../fonts/woff/hack-regular-webfont.woff?v=2.020') format('woff'), url('../fonts/web-ttf/hack-regular-webfont.ttf?v=2.020') format('truetype'); + font-weight: 400; + font-style: normal; +} + +@font-face { + font-family: 'Hack'; + src: url('../fonts/eot/hack-bold-webfont.eot?v=2.020'); + src: url('../fonts/eot/hack-bold-webfont.eot?#iefix&v=2.020') format('embedded-opentype'), url('../fonts/woff2/hack-bold-webfont.woff2?v=2.020') format('woff2'), url('../fonts/woff/hack-bold-webfont.woff?v=2.020') format('woff'), url('../fonts/web-ttf/hack-bold-webfont.ttf?v=2.020') format('truetype'); + font-weight: 700; + font-style: normal; +} + +@font-face { + font-family: 'Hack'; + src: url('../fonts/eot/hack-italic-webfont.eot?v=2.020'); + src: url('../fonts/eot/hack-italic-webfont.eot?#iefix&v=2.020') format('embedded-opentype'), url('../fonts/woff2/hack-italic-webfont.woff2?v=2.020') format('woff2'), url('../fonts/woff/hack-italic-webfont.woff?v=2.020') format('woff'), url('../fonts/web-ttf/hack-italic-webfont.ttf?v=2.020') format('truetype'); + font-weight: 400; + font-style: italic; +} + +@font-face { + font-family: 'Hack'; + src: url('../fonts/eot/hack-bolditalic-webfont.eot?v=2.020'); + src: url('../fonts/eot/hack-bolditalic-webfont.eot?#iefix&v=2.020') format('embedded-opentype'), url('../fonts/woff2/hack-bolditalic-webfont.woff2?v=2.020') format('woff2'), url('../fonts/woff/hack-bolditalic-webfont.woff?v=2.020') format('woff'), url('../fonts/web-ttf/hack-bolditalic-webfont.ttf?v=2.020') format('truetype'); + font-weight: 700; + font-style: italic; +} + diff --git a/pagure/static/hack_fonts/css/hack-extended-2.020.min.css b/pagure/static/hack_fonts/css/hack-extended-2.020.min.css new file mode 100644 index 0000000..11f9859 --- /dev/null +++ b/pagure/static/hack_fonts/css/hack-extended-2.020.min.css @@ -0,0 +1,4 @@ +/*! + * Hack v2.020 - https://sourcefoundry.org/hack/ + * Licenses - Fonts: Hack Open Font License + Bitstream Vera license, CSS: MIT License + */@font-face{font-family:'Hack';src:url('../fonts/eot/hack-regular-webfont.eot?v=2.020');src:url('../fonts/eot/hack-regular-webfont.eot?#iefix&v=2.020') format('embedded-opentype'),url('../fonts/woff2/hack-regular-webfont.woff2?v=2.020') format('woff2'),url('../fonts/woff/hack-regular-webfont.woff?v=2.020') format('woff'),url('../fonts/web-ttf/hack-regular-webfont.ttf?v=2.020') format('truetype');font-weight:400;font-style:normal}@font-face{font-family:'Hack';src:url('../fonts/eot/hack-bold-webfont.eot?v=2.020');src:url('../fonts/eot/hack-bold-webfont.eot?#iefix&v=2.020') format('embedded-opentype'),url('../fonts/woff2/hack-bold-webfont.woff2?v=2.020') format('woff2'),url('../fonts/woff/hack-bold-webfont.woff?v=2.020') format('woff'),url('../fonts/web-ttf/hack-bold-webfont.ttf?v=2.020') format('truetype');font-weight:700;font-style:normal}@font-face{font-family:'Hack';src:url('../fonts/eot/hack-italic-webfont.eot?v=2.020');src:url('../fonts/eot/hack-italic-webfont.eot?#iefix&v=2.020') format('embedded-opentype'),url('../fonts/woff2/hack-italic-webfont.woff2?v=2.020') format('woff2'),url('../fonts/woff/hack-italic-webfont.woff?v=2.020') format('woff'),url('../fonts/web-ttf/hack-italic-webfont.ttf?v=2.020') format('truetype');font-weight:400;font-style:italic}@font-face{font-family:'Hack';src:url('../fonts/eot/hack-bolditalic-webfont.eot?v=2.020');src:url('../fonts/eot/hack-bolditalic-webfont.eot?#iefix&v=2.020') format('embedded-opentype'),url('../fonts/woff2/hack-bolditalic-webfont.woff2?v=2.020') format('woff2'),url('../fonts/woff/hack-bolditalic-webfont.woff?v=2.020') format('woff'),url('../fonts/web-ttf/hack-bolditalic-webfont.ttf?v=2.020') format('truetype');font-weight:700;font-style:italic} \ No newline at end of file diff --git a/pagure/static/hack_fonts/css/hack-extended.css b/pagure/static/hack_fonts/css/hack-extended.css new file mode 120000 index 0000000..f08cb16 --- /dev/null +++ b/pagure/static/hack_fonts/css/hack-extended.css @@ -0,0 +1 @@ +hack-extended-2.020.css \ No newline at end of file diff --git a/pagure/static/hack_fonts/css/hack-extended.min.css b/pagure/static/hack_fonts/css/hack-extended.min.css deleted file mode 100644 index d8abefd..0000000 --- a/pagure/static/hack_fonts/css/hack-extended.min.css +++ /dev/null @@ -1,4 +0,0 @@ -/*! - * Hack v2.018 - https://sourcefoundry.org/hack/ - * Licenses - Fonts: Hack Open Font License + Bitstream Vera license, CSS: MIT License - */@font-face{font-family:'Hack';src:url('../fonts/eot/hack-regular-webfont.eot?v=2.018');src:url('../fonts/eot/hack-regular-webfont.eot?#iefix&v=2.018') format('embedded-opentype'),url('../fonts/woff2/hack-regular-webfont.woff2?v=2.018') format('woff2'),url('../fonts/woff/hack-regular-webfont.woff?v=2.018') format('woff'),url('../fonts/web-ttf/hack-regular-webfont.ttf?v=2.018') format('truetype'),url('../fonts/svg/hack-regular-webfont.svg?v=2.018#hackregular') format('svg');font-weight:400;font-style:normal}@font-face{font-family:'Hack';src:url('../fonts/eot/hack-bold-webfont.eot?v=2.018');src:url('../fonts/eot/hack-bold-webfont.eot?#iefix&v=2.018') format('embedded-opentype'),url('../fonts/woff2/hack-bold-webfont.woff2?v=2.018') format('woff2'),url('../fonts/woff/hack-bold-webfont.woff?v=2.018') format('woff'),url('../fonts/web-ttf/hack-bold-webfont.ttf?v=2.018') format('truetype'),url('../fonts/svg/hack-bold-webfont.svg?v=2.018#hackbold') format('svg');font-weight:700;font-style:normal}@font-face{font-family:'Hack';src:url('../fonts/eot/hack-italic-webfont.eot?v=2.018');src:url('../fonts/eot/hack-italic-webfont.eot?#iefix&v=2.018') format('embedded-opentype'),url('../fonts/woff2/hack-italic-webfont.woff2?v=2.018') format('woff2'),url('../fonts/woff/hack-italic-webfont.woff?v=2.018') format('woff'),url('../fonts/web-ttf/hack-italic-webfont.ttf?v=2.018') format('truetype'),url('../fonts/svg/hack-italic-webfont.svg?v=2.018#hackitalic') format('svg');font-weight:400;font-style:italic}@font-face{font-family:'Hack';src:url('../fonts/eot/hack-bolditalic-webfont.eot?v=2.018');src:url('../fonts/eot/hack-bolditalic-webfont.eot?#iefix&v=2.018') format('embedded-opentype'),url('../fonts/woff2/hack-bolditalic-webfont.woff2?v=2.018') format('woff2'),url('../fonts/woff/hack-bolditalic-webfont.woff?v=2.018') format('woff'),url('../fonts/web-ttf/hack-bolditalic-webfont.ttf?v=2.018') format('truetype'),url('../fonts/svg/hack-bolditalic-webfont.svg?v=2.010#hackbolditalic') format('svg');font-weight:700;font-style:italic} \ No newline at end of file diff --git a/pagure/static/hack_fonts/css/hack-extended.min.css b/pagure/static/hack_fonts/css/hack-extended.min.css new file mode 120000 index 0000000..ceb0a59 --- /dev/null +++ b/pagure/static/hack_fonts/css/hack-extended.min.css @@ -0,0 +1 @@ +hack-extended-2.020.min.css \ No newline at end of file diff --git a/pagure/static/jdenticon-1.3.2.js b/pagure/static/jdenticon-1.3.2.js new file mode 100644 index 0000000..c56ee80 --- /dev/null +++ b/pagure/static/jdenticon-1.3.2.js @@ -0,0 +1,801 @@ +/** + * Jdenticon 1.3.2 + * http://jdenticon.com + * + * Built: 2015-10-10T11:55:57.451Z + * + * Copyright (c) 2014-2015 Daniel Mester Pirttijärvi + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source distribution. + * + */ + +/*jslint bitwise: true */ + +(function (global, name, factory) { + var jQuery = global["jQuery"], + jdenticon = factory(global, jQuery); + + // Node.js + if (typeof module !== "undefined" && "exports" in module) { + module["exports"] = jdenticon; + } + // RequireJS + else if (typeof define === "function" && define["amd"]) { + define([], function () { return jdenticon; }); + } + // No module loader + else { + global[name] = jdenticon; + } +})(this, "jdenticon", function (global, jQuery) { + "use strict"; + + + + + /** + * Represents a point. + * @private + * @constructor + */ + function Point(x, y) { + this.x = x; + this.y = y; + }; + + + /** + * Translates and rotates a point before being passed on to the canvas context. This was previously done by the canvas context itself, + * but this caused a rendering issue in Chrome on sizes > 256 where the rotation transformation of inverted paths was not done properly. + * @param {number} x The x-coordinate of the upper left corner of the transformed rectangle. + * @param {number} y The y-coordinate of the upper left corner of the transformed rectangle. + * @param {number} size The size of the transformed rectangle. + * @param {number} rotation Rotation specified as 0 = 0 rad, 1 = 0.5π rad, 2 = π rad, 3 = 1.5π rad + * @private + * @constructor + */ + function Transform(x, y, size, rotation) { + this._x = x; + this._y = y; + this._size = size; + this._rotation = rotation; + } + Transform.prototype = { + /** + * Transforms the specified point based on the translation and rotation specification for this Transform. + * @param {number} x x-coordinate + * @param {number} y y-coordinate + * @param {number=} w The width of the transformed rectangle. If greater than 0, this will ensure the returned point is of the upper left corner of the transformed rectangle. + * @param {number=} h The height of the transformed rectangle. If greater than 0, this will ensure the returned point is of the upper left corner of the transformed rectangle. + */ + transformPoint: function (x, y, w, h) { + var right = this._x + this._size, + bottom = this._y + this._size; + return this._rotation === 1 ? new Point(right - y - (h || 0), this._y + x) : + this._rotation === 2 ? new Point(right - x - (w || 0), bottom - y - (h || 0)) : + this._rotation === 3 ? new Point(this._x + y, bottom - x - (w || 0)) : + new Point(this._x + x, this._y + y); + } + }; + Transform.noTransform = new Transform(0, 0, 0, 0); + + + + /** + * Provides helper functions for rendering common basic shapes. + * @private + * @constructor + */ + function Graphics(renderer) { + this._renderer = renderer; + this._transform = Transform.noTransform; + } + Graphics.prototype = { + /** + * Adds a polygon to the underlying renderer. + * @param {Array} points The points of the polygon clockwise on the format [ x0, y0, x1, y1, ..., xn, yn ] + * @param {boolean=} invert Specifies if the polygon will be inverted. + */ + addPolygon: function (points, invert) { + var di = invert ? -2 : 2, + transform = this._transform, + transformedPoints = [], + i; + + for (i = invert ? points.length - 2 : 0; i < points.length && i >= 0; i += di) { + transformedPoints.push(transform.transformPoint(points[i], points[i + 1])); + } + + this._renderer.addPolygon(transformedPoints); + }, + + /** + * Adds a polygon to the underlying renderer. + * Source: http://stackoverflow.com/a/2173084 + * @param {number} x The x-coordinate of the upper left corner of the rectangle holding the entire ellipse. + * @param {number} y The y-coordinate of the upper left corner of the rectangle holding the entire ellipse. + * @param {number} size The size of the ellipse. + * @param {boolean=} invert Specifies if the ellipse will be inverted. + */ + addCircle: function (x, y, size, invert) { + var p = this._transform.transformPoint(x, y, size, size); + this._renderer.addCircle(p, size, invert); + }, + + /** + * Adds a rectangle to the underlying renderer. + * @param {number} x The x-coordinate of the upper left corner of the rectangle. + * @param {number} y The y-coordinate of the upper left corner of the rectangle. + * @param {number} w The width of the rectangle. + * @param {number} h The height of the rectangle. + * @param {boolean=} invert Specifies if the rectangle will be inverted. + */ + addRectangle: function (x, y, w, h, invert) { + this.addPolygon([ + x, y, + x + w, y, + x + w, y + h, + x, y + h + ], invert); + }, + + /** + * Adds a right triangle to the underlying renderer. + * @param {number} x The x-coordinate of the upper left corner of the rectangle holding the triangle. + * @param {number} y The y-coordinate of the upper left corner of the rectangle holding the triangle. + * @param {number} w The width of the triangle. + * @param {number} h The height of the triangle. + * @param {number} r The rotation of the triangle (clockwise). 0 = right corner of the triangle in the lower left corner of the bounding rectangle. + * @param {boolean=} invert Specifies if the triangle will be inverted. + */ + addTriangle: function (x, y, w, h, r, invert) { + var points = [ + x + w, y, + x + w, y + h, + x, y + h, + x, y + ]; + points.splice(((r || 0) % 4) * 2, 2); + this.addPolygon(points, invert); + }, + + /** + * Adds a rhombus to the underlying renderer. + * @param {number} x The x-coordinate of the upper left corner of the rectangle holding the rhombus. + * @param {number} y The y-coordinate of the upper left corner of the rectangle holding the rhombus. + * @param {number} w The width of the rhombus. + * @param {number} h The height of the rhombus. + * @param {boolean=} invert Specifies if the rhombus will be inverted. + */ + addRhombus: function (x, y, w, h, invert) { + this.addPolygon([ + x + w / 2, y, + x + w, y + h / 2, + x + w / 2, y + h, + x, y + h / 2 + ], invert); + } + }; + + + + + var shapes = { + center: [ + /** @param {Graphics} g */ + function (g, cell, index) { + var k = cell * 0.42; + g.addPolygon([ + 0, 0, + cell, 0, + cell, cell - k * 2, + cell - k, cell, + 0, cell + ]); + }, + /** @param {Graphics} g */ + function (g, cell, index) { + var w = 0 | (cell * 0.5), + h = 0 | (cell * 0.8); + g.addTriangle(cell - w, 0, w, h, 2); + }, + /** @param {Graphics} g */ + function (g, cell, index) { + var s = 0 | (cell / 3); + g.addRectangle(s, s, cell - s, cell - s); + }, + /** @param {Graphics} g */ + function (g, cell, index) { + var inner = 0 | (cell * 0.1), + outer = 0 | (cell * 0.25); + g.addRectangle(outer, outer, cell - inner - outer, cell - inner - outer); + }, + /** @param {Graphics} g */ + function (g, cell, index) { + var m = 0 | (cell * 0.15), + s = 0 | (cell * 0.5); + g.addCircle(cell - s - m, cell - s - m, s); + }, + /** @param {Graphics} g */ + function (g, cell, index) { + var inner = cell * 0.1, + outer = inner * 4; + + g.addRectangle(0, 0, cell, cell); + g.addPolygon([ + outer, outer, + cell - inner, outer, + outer + (cell - outer - inner) / 2, cell - inner + ], true); + }, + /** @param {Graphics} g */ + function (g, cell, index) { + g.addPolygon([ + 0, 0, + cell, 0, + cell, cell * 0.7, + cell * 0.4, cell * 0.4, + cell * 0.7, cell, + 0, cell + ]); + }, + /** @param {Graphics} g */ + function (g, cell, index) { + g.addTriangle(cell / 2, cell / 2, cell / 2, cell / 2, 3); + }, + /** @param {Graphics} g */ + function (g, cell, index) { + g.addRectangle(0, 0, cell, cell / 2); + g.addRectangle(0, cell / 2, cell / 2, cell / 2); + g.addTriangle(cell / 2, cell / 2, cell / 2, cell / 2, 1); + }, + /** @param {Graphics} g */ + function (g, cell, index) { + var inner = 0 | (cell * 0.14), + outer = 0 | (cell * 0.35); + g.addRectangle(0, 0, cell, cell); + g.addRectangle(outer, outer, cell - outer - inner, cell - outer - inner, true); + }, + /** @param {Graphics} g */ + function (g, cell, index) { + var inner = cell * 0.12, + outer = inner * 3; + + g.addRectangle(0, 0, cell, cell); + g.addCircle(outer, outer, cell - inner - outer, true); + }, + /** @param {Graphics} g */ + function (g, cell, index) { + g.addTriangle(cell / 2, cell / 2, cell / 2, cell / 2, 3); + }, + /** @param {Graphics} g */ + function (g, cell, index) { + var m = cell * 0.25; + g.addRectangle(0, 0, cell, cell); + g.addRhombus(m, m, cell - m, cell - m, true); + }, + /** @param {Graphics} g */ + function (g, cell, index) { + var m = cell * 0.4, s = cell * 1.2; + if (!index) { + g.addCircle(m, m, s); + } + } + ], + + outer: [ + /** @param {Graphics} g */ + function (g, cell, index) { + g.addTriangle(0, 0, cell, cell, 0); + }, + /** @param {Graphics} g */ + function (g, cell, index) { + g.addTriangle(0, cell / 2, cell, cell / 2, 0); + }, + /** @param {Graphics} g */ + function (g, cell, index) { + g.addRhombus(0, 0, cell, cell); + }, + /** @param {Graphics} g */ + function (g, cell, index) { + var m = cell / 6; + g.addCircle(m, m, cell - 2 * m); + } + ] + }; + + + + + function decToHex(v) { + v |= 0; // Ensure integer value + return v < 0 ? "00" : + v < 16 ? "0" + v.toString(16) : + v < 256 ? v.toString(16) : + "ff"; + } + + function hueToRgb(m1, m2, h) { + h = h < 0 ? h + 6 : h > 6 ? h - 6 : h; + return decToHex(255 * ( + h < 1 ? m1 + (m2 - m1) * h : + h < 3 ? m2 : + h < 4 ? m1 + (m2 - m1) * (4 - h) : + m1)); + } + + /** + * Functions for converting colors to hex-rgb representations. + * @private + */ + var color = { + /** + * @param {number} r Red channel [0, 255] + * @param {number} g Green channel [0, 255] + * @param {number} b Blue channel [0, 255] + */ + rgb: function (r, g, b) { + return "#" + decToHex(r) + decToHex(g) + decToHex(b); + }, + /** + * @param h Hue [0, 1] + * @param s Saturation [0, 1] + * @param l Lightness [0, 1] + */ + hsl: function (h, s, l) { + // Based on http://www.w3.org/TR/2011/REC-css3-color-20110607/#hsl-color + if (s == 0) { + var partialHex = decToHex(l * 255); + return "#" + partialHex + partialHex + partialHex; + } + else { + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s, + m1 = l * 2 - m2; + return "#" + + hueToRgb(m1, m2, h * 6 + 2) + + hueToRgb(m1, m2, h * 6) + + hueToRgb(m1, m2, h * 6 - 2); + } + }, + // This function will correct the lightness for the "dark" hues + correctedHsl: function (h, s, l) { + // The corrector specifies the perceived middle lightnesses for each hue + var correctors = [ 0.55, 0.5, 0.5, 0.46, 0.6, 0.55, 0.55 ], + corrector = correctors[(h * 6 + 0.5) | 0]; + + // Adjust the input lightness relative to the corrector + l = l < 0.5 ? l * corrector * 2 : corrector + (l - 0.5) * (1 - corrector) * 2; + + return color.hsl(h, s, l); + } + }; + + + + + /** + * Gets a set of identicon color candidates for a specified hue and config. + */ + function colorTheme(hue, config) { + return [ + // Dark gray + color.hsl(0, 0, config.grayscaleLightness(0)), + // Mid color + color.correctedHsl(hue, config.saturation, config.colorLightness(0.5)), + // Light gray + color.hsl(0, 0, config.grayscaleLightness(1)), + // Light color + color.correctedHsl(hue, config.saturation, config.colorLightness(1)), + // Dark color + color.correctedHsl(hue, config.saturation, config.colorLightness(0)) + ]; + } + + + + + /** + * Draws an identicon to a specified renderer. + */ + function iconGenerator(renderer, hash, x, y, size, padding, config) { + var undefined; + + // Calculate padding + padding = (size * (padding === undefined ? 0.08 : padding)) | 0; + size -= padding * 2; + + // Sizes smaller than 30 px are not supported. If really needed, apply a scaling transformation + // to the context before passing it to this function. + if (size < 30) { + throw new Error("Jdenticon cannot render identicons smaller than 30 pixels."); + } + if (!/^[0-9a-f]{11,}$/i.test(hash)) { + throw new Error("Invalid hash passed to Jdenticon."); + } + + var graphics = new Graphics(renderer); + + // Calculate cell size and ensure it is an integer + var cell = 0 | (size / 4); + + // Since the cell size is integer based, the actual icon will be slightly smaller than specified => center icon + x += 0 | (padding + size / 2 - cell * 2); + y += 0 | (padding + size / 2 - cell * 2); + + function renderShape(colorIndex, shapes, index, rotationIndex, positions) { + var r = rotationIndex ? parseInt(hash.charAt(rotationIndex), 16) : 0, + shape = shapes[parseInt(hash.charAt(index), 16) % shapes.length], + i; + + renderer.beginShape(availableColors[selectedColorIndexes[colorIndex]]); + + for (i = 0; i < positions.length; i++) { + graphics._transform = new Transform(x + positions[i][0] * cell, y + positions[i][1] * cell, cell, r++ % 4); + shape(graphics, cell, i); + } + + renderer.endShape(); + } + + // AVAILABLE COLORS + var hue = parseInt(hash.substr(-7), 16) / 0xfffffff, + + // Available colors for this icon + availableColors = colorTheme(hue, config), + + // The index of the selected colors + selectedColorIndexes = [], + index; + + function isDuplicate(values) { + if (values.indexOf(index) >= 0) { + for (var i = 0; i < values.length; i++) { + if (selectedColorIndexes.indexOf(values[i]) >= 0) { + return true; + } + } + } + } + + for (var i = 0; i < 3; i++) { + index = parseInt(hash.charAt(8 + i), 16) % availableColors.length; + if (isDuplicate([0, 4]) || // Disallow dark gray and dark color combo + isDuplicate([2, 3])) { // Disallow light gray and light color combo + index = 1; + } + selectedColorIndexes.push(index); + } + + // ACTUAL RENDERING + // Sides + renderShape(0, shapes.outer, 2, 3, [[1, 0], [2, 0], [2, 3], [1, 3], [0, 1], [3, 1], [3, 2], [0, 2]]); + // Corners + renderShape(1, shapes.outer, 4, 5, [[0, 0], [3, 0], [3, 3], [0, 3]]); + // Center + renderShape(2, shapes.center, 1, null, [[1, 1], [2, 1], [2, 2], [1, 2]]); + }; + + + + /** + * Represents an SVG path element. + * @private + * @constructor + */ + function SvgPath() { + /** + * This property holds the data string (path.d) of the SVG path. + */ + this.dataString = ""; + } + SvgPath.prototype = { + /** + * Adds a polygon with the current fill color to the SVG path. + * @param points An array of Point objects. + */ + addPolygon: function (points) { + var dataString = "M" + points[0].x + " " + points[0].y; + for (var i = 1; i < points.length; i++) { + dataString += "L" + points[i].x + " " + points[i].y; + } + this.dataString += dataString + "Z"; + }, + /** + * Adds a circle with the current fill color to the SVG path. + * @param {Point} point The upper left corner of the circle bounding box. + * @param {number} diameter The diameter of the circle. + * @param {boolean} counterClockwise True if the circle is drawn counter-clockwise (will result in a hole if rendered on a clockwise path). + */ + addCircle: function (point, diameter, counterClockwise) { + var sweepFlag = counterClockwise ? 0 : 1, + radius = diameter / 2; + this.dataString += + "M" + (point.x) + " " + (point.y + radius) + + "a" + radius + "," + radius + " 0 1," + sweepFlag + " " + diameter + ",0" + + "a" + radius + "," + radius + " 0 1," + sweepFlag + " " + (-diameter) + ",0"; + } + }; + + + + /** + * Renderer producing SVG output. + * @private + * @constructor + */ + function SvgRenderer(width, height) { + this._pathsByColor = { }; + this._size = { w: width, h: height }; + } + SvgRenderer.prototype = { + /** + * Marks the beginning of a new shape of the specified color. Should be ended with a call to endShape. + * @param {string} color Fill color on format #xxxxxx. + */ + beginShape: function (color) { + this._path = this._pathsByColor[color] || (this._pathsByColor[color] = new SvgPath()); + }, + /** + * Marks the end of the currently drawn shape. + */ + endShape: function () { }, + /** + * Adds a polygon with the current fill color to the SVG. + * @param points An array of Point objects. + */ + addPolygon: function (points) { + this._path.addPolygon(points); + }, + /** + * Adds a circle with the current fill color to the SVG. + * @param {Point} point The upper left corner of the circle bounding box. + * @param {number} diameter The diameter of the circle. + * @param {boolean} counterClockwise True if the circle is drawn counter-clockwise (will result in a hole if rendered on a clockwise path). + */ + addCircle: function (point, diameter, counterClockwise) { + this._path.addCircle(point, diameter, counterClockwise); + }, + /** + * Gets the rendered image as an SVG string. + * @param {boolean=} fragment If true, the container svg element is not included in the result. + */ + toSvg: function (fragment) { + var svg = fragment ? '' : + ''; + + for (var color in this._pathsByColor) { + svg += ''; + } + + return fragment ? svg : + svg + ''; + } + }; + + + + /** + * Renderer redirecting drawing commands to a canvas context. + * @private + * @constructor + */ + function CanvasRenderer(ctx, width, height) { + this._ctx = ctx; + ctx.clearRect(0, 0, width, height); + } + CanvasRenderer.prototype = { + /** + * Marks the beginning of a new shape of the specified color. Should be ended with a call to endShape. + * @param {string} color Fill color on format #xxxxxx. + */ + beginShape: function (color) { + this._ctx.fillStyle = color; + this._ctx.beginPath(); + }, + /** + * Marks the end of the currently drawn shape. This causes the queued paths to be rendered on the canvas. + */ + endShape: function () { + this._ctx.fill(); + }, + /** + * Adds a polygon to the rendering queue. + * @param points An array of Point objects. + */ + addPolygon: function (points) { + var ctx = this._ctx, i; + ctx.moveTo(points[0].x, points[0].y); + for (i = 1; i < points.length; i++) { + ctx.lineTo(points[i].x, points[i].y); + } + ctx.closePath(); + }, + /** + * Adds a circle to the rendering queue. + * @param {Point} point The upper left corner of the circle bounding box. + * @param {number} diameter The diameter of the circle. + * @param {boolean} counterClockwise True if the circle is drawn counter-clockwise (will result in a hole if rendered on a clockwise path). + */ + addCircle: function (point, diameter, counterClockwise) { + var ctx = this._ctx, + radius = diameter / 2; + ctx.arc(point.x + radius, point.y + radius, radius, 0, Math.PI * 2, counterClockwise); + ctx.closePath(); + } + }; + + + + + + + var /** @const */ + HASH_ATTRIBUTE = "data-jdenticon-hash", + supportsQuerySelectorAll = "document" in global && "querySelectorAll" in document; + + /** + * Gets the normalized current Jdenticon color configuration. Missing fields have default values. + */ + function getCurrentConfig() { + var configObject = jdenticon["config"] || global["jdenticon_config"] || { }, + lightnessConfig = configObject["lightness"] || { }, + saturation = configObject["saturation"]; + + /** + * Creates a lightness range. + */ + function lightness(configName, defaultMin, defaultMax) { + var range = lightnessConfig[configName] instanceof Array ? lightnessConfig[configName] : [defaultMin, defaultMax]; + + /** + * Gets a lightness relative the specified value in the specified lightness range. + */ + return function (value) { + value = range[0] + value * (range[1] - range[0]); + return value < 0 ? 0 : value > 1 ? 1 : value; + }; + } + + return { + saturation: typeof saturation == "number" ? saturation : 0.5, + colorLightness: lightness("color", 0.4, 0.8), + grayscaleLightness: lightness("grayscale", 0.3, 0.9) + } + } + + /** + * Updates the identicon in the specified canvas or svg elements. + * @param {string=} hash Optional hash to be rendered. If not specified, the hash specified by the data-jdenticon-hash is used. + * @param {number=} padding Optional padding in percents. Extra padding might be added to center the rendered identicon. + */ + function update(el, hash, padding) { + if (typeof(el) === "string") { + if (supportsQuerySelectorAll) { + var elements = document.querySelectorAll(el); + for (var i = 0; i < elements.length; i++) { + update(elements[i], hash, padding); + } + } + return; + } + if (!el || !el["tagName"]) { + // No element found + return; + } + hash = hash || el.getAttribute(HASH_ATTRIBUTE); + if (!hash) { + // No hash specified + return; + } + + var isSvg = el["tagName"].toLowerCase() == "svg", + isCanvas = el["tagName"].toLowerCase() == "canvas"; + + // Ensure we have a supported element + if (!isSvg && !(isCanvas && "getContext" in el)) { + return; + } + + var width = Number(el.getAttribute("width")) || el.clientWidth || 0, + height = Number(el.getAttribute("height")) || el.clientHeight || 0, + renderer = isSvg ? new SvgRenderer(width, height) : new CanvasRenderer(el.getContext("2d"), width, height), + size = Math.min(width, height); + + // Draw icon + iconGenerator(renderer, hash, 0, 0, size, padding, getCurrentConfig()); + + // SVG needs postprocessing + if (isSvg) { + // Parse svg to a temporary span element. + // Simply using innerHTML does unfortunately not work on IE. + var wrapper = document.createElement("span"); + wrapper.innerHTML = renderer.toSvg(false); + + // Then replace the content of the target element with the parsed svg. + while (el.firstChild) { + el.removeChild(el.firstChild); + } + var newNodes = wrapper.firstChild.childNodes; + while (newNodes.length) { + el.appendChild(newNodes[0]); + } + + // Set viewBox attribute to ensure the svg scales nicely. + el.setAttribute("viewBox", "0 0 " + width + " " + height); + } + } + + /** + * Draws an identicon to a context. + */ + function drawIcon(ctx, hash, size) { + if (!ctx) { + throw new Error("No canvas specified."); + } + + var renderer = new CanvasRenderer(ctx, size, size); + iconGenerator(renderer, hash, 0, 0, size, 0, getCurrentConfig()); + } + + /** + * Draws an identicon to a context. + * @param {number=} padding Optional padding in percents. Extra padding might be added to center the rendered identicon. + */ + function toSvg(hash, size, padding) { + var renderer = new SvgRenderer(size, size); + iconGenerator(renderer, hash, 0, 0, size, padding, getCurrentConfig()); + return renderer.toSvg(); + } + + /** + * Updates all canvas elements with the data-jdenticon-hash attribute. + */ + function jdenticon() { + if (supportsQuerySelectorAll) { + update("svg[" + HASH_ATTRIBUTE + "],canvas[" + HASH_ATTRIBUTE + "]"); + } + } + + // Public API + jdenticon["drawIcon"] = drawIcon; + jdenticon["toSvg"] = toSvg; + jdenticon["update"] = update; + jdenticon["version"] = "1.3.2"; + + // Basic jQuery plugin + if (jQuery) { + jQuery["fn"]["jdenticon"] = function (hash, padding) { + this["each"](function (index, el) { + update(el, hash, padding); + }); + return this; + }; + } + + // Schedule to render all identicons on the page once it has been loaded. + if (typeof setTimeout === "function") { + setTimeout(jdenticon, 0); + } + + return jdenticon; + +}); \ No newline at end of file diff --git a/pagure/static/jdenticon-1.3.2.min.js b/pagure/static/jdenticon-1.3.2.min.js new file mode 100644 index 0000000..610d18e --- /dev/null +++ b/pagure/static/jdenticon-1.3.2.min.js @@ -0,0 +1,13 @@ +// Jdenticon 1.3.2 | jdenticon.com | zlib licensed | (c) 2014-2015 Daniel Mester Pirttijärvi +(function(k,g,h){var l=h(k,k.jQuery);"undefined"!==typeof module&&"exports"in module?module.exports=l:"function"===typeof define&&define.amd?define([],function(){return l}):k[g]=l})(this,"jdenticon",function(k,g){function h(b,a){this.x=b;this.y=a}function l(b,a,c,d){this.o=b;this.s=a;this.f=c;this.l=d}function A(b){this.C=b;this.m=l.O}function m(b){b|=0;return 0>b?"00":16>b?"0"+b.toString(16):256>b?b.toString(16):"ff"}function q(b,a,c){c=0>c?c+6:6c?b+(a-b)*c:3>c?a:4>c?b+(a- +b)*(4-c):b))}function D(b,a){return[n.w(0,0,a.H(0)),n.v(b,a.A,a.u(.5)),n.w(0,0,a.H(1)),n.v(b,a.A,a.u(1)),n.v(b,a.A,a.u(0))]}function r(b,a,c,d,t){var f=0,u=0;function v(c,d,t,e,g){e=e?parseInt(a.charAt(e),16):0;d=d[parseInt(a.charAt(t),16)%d.length];b.F(n[m[c]]);for(c=0;cc)throw Error("Jdenticon cannot render identicons smaller than 30 pixels."); +if(!/^[0-9a-f]{11,}$/i.test(a))throw Error("Invalid hash passed to Jdenticon.");var k=new A(b),h=0|c/4,f=f+(0|d+c/2-2*h),u=u+(0|d+c/2-2*h),n=D(parseInt(a.substr(-7),16)/268435455,t),m=[],g;for(c=0;3>c;c++){g=parseInt(a.charAt(8+c),16)%n.length;if(e([0,4])||e([2,3]))g=1;m.push(g)}v(0,w.J,2,3,[[1,0],[2,0],[2,3],[1,3],[0,1],[3,1],[3,2],[0,2]]);v(1,w.J,4,5,[[0,0],[3,0],[3,3],[0,3]]);v(2,w.N,1,null,[[1,1],[2,1],[2,2],[1,2]])}function B(){this.i=""}function x(b,a){this.j={};this.f={M:b,I:a}}function y(b, +a,c){this.h=b;b.clearRect(0,0,a,c)}function z(){function b(a,b,f){var e=c[a]instanceof Array?c[a]:[b,f];return function(a){a=e[0]+a*(e[1]-e[0]);return 0>a?0:1=c?c*(a+1):c+a-c*a;c=2*c-a;return"#"+q(c,a,6*b+2)+q(c,a,6*b)+q(c,a,6*b-2)},v:function(b,a,c){var d=[.55,.5,.5,.46,.6,.55,.55][6*b+.5|0];return n.w(b,a,.5>c?c*d*2:d+(c-.5)*(1-d)*2)}};B.prototype={a:function(b){for(var a="M"+b[0].x+" "+b[0].y,c=1;c< +b.length;c++)a+="L"+b[c].x+" "+b[c].y;this.i+=a+"Z"},b:function(b,a,c){c=c?0:1;var d=a/2;this.i+="M"+b.x+" "+(b.y+d)+"a"+d+","+d+" 0 1,"+c+" "+a+",0a"+d+","+d+" 0 1,"+c+" "+-a+",0"}};x.prototype={F:function(b){this.B=this.j[b]||(this.j[b]=new B)},G:function(){},a:function(b){this.B.a(b)},b:function(b,a,c){this.B.b(b,a,c)},K:function(b){var a=b?"":'', +c;for(c in this.j)a+='';return b?a:a+""}};y.prototype={F:function(b){this.h.fillStyle=b;this.h.beginPath()},G:function(){this.h.fill()},a:function(b){var a=this.h,c;a.moveTo(b[0].x,b[0].y);for(c=1;c)[^>]*|#([\w-]*))$/,k=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,E=/^[\],:{}\s]*$/,S=/(?:^|:|,)(?:\s*\[)+/g,A=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,j=/"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,D=/^-ms-/,L=/-([\da-z])/gi,H=function(e,t){return t.toUpperCase()},q=function(e){(a.addEventListener||"load"===e.type||"complete"===a.readyState)&&(_(),x.ready())},_=function(){a.addEventListener?(a.removeEventListener("DOMContentLoaded",q,!1),e.removeEventListener("load",q,!1)):(a.detachEvent("onreadystatechange",q),e.detachEvent("onload",q))};x.fn=x.prototype={jquery:f,constructor:x,init:function(e,n,r){var i,o;if(!e)return this;if("string"==typeof e){if(i="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:N.exec(e),!i||!i[1]&&n)return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e);if(i[1]){if(n=n instanceof x?n[0]:n,x.merge(this,x.parseHTML(i[1],n&&n.nodeType?n.ownerDocument||n:a,!0)),k.test(i[1])&&x.isPlainObject(n))for(i in n)x.isFunction(this[i])?this[i](n[i]):this.attr(i,n[i]);return this}if(o=a.getElementById(i[2]),o&&o.parentNode){if(o.id!==i[2])return r.find(e);this.length=1,this[0]=o}return this.context=a,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):x.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),x.makeArray(e,this))},selector:"",length:0,toArray:function(){return g.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=x.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return x.each(this,e,t)},ready:function(e){return x.ready.promise().done(e),this},slice:function(){return this.pushStack(g.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(x.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:h,sort:[].sort,splice:[].splice},x.fn.init.prototype=x.fn,x.extend=x.fn.extend=function(){var e,n,r,i,o,a,s=arguments[0]||{},l=1,u=arguments.length,c=!1;for("boolean"==typeof s&&(c=s,s=arguments[1]||{},l=2),"object"==typeof s||x.isFunction(s)||(s={}),u===l&&(s=this,--l);u>l;l++)if(null!=(o=arguments[l]))for(i in o)e=s[i],r=o[i],s!==r&&(c&&r&&(x.isPlainObject(r)||(n=x.isArray(r)))?(n?(n=!1,a=e&&x.isArray(e)?e:[]):a=e&&x.isPlainObject(e)?e:{},s[i]=x.extend(c,a,r)):r!==t&&(s[i]=r));return s},x.extend({expando:"jQuery"+(f+Math.random()).replace(/\D/g,""),noConflict:function(t){return e.$===x&&(e.$=u),t&&e.jQuery===x&&(e.jQuery=l),x},isReady:!1,readyWait:1,holdReady:function(e){e?x.readyWait++:x.ready(!0)},ready:function(e){if(e===!0?!--x.readyWait:!x.isReady){if(!a.body)return setTimeout(x.ready);x.isReady=!0,e!==!0&&--x.readyWait>0||(n.resolveWith(a,[x]),x.fn.trigger&&x(a).trigger("ready").off("ready"))}},isFunction:function(e){return"function"===x.type(e)},isArray:Array.isArray||function(e){return"array"===x.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?c[y.call(e)]||"object":typeof e},isPlainObject:function(e){var n;if(!e||"object"!==x.type(e)||e.nodeType||x.isWindow(e))return!1;try{if(e.constructor&&!v.call(e,"constructor")&&!v.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(r){return!1}if(x.support.ownLast)for(n in e)return v.call(e,n);for(n in e);return n===t||v.call(e,n)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||a;var r=k.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=x.buildFragment([e],t,i),i&&x(i).remove(),x.merge([],r.childNodes))},parseJSON:function(n){return e.JSON&&e.JSON.parse?e.JSON.parse(n):null===n?n:"string"==typeof n&&(n=x.trim(n),n&&E.test(n.replace(A,"@").replace(j,"]").replace(S,"")))?Function("return "+n)():(x.error("Invalid JSON: "+n),t)},parseXML:function(n){var r,i;if(!n||"string"!=typeof n)return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(o){r=t}return r&&r.documentElement&&!r.getElementsByTagName("parsererror").length||x.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&x.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(D,"ms-").replace(L,H)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,a=M(e);if(n){if(a){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(a){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:b&&!b.call("\ufeff\u00a0")?function(e){return null==e?"":b.call(e)}:function(e){return null==e?"":(e+"").replace(C,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(M(Object(e))?x.merge(n,"string"==typeof e?[e]:e):h.call(n,e)),n},inArray:function(e,t,n){var r;if(t){if(m)return m.call(t,e,n);for(r=t.length,n=n?0>n?Math.max(0,r+n):n:0;r>n;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,o=0;if("number"==typeof r)for(;r>o;o++)e[i++]=n[o];else while(n[o]!==t)e[i++]=n[o++];return e.length=i,e},grep:function(e,t,n){var r,i=[],o=0,a=e.length;for(n=!!n;a>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,a=M(e),s=[];if(a)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(s[s.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(s[s.length]=r);return d.apply([],s)},guid:1,proxy:function(e,n){var r,i,o;return"string"==typeof n&&(o=e[n],n=e,e=o),x.isFunction(e)?(r=g.call(arguments,2),i=function(){return e.apply(n||this,r.concat(g.call(arguments)))},i.guid=e.guid=e.guid||x.guid++,i):t},access:function(e,n,r,i,o,a,s){var l=0,u=e.length,c=null==r;if("object"===x.type(r)){o=!0;for(l in r)x.access(e,n,l,r[l],!0,a,s)}else if(i!==t&&(o=!0,x.isFunction(i)||(s=!0),c&&(s?(n.call(e,i),n=null):(c=n,n=function(e,t,n){return c.call(x(e),n)})),n))for(;u>l;l++)n(e[l],r,s?i:i.call(e[l],l,n(e[l],r)));return o?e:c?n.call(e):u?n(e[0],r):a},now:function(){return(new Date).getTime()},swap:function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i}}),x.ready.promise=function(t){if(!n)if(n=x.Deferred(),"complete"===a.readyState)setTimeout(x.ready);else if(a.addEventListener)a.addEventListener("DOMContentLoaded",q,!1),e.addEventListener("load",q,!1);else{a.attachEvent("onreadystatechange",q),e.attachEvent("onload",q);var r=!1;try{r=null==e.frameElement&&a.documentElement}catch(i){}r&&r.doScroll&&function o(){if(!x.isReady){try{r.doScroll("left")}catch(e){return setTimeout(o,50)}_(),x.ready()}}()}return n.promise(t)},x.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){c["[object "+t+"]"]=t.toLowerCase()});function M(e){var t=e.length,n=x.type(e);return x.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}r=x(a),function(e,t){var n,r,i,o,a,s,l,u,c,p,f,d,h,g,m,y,v,b="sizzle"+-new Date,w=e.document,T=0,C=0,N=st(),k=st(),E=st(),S=!1,A=function(e,t){return e===t?(S=!0,0):0},j=typeof t,D=1<<31,L={}.hasOwnProperty,H=[],q=H.pop,_=H.push,M=H.push,O=H.slice,F=H.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},B="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",P="[\\x20\\t\\r\\n\\f]",R="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",W=R.replace("w","w#"),$="\\["+P+"*("+R+")"+P+"*(?:([*^$|!~]?=)"+P+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+W+")|)|)"+P+"*\\]",I=":("+R+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+$.replace(3,8)+")*)|.*)\\)|)",z=RegExp("^"+P+"+|((?:^|[^\\\\])(?:\\\\.)*)"+P+"+$","g"),X=RegExp("^"+P+"*,"+P+"*"),U=RegExp("^"+P+"*([>+~]|"+P+")"+P+"*"),V=RegExp(P+"*[+~]"),Y=RegExp("="+P+"*([^\\]'\"]*)"+P+"*\\]","g"),J=RegExp(I),G=RegExp("^"+W+"$"),Q={ID:RegExp("^#("+R+")"),CLASS:RegExp("^\\.("+R+")"),TAG:RegExp("^("+R.replace("w","w*")+")"),ATTR:RegExp("^"+$),PSEUDO:RegExp("^"+I),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+P+"*(even|odd|(([+-]|)(\\d*)n|)"+P+"*(?:([+-]|)"+P+"*(\\d+)|))"+P+"*\\)|)","i"),bool:RegExp("^(?:"+B+")$","i"),needsContext:RegExp("^"+P+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+P+"*((?:-\\d)?\\d*)"+P+"*\\)|)(?=[^-]|$)","i")},K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,et=/^(?:input|select|textarea|button)$/i,tt=/^h\d$/i,nt=/'|\\/g,rt=RegExp("\\\\([\\da-f]{1,6}"+P+"?|("+P+")|.)","ig"),it=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:0>r?String.fromCharCode(r+65536):String.fromCharCode(55296|r>>10,56320|1023&r)};try{M.apply(H=O.call(w.childNodes),w.childNodes),H[w.childNodes.length].nodeType}catch(ot){M={apply:H.length?function(e,t){_.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function at(e,t,n,i){var o,a,s,l,u,c,d,m,y,x;if((t?t.ownerDocument||t:w)!==f&&p(t),t=t||f,n=n||[],!e||"string"!=typeof e)return n;if(1!==(l=t.nodeType)&&9!==l)return[];if(h&&!i){if(o=Z.exec(e))if(s=o[1]){if(9===l){if(a=t.getElementById(s),!a||!a.parentNode)return n;if(a.id===s)return n.push(a),n}else if(t.ownerDocument&&(a=t.ownerDocument.getElementById(s))&&v(t,a)&&a.id===s)return n.push(a),n}else{if(o[2])return M.apply(n,t.getElementsByTagName(e)),n;if((s=o[3])&&r.getElementsByClassName&&t.getElementsByClassName)return M.apply(n,t.getElementsByClassName(s)),n}if(r.qsa&&(!g||!g.test(e))){if(m=d=b,y=t,x=9===l&&e,1===l&&"object"!==t.nodeName.toLowerCase()){c=mt(e),(d=t.getAttribute("id"))?m=d.replace(nt,"\\$&"):t.setAttribute("id",m),m="[id='"+m+"'] ",u=c.length;while(u--)c[u]=m+yt(c[u]);y=V.test(e)&&t.parentNode||t,x=c.join(",")}if(x)try{return M.apply(n,y.querySelectorAll(x)),n}catch(T){}finally{d||t.removeAttribute("id")}}}return kt(e.replace(z,"$1"),t,n,i)}function st(){var e=[];function t(n,r){return e.push(n+=" ")>o.cacheLength&&delete t[e.shift()],t[n]=r}return t}function lt(e){return e[b]=!0,e}function ut(e){var t=f.createElement("div");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function ct(e,t){var n=e.split("|"),r=e.length;while(r--)o.attrHandle[n[r]]=t}function pt(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||D)-(~e.sourceIndex||D);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function ft(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function dt(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function ht(e){return lt(function(t){return t=+t,lt(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}s=at.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},r=at.support={},p=at.setDocument=function(e){var n=e?e.ownerDocument||e:w,i=n.defaultView;return n!==f&&9===n.nodeType&&n.documentElement?(f=n,d=n.documentElement,h=!s(n),i&&i.attachEvent&&i!==i.top&&i.attachEvent("onbeforeunload",function(){p()}),r.attributes=ut(function(e){return e.className="i",!e.getAttribute("className")}),r.getElementsByTagName=ut(function(e){return e.appendChild(n.createComment("")),!e.getElementsByTagName("*").length}),r.getElementsByClassName=ut(function(e){return e.innerHTML="
          ",e.firstChild.className="i",2===e.getElementsByClassName("i").length}),r.getById=ut(function(e){return d.appendChild(e).id=b,!n.getElementsByName||!n.getElementsByName(b).length}),r.getById?(o.find.ID=function(e,t){if(typeof t.getElementById!==j&&h){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},o.filter.ID=function(e){var t=e.replace(rt,it);return function(e){return e.getAttribute("id")===t}}):(delete o.find.ID,o.filter.ID=function(e){var t=e.replace(rt,it);return function(e){var n=typeof e.getAttributeNode!==j&&e.getAttributeNode("id");return n&&n.value===t}}),o.find.TAG=r.getElementsByTagName?function(e,n){return typeof n.getElementsByTagName!==j?n.getElementsByTagName(e):t}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},o.find.CLASS=r.getElementsByClassName&&function(e,n){return typeof n.getElementsByClassName!==j&&h?n.getElementsByClassName(e):t},m=[],g=[],(r.qsa=K.test(n.querySelectorAll))&&(ut(function(e){e.innerHTML="",e.querySelectorAll("[selected]").length||g.push("\\["+P+"*(?:value|"+B+")"),e.querySelectorAll(":checked").length||g.push(":checked")}),ut(function(e){var t=n.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("t",""),e.querySelectorAll("[t^='']").length&&g.push("[*^$]="+P+"*(?:''|\"\")"),e.querySelectorAll(":enabled").length||g.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),g.push(",.*:")})),(r.matchesSelector=K.test(y=d.webkitMatchesSelector||d.mozMatchesSelector||d.oMatchesSelector||d.msMatchesSelector))&&ut(function(e){r.disconnectedMatch=y.call(e,"div"),y.call(e,"[s!='']:x"),m.push("!=",I)}),g=g.length&&RegExp(g.join("|")),m=m.length&&RegExp(m.join("|")),v=K.test(d.contains)||d.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},A=d.compareDocumentPosition?function(e,t){if(e===t)return S=!0,0;var i=t.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(t);return i?1&i||!r.sortDetached&&t.compareDocumentPosition(e)===i?e===n||v(w,e)?-1:t===n||v(w,t)?1:c?F.call(c,e)-F.call(c,t):0:4&i?-1:1:e.compareDocumentPosition?-1:1}:function(e,t){var r,i=0,o=e.parentNode,a=t.parentNode,s=[e],l=[t];if(e===t)return S=!0,0;if(!o||!a)return e===n?-1:t===n?1:o?-1:a?1:c?F.call(c,e)-F.call(c,t):0;if(o===a)return pt(e,t);r=e;while(r=r.parentNode)s.unshift(r);r=t;while(r=r.parentNode)l.unshift(r);while(s[i]===l[i])i++;return i?pt(s[i],l[i]):s[i]===w?-1:l[i]===w?1:0},n):f},at.matches=function(e,t){return at(e,null,null,t)},at.matchesSelector=function(e,t){if((e.ownerDocument||e)!==f&&p(e),t=t.replace(Y,"='$1']"),!(!r.matchesSelector||!h||m&&m.test(t)||g&&g.test(t)))try{var n=y.call(e,t);if(n||r.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(i){}return at(t,f,null,[e]).length>0},at.contains=function(e,t){return(e.ownerDocument||e)!==f&&p(e),v(e,t)},at.attr=function(e,n){(e.ownerDocument||e)!==f&&p(e);var i=o.attrHandle[n.toLowerCase()],a=i&&L.call(o.attrHandle,n.toLowerCase())?i(e,n,!h):t;return a===t?r.attributes||!h?e.getAttribute(n):(a=e.getAttributeNode(n))&&a.specified?a.value:null:a},at.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},at.uniqueSort=function(e){var t,n=[],i=0,o=0;if(S=!r.detectDuplicates,c=!r.sortStable&&e.slice(0),e.sort(A),S){while(t=e[o++])t===e[o]&&(i=n.push(o));while(i--)e.splice(n[i],1)}return e},a=at.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=a(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=a(t);return n},o=at.selectors={cacheLength:50,createPseudo:lt,match:Q,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(rt,it),e[3]=(e[4]||e[5]||"").replace(rt,it),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||at.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&at.error(e[0]),e},PSEUDO:function(e){var n,r=!e[5]&&e[2];return Q.CHILD.test(e[0])?null:(e[3]&&e[4]!==t?e[2]=e[4]:r&&J.test(r)&&(n=mt(r,!0))&&(n=r.indexOf(")",r.length-n)-r.length)&&(e[0]=e[0].slice(0,n),e[2]=r.slice(0,n)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(rt,it).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=N[e+" "];return t||(t=RegExp("(^|"+P+")"+e+"("+P+"|$)"))&&N(e,function(e){return t.test("string"==typeof e.className&&e.className||typeof e.getAttribute!==j&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=at.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,l){var u,c,p,f,d,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!l&&!s;if(m){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){c=m[b]||(m[b]={}),u=c[e]||[],d=u[0]===T&&u[1],f=u[0]===T&&u[2],p=d&&m.childNodes[d];while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[T,d,f];break}}else if(v&&(u=(t[b]||(t[b]={}))[e])&&u[0]===T)f=u[1];else while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(v&&((p[b]||(p[b]={}))[e]=[T,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=o.pseudos[e]||o.setFilters[e.toLowerCase()]||at.error("unsupported pseudo: "+e);return r[b]?r(t):r.length>1?(n=[e,e,"",t],o.setFilters.hasOwnProperty(e.toLowerCase())?lt(function(e,n){var i,o=r(e,t),a=o.length;while(a--)i=F.call(e,o[a]),e[i]=!(n[i]=o[a])}):function(e){return r(e,0,n)}):r}},pseudos:{not:lt(function(e){var t=[],n=[],r=l(e.replace(z,"$1"));return r[b]?lt(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:lt(function(e){return function(t){return at(e,t).length>0}}),contains:lt(function(e){return function(t){return(t.textContent||t.innerText||a(t)).indexOf(e)>-1}}),lang:lt(function(e){return G.test(e||"")||at.error("unsupported lang: "+e),e=e.replace(rt,it).toLowerCase(),function(t){var n;do if(n=h?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===d},focus:function(e){return e===f.activeElement&&(!f.hasFocus||f.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!o.pseudos.empty(e)},header:function(e){return tt.test(e.nodeName)},input:function(e){return et.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:ht(function(){return[0]}),last:ht(function(e,t){return[t-1]}),eq:ht(function(e,t,n){return[0>n?n+t:n]}),even:ht(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:ht(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:ht(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:ht(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}},o.pseudos.nth=o.pseudos.eq;for(n in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})o.pseudos[n]=ft(n);for(n in{submit:!0,reset:!0})o.pseudos[n]=dt(n);function gt(){}gt.prototype=o.filters=o.pseudos,o.setFilters=new gt;function mt(e,t){var n,r,i,a,s,l,u,c=k[e+" "];if(c)return t?0:c.slice(0);s=e,l=[],u=o.preFilter;while(s){(!n||(r=X.exec(s)))&&(r&&(s=s.slice(r[0].length)||s),l.push(i=[])),n=!1,(r=U.exec(s))&&(n=r.shift(),i.push({value:n,type:r[0].replace(z," ")}),s=s.slice(n.length));for(a in o.filter)!(r=Q[a].exec(s))||u[a]&&!(r=u[a](r))||(n=r.shift(),i.push({value:n,type:a,matches:r}),s=s.slice(n.length));if(!n)break}return t?s.length:s?at.error(e):k(e,l).slice(0)}function yt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function vt(e,t,n){var r=t.dir,o=n&&"parentNode"===r,a=C++;return t.first?function(t,n,i){while(t=t[r])if(1===t.nodeType||o)return e(t,n,i)}:function(t,n,s){var l,u,c,p=T+" "+a;if(s){while(t=t[r])if((1===t.nodeType||o)&&e(t,n,s))return!0}else while(t=t[r])if(1===t.nodeType||o)if(c=t[b]||(t[b]={}),(u=c[r])&&u[0]===p){if((l=u[1])===!0||l===i)return l===!0}else if(u=c[r]=[p],u[1]=e(t,n,s)||i,u[1]===!0)return!0}}function bt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function xt(e,t,n,r,i){var o,a=[],s=0,l=e.length,u=null!=t;for(;l>s;s++)(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),u&&t.push(s));return a}function wt(e,t,n,r,i,o){return r&&!r[b]&&(r=wt(r)),i&&!i[b]&&(i=wt(i,o)),lt(function(o,a,s,l){var u,c,p,f=[],d=[],h=a.length,g=o||Nt(t||"*",s.nodeType?[s]:s,[]),m=!e||!o&&t?g:xt(g,f,e,s,l),y=n?i||(o?e:h||r)?[]:a:m;if(n&&n(m,y,s,l),r){u=xt(y,d),r(u,[],s,l),c=u.length;while(c--)(p=u[c])&&(y[d[c]]=!(m[d[c]]=p))}if(o){if(i||e){if(i){u=[],c=y.length;while(c--)(p=y[c])&&u.push(m[c]=p);i(null,y=[],u,l)}c=y.length;while(c--)(p=y[c])&&(u=i?F.call(o,p):f[c])>-1&&(o[u]=!(a[u]=p))}}else y=xt(y===a?y.splice(h,y.length):y),i?i(null,a,y,l):M.apply(a,y)})}function Tt(e){var t,n,r,i=e.length,a=o.relative[e[0].type],s=a||o.relative[" "],l=a?1:0,c=vt(function(e){return e===t},s,!0),p=vt(function(e){return F.call(t,e)>-1},s,!0),f=[function(e,n,r){return!a&&(r||n!==u)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;i>l;l++)if(n=o.relative[e[l].type])f=[vt(bt(f),n)];else{if(n=o.filter[e[l].type].apply(null,e[l].matches),n[b]){for(r=++l;i>r;r++)if(o.relative[e[r].type])break;return wt(l>1&&bt(f),l>1&&yt(e.slice(0,l-1).concat({value:" "===e[l-2].type?"*":""})).replace(z,"$1"),n,r>l&&Tt(e.slice(l,r)),i>r&&Tt(e=e.slice(r)),i>r&&yt(e))}f.push(n)}return bt(f)}function Ct(e,t){var n=0,r=t.length>0,a=e.length>0,s=function(s,l,c,p,d){var h,g,m,y=[],v=0,b="0",x=s&&[],w=null!=d,C=u,N=s||a&&o.find.TAG("*",d&&l.parentNode||l),k=T+=null==C?1:Math.random()||.1;for(w&&(u=l!==f&&l,i=n);null!=(h=N[b]);b++){if(a&&h){g=0;while(m=e[g++])if(m(h,l,c)){p.push(h);break}w&&(T=k,i=++n)}r&&((h=!m&&h)&&v--,s&&x.push(h))}if(v+=b,r&&b!==v){g=0;while(m=t[g++])m(x,y,l,c);if(s){if(v>0)while(b--)x[b]||y[b]||(y[b]=q.call(p));y=xt(y)}M.apply(p,y),w&&!s&&y.length>0&&v+t.length>1&&at.uniqueSort(p)}return w&&(T=k,u=C),x};return r?lt(s):s}l=at.compile=function(e,t){var n,r=[],i=[],o=E[e+" "];if(!o){t||(t=mt(e)),n=t.length;while(n--)o=Tt(t[n]),o[b]?r.push(o):i.push(o);o=E(e,Ct(i,r))}return o};function Nt(e,t,n){var r=0,i=t.length;for(;i>r;r++)at(e,t[r],n);return n}function kt(e,t,n,i){var a,s,u,c,p,f=mt(e);if(!i&&1===f.length){if(s=f[0]=f[0].slice(0),s.length>2&&"ID"===(u=s[0]).type&&r.getById&&9===t.nodeType&&h&&o.relative[s[1].type]){if(t=(o.find.ID(u.matches[0].replace(rt,it),t)||[])[0],!t)return n;e=e.slice(s.shift().value.length)}a=Q.needsContext.test(e)?0:s.length;while(a--){if(u=s[a],o.relative[c=u.type])break;if((p=o.find[c])&&(i=p(u.matches[0].replace(rt,it),V.test(s[0].type)&&t.parentNode||t))){if(s.splice(a,1),e=i.length&&yt(s),!e)return M.apply(n,i),n;break}}}return l(e,f)(i,t,!h,n,V.test(e)),n}r.sortStable=b.split("").sort(A).join("")===b,r.detectDuplicates=S,p(),r.sortDetached=ut(function(e){return 1&e.compareDocumentPosition(f.createElement("div"))}),ut(function(e){return e.innerHTML="","#"===e.firstChild.getAttribute("href")})||ct("type|href|height|width",function(e,n,r){return r?t:e.getAttribute(n,"type"===n.toLowerCase()?1:2)}),r.attributes&&ut(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||ct("value",function(e,n,r){return r||"input"!==e.nodeName.toLowerCase()?t:e.defaultValue}),ut(function(e){return null==e.getAttribute("disabled")})||ct(B,function(e,n,r){var i;return r?t:(i=e.getAttributeNode(n))&&i.specified?i.value:e[n]===!0?n.toLowerCase():null}),x.find=at,x.expr=at.selectors,x.expr[":"]=x.expr.pseudos,x.unique=at.uniqueSort,x.text=at.getText,x.isXMLDoc=at.isXML,x.contains=at.contains}(e);var O={};function F(e){var t=O[e]={};return x.each(e.match(T)||[],function(e,n){t[n]=!0}),t}x.Callbacks=function(e){e="string"==typeof e?O[e]||F(e):x.extend({},e);var n,r,i,o,a,s,l=[],u=!e.once&&[],c=function(t){for(r=e.memory&&t,i=!0,a=s||0,s=0,o=l.length,n=!0;l&&o>a;a++)if(l[a].apply(t[0],t[1])===!1&&e.stopOnFalse){r=!1;break}n=!1,l&&(u?u.length&&c(u.shift()):r?l=[]:p.disable())},p={add:function(){if(l){var t=l.length;(function i(t){x.each(t,function(t,n){var r=x.type(n);"function"===r?e.unique&&p.has(n)||l.push(n):n&&n.length&&"string"!==r&&i(n)})})(arguments),n?o=l.length:r&&(s=t,c(r))}return this},remove:function(){return l&&x.each(arguments,function(e,t){var r;while((r=x.inArray(t,l,r))>-1)l.splice(r,1),n&&(o>=r&&o--,a>=r&&a--)}),this},has:function(e){return e?x.inArray(e,l)>-1:!(!l||!l.length)},empty:function(){return l=[],o=0,this},disable:function(){return l=u=r=t,this},disabled:function(){return!l},lock:function(){return u=t,r||p.disable(),this},locked:function(){return!u},fireWith:function(e,t){return!l||i&&!u||(t=t||[],t=[e,t.slice?t.slice():t],n?u.push(t):c(t)),this},fire:function(){return p.fireWith(this,arguments),this},fired:function(){return!!i}};return p},x.extend({Deferred:function(e){var t=[["resolve","done",x.Callbacks("once memory"),"resolved"],["reject","fail",x.Callbacks("once memory"),"rejected"],["notify","progress",x.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return x.Deferred(function(n){x.each(t,function(t,o){var a=o[0],s=x.isFunction(e[t])&&e[t];i[o[1]](function(){var e=s&&s.apply(this,arguments);e&&x.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[a+"With"](this===r?n.promise():this,s?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?x.extend(e,r):r}},i={};return r.pipe=r.then,x.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=g.call(arguments),r=n.length,i=1!==r||e&&x.isFunction(e.promise)?r:0,o=1===i?e:x.Deferred(),a=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?g.call(arguments):r,n===s?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},s,l,u;if(r>1)for(s=Array(r),l=Array(r),u=Array(r);r>t;t++)n[t]&&x.isFunction(n[t].promise)?n[t].promise().done(a(t,u,n)).fail(o.reject).progress(a(t,l,s)):--i;return i||o.resolveWith(u,n),o.promise()}}),x.support=function(t){var n,r,o,s,l,u,c,p,f,d=a.createElement("div");if(d.setAttribute("className","t"),d.innerHTML="
          a",n=d.getElementsByTagName("*")||[],r=d.getElementsByTagName("a")[0],!r||!r.style||!n.length)return t;s=a.createElement("select"),u=s.appendChild(a.createElement("option")),o=d.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t.getSetAttribute="t"!==d.className,t.leadingWhitespace=3===d.firstChild.nodeType,t.tbody=!d.getElementsByTagName("tbody").length,t.htmlSerialize=!!d.getElementsByTagName("link").length,t.style=/top/.test(r.getAttribute("style")),t.hrefNormalized="/a"===r.getAttribute("href"),t.opacity=/^0.5/.test(r.style.opacity),t.cssFloat=!!r.style.cssFloat,t.checkOn=!!o.value,t.optSelected=u.selected,t.enctype=!!a.createElement("form").enctype,t.html5Clone="<:nav>"!==a.createElement("nav").cloneNode(!0).outerHTML,t.inlineBlockNeedsLayout=!1,t.shrinkWrapBlocks=!1,t.pixelPosition=!1,t.deleteExpando=!0,t.noCloneEvent=!0,t.reliableMarginRight=!0,t.boxSizingReliable=!0,o.checked=!0,t.noCloneChecked=o.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!u.disabled;try{delete d.test}catch(h){t.deleteExpando=!1}o=a.createElement("input"),o.setAttribute("value",""),t.input=""===o.getAttribute("value"),o.value="t",o.setAttribute("type","radio"),t.radioValue="t"===o.value,o.setAttribute("checked","t"),o.setAttribute("name","t"),l=a.createDocumentFragment(),l.appendChild(o),t.appendChecked=o.checked,t.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,d.attachEvent&&(d.attachEvent("onclick",function(){t.noCloneEvent=!1}),d.cloneNode(!0).click());for(f in{submit:!0,change:!0,focusin:!0})d.setAttribute(c="on"+f,"t"),t[f+"Bubbles"]=c in e||d.attributes[c].expando===!1;d.style.backgroundClip="content-box",d.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===d.style.backgroundClip;for(f in x(t))break;return t.ownLast="0"!==f,x(function(){var n,r,o,s="padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",l=a.getElementsByTagName("body")[0];l&&(n=a.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",l.appendChild(n).appendChild(d),d.innerHTML="
          t
          ",o=d.getElementsByTagName("td"),o[0].style.cssText="padding:0;margin:0;border:0;display:none",p=0===o[0].offsetHeight,o[0].style.display="",o[1].style.display="none",t.reliableHiddenOffsets=p&&0===o[0].offsetHeight,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",x.swap(l,null!=l.style.zoom?{zoom:1}:{},function(){t.boxSizing=4===d.offsetWidth}),e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(d,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(d,null)||{width:"4px"}).width,r=d.appendChild(a.createElement("div")),r.style.cssText=d.style.cssText=s,r.style.marginRight=r.style.width="0",d.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),typeof d.style.zoom!==i&&(d.innerHTML="",d.style.cssText=s+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=3===d.offsetWidth,d.style.display="block",d.innerHTML="
          ",d.firstChild.style.width="5px",t.shrinkWrapBlocks=3!==d.offsetWidth,t.inlineBlockNeedsLayout&&(l.style.zoom=1)),l.removeChild(n),n=d=o=r=null)}),n=s=l=u=r=o=null,t +}({});var B=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,P=/([A-Z])/g;function R(e,n,r,i){if(x.acceptData(e)){var o,a,s=x.expando,l=e.nodeType,u=l?x.cache:e,c=l?e[s]:e[s]&&s;if(c&&u[c]&&(i||u[c].data)||r!==t||"string"!=typeof n)return c||(c=l?e[s]=p.pop()||x.guid++:s),u[c]||(u[c]=l?{}:{toJSON:x.noop}),("object"==typeof n||"function"==typeof n)&&(i?u[c]=x.extend(u[c],n):u[c].data=x.extend(u[c].data,n)),a=u[c],i||(a.data||(a.data={}),a=a.data),r!==t&&(a[x.camelCase(n)]=r),"string"==typeof n?(o=a[n],null==o&&(o=a[x.camelCase(n)])):o=a,o}}function W(e,t,n){if(x.acceptData(e)){var r,i,o=e.nodeType,a=o?x.cache:e,s=o?e[x.expando]:x.expando;if(a[s]){if(t&&(r=n?a[s]:a[s].data)){x.isArray(t)?t=t.concat(x.map(t,x.camelCase)):t in r?t=[t]:(t=x.camelCase(t),t=t in r?[t]:t.split(" ")),i=t.length;while(i--)delete r[t[i]];if(n?!I(r):!x.isEmptyObject(r))return}(n||(delete a[s].data,I(a[s])))&&(o?x.cleanData([e],!0):x.support.deleteExpando||a!=a.window?delete a[s]:a[s]=null)}}}x.extend({cache:{},noData:{applet:!0,embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(e){return e=e.nodeType?x.cache[e[x.expando]]:e[x.expando],!!e&&!I(e)},data:function(e,t,n){return R(e,t,n)},removeData:function(e,t){return W(e,t)},_data:function(e,t,n){return R(e,t,n,!0)},_removeData:function(e,t){return W(e,t,!0)},acceptData:function(e){if(e.nodeType&&1!==e.nodeType&&9!==e.nodeType)return!1;var t=e.nodeName&&x.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute("classid")===t}}),x.fn.extend({data:function(e,n){var r,i,o=null,a=0,s=this[0];if(e===t){if(this.length&&(o=x.data(s),1===s.nodeType&&!x._data(s,"parsedAttrs"))){for(r=s.attributes;r.length>a;a++)i=r[a].name,0===i.indexOf("data-")&&(i=x.camelCase(i.slice(5)),$(s,i,o[i]));x._data(s,"parsedAttrs",!0)}return o}return"object"==typeof e?this.each(function(){x.data(this,e)}):arguments.length>1?this.each(function(){x.data(this,e,n)}):s?$(s,e,x.data(s,e)):null},removeData:function(e){return this.each(function(){x.removeData(this,e)})}});function $(e,n,r){if(r===t&&1===e.nodeType){var i="data-"+n.replace(P,"-$1").toLowerCase();if(r=e.getAttribute(i),"string"==typeof r){try{r="true"===r?!0:"false"===r?!1:"null"===r?null:+r+""===r?+r:B.test(r)?x.parseJSON(r):r}catch(o){}x.data(e,n,r)}else r=t}return r}function I(e){var t;for(t in e)if(("data"!==t||!x.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}x.extend({queue:function(e,n,r){var i;return e?(n=(n||"fx")+"queue",i=x._data(e,n),r&&(!i||x.isArray(r)?i=x._data(e,n,x.makeArray(r)):i.push(r)),i||[]):t},dequeue:function(e,t){t=t||"fx";var n=x.queue(e,t),r=n.length,i=n.shift(),o=x._queueHooks(e,t),a=function(){x.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return x._data(e,n)||x._data(e,n,{empty:x.Callbacks("once memory").add(function(){x._removeData(e,t+"queue"),x._removeData(e,n)})})}}),x.fn.extend({queue:function(e,n){var r=2;return"string"!=typeof e&&(n=e,e="fx",r--),r>arguments.length?x.queue(this[0],e):n===t?this:this.each(function(){var t=x.queue(this,e,n);x._queueHooks(this,e),"fx"===e&&"inprogress"!==t[0]&&x.dequeue(this,e)})},dequeue:function(e){return this.each(function(){x.dequeue(this,e)})},delay:function(e,t){return e=x.fx?x.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,n){var r,i=1,o=x.Deferred(),a=this,s=this.length,l=function(){--i||o.resolveWith(a,[a])};"string"!=typeof e&&(n=e,e=t),e=e||"fx";while(s--)r=x._data(a[s],e+"queueHooks"),r&&r.empty&&(i++,r.empty.add(l));return l(),o.promise(n)}});var z,X,U=/[\t\r\n\f]/g,V=/\r/g,Y=/^(?:input|select|textarea|button|object)$/i,J=/^(?:a|area)$/i,G=/^(?:checked|selected)$/i,Q=x.support.getSetAttribute,K=x.support.input;x.fn.extend({attr:function(e,t){return x.access(this,x.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){x.removeAttr(this,e)})},prop:function(e,t){return x.access(this,x.prop,e,t,arguments.length>1)},removeProp:function(e){return e=x.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,o,a=0,s=this.length,l="string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).addClass(e.call(this,t,this.className))});if(l)for(t=(e||"").match(T)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(U," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=x.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,a=0,s=this.length,l=0===arguments.length||"string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).removeClass(e.call(this,t,this.className))});if(l)for(t=(e||"").match(T)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(U," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?x.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e;return"boolean"==typeof t&&"string"===n?t?this.addClass(e):this.removeClass(e):x.isFunction(e)?this.each(function(n){x(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var t,r=0,o=x(this),a=e.match(T)||[];while(t=a[r++])o.hasClass(t)?o.removeClass(t):o.addClass(t)}else(n===i||"boolean"===n)&&(this.className&&x._data(this,"__className__",this.className),this.className=this.className||e===!1?"":x._data(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(U," ").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,o=this[0];{if(arguments.length)return i=x.isFunction(e),this.each(function(n){var o;1===this.nodeType&&(o=i?e.call(this,n,x(this).val()):e,null==o?o="":"number"==typeof o?o+="":x.isArray(o)&&(o=x.map(o,function(e){return null==e?"":e+""})),r=x.valHooks[this.type]||x.valHooks[this.nodeName.toLowerCase()],r&&"set"in r&&r.set(this,o,"value")!==t||(this.value=o))});if(o)return r=x.valHooks[o.type]||x.valHooks[o.nodeName.toLowerCase()],r&&"get"in r&&(n=r.get(o,"value"))!==t?n:(n=o.value,"string"==typeof n?n.replace(V,""):null==n?"":n)}}}),x.extend({valHooks:{option:{get:function(e){var t=x.find.attr(e,"value");return null!=t?t:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,a=o?null:[],s=o?i+1:r.length,l=0>i?s:o?i:0;for(;s>l;l++)if(n=r[l],!(!n.selected&&l!==i||(x.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&x.nodeName(n.parentNode,"optgroup"))){if(t=x(n).val(),o)return t;a.push(t)}return a},set:function(e,t){var n,r,i=e.options,o=x.makeArray(t),a=i.length;while(a--)r=i[a],(r.selected=x.inArray(x(r).val(),o)>=0)&&(n=!0);return n||(e.selectedIndex=-1),o}}},attr:function(e,n,r){var o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return typeof e.getAttribute===i?x.prop(e,n,r):(1===s&&x.isXMLDoc(e)||(n=n.toLowerCase(),o=x.attrHooks[n]||(x.expr.match.bool.test(n)?X:z)),r===t?o&&"get"in o&&null!==(a=o.get(e,n))?a:(a=x.find.attr(e,n),null==a?t:a):null!==r?o&&"set"in o&&(a=o.set(e,r,n))!==t?a:(e.setAttribute(n,r+""),r):(x.removeAttr(e,n),t))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(T);if(o&&1===e.nodeType)while(n=o[i++])r=x.propFix[n]||n,x.expr.match.bool.test(n)?K&&Q||!G.test(n)?e[r]=!1:e[x.camelCase("default-"+n)]=e[r]=!1:x.attr(e,n,""),e.removeAttribute(Q?n:r)},attrHooks:{type:{set:function(e,t){if(!x.support.radioValue&&"radio"===t&&x.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{"for":"htmlFor","class":"className"},prop:function(e,n,r){var i,o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return a=1!==s||!x.isXMLDoc(e),a&&(n=x.propFix[n]||n,o=x.propHooks[n]),r!==t?o&&"set"in o&&(i=o.set(e,r,n))!==t?i:e[n]=r:o&&"get"in o&&null!==(i=o.get(e,n))?i:e[n]},propHooks:{tabIndex:{get:function(e){var t=x.find.attr(e,"tabindex");return t?parseInt(t,10):Y.test(e.nodeName)||J.test(e.nodeName)&&e.href?0:-1}}}}),X={set:function(e,t,n){return t===!1?x.removeAttr(e,n):K&&Q||!G.test(n)?e.setAttribute(!Q&&x.propFix[n]||n,n):e[x.camelCase("default-"+n)]=e[n]=!0,n}},x.each(x.expr.match.bool.source.match(/\w+/g),function(e,n){var r=x.expr.attrHandle[n]||x.find.attr;x.expr.attrHandle[n]=K&&Q||!G.test(n)?function(e,n,i){var o=x.expr.attrHandle[n],a=i?t:(x.expr.attrHandle[n]=t)!=r(e,n,i)?n.toLowerCase():null;return x.expr.attrHandle[n]=o,a}:function(e,n,r){return r?t:e[x.camelCase("default-"+n)]?n.toLowerCase():null}}),K&&Q||(x.attrHooks.value={set:function(e,n,r){return x.nodeName(e,"input")?(e.defaultValue=n,t):z&&z.set(e,n,r)}}),Q||(z={set:function(e,n,r){var i=e.getAttributeNode(r);return i||e.setAttributeNode(i=e.ownerDocument.createAttribute(r)),i.value=n+="","value"===r||n===e.getAttribute(r)?n:t}},x.expr.attrHandle.id=x.expr.attrHandle.name=x.expr.attrHandle.coords=function(e,n,r){var i;return r?t:(i=e.getAttributeNode(n))&&""!==i.value?i.value:null},x.valHooks.button={get:function(e,n){var r=e.getAttributeNode(n);return r&&r.specified?r.value:t},set:z.set},x.attrHooks.contenteditable={set:function(e,t,n){z.set(e,""===t?!1:t,n)}},x.each(["width","height"],function(e,n){x.attrHooks[n]={set:function(e,r){return""===r?(e.setAttribute(n,"auto"),r):t}}})),x.support.hrefNormalized||x.each(["href","src"],function(e,t){x.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}}),x.support.style||(x.attrHooks.style={get:function(e){return e.style.cssText||t},set:function(e,t){return e.style.cssText=t+""}}),x.support.optSelected||(x.propHooks.selected={get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}}),x.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){x.propFix[this.toLowerCase()]=this}),x.support.enctype||(x.propFix.enctype="encoding"),x.each(["radio","checkbox"],function(){x.valHooks[this]={set:function(e,n){return x.isArray(n)?e.checked=x.inArray(x(e).val(),n)>=0:t}},x.support.checkOn||(x.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var Z=/^(?:input|select|textarea)$/i,et=/^key/,tt=/^(?:mouse|contextmenu)|click/,nt=/^(?:focusinfocus|focusoutblur)$/,rt=/^([^.]*)(?:\.(.+)|)$/;function it(){return!0}function ot(){return!1}function at(){try{return a.activeElement}catch(e){}}x.event={global:{},add:function(e,n,r,o,a){var s,l,u,c,p,f,d,h,g,m,y,v=x._data(e);if(v){r.handler&&(c=r,r=c.handler,a=c.selector),r.guid||(r.guid=x.guid++),(l=v.events)||(l=v.events={}),(f=v.handle)||(f=v.handle=function(e){return typeof x===i||e&&x.event.triggered===e.type?t:x.event.dispatch.apply(f.elem,arguments)},f.elem=e),n=(n||"").match(T)||[""],u=n.length;while(u--)s=rt.exec(n[u])||[],g=y=s[1],m=(s[2]||"").split(".").sort(),g&&(p=x.event.special[g]||{},g=(a?p.delegateType:p.bindType)||g,p=x.event.special[g]||{},d=x.extend({type:g,origType:y,data:o,handler:r,guid:r.guid,selector:a,needsContext:a&&x.expr.match.needsContext.test(a),namespace:m.join(".")},c),(h=l[g])||(h=l[g]=[],h.delegateCount=0,p.setup&&p.setup.call(e,o,m,f)!==!1||(e.addEventListener?e.addEventListener(g,f,!1):e.attachEvent&&e.attachEvent("on"+g,f))),p.add&&(p.add.call(e,d),d.handler.guid||(d.handler.guid=r.guid)),a?h.splice(h.delegateCount++,0,d):h.push(d),x.event.global[g]=!0);e=null}},remove:function(e,t,n,r,i){var o,a,s,l,u,c,p,f,d,h,g,m=x.hasData(e)&&x._data(e);if(m&&(c=m.events)){t=(t||"").match(T)||[""],u=t.length;while(u--)if(s=rt.exec(t[u])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){p=x.event.special[d]||{},d=(r?p.delegateType:p.bindType)||d,f=c[d]||[],s=s[2]&&RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),l=o=f.length;while(o--)a=f[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&("**"!==r||!a.selector)||(f.splice(o,1),a.selector&&f.delegateCount--,p.remove&&p.remove.call(e,a));l&&!f.length&&(p.teardown&&p.teardown.call(e,h,m.handle)!==!1||x.removeEvent(e,d,m.handle),delete c[d])}else for(d in c)x.event.remove(e,d+t[u],n,r,!0);x.isEmptyObject(c)&&(delete m.handle,x._removeData(e,"events"))}},trigger:function(n,r,i,o){var s,l,u,c,p,f,d,h=[i||a],g=v.call(n,"type")?n.type:n,m=v.call(n,"namespace")?n.namespace.split("."):[];if(u=f=i=i||a,3!==i.nodeType&&8!==i.nodeType&&!nt.test(g+x.event.triggered)&&(g.indexOf(".")>=0&&(m=g.split("."),g=m.shift(),m.sort()),l=0>g.indexOf(":")&&"on"+g,n=n[x.expando]?n:new x.Event(g,"object"==typeof n&&n),n.isTrigger=o?2:3,n.namespace=m.join("."),n.namespace_re=n.namespace?RegExp("(^|\\.)"+m.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,n.result=t,n.target||(n.target=i),r=null==r?[n]:x.makeArray(r,[n]),p=x.event.special[g]||{},o||!p.trigger||p.trigger.apply(i,r)!==!1)){if(!o&&!p.noBubble&&!x.isWindow(i)){for(c=p.delegateType||g,nt.test(c+g)||(u=u.parentNode);u;u=u.parentNode)h.push(u),f=u;f===(i.ownerDocument||a)&&h.push(f.defaultView||f.parentWindow||e)}d=0;while((u=h[d++])&&!n.isPropagationStopped())n.type=d>1?c:p.bindType||g,s=(x._data(u,"events")||{})[n.type]&&x._data(u,"handle"),s&&s.apply(u,r),s=l&&u[l],s&&x.acceptData(u)&&s.apply&&s.apply(u,r)===!1&&n.preventDefault();if(n.type=g,!o&&!n.isDefaultPrevented()&&(!p._default||p._default.apply(h.pop(),r)===!1)&&x.acceptData(i)&&l&&i[g]&&!x.isWindow(i)){f=i[l],f&&(i[l]=null),x.event.triggered=g;try{i[g]()}catch(y){}x.event.triggered=t,f&&(i[l]=f)}return n.result}},dispatch:function(e){e=x.event.fix(e);var n,r,i,o,a,s=[],l=g.call(arguments),u=(x._data(this,"events")||{})[e.type]||[],c=x.event.special[e.type]||{};if(l[0]=e,e.delegateTarget=this,!c.preDispatch||c.preDispatch.call(this,e)!==!1){s=x.event.handlers.call(this,e,u),n=0;while((o=s[n++])&&!e.isPropagationStopped()){e.currentTarget=o.elem,a=0;while((i=o.handlers[a++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(i.namespace))&&(e.handleObj=i,e.data=i.data,r=((x.event.special[i.origType]||{}).handle||i.handler).apply(o.elem,l),r!==t&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,e),e.result}},handlers:function(e,n){var r,i,o,a,s=[],l=n.delegateCount,u=e.target;if(l&&u.nodeType&&(!e.button||"click"!==e.type))for(;u!=this;u=u.parentNode||this)if(1===u.nodeType&&(u.disabled!==!0||"click"!==e.type)){for(o=[],a=0;l>a;a++)i=n[a],r=i.selector+" ",o[r]===t&&(o[r]=i.needsContext?x(r,this).index(u)>=0:x.find(r,this,null,[u]).length),o[r]&&o.push(i);o.length&&s.push({elem:u,handlers:o})}return n.length>l&&s.push({elem:this,handlers:n.slice(l)}),s},fix:function(e){if(e[x.expando])return e;var t,n,r,i=e.type,o=e,s=this.fixHooks[i];s||(this.fixHooks[i]=s=tt.test(i)?this.mouseHooks:et.test(i)?this.keyHooks:{}),r=s.props?this.props.concat(s.props):this.props,e=new x.Event(o),t=r.length;while(t--)n=r[t],e[n]=o[n];return e.target||(e.target=o.srcElement||a),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,o):e},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,n){var r,i,o,s=n.button,l=n.fromElement;return null==e.pageX&&null!=n.clientX&&(i=e.target.ownerDocument||a,o=i.documentElement,r=i.body,e.pageX=n.clientX+(o&&o.scrollLeft||r&&r.scrollLeft||0)-(o&&o.clientLeft||r&&r.clientLeft||0),e.pageY=n.clientY+(o&&o.scrollTop||r&&r.scrollTop||0)-(o&&o.clientTop||r&&r.clientTop||0)),!e.relatedTarget&&l&&(e.relatedTarget=l===e.target?n.toElement:l),e.which||s===t||(e.which=1&s?1:2&s?3:4&s?2:0),e}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==at()&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:"focusin"},blur:{trigger:function(){return this===at()&&this.blur?(this.blur(),!1):t},delegateType:"focusout"},click:{trigger:function(){return x.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):t},_default:function(e){return x.nodeName(e.target,"a")}},beforeunload:{postDispatch:function(e){e.result!==t&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=x.extend(new x.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?x.event.trigger(i,null,t):x.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},x.removeEvent=a.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r="on"+t;e.detachEvent&&(typeof e[r]===i&&(e[r]=null),e.detachEvent(r,n))},x.Event=function(e,n){return this instanceof x.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?it:ot):this.type=e,n&&x.extend(this,n),this.timeStamp=e&&e.timeStamp||x.now(),this[x.expando]=!0,t):new x.Event(e,n)},x.Event.prototype={isDefaultPrevented:ot,isPropagationStopped:ot,isImmediatePropagationStopped:ot,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=it,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=it,e&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=it,this.stopPropagation()}},x.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){x.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return(!i||i!==r&&!x.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),x.support.submitBubbles||(x.event.special.submit={setup:function(){return x.nodeName(this,"form")?!1:(x.event.add(this,"click._submit keypress._submit",function(e){var n=e.target,r=x.nodeName(n,"input")||x.nodeName(n,"button")?n.form:t;r&&!x._data(r,"submitBubbles")&&(x.event.add(r,"submit._submit",function(e){e._submit_bubble=!0}),x._data(r,"submitBubbles",!0))}),t)},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&x.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){return x.nodeName(this,"form")?!1:(x.event.remove(this,"._submit"),t)}}),x.support.changeBubbles||(x.event.special.change={setup:function(){return Z.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(x.event.add(this,"propertychange._change",function(e){"checked"===e.originalEvent.propertyName&&(this._just_changed=!0)}),x.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),x.event.simulate("change",this,e,!0)})),!1):(x.event.add(this,"beforeactivate._change",function(e){var t=e.target;Z.test(t.nodeName)&&!x._data(t,"changeBubbles")&&(x.event.add(t,"change._change",function(e){!this.parentNode||e.isSimulated||e.isTrigger||x.event.simulate("change",this.parentNode,e,!0)}),x._data(t,"changeBubbles",!0))}),t)},handle:function(e){var n=e.target;return this!==n||e.isSimulated||e.isTrigger||"radio"!==n.type&&"checkbox"!==n.type?e.handleObj.handler.apply(this,arguments):t},teardown:function(){return x.event.remove(this,"._change"),!Z.test(this.nodeName)}}),x.support.focusinBubbles||x.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){x.event.simulate(t,e.target,x.event.fix(e),!0)};x.event.special[t]={setup:function(){0===n++&&a.addEventListener(e,r,!0)},teardown:function(){0===--n&&a.removeEventListener(e,r,!0)}}}),x.fn.extend({on:function(e,n,r,i,o){var a,s;if("object"==typeof e){"string"!=typeof n&&(r=r||n,n=t);for(a in e)this.on(a,n,r,e[a],o);return this}if(null==r&&null==i?(i=n,r=n=t):null==i&&("string"==typeof n?(i=r,r=t):(i=r,r=n,n=t)),i===!1)i=ot;else if(!i)return this;return 1===o&&(s=i,i=function(e){return x().off(e),s.apply(this,arguments)},i.guid=s.guid||(s.guid=x.guid++)),this.each(function(){x.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,o;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,x(e.delegateTarget).off(i.namespace?i.origType+"."+i.namespace:i.origType,i.selector,i.handler),this;if("object"==typeof e){for(o in e)this.off(o,n,e[o]);return this}return(n===!1||"function"==typeof n)&&(r=n,n=t),r===!1&&(r=ot),this.each(function(){x.event.remove(this,e,r,n)})},trigger:function(e,t){return this.each(function(){x.event.trigger(e,t,this)})},triggerHandler:function(e,n){var r=this[0];return r?x.event.trigger(e,n,r,!0):t}});var st=/^.[^:#\[\.,]*$/,lt=/^(?:parents|prev(?:Until|All))/,ut=x.expr.match.needsContext,ct={children:!0,contents:!0,next:!0,prev:!0};x.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if("string"!=typeof e)return this.pushStack(x(e).filter(function(){for(t=0;i>t;t++)if(x.contains(r[t],this))return!0}));for(t=0;i>t;t++)x.find(e,r[t],n);return n=this.pushStack(i>1?x.unique(n):n),n.selector=this.selector?this.selector+" "+e:e,n},has:function(e){var t,n=x(e,this),r=n.length;return this.filter(function(){for(t=0;r>t;t++)if(x.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(ft(this,e||[],!0))},filter:function(e){return this.pushStack(ft(this,e||[],!1))},is:function(e){return!!ft(this,"string"==typeof e&&ut.test(e)?x(e):e||[],!1).length},closest:function(e,t){var n,r=0,i=this.length,o=[],a=ut.test(e)||"string"!=typeof e?x(e,t||this.context):0;for(;i>r;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(11>n.nodeType&&(a?a.index(n)>-1:1===n.nodeType&&x.find.matchesSelector(n,e))){n=o.push(n);break}return this.pushStack(o.length>1?x.unique(o):o)},index:function(e){return e?"string"==typeof e?x.inArray(this[0],x(e)):x.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?x(e,t):x.makeArray(e&&e.nodeType?[e]:e),r=x.merge(this.get(),n);return this.pushStack(x.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function pt(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}x.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return x.dir(e,"parentNode")},parentsUntil:function(e,t,n){return x.dir(e,"parentNode",n)},next:function(e){return pt(e,"nextSibling")},prev:function(e){return pt(e,"previousSibling")},nextAll:function(e){return x.dir(e,"nextSibling")},prevAll:function(e){return x.dir(e,"previousSibling")},nextUntil:function(e,t,n){return x.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return x.dir(e,"previousSibling",n)},siblings:function(e){return x.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return x.sibling(e.firstChild)},contents:function(e){return x.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:x.merge([],e.childNodes)}},function(e,t){x.fn[e]=function(n,r){var i=x.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=x.filter(r,i)),this.length>1&&(ct[e]||(i=x.unique(i)),lt.test(e)&&(i=i.reverse())),this.pushStack(i)}}),x.extend({filter:function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?x.find.matchesSelector(r,e)?[r]:[]:x.find.matches(e,x.grep(t,function(e){return 1===e.nodeType}))},dir:function(e,n,r){var i=[],o=e[n];while(o&&9!==o.nodeType&&(r===t||1!==o.nodeType||!x(o).is(r)))1===o.nodeType&&i.push(o),o=o[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function ft(e,t,n){if(x.isFunction(t))return x.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return x.grep(e,function(e){return e===t!==n});if("string"==typeof t){if(st.test(t))return x.filter(t,e,n);t=x.filter(t,e)}return x.grep(e,function(e){return x.inArray(e,t)>=0!==n})}function dt(e){var t=ht.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}var ht="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",gt=/ jQuery\d+="(?:null|\d+)"/g,mt=RegExp("<(?:"+ht+")[\\s/>]","i"),yt=/^\s+/,vt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bt=/<([\w:]+)/,xt=/\s*$/g,At={option:[1,""],legend:[1,"
          ","
          "],area:[1,"",""],param:[1,"",""],thead:[1,"","
          "],tr:[2,"","
          "],col:[2,"","
          "],td:[3,"","
          "],_default:x.support.htmlSerialize?[0,"",""]:[1,"X
          ","
          "]},jt=dt(a),Dt=jt.appendChild(a.createElement("div"));At.optgroup=At.option,At.tbody=At.tfoot=At.colgroup=At.caption=At.thead,At.th=At.td,x.fn.extend({text:function(e){return x.access(this,function(e){return e===t?x.text(this):this.empty().append((this[0]&&this[0].ownerDocument||a).createTextNode(e))},null,e,arguments.length)},append:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.appendChild(e)}})},prepend:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=e?x.filter(e,this):this,i=0;for(;null!=(n=r[i]);i++)t||1!==n.nodeType||x.cleanData(Ft(n)),n.parentNode&&(t&&x.contains(n.ownerDocument,n)&&_t(Ft(n,"script")),n.parentNode.removeChild(n));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++){1===e.nodeType&&x.cleanData(Ft(e,!1));while(e.firstChild)e.removeChild(e.firstChild);e.options&&x.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return x.clone(this,e,t)})},html:function(e){return x.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return 1===n.nodeType?n.innerHTML.replace(gt,""):t;if(!("string"!=typeof e||Tt.test(e)||!x.support.htmlSerialize&&mt.test(e)||!x.support.leadingWhitespace&&yt.test(e)||At[(bt.exec(e)||["",""])[1].toLowerCase()])){e=e.replace(vt,"<$1>");try{for(;i>r;r++)n=this[r]||{},1===n.nodeType&&(x.cleanData(Ft(n,!1)),n.innerHTML=e);n=0}catch(o){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=x.map(this,function(e){return[e.nextSibling,e.parentNode]}),t=0;return this.domManip(arguments,function(n){var r=e[t++],i=e[t++];i&&(r&&r.parentNode!==i&&(r=this.nextSibling),x(this).remove(),i.insertBefore(n,r))},!0),t?this:this.remove()},detach:function(e){return this.remove(e,!0)},domManip:function(e,t,n){e=d.apply([],e);var r,i,o,a,s,l,u=0,c=this.length,p=this,f=c-1,h=e[0],g=x.isFunction(h);if(g||!(1>=c||"string"!=typeof h||x.support.checkClone)&&Nt.test(h))return this.each(function(r){var i=p.eq(r);g&&(e[0]=h.call(this,r,i.html())),i.domManip(e,t,n)});if(c&&(l=x.buildFragment(e,this[0].ownerDocument,!1,!n&&this),r=l.firstChild,1===l.childNodes.length&&(l=r),r)){for(a=x.map(Ft(l,"script"),Ht),o=a.length;c>u;u++)i=l,u!==f&&(i=x.clone(i,!0,!0),o&&x.merge(a,Ft(i,"script"))),t.call(this[u],i,u);if(o)for(s=a[a.length-1].ownerDocument,x.map(a,qt),u=0;o>u;u++)i=a[u],kt.test(i.type||"")&&!x._data(i,"globalEval")&&x.contains(s,i)&&(i.src?x._evalUrl(i.src):x.globalEval((i.text||i.textContent||i.innerHTML||"").replace(St,"")));l=r=null}return this}});function Lt(e,t){return x.nodeName(e,"table")&&x.nodeName(1===t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function Ht(e){return e.type=(null!==x.find.attr(e,"type"))+"/"+e.type,e}function qt(e){var t=Et.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function _t(e,t){var n,r=0;for(;null!=(n=e[r]);r++)x._data(n,"globalEval",!t||x._data(t[r],"globalEval"))}function Mt(e,t){if(1===t.nodeType&&x.hasData(e)){var n,r,i,o=x._data(e),a=x._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)x.event.add(t,n,s[n][r])}a.data&&(a.data=x.extend({},a.data))}}function Ot(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!x.support.noCloneEvent&&t[x.expando]){i=x._data(t);for(r in i.events)x.removeEvent(t,r,i.handle);t.removeAttribute(x.expando)}"script"===n&&t.text!==e.text?(Ht(t).text=e.text,qt(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),x.support.html5Clone&&e.innerHTML&&!x.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&Ct.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}x.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){x.fn[e]=function(e){var n,r=0,i=[],o=x(e),a=o.length-1;for(;a>=r;r++)n=r===a?this:this.clone(!0),x(o[r])[t](n),h.apply(i,n.get());return this.pushStack(i)}});function Ft(e,n){var r,o,a=0,s=typeof e.getElementsByTagName!==i?e.getElementsByTagName(n||"*"):typeof e.querySelectorAll!==i?e.querySelectorAll(n||"*"):t;if(!s)for(s=[],r=e.childNodes||e;null!=(o=r[a]);a++)!n||x.nodeName(o,n)?s.push(o):x.merge(s,Ft(o,n));return n===t||n&&x.nodeName(e,n)?x.merge([e],s):s}function Bt(e){Ct.test(e.type)&&(e.defaultChecked=e.checked)}x.extend({clone:function(e,t,n){var r,i,o,a,s,l=x.contains(e.ownerDocument,e);if(x.support.html5Clone||x.isXMLDoc(e)||!mt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(Dt.innerHTML=e.outerHTML,Dt.removeChild(o=Dt.firstChild)),!(x.support.noCloneEvent&&x.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||x.isXMLDoc(e)))for(r=Ft(o),s=Ft(e),a=0;null!=(i=s[a]);++a)r[a]&&Ot(i,r[a]);if(t)if(n)for(s=s||Ft(e),r=r||Ft(o),a=0;null!=(i=s[a]);a++)Mt(i,r[a]);else Mt(e,o);return r=Ft(o,"script"),r.length>0&&_t(r,!l&&Ft(e,"script")),r=s=i=null,o},buildFragment:function(e,t,n,r){var i,o,a,s,l,u,c,p=e.length,f=dt(t),d=[],h=0;for(;p>h;h++)if(o=e[h],o||0===o)if("object"===x.type(o))x.merge(d,o.nodeType?[o]:o);else if(wt.test(o)){s=s||f.appendChild(t.createElement("div")),l=(bt.exec(o)||["",""])[1].toLowerCase(),c=At[l]||At._default,s.innerHTML=c[1]+o.replace(vt,"<$1>")+c[2],i=c[0];while(i--)s=s.lastChild;if(!x.support.leadingWhitespace&&yt.test(o)&&d.push(t.createTextNode(yt.exec(o)[0])),!x.support.tbody){o="table"!==l||xt.test(o)?""!==c[1]||xt.test(o)?0:s:s.firstChild,i=o&&o.childNodes.length;while(i--)x.nodeName(u=o.childNodes[i],"tbody")&&!u.childNodes.length&&o.removeChild(u)}x.merge(d,s.childNodes),s.textContent="";while(s.firstChild)s.removeChild(s.firstChild);s=f.lastChild}else d.push(t.createTextNode(o));s&&f.removeChild(s),x.support.appendChecked||x.grep(Ft(d,"input"),Bt),h=0;while(o=d[h++])if((!r||-1===x.inArray(o,r))&&(a=x.contains(o.ownerDocument,o),s=Ft(f.appendChild(o),"script"),a&&_t(s),n)){i=0;while(o=s[i++])kt.test(o.type||"")&&n.push(o)}return s=null,f},cleanData:function(e,t){var n,r,o,a,s=0,l=x.expando,u=x.cache,c=x.support.deleteExpando,f=x.event.special;for(;null!=(n=e[s]);s++)if((t||x.acceptData(n))&&(o=n[l],a=o&&u[o])){if(a.events)for(r in a.events)f[r]?x.event.remove(n,r):x.removeEvent(n,r,a.handle); +u[o]&&(delete u[o],c?delete n[l]:typeof n.removeAttribute!==i?n.removeAttribute(l):n[l]=null,p.push(o))}},_evalUrl:function(e){return x.ajax({url:e,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})}}),x.fn.extend({wrapAll:function(e){if(x.isFunction(e))return this.each(function(t){x(this).wrapAll(e.call(this,t))});if(this[0]){var t=x(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&1===e.firstChild.nodeType)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return x.isFunction(e)?this.each(function(t){x(this).wrapInner(e.call(this,t))}):this.each(function(){var t=x(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=x.isFunction(e);return this.each(function(n){x(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){x.nodeName(this,"body")||x(this).replaceWith(this.childNodes)}).end()}});var Pt,Rt,Wt,$t=/alpha\([^)]*\)/i,It=/opacity\s*=\s*([^)]*)/,zt=/^(top|right|bottom|left)$/,Xt=/^(none|table(?!-c[ea]).+)/,Ut=/^margin/,Vt=RegExp("^("+w+")(.*)$","i"),Yt=RegExp("^("+w+")(?!px)[a-z%]+$","i"),Jt=RegExp("^([+-])=("+w+")","i"),Gt={BODY:"block"},Qt={position:"absolute",visibility:"hidden",display:"block"},Kt={letterSpacing:0,fontWeight:400},Zt=["Top","Right","Bottom","Left"],en=["Webkit","O","Moz","ms"];function tn(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=en.length;while(i--)if(t=en[i]+n,t in e)return t;return r}function nn(e,t){return e=t||e,"none"===x.css(e,"display")||!x.contains(e.ownerDocument,e)}function rn(e,t){var n,r,i,o=[],a=0,s=e.length;for(;s>a;a++)r=e[a],r.style&&(o[a]=x._data(r,"olddisplay"),n=r.style.display,t?(o[a]||"none"!==n||(r.style.display=""),""===r.style.display&&nn(r)&&(o[a]=x._data(r,"olddisplay",ln(r.nodeName)))):o[a]||(i=nn(r),(n&&"none"!==n||!i)&&x._data(r,"olddisplay",i?n:x.css(r,"display"))));for(a=0;s>a;a++)r=e[a],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[a]||"":"none"));return e}x.fn.extend({css:function(e,n){return x.access(this,function(e,n,r){var i,o,a={},s=0;if(x.isArray(n)){for(o=Rt(e),i=n.length;i>s;s++)a[n[s]]=x.css(e,n[s],!1,o);return a}return r!==t?x.style(e,n,r):x.css(e,n)},e,n,arguments.length>1)},show:function(){return rn(this,!0)},hide:function(){return rn(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){nn(this)?x(this).show():x(this).hide()})}}),x.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Wt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":x.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var o,a,s,l=x.camelCase(n),u=e.style;if(n=x.cssProps[l]||(x.cssProps[l]=tn(u,l)),s=x.cssHooks[n]||x.cssHooks[l],r===t)return s&&"get"in s&&(o=s.get(e,!1,i))!==t?o:u[n];if(a=typeof r,"string"===a&&(o=Jt.exec(r))&&(r=(o[1]+1)*o[2]+parseFloat(x.css(e,n)),a="number"),!(null==r||"number"===a&&isNaN(r)||("number"!==a||x.cssNumber[l]||(r+="px"),x.support.clearCloneStyle||""!==r||0!==n.indexOf("background")||(u[n]="inherit"),s&&"set"in s&&(r=s.set(e,r,i))===t)))try{u[n]=r}catch(c){}}},css:function(e,n,r,i){var o,a,s,l=x.camelCase(n);return n=x.cssProps[l]||(x.cssProps[l]=tn(e.style,l)),s=x.cssHooks[n]||x.cssHooks[l],s&&"get"in s&&(a=s.get(e,!0,r)),a===t&&(a=Wt(e,n,i)),"normal"===a&&n in Kt&&(a=Kt[n]),""===r||r?(o=parseFloat(a),r===!0||x.isNumeric(o)?o||0:a):a}}),e.getComputedStyle?(Rt=function(t){return e.getComputedStyle(t,null)},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s.getPropertyValue(n)||s[n]:t,u=e.style;return s&&(""!==l||x.contains(e.ownerDocument,e)||(l=x.style(e,n)),Yt.test(l)&&Ut.test(n)&&(i=u.width,o=u.minWidth,a=u.maxWidth,u.minWidth=u.maxWidth=u.width=l,l=s.width,u.width=i,u.minWidth=o,u.maxWidth=a)),l}):a.documentElement.currentStyle&&(Rt=function(e){return e.currentStyle},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s[n]:t,u=e.style;return null==l&&u&&u[n]&&(l=u[n]),Yt.test(l)&&!zt.test(n)&&(i=u.left,o=e.runtimeStyle,a=o&&o.left,a&&(o.left=e.currentStyle.left),u.left="fontSize"===n?"1em":l,l=u.pixelLeft+"px",u.left=i,a&&(o.left=a)),""===l?"auto":l});function on(e,t,n){var r=Vt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function an(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;for(;4>o;o+=2)"margin"===n&&(a+=x.css(e,n+Zt[o],!0,i)),r?("content"===n&&(a-=x.css(e,"padding"+Zt[o],!0,i)),"margin"!==n&&(a-=x.css(e,"border"+Zt[o]+"Width",!0,i))):(a+=x.css(e,"padding"+Zt[o],!0,i),"padding"!==n&&(a+=x.css(e,"border"+Zt[o]+"Width",!0,i)));return a}function sn(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=Rt(e),a=x.support.boxSizing&&"border-box"===x.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=Wt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Yt.test(i))return i;r=a&&(x.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+an(e,t,n||(a?"border":"content"),r,o)+"px"}function ln(e){var t=a,n=Gt[e];return n||(n=un(e,t),"none"!==n&&n||(Pt=(Pt||x("