├── icon-192.png
├── manifest.json
├── README.md
├── LICENSE
├── sw.js
├── index.html
├── game.js
└── twemoji.js
/icon-192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muan/emoji-minesweeper/HEAD/icon-192.png
--------------------------------------------------------------------------------
/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "Minesweeper",
3 | "name": "Emoji Minesweeper",
4 | "icons": [
5 | {
6 | "src": "/icon-192.png",
7 | "type": "image/png",
8 | "sizes": "192x192"
9 | }
10 | ],
11 | "start_url": "/emoji-minesweeper/",
12 | "background_color": "#ffffff",
13 | "display": "standalone",
14 | "scope": "/emoji-minesweeper/"
15 | }
16 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # emoji-minesweeper [](https://github.com/feross/standard)
2 |
3 | ### How to play
4 |
5 | - Left click to step on a spot
6 | - Right click to mark a spot as a bomb
7 | - Double click to open all 8 spots nearby a target (except ones already marked as bombs using right clicks)
8 |
9 | **This is a work in progress**
10 |
11 | 
12 |
13 | ### API
14 |
15 | ```javascript
16 | // to start a new game
17 | new Game(cols, rows, bombs, [emptyemoji, bombemoji, flagemoji, starteremoji], twemojiOrNot)
18 |
19 | // for example:
20 | new Game(10, 10, 10, ["🌱", "💥", "🚩", "◻️"], true)
21 | new Game(16, 16, 30, ["🐱", "📛", "💣", "🔍"], false)
22 | ```
23 |
24 | ### Todos
25 |
26 | - Mobile!
27 |
28 | ### Zap :zap:
29 |
30 | :heart: https://github.com/twitter/twemoji
31 |
32 | ### Why
33 |
34 | [WHY IS THIS A QUESTION?!](https://twitter.com/muanchiou/status/601633821012856832)
35 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Mu-An Chiou
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/sw.js:
--------------------------------------------------------------------------------
1 | var APP_PREFIX = 'EmojiMinesweeper'
2 | var VERSION = 'v0.0.2'
3 | var CACHE_NAME = APP_PREFIX + VERSION
4 | var URLS = [
5 | '/emoji-minesweeper/',
6 | '/emoji-minesweeper/index.html',
7 | '/emoji-minesweeper/game.js',
8 | '/emoji-minesweeper/twemoji.js'
9 |
10 | ]
11 |
12 | // Respond with cached resources
13 | self.addEventListener('fetch', function (e) {
14 | console.log('fetch request : ' + e.request.url)
15 | e.respondWith(
16 | caches.match(e.request).then(function (request) {
17 | if (request) { // if cache is available, respond with cache
18 | console.log('responding with cache : ' + e.request.url)
19 | return request
20 | } else { // if there are no cache, try fetching request
21 | console.log('file is not cached, fetching : ' + e.request.url)
22 | return fetch(e.request)
23 | }
24 | })
25 | )
26 | })
27 |
28 | // Cache resources
29 | self.addEventListener('install', function (e) {
30 | e.waitUntil(
31 | caches.open(CACHE_NAME).then(function (cache) {
32 | console.log('installing cache : ' + CACHE_NAME)
33 | return cache.addAll(URLS)
34 | })
35 | )
36 | })
37 |
38 | // Delete outdated caches
39 | self.addEventListener('activate', function (e) {
40 | e.waitUntil(
41 | caches.keys().then(function (keyList) {
42 | var cacheWhitelist = keyList.filter(function (key) {
43 | return key.indexOf(APP_PREFIX)
44 | })
45 | cacheWhitelist.push(CACHE_NAME)
46 |
47 | return Promise.all(keyList.map(function (key, i) {
48 | if (cacheWhitelist.indexOf(key) === -1) {
49 | console.log('deleting cache : ' + keyList[i] )
50 | return caches.delete(keyList[i])
51 | }
52 | }))
53 | })
54 | )
55 | })
56 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 💥
5 |
6 |
7 |
8 |
9 |
10 |
267 |
268 |
269 |
270 |
271 |
292 |
296 |
297 |
298 |
303 |
304 | [Code]
305 |
306 |
307 |
310 |
311 |
312 |
313 |
314 |
315 |
340 |
349 |
350 |
351 |
352 |
--------------------------------------------------------------------------------
/game.js:
--------------------------------------------------------------------------------
1 | /* global twemoji, alert, MouseEvent, game */
2 | const numbers = ['1️⃣', '2️⃣', '3️⃣', '4️⃣', '5️⃣', '6️⃣', '7️⃣', '8️⃣']
3 | const iDevise = navigator.platform.match(/^iP/)
4 | const feedback = document.querySelector('.feedback')
5 |
6 | var Game = function (cols, rows, number_of_bombs, set, usetwemoji) {
7 | this.number_of_cells = cols * rows
8 | this.map = document.getElementById('map')
9 | this.cols = Number(cols)
10 | this.rows = Number(rows)
11 | this.number_of_bombs = Number(number_of_bombs)
12 | this.rate = number_of_bombs / this.number_of_cells
13 |
14 | this.emojiset = set
15 | this.numbermoji = [this.emojiset[0]].concat(numbers)
16 | this.usetwemoji = usetwemoji || false
17 |
18 | this.init()
19 | }
20 |
21 | Game.prototype.init = function () {
22 | this.prepareEmoji()
23 |
24 | if (this.number_of_cells > 2500) { alert('too big, go away, have less than 2500 cells'); return false }
25 | if (this.number_of_cells <= this.number_of_bombs) { alert('more bombs than cells, can\'t do it'); return false }
26 | var that = this
27 | this.moveIt(true)
28 | this.map.innerHTML = ''
29 | var grid_data = this.bomb_array()
30 |
31 | function getIndex (x, y) {
32 | if (x > that.cols || x <= 0) return -1
33 | if (y > that.cols || y <= 0) return -1
34 | return that.cols * (y - 1 ) + x - 1
35 | }
36 |
37 | var row = document.createElement('div')
38 | row.setAttribute('role', 'row')
39 | grid_data.forEach(function (isBomb, i) {
40 | var cell = document.createElement('span')
41 | cell.setAttribute('role', 'gridcell')
42 | var mine = that.mine(isBomb)
43 | var x = Math.floor((i + 1) % that.cols) || that.cols
44 | var y = Math.ceil((i + 1) / that.cols)
45 | var neighbors_cords = [[x, y - 1], [x, y + 1], [x - 1, y - 1], [x - 1, y], [x - 1, y + 1], [x + 1, y - 1], [x + 1, y], [x + 1, y + 1]]
46 | if(!isBomb) {
47 | var neighbors = neighbors_cords.map(function (xy) { return grid_data[getIndex(xy[0], xy[1])] })
48 | mine.mine_count = neighbors.filter(function (neighbor_bomb) { return neighbor_bomb }).length
49 | }
50 | mine.classList.add('x' + x, 'y' + y)
51 | mine.neighbors = neighbors_cords.map(function (xy) { return `.x${xy[0]}.y${xy[1]}` })
52 |
53 | cell.appendChild(mine)
54 | row.appendChild(cell)
55 | if (x === that.cols) {
56 | that.map.appendChild(row)
57 | row = document.createElement('div')
58 | row.setAttribute('role', 'row')
59 | }
60 | })
61 |
62 | this.resetMetadata()
63 | this.bindEvents()
64 | this.updateBombsLeft()
65 | }
66 |
67 | Game.prototype.bindEvents = function () {
68 | var that = this
69 | var cells = document.getElementsByClassName('cell')
70 |
71 | Array.prototype.forEach.call(cells, function (target) {
72 | // clicking on a cell and revealing cell
73 | target.addEventListener('click', function (evt) {
74 | if (!target.isMasked || target.isFlagged) return
75 | if (document.getElementsByClassName('unmasked').length === 0) {
76 | that.startTimer()
77 |
78 | if (target.isBomb) {
79 | that.restart(that.usetwemoji)
80 | var targetClasses = target.className.replace('unmasked', '')
81 | document.getElementsByClassName(targetClasses)[0].click()
82 | return
83 | }
84 | }
85 | if (evt.view) that.moveIt()
86 |
87 | target.reveal()
88 | that.updateFeedback(target.getAttribute('aria-label'))
89 |
90 | if (target.mine_count === 0 && !target.isBomb) {
91 | that.revealNeighbors(target)
92 | }
93 | that.game()
94 | })
95 |
96 | // double clicking on a cell and opening the cell and all 8 of its neighbors
97 | target.addEventListener('dblclick', function () {
98 | if (target.isFlagged) return
99 | that.moveIt()
100 |
101 | target.reveal()
102 | that.revealNeighbors(target)
103 | that.game()
104 | })
105 |
106 | // marking a cell as a potential bomb
107 | target.addEventListener('contextmenu', function (evt) {
108 | var emoji
109 | evt.preventDefault()
110 | if (!target.isMasked) { return }
111 | if (target.isFlagged) {
112 | target.setAttribute('aria-label','Field')
113 | that.updateFeedback('Unflagged as potential bomb')
114 | emoji = that.emojiset[3].cloneNode()
115 | target.isFlagged = false
116 | } else {
117 | target.setAttribute('aria-label', 'Flagged as potential bomb')
118 | that.updateFeedback('Flagged as potential bomb')
119 | emoji = that.emojiset[2].cloneNode()
120 | target.isFlagged = true
121 | }
122 | target.childNodes[0].remove()
123 | target.appendChild(emoji)
124 | that.updateBombsLeft()
125 | })
126 |
127 | // support to HOLD to mark bomb, works in Android by default
128 | if (iDevise) {
129 | target.addEventListener('touchstart', function (evt) {
130 | that.holding = setTimeout(function () {
131 | target.dispatchEvent(new Event('contextmenu'))
132 | }, 500)
133 | })
134 |
135 | target.addEventListener('touchend', function (evt) {
136 | clearTimeout(that.holding)
137 | })
138 | }
139 | })
140 |
141 | window.addEventListener('keydown', function (evt) {
142 | if (evt.key == 'r' || evt.which == 'R'.charCodeAt()) {
143 | that.restart(that.usetwemoji)
144 | }
145 | })
146 | }
147 |
148 | Game.prototype.game = function () {
149 | if (this.result) return
150 | var cells = document.getElementsByClassName('cell')
151 | var masked = Array.prototype.filter.call(cells, function (cell) {
152 | return cell.isMasked
153 | })
154 | var bombs = Array.prototype.filter.call(cells, function (cell) {
155 | return cell.isBomb && !cell.isMasked
156 | })
157 |
158 | if (bombs.length > 0) {
159 | Array.prototype.forEach.call(masked, function (cell) { cell.reveal() })
160 | this.result = 'lost'
161 | this.showMessage()
162 | } else if (masked.length === this.number_of_bombs) {
163 | Array.prototype.forEach.call(masked, function (cell) { cell.reveal(true) })
164 | this.result = 'won'
165 | this.showMessage()
166 | }
167 | }
168 |
169 | Game.prototype.restart = function (usetwemoji) {
170 | clearInterval(this.timer)
171 | this.result = false
172 | this.timer = false
173 | this.usetwemoji = usetwemoji
174 | this.init()
175 | }
176 |
177 | Game.prototype.resetMetadata = function () {
178 | document.getElementById('timer').textContent = '0.00'
179 | document.querySelector('.wrapper').classList.remove('won', 'lost')
180 | document.querySelector('.result-emoji').textContent = ''
181 | document.querySelector('.default-emoji').innerHTML = this.usetwemoji ? twemoji.parse('😀') : '😀'
182 | document.querySelector('.js-settings').innerHTML = this.usetwemoji ? twemoji.parse('🔧') : '🔧'
183 | }
184 |
185 | Game.prototype.startTimer = function () {
186 | if (this.timer) return
187 | this.startTime = new Date()
188 | this.timer = setInterval(function () {
189 | document.getElementById('timer').textContent = ((new Date() - game.startTime) / 1000).toFixed(2)
190 | }, 100)
191 | }
192 |
193 | Game.prototype.mine = function (bomb) {
194 | var that = this
195 | var base = document.createElement('button')
196 | base.type = 'button'
197 | base.setAttribute('aria-label', 'Field')
198 | base.className = 'cell'
199 | base.appendChild(this.emojiset[3].cloneNode())
200 | base.isMasked = true
201 | if (bomb) base.isBomb = true
202 | base.reveal = function (won) {
203 | var emoji = base.isBomb ? (won ? that.emojiset[2] : that.emojiset[1]) : that.numbermoji[base.mine_count]
204 | var text = base.isBomb ? (won ? "Bomb discovered" : "Boom!") : (base.mine_count === 0 ? "Empty field" : base.mine_count + " bombs nearby")
205 | this.childNodes[0].remove()
206 | this.setAttribute('aria-label', text)
207 | this.appendChild(emoji.cloneNode())
208 | this.isMasked = false
209 | this.classList.add('unmasked')
210 | }
211 | return base
212 | }
213 |
214 | Game.prototype.revealNeighbors = function (mine) {
215 | var neighbors = document.querySelectorAll(mine.neighbors)
216 | for(var i = 0; i < neighbors.length; i++) {
217 | if (neighbors[i].isMasked && !neighbors[i].isFlagged) {
218 | neighbors[i].reveal()
219 |
220 | if (neighbors[i].mine_count === 0 && !neighbors[i].isBomb) {
221 | this.revealNeighbors(neighbors[i])
222 | }
223 | }
224 | }
225 | }
226 |
227 | Game.prototype.prepareEmoji = function () {
228 | var that = this
229 | function makeEmojiElement (emoji) {
230 | var ele
231 | if(that.usetwemoji) {
232 | if (emoji.src) {
233 | ele = emoji
234 | } else {
235 | ele = document.createElement('img')
236 | ele.className = 'emoji'
237 | ele.setAttribute('aria-hidden', 'true')
238 | ele.src = twemoji.parse(emoji).match(/src=\"(.+)\">/)[1]
239 | }
240 | } else {
241 | ele = document.createTextNode(emoji.alt || emoji.data || emoji)
242 | }
243 | return ele
244 | }
245 |
246 | this.emojiset = this.emojiset.map(makeEmojiElement)
247 | this.numbermoji = this.numbermoji.map(makeEmojiElement)
248 | }
249 |
250 | Game.prototype.bomb_array = function () {
251 | var chance = Math.floor(this.rate * this.number_of_cells)
252 | var arr = []
253 | for (var i = 0; i < chance; i++) {
254 | arr.push(true)
255 | }
256 | for (var n = 0; n < (this.number_of_cells - chance); n++) {
257 | arr.push(false)
258 | }
259 | return this.shuffle(arr)
260 | }
261 |
262 | Game.prototype.shuffle = function (array) {
263 | var currentIndex = array.length, temporaryValue, randomIndex
264 | while (currentIndex !== 0) {
265 | randomIndex = Math.floor(Math.random() * currentIndex)
266 | currentIndex -= 1
267 | temporaryValue = array[currentIndex]
268 | array[currentIndex] = array[randomIndex]
269 | array[randomIndex] = temporaryValue
270 | }
271 | return array
272 | }
273 |
274 | Game.prototype.moveIt = function (zero) {
275 | zero ? this.moves = 0 : this.moves++
276 | document.getElementById('moves').textContent = this.moves
277 | }
278 |
279 | Game.prototype.updateBombsLeft = function () {
280 | var flagged = Array.prototype.filter.call(document.getElementsByClassName('cell'), function (target) { return target.isFlagged })
281 | document.getElementById('bombs-left').textContent = `${this.number_of_bombs - flagged.length}/${this.number_of_bombs}`
282 | }
283 |
284 | Game.prototype.updateFeedback = function (text) {
285 | feedback.textContent = text
286 | // Toggle period to force voiceover to read out the same content
287 | if (this.feedbackToggle) feedback.textContent += "."
288 | this.feedbackToggle = !this.feedbackToggle
289 | }
290 |
291 | Game.prototype.showMessage = function () {
292 | clearInterval(this.timer)
293 | var seconds = ((new Date() - this.startTime) / 1000).toFixed(2)
294 | var winner = this.result === 'won'
295 | var emoji = winner ? '😎' : '😵'
296 | this.updateFeedback(winner ? "Yay, you won!" : "Boom! you lost.")
297 | document.querySelector('.wrapper').classList.add(this.result)
298 | document.getElementById('timer').textContent = seconds
299 | document.getElementById('result').innerHTML = this.usetwemoji ? twemoji.parse(emoji) : emoji
300 | }
301 |
302 | // console documentation
303 |
304 | console.log('Use: `new Game(cols, rows, bombs, [emptyemoji, bombemoji, flagemoji, starteremoji], twemojiOrNot)` to start a new game with customizations.')
305 | console.log(' Eg: `game = new Game(10, 10, 10, ["🌱", "💥", "🚩", "◻️"], false)`')
306 | console.log(' Or: `game = new Game(16, 16, 30, ["🐣", "💣", "🚧", "◻️"], true)`')
307 |
--------------------------------------------------------------------------------
/twemoji.js:
--------------------------------------------------------------------------------
1 | /*! Copyright Twitter Inc. and other contributors. Licensed under MIT */
2 | var twemoji=function(){"use strict";var twemoji={base:(location.protocol==="https:"?"https:":"http:")+"//twemoji.maxcdn.com/",ext:".png",size:"36x36",className:"emoji",convert:{fromCodePoint:fromCodePoint,toCodePoint:toCodePoint},onerror:function onerror(){if(this.parentNode){this.parentNode.replaceChild(createText(this.alt),this)}},parse:parse,replace:replace,test:test},escaper={"&":"&","<":"<",">":">","'":"'",'"':"""},re=/((?:\ud83c\udde8\ud83c\uddf3|\ud83c\uddfa\ud83c\uddf8|\ud83c\uddf7\ud83c\uddfa|\ud83c\uddf0\ud83c\uddf7|\ud83c\uddef\ud83c\uddf5|\ud83c\uddee\ud83c\uddf9|\ud83c\uddec\ud83c\udde7|\ud83c\uddeb\ud83c\uddf7|\ud83c\uddea\ud83c\uddf8|\ud83c\udde9\ud83c\uddea|\u0039\ufe0f?\u20e3|\u0038\ufe0f?\u20e3|\u0037\ufe0f?\u20e3|\u0036\ufe0f?\u20e3|\u0035\ufe0f?\u20e3|\u0034\ufe0f?\u20e3|\u0033\ufe0f?\u20e3|\u0032\ufe0f?\u20e3|\u0031\ufe0f?\u20e3|\u0030\ufe0f?\u20e3|\u0023\ufe0f?\u20e3|\ud83d\udeb3|\ud83d\udeb1|\ud83d\udeb0|\ud83d\udeaf|\ud83d\udeae|\ud83d\udea6|\ud83d\udea3|\ud83d\udea1|\ud83d\udea0|\ud83d\ude9f|\ud83d\ude9e|\ud83d\ude9d|\ud83d\ude9c|\ud83d\ude9b|\ud83d\ude98|\ud83d\ude96|\ud83d\ude94|\ud83d\ude90|\ud83d\ude8e|\ud83d\ude8d|\ud83d\ude8b|\ud83d\ude8a|\ud83d\ude88|\ud83d\ude86|\ud83d\ude82|\ud83d\ude81|\ud83d\ude36|\ud83d\ude34|\ud83d\ude2f|\ud83d\ude2e|\ud83d\ude2c|\ud83d\ude27|\ud83d\ude26|\ud83d\ude1f|\ud83d\ude1b|\ud83d\ude19|\ud83d\ude17|\ud83d\ude15|\ud83d\ude11|\ud83d\ude10|\ud83d\ude0e|\ud83d\ude08|\ud83d\ude07|\ud83d\ude00|\ud83d\udd67|\ud83d\udd66|\ud83d\udd65|\ud83d\udd64|\ud83d\udd63|\ud83d\udd62|\ud83d\udd61|\ud83d\udd60|\ud83d\udd5f|\ud83d\udd5e|\ud83d\udd5d|\ud83d\udd5c|\ud83d\udd2d|\ud83d\udd2c|\ud83d\udd15|\ud83d\udd09|\ud83d\udd08|\ud83d\udd07|\ud83d\udd06|\ud83d\udd05|\ud83d\udd04|\ud83d\udd02|\ud83d\udd01|\ud83d\udd00|\ud83d\udcf5|\ud83d\udcef|\ud83d\udced|\ud83d\udcec|\ud83d\udcb7|\ud83d\udcb6|\ud83d\udcad|\ud83d\udc6d|\ud83d\udc6c|\ud83d\udc65|\ud83d\udc2a|\ud83d\udc16|\ud83d\udc15|\ud83d\udc13|\ud83d\udc10|\ud83d\udc0f|\ud83d\udc0b|\ud83d\udc0a|\ud83d\udc09|\ud83d\udc08|\ud83d\udc07|\ud83d\udc06|\ud83d\udc05|\ud83d\udc04|\ud83d\udc03|\ud83d\udc02|\ud83d\udc01|\ud83d\udc00|\ud83c\udfe4|\ud83c\udfc9|\ud83c\udfc7|\ud83c\udf7c|\ud83c\udf50|\ud83c\udf4b|\ud83c\udf33|\ud83c\udf32|\ud83c\udf1e|\ud83c\udf1d|\ud83c\udf1c|\ud83c\udf1a|\ud83c\udf18|\ud83c\udccf|\ud83c\udd8e|\ud83c\udd91|\ud83c\udd92|\ud83c\udd93|\ud83c\udd94|\ud83c\udd95|\ud83c\udd96|\ud83c\udd97|\ud83c\udd98|\ud83c\udd99|\ud83c\udd9a|\ud83d\udc77|\ud83d\udec5|\ud83d\udec4|\ud83d\udec3|\ud83d\udec2|\ud83d\udec1|\ud83d\udebf|\ud83d\udeb8|\ud83d\udeb7|\ud83d\udeb5|\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|\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\udeb4|\ud83d\udc78|\ud83d\udc79|\ud83d\udc7a|\ud83d\udc7b|\ud83d\udc7c|\ud83d\udc7d|\ud83d\udc7e|\ud83d\udc7f|\ud83d\udc80|\ud83d\udc81|\ud83d\udc82|\ud83d\udc83|\ud83d\udc84|\ud83d\udc85|\ud83d\udc86|\ud83d\udc87|\ud83d\udc88|\ud83d\udc89|\ud83d\udc8a|\ud83d\udc8b|\ud83d\udc8c|\ud83d\udc8d|\ud83d\udc8e|\ud83d\udc8f|\ud83d\udc90|\ud83d\udc91|\ud83d\udc92|\ud83d\udc93|\ud83d\udc94|\ud83d\udc95|\ud83d\udc96|\ud83d\udc97|\ud83d\udc98|\ud83d\udc99|\ud83d\udc9a|\ud83d\udc9b|\ud83d\udc9c|\ud83d\udc9d|\ud83d\udc9e|\ud83d\udc9f|\ud83d\udca0|\ud83d\udca1|\ud83d\udca2|\ud83d\udca3|\ud83d\udca4|\ud83d\udca5|\ud83d\udca6|\ud83d\udca7|\ud83d\udca8|\ud83d\udca9|\ud83d\udcaa|\ud83d\udcab|\ud83d\udcac|\ud83d\udcae|\ud83d\udcaf|\ud83d\udcb0|\ud83d\udcb1|\ud83d\udcb2|\ud83d\udcb3|\ud83d\udcb4|\ud83d\udcb5|\ud83d\udcb8|\ud83d\udcb9|\ud83d\udcba|\ud83d\udcbb|\ud83d\udcbc|\ud83d\udcbd|\ud83d\udcbe|\ud83d\udcbf|\ud83d\udcc0|\ud83d\udcc1|\ud83d\udcc2|\ud83d\udcc3|\ud83d\udcc4|\ud83d\udcc5|\ud83d\udcc6|\ud83d\udcc7|\ud83d\udcc8|\ud83d\udcc9|\ud83d\udcca|\ud83d\udccb|\ud83d\udccc|\ud83d\udccd|\ud83d\udcce|\ud83d\udccf|\ud83d\udcd0|\ud83d\udcd1|\ud83d\udcd2|\ud83d\udcd3|\ud83d\udcd4|\ud83d\udcd5|\ud83d\udcd6|\ud83d\udcd7|\ud83d\udcd8|\ud83d\udcd9|\ud83d\udcda|\ud83d\udcdb|\ud83d\udcdc|\ud83d\udcdd|\ud83d\udcde|\ud83d\udcdf|\ud83d\udce0|\ud83d\udce1|\ud83d\udce2|\ud83d\udce3|\ud83d\udce4|\ud83d\udce5|\ud83d\udce6|\ud83d\udce7|\ud83d\udce8|\ud83d\udce9|\ud83d\udcea|\ud83d\udceb|\ud83d\udcee|\ud83d\udcf0|\ud83d\udcf1|\ud83d\udcf2|\ud83d\udcf3|\ud83d\udcf4|\ud83d\udcf6|\ud83d\udcf7|\ud83d\udcf9|\ud83d\udcfa|\ud83d\udcfb|\ud83d\udcfc|\ud83d\udd03|\ud83d\udd0a|\ud83d\udd0b|\ud83d\udd0c|\ud83d\udd0d|\ud83d\udd0e|\ud83d\udd0f|\ud83d\udd10|\ud83d\udd11|\ud83d\udd12|\ud83d\udd13|\ud83d\udd14|\ud83d\udd16|\ud83d\udd17|\ud83d\udd18|\ud83d\udd19|\ud83d\udd1a|\ud83d\udd1b|\ud83d\udd1c|\ud83d\udd1d|\ud83d\udd1e|\ud83d\udd1f|\ud83d\udd20|\ud83d\udd21|\ud83d\udd22|\ud83d\udd23|\ud83d\udd24|\ud83d\udd25|\ud83d\udd26|\ud83d\udd27|\ud83d\udd28|\ud83d\udd29|\ud83d\udd2a|\ud83d\udd2b|\ud83d\udd2e|\ud83d\udd2f|\ud83d\udd30|\ud83d\udd31|\ud83d\udd32|\ud83d\udd33|\ud83d\udd34|\ud83d\udd35|\ud83d\udd36|\ud83d\udd37|\ud83d\udd38|\ud83d\udd39|\ud83d\udd3a|\ud83d\udd3b|\ud83d\udd3c|\ud83d\udd3d|\ud83d\udd50|\ud83d\udd51|\ud83d\udd52|\ud83d\udd53|\ud83d\udd54|\ud83d\udd55|\ud83d\udd56|\ud83d\udd57|\ud83d\udd58|\ud83d\udd59|\ud83d\udd5a|\ud83d\udd5b|\ud83d\uddfb|\ud83d\uddfc|\ud83d\uddfd|\ud83d\uddfe|\ud83d\uddff|\ud83d\ude01|\ud83d\ude02|\ud83d\ude03|\ud83d\ude04|\ud83d\ude05|\ud83d\ude06|\ud83d\ude09|\ud83d\ude0a|\ud83d\ude0b|\ud83d\ude0c|\ud83d\ude0d|\ud83d\ude0f|\ud83d\ude12|\ud83d\ude13|\ud83d\ude14|\ud83d\ude16|\ud83d\ude18|\ud83d\ude1a|\ud83d\ude1c|\ud83d\ude1d|\ud83d\ude1e|\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|\ud83c\udde6|\ud83c\udde7|\ud83c\udde8|\ud83c\udde9|\ud83c\uddea|\ud83c\uddeb|\ud83c\uddec|\ud83c\udded|\ud83c\uddee|\ud83c\uddef|\ud83c\uddf0|\ud83c\uddf1|\ud83c\uddf2|\ud83c\uddf3|\ud83c\uddf4|\ud83c\uddf5|\ud83c\uddf6|\ud83c\uddf7|\ud83c\uddf8|\ud83c\uddf9|\ud83c\uddfa|\ud83c\uddfb|\ud83c\uddfc|\ud83c\uddfd|\ud83c\uddfe|\ud83c\uddff|\ud83c\udf0d|\ud83c\udf0e|\ud83c\udf10|\ud83c\udf12|\ud83c\udf16|\ud83c\udf17|\ue50a|\u27b0|\u2797|\u2796|\u2795|\u2755|\u2754|\u2753|\u274e|\u274c|\u2728|\u270b|\u270a|\u2705|\u26ce|\u23f3|\u23f0|\u23ec|\u23eb|\u23ea|\u23e9|\u27bf|\u00a9|\u00ae)|(?:(?:\ud83c\udc04|\ud83c\udd70|\ud83c\udd71|\ud83c\udd7e|\ud83c\udd7f|\ud83c\ude02|\ud83c\ude1a|\ud83c\ude2f|\ud83c\ude37|\u3299|\u303d|\u3030|\u2b55|\u2b50|\u2b1c|\u2b1b|\u2b07|\u2b06|\u2b05|\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|\u2693|\u267f|\u267b|\u3297|\u2666|\u2665|\u2663|\u2660|\u2653|\u2652|\u2651|\u2650|\u264f|\u264e|\u264d|\u264c|\u264b|\u264a|\u2649|\u2648|\u263a|\u261d|\u2615|\u2614|\u2611|\u260e|\u2601|\u2600|\u25fe|\u25fd|\u25fc|\u25fb|\u25c0|\u25b6|\u25ab|\u25aa|\u24c2|\u231b|\u231a|\u21aa|\u21a9|\u2199|\u2198|\u2197|\u2196|\u2195|\u2194|\u2139|\u2122|\u2049|\u203c|\u2668)([\uFE0E\uFE0F]?)))/g,rescaper=/[&<>'"]/g,shouldntBeParsed=/IFRAME|NOFRAMES|NOSCRIPT|SCRIPT|SELECT|STYLE|TEXTAREA|[a-z]/,fromCharCode=String.fromCharCode;return twemoji;function createText(text){return document.createTextNode(text)}function escapeHTML(s){return s.replace(rescaper,replacer)}function defaultImageSrcGenerator(icon,options){return"".concat(options.base,options.size,"/",icon,options.ext)}function grabAllTextNodes(node,allText){var childNodes=node.childNodes,length=childNodes.length,subnode,nodeType;while(length--){subnode=childNodes[length];nodeType=subnode.nodeType;if(nodeType===3){allText.push(subnode)}else if(nodeType===1&&!shouldntBeParsed.test(subnode.nodeName)){grabAllTextNodes(subnode,allText)}}return allText}function grabTheRightIcon(icon,variant){return toCodePoint(variant==="️"?icon.slice(0,-1):icon.length===3&&icon.charAt(1)==="️"?icon.charAt(0)+icon.charAt(2):icon)}function parseNode(node,options){var allText=grabAllTextNodes(node,[]),length=allText.length,attrib,attrname,modified,fragment,subnode,text,match,i,index,img,alt,icon,variant,src;while(length--){modified=false;fragment=document.createDocumentFragment();subnode=allText[length];text=subnode.nodeValue;i=0;while(match=re.exec(text)){index=match.index;if(index!==i){fragment.appendChild(createText(text.slice(i,index)))}alt=match[0];icon=match[1];variant=match[2];i=index+alt.length;if(variant!=="︎"){src=options.callback(grabTheRightIcon(icon,variant),options,variant);if(src){img=new Image;img.onerror=options.onerror;img.setAttribute("draggable","false");attrib=options.attributes(icon,variant);for(attrname in attrib){if(attrib.hasOwnProperty(attrname)&&attrname.indexOf("on")!==0&&!img.hasAttribute(attrname)){img.setAttribute(attrname,attrib[attrname])}}img.className=options.className;img.alt=alt;img.src=src;modified=true;fragment.appendChild(img)}}if(!img)fragment.appendChild(createText(alt));img=null}if(modified){if(i")}}return ret})}function replacer(m){return escaper[m]}function returnNull(){return null}function toSizeSquaredAsset(value){return typeof value==="number"?value+"x"+value:value}function fromCodePoint(codepoint){var code=typeof codepoint==="string"?parseInt(codepoint,16):codepoint;if(code<65536){return fromCharCode(code)}code-=65536;return fromCharCode(55296+(code>>10),56320+(code&1023))}function parse(what,how){if(!how||typeof how==="function"){how={callback:how}}return(typeof what==="string"?parseString:parseNode)(what,{callback:how.callback||defaultImageSrcGenerator,attributes:typeof how.attributes==="function"?how.attributes:returnNull,base:typeof how.base==="string"?how.base:twemoji.base,ext:how.ext||twemoji.ext,size:how.folder||toSizeSquaredAsset(how.size||twemoji.size),className:how.className||twemoji.className,onerror:how.onerror||twemoji.onerror})}function replace(text,callback){return String(text).replace(re,callback)}function test(text){re.lastIndex=0;var result=re.test(text);re.lastIndex=0;return result}function toCodePoint(unicodeSurrogates,sep){var r=[],c=0,p=0,i=0;while(i