diff --git a/1/templates/preview.html b/1/templates/preview.html
deleted file mode 100644
index 1ee8325a..00000000
--- a/1/templates/preview.html
+++ /dev/null
@@ -1,55 +0,0 @@
-
-
-
- Twitter Emoji (Twemoji) Preview
-
-
-
-
-
-
-
-
-
diff --git a/1/test/preview-svg.html b/1/test/preview-svg.html
deleted file mode 100644
index cfb1657f..00000000
--- a/1/test/preview-svg.html
+++ /dev/null
@@ -1,928 +0,0 @@
-
-
-
- Twitter Emoji (Twemoji) Preview
-
-
-
-
-
-
- - 🀄
- - 🃏
- - 🅰
- - 🅱
- - 🅾
- - 🅿
- - 🆎
- - 🆑
- - 🆒
- - 🆓
- - 🆔
- - 🆕
- - 🆖
- - 🆗
- - 🆘
- - 🆙
- - 🆚
- - 🇦
- - 🇧
- - 🇨🇳
- - 🇨
- - 🇩🇪
- - 🇩
- - 🇪🇸
- - 🇪
- - 🇫🇷
- - 🇫
- - 🇬🇧
- - 🇬
- - 🇭
- - 🇮🇹
- - 🇮
- - 🇯🇵
- - 🇯
- - 🇰🇷
- - 🇰
- - 🇱
- - 🇲
- - 🇳
- - 🇴
- - 🇵
- - 🇶
- - 🇷🇺
- - 🇷
- - 🇸
- - 🇹
- - 🇺🇸
- - 🇺
- - 🇻
- - 🇼
- - 🇽
- - 🇾
- - 🇿
- - 🈁
- - 🈂
- - 🈚
- - 🈯
- - 🈲
- - 🈳
- - 🈴
- - 🈵
- - 🈶
- - 🈷
- - 🈸
- - 🈹
- - 🈺
- - 🉐
- - 🉑
- - 🌀
- - 🌁
- - 🌂
- - 🌃
- - 🌄
- - 🌅
- - 🌆
- - 🌇
- - 🌈
- - 🌉
- - 🌊
- - 🌋
- - 🌌
- - 🌍
- - 🌎
- - 🌏
- - 🌐
- - 🌑
- - 🌒
- - 🌓
- - 🌔
- - 🌕
- - 🌖
- - 🌗
- - 🌘
- - 🌙
- - 🌚
- - 🌛
- - 🌜
- - 🌝
- - 🌞
- - 🌟
- - 🌠
- - 🌰
- - 🌱
- - 🌲
- - 🌳
- - 🌴
- - 🌵
- - 🌷
- - 🌸
- - 🌹
- - 🌺
- - 🌻
- - 🌼
- - 🌽
- - 🌾
- - 🌿
- - 🍀
- - 🍁
- - 🍂
- - 🍃
- - 🍄
- - 🍅
- - 🍆
- - 🍇
- - 🍈
- - 🍉
- - 🍊
- - 🍋
- - 🍌
- - 🍍
- - 🍎
- - 🍏
- - 🍐
- - 🍑
- - 🍒
- - 🍓
- - 🍔
- - 🍕
- - 🍖
- - 🍗
- - 🍘
- - 🍙
- - 🍚
- - 🍛
- - 🍜
- - 🍝
- - 🍞
- - 🍟
- - 🍠
- - 🍡
- - 🍢
- - 🍣
- - 🍤
- - 🍥
- - 🍦
- - 🍧
- - 🍨
- - 🍩
- - 🍪
- - 🍫
- - 🍬
- - 🍭
- - 🍮
- - 🍯
- - 🍰
- - 🍱
- - 🍲
- - 🍳
- - 🍴
- - 🍵
- - 🍶
- - 🍷
- - 🍸
- - 🍹
- - 🍺
- - 🍻
- - 🍼
- - 🎀
- - 🎁
- - 🎂
- - 🎃
- - 🎄
- - 🎅
- - 🎆
- - 🎇
- - 🎈
- - 🎉
- - 🎊
- - 🎋
- - 🎌
- - 🎍
- - 🎎
- - 🎏
- - 🎐
- - 🎑
- - 🎒
- - 🎓
- - 🎠
- - 🎡
- - 🎢
- - 🎣
- - 🎤
- - 🎥
- - 🎦
- - 🎧
- - 🎨
- - 🎩
- - 🎪
- - 🎫
- - 🎬
- - 🎭
- - 🎮
- - 🎯
- - 🎰
- - 🎱
- - 🎲
- - 🎳
- - 🎴
- - 🎵
- - 🎶
- - 🎷
- - 🎸
- - 🎹
- - 🎺
- - 🎻
- - 🎼
- - 🎽
- - 🎾
- - 🎿
- - 🏀
- - 🏁
- - 🏂
- - 🏃
- - 🏄
- - 🏆
- - 🏇
- - 🏈
- - 🏉
- - 🏊
- - 🏠
- - 🏡
- - 🏢
- - 🏣
- - 🏤
- - 🏥
- - 🏦
- - 🏧
- - 🏨
- - 🏩
- - 🏪
- - 🏫
- - 🏬
- - 🏭
- - 🏮
- - 🏯
- - 🏰
- - 🐀
- - 🐁
- - 🐂
- - 🐃
- - 🐄
- - 🐅
- - 🐆
- - 🐇
- - 🐈
- - 🐉
- - 🐊
- - 🐋
- - 🐌
- - 🐍
- - 🐎
- - 🐏
- - 🐐
- - 🐑
- - 🐒
- - 🐓
- - 🐔
- - 🐕
- - 🐖
- - 🐗
- - 🐘
- - 🐙
- - 🐚
- - 🐛
- - 🐜
- - 🐝
- - 🐞
- - 🐟
- - 🐠
- - 🐡
- - 🐢
- - 🐣
- - 🐤
- - 🐥
- - 🐦
- - 🐧
- - 🐨
- - 🐩
- - 🐪
- - 🐫
- - 🐬
- - 🐭
- - 🐮
- - 🐯
- - 🐰
- - 🐱
- - 🐲
- - 🐳
- - 🐴
- - 🐵
- - 🐶
- - 🐷
- - 🐸
- - 🐹
- - 🐺
- - 🐻
- - 🐼
- - 🐽
- - 🐾
- - 👀
- - 👂
- - 👃
- - 👄
- - 👅
- - 👆
- - 👇
- - 👈
- - 👉
- - 👊
- - 👋
- - 👌
- - 👍
- - 👎
- - 👏
- - 👐
- - 👑
- - 👒
- - 👓
- - 👔
- - 👕
- - 👖
- - 👗
- - 👘
- - 👙
- - 👚
- - 👛
- - 👜
- - 👝
- - 👞
- - 👟
- - 👠
- - 👡
- - 👢
- - 👣
- - 👤
- - 👥
- - 👦
- - 👧
- - 👨
- - 👩
- - 👪
- - 👫
- - 👬
- - 👭
- - 👮
- - 👯
- - 👰
- - 👱
- - 👲
- - 👳
- - 👴
- - 👵
- - 👶
- - 👷
- - 👸
- - 👹
- - 👺
- - 👻
- - 👼
- - 👽
- - 👾
- - 👿
- - 💀
- - 💁
- - 💂
- - 💃
- - 💄
- - 💅
- - 💆
- - 💇
- - 💈
- - 💉
- - 💊
- - 💋
- - 💌
- - 💍
- - 💎
- - 💏
- - 💐
- - 💑
- - 💒
- - 💓
- - 💔
- - 💕
- - 💖
- - 💗
- - 💘
- - 💙
- - 💚
- - 💛
- - 💜
- - 💝
- - 💞
- - 💟
- - 💠
- - 💡
- - 💢
- - 💣
- - 💤
- - 💥
- - 💦
- - 💧
- - 💨
- - 💩
- - 💪
- - 💫
- - 💬
- - 💭
- - 💮
- - 💯
- - 💰
- - 💱
- - 💲
- - 💳
- - 💴
- - 💵
- - 💶
- - 💷
- - 💸
- - 💹
- - 💺
- - 💻
- - 💼
- - 💽
- - 💾
- - 💿
- - 📀
- - 📁
- - 📂
- - 📃
- - 📄
- - 📅
- - 📆
- - 📇
- - 📈
- - 📉
- - 📊
- - 📋
- - 📌
- - 📍
- - 📎
- - 📏
- - 📐
- - 📑
- - 📒
- - 📓
- - 📔
- - 📕
- - 📖
- - 📗
- - 📘
- - 📙
- - 📚
- - 📛
- - 📜
- - 📝
- - 📞
- - 📟
- - 📠
- - 📡
- - 📢
- - 📣
- - 📤
- - 📥
- - 📦
- - 📧
- - 📨
- - 📩
- - 📪
- - 📫
- - 📬
- - 📭
- - 📮
- - 📯
- - 📰
- - 📱
- - 📲
- - 📳
- - 📴
- - 📵
- - 📶
- - 📷
- - 📹
- - 📺
- - 📻
- - 📼
- - 🔀
- - 🔁
- - 🔂
- - 🔃
- - 🔄
- - 🔅
- - 🔆
- - 🔇
- - 🔈
- - 🔉
- - 🔊
- - 🔋
- - 🔌
- - 🔍
- - 🔎
- - 🔏
- - 🔐
- - 🔑
- - 🔒
- - 🔓
- - 🔔
- - 🔕
- - 🔖
- - 🔗
- - 🔘
- - 🔙
- - 🔚
- - 🔛
- - 🔜
- - 🔝
- - 🔞
- - 🔟
- - 🔠
- - 🔡
- - 🔢
- - 🔣
- - 🔤
- - 🔥
- - 🔦
- - 🔧
- - 🔨
- - 🔩
- - 🔪
- - 🔫
- - 🔬
- - 🔭
- - 🔮
- - 🔯
- - 🔰
- - 🔱
- - 🔲
- - 🔳
- - 🔴
- - 🔵
- - 🔶
- - 🔷
- - 🔸
- - 🔹
- - 🔺
- - 🔻
- - 🔼
- - 🔽
- - 🕐
- - 🕑
- - 🕒
- - 🕓
- - 🕔
- - 🕕
- - 🕖
- - 🕗
- - 🕘
- - 🕙
- - 🕚
- - 🕛
- - 🕜
- - 🕝
- - 🕞
- - 🕟
- - 🕠
- - 🕡
- - 🕢
- - 🕣
- - 🕤
- - 🕥
- - 🕦
- - 🕧
- - 🗻
- - 🗼
- - 🗽
- - 🗾
- - 🗿
- - 😀
- - 😁
- - 😂
- - 😃
- - 😄
- - 😅
- - 😆
- - 😇
- - 😈
- - 😉
- - 😊
- - 😋
- - 😌
- - 😍
- - 😎
- - 😏
- - 😐
- - 😑
- - 😒
- - 😓
- - 😔
- - 😕
- - 😖
- - 😗
- - 😘
- - 😙
- - 😚
- - 😛
- - 😜
- - 😝
- - 😞
- - 😟
- - 😠
- - 😡
- - 😢
- - 😣
- - 😤
- - 😥
- - 😦
- - 😧
- - 😨
- - 😩
- - 😪
- - 😫
- - 😬
- - 😭
- - 😮
- - 😯
- - 😰
- - 😱
- - 😲
- - 😳
- - 😴
- - 😵
- - 😶
- - 😷
- - 😸
- - 😹
- - 😺
- - 😻
- - 😼
- - 😽
- - 😾
- - 😿
- - 🙀
- - 🙁
- - 🙂
- - 🙅
- - 🙆
- - 🙇
- - 🙈
- - 🙉
- - 🙊
- - 🙋
- - 🙌
- - 🙍
- - 🙎
- - 🙏
- - 🚀
- - 🚁
- - 🚂
- - 🚃
- - 🚄
- - 🚅
- - 🚆
- - 🚇
- - 🚈
- - 🚉
- - 🚊
- - 🚋
- - 🚌
- - 🚍
- - 🚎
- - 🚏
- - 🚐
- - 🚑
- - 🚒
- - 🚓
- - 🚔
- - 🚕
- - 🚖
- - 🚗
- - 🚘
- - 🚙
- - 🚚
- - 🚛
- - 🚜
- - 🚝
- - 🚞
- - 🚟
- - 🚠
- - 🚡
- - 🚢
- - 🚣
- - 🚤
- - 🚥
- - 🚦
- - 🚧
- - 🚨
- - 🚩
- - 🚪
- - 🚫
- - 🚬
- - 🚭
- - 🚮
- - 🚯
- - 🚰
- - 🚱
- - 🚲
- - 🚳
- - 🚴
- - 🚵
- - 🚶
- - 🚷
- - 🚸
- - 🚹
- - 🚺
- - 🚻
- - 🚼
- - 🚽
- - 🚾
- - 🚿
- - 🛀
- - 🛁
- - 🛂
- - 🛃
- - 🛄
- - 🛅
- - ‼
- - ⁉
- - ™
- - ℹ
- - ↔
- - ↕
- - ↖
- - ↗
- - ↘
- - ↙
- - ↩
- - ↪
- - #⃣
- - ⌚
- - ⌛
- - ⏩
- - ⏪
- - ⏫
- - ⏬
- - ⏰
- - ⏳
- - Ⓜ
- - ▪
- - ▫
- - ▶
- - ◀
- - ◻
- - ◼
- - ◽
- - ◾
- - ☀
- - ☁
- - ☎
- - ☑
- - ☔
- - ☕
- - ☝
- - ☺
- - ♈
- - ♉
- - ♊
- - ♋
- - ♌
- - ♍
- - ♎
- - ♏
- - ♐
- - ♑
- - ♒
- - ♓
- - ♠
- - ♣
- - ♥
- - ♦
- - ♨
- - ♻
- - ♿
- - ⚓
- - ⚠
- - ⚡
- - ⚪
- - ⚫
- - ⚽
- - ⚾
- - ⛄
- - ⛅
- - ⛎
- - ⛔
- - ⛪
- - ⛲
- - ⛳
- - ⛵
- - ⛺
- - ⛽
- - ✂
- - ✅
- - ✈
- - ✉
- - ✊
- - ✋
- - ✌
- - ✏
- - ✒
- - ✔
- - ✖
- - ✨
- - ✳
- - ✴
- - ❄
- - ❇
- - ❌
- - ❎
- - ❓
- - ❔
- - ❕
- - ❗
- - ❤
- - ➕
- - ➖
- - ➗
- - ➡
- - ➰
- - ➿
- - ⤴
- - ⤵
- - ⬅
- - ⬆
- - ⬇
- - ⬛
- - ⬜
- - ⭐
- - ⭕
- - 0⃣
- - 〰
- - 〽
- - 1⃣
- - 2⃣
- - ㊗
- - ㊙
- - 3⃣
- - 4⃣
- - 5⃣
- - 6⃣
- - 7⃣
- - 8⃣
- - 9⃣
- - ©
- - ®
- -
-
-
-
-
diff --git a/1/test/preview.html b/1/test/preview.html
deleted file mode 100644
index db139f4d..00000000
--- a/1/test/preview.html
+++ /dev/null
@@ -1,928 +0,0 @@
-
-
-
- Twitter Emoji (Twemoji) Preview
-
-
-
-
-
-
- - 🀄
- - 🃏
- - 🅰
- - 🅱
- - 🅾
- - 🅿
- - 🆎
- - 🆑
- - 🆒
- - 🆓
- - 🆔
- - 🆕
- - 🆖
- - 🆗
- - 🆘
- - 🆙
- - 🆚
- - 🇦
- - 🇧
- - 🇨🇳
- - 🇨
- - 🇩🇪
- - 🇩
- - 🇪🇸
- - 🇪
- - 🇫🇷
- - 🇫
- - 🇬🇧
- - 🇬
- - 🇭
- - 🇮🇹
- - 🇮
- - 🇯🇵
- - 🇯
- - 🇰🇷
- - 🇰
- - 🇱
- - 🇲
- - 🇳
- - 🇴
- - 🇵
- - 🇶
- - 🇷🇺
- - 🇷
- - 🇸
- - 🇹
- - 🇺🇸
- - 🇺
- - 🇻
- - 🇼
- - 🇽
- - 🇾
- - 🇿
- - 🈁
- - 🈂
- - 🈚
- - 🈯
- - 🈲
- - 🈳
- - 🈴
- - 🈵
- - 🈶
- - 🈷
- - 🈸
- - 🈹
- - 🈺
- - 🉐
- - 🉑
- - 🌀
- - 🌁
- - 🌂
- - 🌃
- - 🌄
- - 🌅
- - 🌆
- - 🌇
- - 🌈
- - 🌉
- - 🌊
- - 🌋
- - 🌌
- - 🌍
- - 🌎
- - 🌏
- - 🌐
- - 🌑
- - 🌒
- - 🌓
- - 🌔
- - 🌕
- - 🌖
- - 🌗
- - 🌘
- - 🌙
- - 🌚
- - 🌛
- - 🌜
- - 🌝
- - 🌞
- - 🌟
- - 🌠
- - 🌰
- - 🌱
- - 🌲
- - 🌳
- - 🌴
- - 🌵
- - 🌷
- - 🌸
- - 🌹
- - 🌺
- - 🌻
- - 🌼
- - 🌽
- - 🌾
- - 🌿
- - 🍀
- - 🍁
- - 🍂
- - 🍃
- - 🍄
- - 🍅
- - 🍆
- - 🍇
- - 🍈
- - 🍉
- - 🍊
- - 🍋
- - 🍌
- - 🍍
- - 🍎
- - 🍏
- - 🍐
- - 🍑
- - 🍒
- - 🍓
- - 🍔
- - 🍕
- - 🍖
- - 🍗
- - 🍘
- - 🍙
- - 🍚
- - 🍛
- - 🍜
- - 🍝
- - 🍞
- - 🍟
- - 🍠
- - 🍡
- - 🍢
- - 🍣
- - 🍤
- - 🍥
- - 🍦
- - 🍧
- - 🍨
- - 🍩
- - 🍪
- - 🍫
- - 🍬
- - 🍭
- - 🍮
- - 🍯
- - 🍰
- - 🍱
- - 🍲
- - 🍳
- - 🍴
- - 🍵
- - 🍶
- - 🍷
- - 🍸
- - 🍹
- - 🍺
- - 🍻
- - 🍼
- - 🎀
- - 🎁
- - 🎂
- - 🎃
- - 🎄
- - 🎅
- - 🎆
- - 🎇
- - 🎈
- - 🎉
- - 🎊
- - 🎋
- - 🎌
- - 🎍
- - 🎎
- - 🎏
- - 🎐
- - 🎑
- - 🎒
- - 🎓
- - 🎠
- - 🎡
- - 🎢
- - 🎣
- - 🎤
- - 🎥
- - 🎦
- - 🎧
- - 🎨
- - 🎩
- - 🎪
- - 🎫
- - 🎬
- - 🎭
- - 🎮
- - 🎯
- - 🎰
- - 🎱
- - 🎲
- - 🎳
- - 🎴
- - 🎵
- - 🎶
- - 🎷
- - 🎸
- - 🎹
- - 🎺
- - 🎻
- - 🎼
- - 🎽
- - 🎾
- - 🎿
- - 🏀
- - 🏁
- - 🏂
- - 🏃
- - 🏄
- - 🏆
- - 🏇
- - 🏈
- - 🏉
- - 🏊
- - 🏠
- - 🏡
- - 🏢
- - 🏣
- - 🏤
- - 🏥
- - 🏦
- - 🏧
- - 🏨
- - 🏩
- - 🏪
- - 🏫
- - 🏬
- - 🏭
- - 🏮
- - 🏯
- - 🏰
- - 🐀
- - 🐁
- - 🐂
- - 🐃
- - 🐄
- - 🐅
- - 🐆
- - 🐇
- - 🐈
- - 🐉
- - 🐊
- - 🐋
- - 🐌
- - 🐍
- - 🐎
- - 🐏
- - 🐐
- - 🐑
- - 🐒
- - 🐓
- - 🐔
- - 🐕
- - 🐖
- - 🐗
- - 🐘
- - 🐙
- - 🐚
- - 🐛
- - 🐜
- - 🐝
- - 🐞
- - 🐟
- - 🐠
- - 🐡
- - 🐢
- - 🐣
- - 🐤
- - 🐥
- - 🐦
- - 🐧
- - 🐨
- - 🐩
- - 🐪
- - 🐫
- - 🐬
- - 🐭
- - 🐮
- - 🐯
- - 🐰
- - 🐱
- - 🐲
- - 🐳
- - 🐴
- - 🐵
- - 🐶
- - 🐷
- - 🐸
- - 🐹
- - 🐺
- - 🐻
- - 🐼
- - 🐽
- - 🐾
- - 👀
- - 👂
- - 👃
- - 👄
- - 👅
- - 👆
- - 👇
- - 👈
- - 👉
- - 👊
- - 👋
- - 👌
- - 👍
- - 👎
- - 👏
- - 👐
- - 👑
- - 👒
- - 👓
- - 👔
- - 👕
- - 👖
- - 👗
- - 👘
- - 👙
- - 👚
- - 👛
- - 👜
- - 👝
- - 👞
- - 👟
- - 👠
- - 👡
- - 👢
- - 👣
- - 👤
- - 👥
- - 👦
- - 👧
- - 👨
- - 👩
- - 👪
- - 👫
- - 👬
- - 👭
- - 👮
- - 👯
- - 👰
- - 👱
- - 👲
- - 👳
- - 👴
- - 👵
- - 👶
- - 👷
- - 👸
- - 👹
- - 👺
- - 👻
- - 👼
- - 👽
- - 👾
- - 👿
- - 💀
- - 💁
- - 💂
- - 💃
- - 💄
- - 💅
- - 💆
- - 💇
- - 💈
- - 💉
- - 💊
- - 💋
- - 💌
- - 💍
- - 💎
- - 💏
- - 💐
- - 💑
- - 💒
- - 💓
- - 💔
- - 💕
- - 💖
- - 💗
- - 💘
- - 💙
- - 💚
- - 💛
- - 💜
- - 💝
- - 💞
- - 💟
- - 💠
- - 💡
- - 💢
- - 💣
- - 💤
- - 💥
- - 💦
- - 💧
- - 💨
- - 💩
- - 💪
- - 💫
- - 💬
- - 💭
- - 💮
- - 💯
- - 💰
- - 💱
- - 💲
- - 💳
- - 💴
- - 💵
- - 💶
- - 💷
- - 💸
- - 💹
- - 💺
- - 💻
- - 💼
- - 💽
- - 💾
- - 💿
- - 📀
- - 📁
- - 📂
- - 📃
- - 📄
- - 📅
- - 📆
- - 📇
- - 📈
- - 📉
- - 📊
- - 📋
- - 📌
- - 📍
- - 📎
- - 📏
- - 📐
- - 📑
- - 📒
- - 📓
- - 📔
- - 📕
- - 📖
- - 📗
- - 📘
- - 📙
- - 📚
- - 📛
- - 📜
- - 📝
- - 📞
- - 📟
- - 📠
- - 📡
- - 📢
- - 📣
- - 📤
- - 📥
- - 📦
- - 📧
- - 📨
- - 📩
- - 📪
- - 📫
- - 📬
- - 📭
- - 📮
- - 📯
- - 📰
- - 📱
- - 📲
- - 📳
- - 📴
- - 📵
- - 📶
- - 📷
- - 📹
- - 📺
- - 📻
- - 📼
- - 🔀
- - 🔁
- - 🔂
- - 🔃
- - 🔄
- - 🔅
- - 🔆
- - 🔇
- - 🔈
- - 🔉
- - 🔊
- - 🔋
- - 🔌
- - 🔍
- - 🔎
- - 🔏
- - 🔐
- - 🔑
- - 🔒
- - 🔓
- - 🔔
- - 🔕
- - 🔖
- - 🔗
- - 🔘
- - 🔙
- - 🔚
- - 🔛
- - 🔜
- - 🔝
- - 🔞
- - 🔟
- - 🔠
- - 🔡
- - 🔢
- - 🔣
- - 🔤
- - 🔥
- - 🔦
- - 🔧
- - 🔨
- - 🔩
- - 🔪
- - 🔫
- - 🔬
- - 🔭
- - 🔮
- - 🔯
- - 🔰
- - 🔱
- - 🔲
- - 🔳
- - 🔴
- - 🔵
- - 🔶
- - 🔷
- - 🔸
- - 🔹
- - 🔺
- - 🔻
- - 🔼
- - 🔽
- - 🕐
- - 🕑
- - 🕒
- - 🕓
- - 🕔
- - 🕕
- - 🕖
- - 🕗
- - 🕘
- - 🕙
- - 🕚
- - 🕛
- - 🕜
- - 🕝
- - 🕞
- - 🕟
- - 🕠
- - 🕡
- - 🕢
- - 🕣
- - 🕤
- - 🕥
- - 🕦
- - 🕧
- - 🗻
- - 🗼
- - 🗽
- - 🗾
- - 🗿
- - 😀
- - 😁
- - 😂
- - 😃
- - 😄
- - 😅
- - 😆
- - 😇
- - 😈
- - 😉
- - 😊
- - 😋
- - 😌
- - 😍
- - 😎
- - 😏
- - 😐
- - 😑
- - 😒
- - 😓
- - 😔
- - 😕
- - 😖
- - 😗
- - 😘
- - 😙
- - 😚
- - 😛
- - 😜
- - 😝
- - 😞
- - 😟
- - 😠
- - 😡
- - 😢
- - 😣
- - 😤
- - 😥
- - 😦
- - 😧
- - 😨
- - 😩
- - 😪
- - 😫
- - 😬
- - 😭
- - 😮
- - 😯
- - 😰
- - 😱
- - 😲
- - 😳
- - 😴
- - 😵
- - 😶
- - 😷
- - 😸
- - 😹
- - 😺
- - 😻
- - 😼
- - 😽
- - 😾
- - 😿
- - 🙀
- - 🙁
- - 🙂
- - 🙅
- - 🙆
- - 🙇
- - 🙈
- - 🙉
- - 🙊
- - 🙋
- - 🙌
- - 🙍
- - 🙎
- - 🙏
- - 🚀
- - 🚁
- - 🚂
- - 🚃
- - 🚄
- - 🚅
- - 🚆
- - 🚇
- - 🚈
- - 🚉
- - 🚊
- - 🚋
- - 🚌
- - 🚍
- - 🚎
- - 🚏
- - 🚐
- - 🚑
- - 🚒
- - 🚓
- - 🚔
- - 🚕
- - 🚖
- - 🚗
- - 🚘
- - 🚙
- - 🚚
- - 🚛
- - 🚜
- - 🚝
- - 🚞
- - 🚟
- - 🚠
- - 🚡
- - 🚢
- - 🚣
- - 🚤
- - 🚥
- - 🚦
- - 🚧
- - 🚨
- - 🚩
- - 🚪
- - 🚫
- - 🚬
- - 🚭
- - 🚮
- - 🚯
- - 🚰
- - 🚱
- - 🚲
- - 🚳
- - 🚴
- - 🚵
- - 🚶
- - 🚷
- - 🚸
- - 🚹
- - 🚺
- - 🚻
- - 🚼
- - 🚽
- - 🚾
- - 🚿
- - 🛀
- - 🛁
- - 🛂
- - 🛃
- - 🛄
- - 🛅
- - ‼
- - ⁉
- - ™
- - ℹ
- - ↔
- - ↕
- - ↖
- - ↗
- - ↘
- - ↙
- - ↩
- - ↪
- - #⃣
- - ⌚
- - ⌛
- - ⏩
- - ⏪
- - ⏫
- - ⏬
- - ⏰
- - ⏳
- - Ⓜ
- - ▪
- - ▫
- - ▶
- - ◀
- - ◻
- - ◼
- - ◽
- - ◾
- - ☀
- - ☁
- - ☎
- - ☑
- - ☔
- - ☕
- - ☝
- - ☺
- - ♈
- - ♉
- - ♊
- - ♋
- - ♌
- - ♍
- - ♎
- - ♏
- - ♐
- - ♑
- - ♒
- - ♓
- - ♠
- - ♣
- - ♥
- - ♦
- - ♨
- - ♻
- - ♿
- - ⚓
- - ⚠
- - ⚡
- - ⚪
- - ⚫
- - ⚽
- - ⚾
- - ⛄
- - ⛅
- - ⛎
- - ⛔
- - ⛪
- - ⛲
- - ⛳
- - ⛵
- - ⛺
- - ⛽
- - ✂
- - ✅
- - ✈
- - ✉
- - ✊
- - ✋
- - ✌
- - ✏
- - ✒
- - ✔
- - ✖
- - ✨
- - ✳
- - ✴
- - ❄
- - ❇
- - ❌
- - ❎
- - ❓
- - ❔
- - ❕
- - ❗
- - ❤
- - ➕
- - ➖
- - ➗
- - ➡
- - ➰
- - ➿
- - ⤴
- - ⤵
- - ⬅
- - ⬆
- - ⬇
- - ⬛
- - ⬜
- - ⭐
- - ⭕
- - 0⃣
- - 〰
- - 〽
- - 1⃣
- - 2⃣
- - ㊗
- - ㊙
- - 3⃣
- - 4⃣
- - 5⃣
- - 6⃣
- - 7⃣
- - 8⃣
- - 9⃣
- - ©
- - ®
- -
-
-
-
-
diff --git a/1/utils/create-dist b/1/utils/create-dist
deleted file mode 100755
index 49c5b496..00000000
--- a/1/utils/create-dist
+++ /dev/null
@@ -1,52 +0,0 @@
-#!/usr/bin/env node
-
-/*! Copyright Twitter Inc. and other contributors. Licensed under MIT *//*
- https://github.com/twitter/twemoji/blob/gh-pages/LICENSE
-*/
-
-var fs = require('fs');
-var path = require('path');
-
-function file(which) {
- return path.join(__dirname, '..', which);
-}
-
-fs.writeFileSync(
- file('twemoji.npm.js'),
- [
- 'var location = global.location || {};',
- fs.readFileSync(file('twemoji.js')),
- 'if (!location.protocol) {',
- ' twemoji.base = twemoji.base.replace(/^http:/, "");',
- '}',
- 'module.exports = twemoji;'
- ].join('\n')
-);
-
-fs.writeFileSync(
- file('twemoji.amd.js'),
- 'define(function () {\n' +
- fs.readFileSync(file('twemoji.js')).toString().replace(
- /^(.)/gm, ' $1'
- ) +
- '\n return twemoji;\n});'
-);
-
-require('child_process').spawn(
- 'node',
- [
- path.join(__dirname, '../../', 'node_modules/uglify-js/bin/uglifyjs'),
- '--verbose',
- file('twemoji.js'),
- '-o',
- file('twemoji.tmp.js')
- ]
-).on('close', function () {
- fs.writeFileSync(
- file('twemoji.min.js'),
- '/*! Copyright Twitter Inc. and other contributors. Licensed under MIT */\n' +
- fs.readFileSync(file('twemoji.tmp.js'))
- );
- fs.unlink(file('twemoji.tmp.js'));
- // gzip -c twemoji.min.js | wc -c
-});
\ No newline at end of file
diff --git a/1/utils/generate b/1/utils/generate
deleted file mode 100755
index f28ac331..00000000
--- a/1/utils/generate
+++ /dev/null
@@ -1,995 +0,0 @@
-#!/usr/bin/env node
-
- /*! Copyright Twitter Inc. and other contributors. Licensed under MIT *//*
- https://github.com/twitter/twemoji/blob/gh-pages/LICENSE
- */
-
-// dependencies
-var fs = require('fs');
-var http = require('http');
-var path = require('path');
-
-function file(which) {
- return path.join(__dirname, '../..', which);
-}
-
-// Twitter assets by property name
-var assets = {
- '72x72': [],
- 'svg': []
-};
-
-// white spaces we don't want to catch via the RegExp
-// there is no asset equivalent for these
-var ignoreMissing = ['2002', '2003', '2005'];
-
-// basic utility to organize async code
-// see: http://webreflection.blogspot.co.uk/2012/03/tweet-sized-queue-system.html
-// or: http://webreflection.blogspot.co.uk/2012/06/working-with-queues.html
-function Queue(args, f) {
- setTimeout(args.next = function next() {
- return (f = args.shift()) ? !!f(args) || !0 : !1;
- }, 0);
- return args;
-}
-
-// main task
-Queue([
-
- // will populate assets arrays
- function grabAllAssets(q) {
- console.log('analyzing all assets ... ');
- // per each path/folder
- Object.keys(assets).forEach(function (path, i, paths) {
- // grab all files in that folder
- fs.readdir(file(path), function (err, files) {
- // and add them to the assets path
- assets[path].push.apply(
- assets[path],
- files.map(upperCaseWithoutExtension)
- );
- // once all assets arrays have been populated
- if (paths.reduce(completed, true)) {
- console.log('[INFO] assets contains ' + assets[path].length + ' emoji.');
- q.next();
- }
- });
- });
- // drop extension + uppercase
- function upperCaseWithoutExtension(file) {
- return file.slice(0, file.lastIndexOf('.')).toUpperCase();
- }
- // returns true if all assets have been populated
- function completed(p, c) {
- return p && assets[c].length;
- }
- },
-
- // will fetch and store all emoji from unicode.org
- function fetchEmojiSources(q) {
- console.log('fetching EmojiSources.txt ... ');
- // grab all emoji and test them against them
- http.get("http://www.unicode.org/Public/UNIDATA/EmojiSources.txt", function (res) {
- var chunks = [];
- // if all good ...
- if (res.statusCode === 200) {
- // grab all data
- res.on('data', chunks.push.bind(chunks));
- // once done ...
- res.on('end', function () {
- console.log('analyzing EmojiSources VS our assets ... ');
- // store all missing assets in one object
- var missing = {};
- // will be used to store an array with all missing
- var missingGrouped = {};
-
- // will be needed later on
- // parse it, clean it, and store it once
- q.emojiSource = chunks
- .join('')
- .split(/\r\n|\r|\n/)
- // filter once
- .filter(function (line) {
- return this.test(line);
- }, /^[0-9A-F]/)
- // take only emoji info
- .map(function (codePoint) {
- return codePoint
- .slice(0, codePoint.indexOf(';'))
- .toUpperCase()
- // drop spaces
- .replace(/\s+/g, '-')
- // drop 0 padded prefixes
- .replace(/^0+/g, '');
- });
-
- console.log('[INFO] parsed ' + q.emojiSource.length + ' standard emoji.');
-
- // find out which one is missing from our assets
- q.emojiSource.forEach(
- function (emoji) {
- // do not loop for emoji we know we should ignore
- if (ignoreMissing.indexOf(emoji) < 0) {
- // verify all others per each folder
- this.forEach(function (path) {
- if (assets[path].indexOf(emoji) < 0) {
- (missing[path] || (missing[path] = [])).push(emoji);
- missingGrouped[emoji] = true;
- }
- });
- }
-
- },
- // and per each folder
- Object.keys(assets)
- );
-
- // if some missing emoji has been found
- if (Object.keys(missing).length) {
- // warn and show which one is missing
- console.warn('[WARNING] missing assets for:');
- console.log(missing);
- }
- // create the array of all emoji we should ignore
- q.ignore = ignoreMissing.concat(Object.keys(missingGrouped));
-
- q.next();
- });
- } else {
- console.error('[ERROR] unable to fetch emoji at unicode.org');
- process.exit(1);
- }
- });
- },
-
- // grab the list of emoji that behave differently when
- // variants such \uFE0E and \uFE0F are in place
- function grabStandardVariants(q) {
- console.log('fetching StandardizedVariants.txt ... ');
- http.get(
- "http://unicode.org/Public/UNIDATA/StandardizedVariants.txt",
- function(res) {
- var chunks = [];
- if (res.statusCode == 200) {
- res.on('data', chunks.push.bind(chunks));
- res.on('end', function () {
- // cleaning up parsing sensitive emoji
- q.variantsSensitive = chunks
- .join('') // all content
- .split(/\r\n|\r|\n/) // split in lines
- .filter(function (line) { // containing FE0E; info
- return this.test(line); // avoiding duplicated with FE0F
- }, / FE0E; text style/)
- .map(function (line) { // cleaned up to grab
- return line.replace(this, '$1') // only first unicode
- .toUpperCase(); // normalized as uppercase
- }, /^([0-9A-F]{4,}) FE0E;.+$/) // sensitive char
- ;
-
- // iOS keyboard allows U+002A U+FE0F U+20E3 even though not a standardized variant (yet?)
- q.variantsSensitive.push('002A');
- // iOS keyboard allows U+2639 U+FE0F even though not a standardized variant (yet?)
- q.variantsSensitive.push('2639');
-
- console.log('[INFO] parsed ' + q.variantsSensitive.length + ' variant sensitive emoji.');
- q.next();
-
- });
- } else {
- console.error('[ERROR] unable to fetch standard variants at unicode.org');
- process.exit(1);
- }
- }
- );
- },
-
- // add our own assets that are not part of the Unicode standard
- function addMissingEmoji(q) {
- q.nonStandard = [];
- Object.keys(assets).forEach(function (path, i) {
- assets[path].forEach(function (emoji) {
- if (
- q.emojiSource.indexOf(emoji) < 0 &&
- q.nonStandard.indexOf(emoji) < 0
- ) {
- q.nonStandard.push(emoji);
- }
- });
- });
-
- if (q.nonStandard.length) {
- console.warn('[WARNING] assets contain ' + q.nonStandard.length + ' non standard emoji:');
- // console.log(q.nonStandard.join(', '));
- }
-
- q.emojiSource = q.emojiSource.concat(q.nonStandard)
- q.next();
- },
-
- // detect complete sets of five skin tones and a base
- function detectDiversityEmoji(q) {
- var isPresent = {};
- q.emojiSource.forEach(function (codePoints) {
- isPresent[codePoints] = true;
- });
- q.diversityBase = q.emojiSource.filter(function (codePoints) {
- // Start with the set of Emoji with the light skin tone
- return /-1F3FB$/.test(codePoints);
- }).map(function (codePoints) {
- // Take the skin tone off
- return codePoints.replace(/-1F3FB$/, '');
- }).filter(function (baseCodePoints) {
- // Verify that all other skin tones + no skin tone are present
- return ['-1F3FC', '-1F3FD', '-1F3FE', '-1F3FF', ''].every(function (suffix) {
- return isPresent[baseCodePoints + suffix];
- });
- });
- console.log('[INFO] parsed ' + q.diversityBase.length + ' diversity emoji.');
- q.next();
- },
-
- // with all info, generate a RegExp that will catch
- // only standard emoji that are present in our assets
- function generateRegExp(q) {
- console.log('generating a RegExp for available assets');
- var zwj = [];
- var diversity = [];
- var sensitive = [];
- var sensitiveKeycaps = [];
- var diversitySensitive = [];
- var skinToneOptions = [
- '\\ud83c\\udffb',
- '\\ud83c\\udffc',
- '\\ud83c\\udffd',
- '\\ud83c\\udffe',
- '\\ud83c\\udfff'
- ];
- var regular = [];
- q.emojiSource.forEach(function (codePoints) {
- var u;
- var codePointsWithoutKeycap;
- codePoints = codePoints.replace(/\b[A-F0-9]+\b/g, function (hex) {
- // Pad all hex numbers to have at least 4 digits to match variantsSensitive
- return hex.length < 4 ? ('000' + hex).slice(-4) : hex;
- });
- if (q.ignore.indexOf(codePoints) < 0) {
- u = toJSON(codePoints);
- codePointsWithoutKeycap = codePoints.replace(/-20E3$/, '');
- if (codePoints.indexOf('200D') >= 0) {
- zwj.push(u);
- } else if (codePoints != codePointsWithoutKeycap && q.variantsSensitive.indexOf(codePointsWithoutKeycap) >= 0) {
- sensitiveKeycaps.push(toJSON(codePointsWithoutKeycap));
- } else if (q.diversityBase.indexOf(codePoints.replace(/-1F3F[B-F]$/, '')) >= 0) {
- // This is a diversity Emoji with or without a skin tone modifier
- // Add it to the regex if this is the base without the modifier
- if (q.diversityBase.indexOf(codePoints) >= 0) {
- if (q.variantsSensitive.indexOf(codePoints) < 0) {
- diversity.push(u);
- } else {
- diversitySensitive.push(u);
- }
- }
- } else if (q.variantsSensitive.indexOf(codePoints) < 0) {
- regular.push(u);
- } else {
- sensitive.push(u);
- }
- }
- });
-
- q.re = '';
-
- // The Zero-width joiner Emojis, if present, need to come first
- if (zwj.length) {
- q.re += generateRegexPartial(zwj) + '|';
- }
-
- // Group the variant sensitive keycaps
- if (sensitiveKeycaps.length) {
- q.re += '(?:' + generateRegexPartial(sensitiveKeycaps) + ')\\ufe0f?\\u20e3|';
- }
-
- // Next, add the diversity enabled Emoji that may include a skin tone suffix
- if (diversity.length + diversitySensitive.length) {
- q.re += '(?:';
- if (diversitySensitive.length) {
- // Some diversity are sensitive to variants
- q.re += '(?:' + generateRegexPartial(diversitySensitive) + ')(?:\\ufe0f|(?!\\ufe0e))';
- if (diversity.length) {
- q.re += '|';
- }
- }
- q.re += generateRegexPartial(diversity) + ')(?:' + generateRegexPartial(skinToneOptions) + '|)|';
- }
-
- // Next, the normal Emoji
- q.re += generateRegexPartial(regular) + '|';
-
- // Finally, add the rest of the sensitive ones that may be followed by U+FE0F but not U+FE0E
- q.re += '(?:' + generateRegexPartial(sensitive) + ')(?:\\ufe0f|(?!\\ufe0e))';
- q.next();
-
- // basic utilities to convert codepoints to JSON strings
- function toJSON(codePoints) {
- return codePoints.split('-').map(function (point) {
- return UTF162JSON(fromCodePoint(point));
- }).join('');
- }
- function fromCodePoint(codepoint) {
- var code = typeof codepoint === 'string' ?
- parseInt(codepoint, 16) : codepoint;
- if (code < 0x10000) {
- return String.fromCharCode(code);
- }
- code -= 0x10000;
- return String.fromCharCode(
- 0xD800 + (code >> 10),
- 0xDC00 + (code & 0x3FF)
- );
- }
- function UTF162JSON(text) {
- for (var i = 0, r = []; i < text.length; i++) {
- r.push('\\u' + ('000' + text.charCodeAt(i).toString(16)).slice(-4));
- }
- return r.join('');
- }
-
- // Items is an array of unicode sequences with \u escaping, like ["\u2963\ufe0f", "\u263a\ufe0f"]
- // items get sorted by length (long to short), then unicode hex values (high to low)
- // output is "or" ed together using | for regex
- // ouput also combines adjacent items using character classes with ranges when they have common prefixes
- // Example: "aab", "aac", "aad", "aag", "ba" becomes "aa[b-dg]|ba"
- function generateRegexPartial(items) {
- var currentPrefix = null;
- var result = [];
- var charClass = [];
- var charRange = [];
- items.map(function (item) {
- // Convert from "\u2963\ufe0f" into ["2963", "fe0f"]
- return item.split('\\u').slice(1);
- }).sort(sortMethod).forEach(function (itemParts) {
- var prefix = itemParts.slice(0, -1).join('\\u');
- if (prefix) {
- prefix = '\\u' + prefix;
- }
- var suffix = itemParts.slice(-1);
- if (prefix !== currentPrefix) {
- flushCharClass();
- }
- currentPrefix = prefix;
- var suffixMinusOne = UTF162JSON(String.fromCharCode(parseInt(suffix, 16) - 1));
-
- if (charRange.length && charRange.slice(-1)[0] !== suffixMinusOne) {
- flushCharRange();
- }
- charRange.push('\\u' + suffix);
- });
-
- flushCharClass();
- return result.join('|');
-
- // a and b are arrays of hex UCS-2 units
- function sortMethod(a, b) {
- return !a.length ? 0 :
- b.length - a.length ||
- parseInt(b[0], 16) - parseInt(a[0], 16) ||
- sortMethod(b.slice(1), a.slice(1)
- );
- }
-
- function flushCharRange() {
- charClass = charClass.concat((charRange.length < 3) ?
- charRange :
- [ charRange[0], '-', charRange.slice(-1)[0] ]
- );
- charRange = [];
- }
-
- function flushCharClass() {
- flushCharRange();
- if (charClass.length) {
- result.push(currentPrefix + (charClass.length == 1 ?
- charClass[0] :
- '[' + charClass.join('') + ']'
- ));
- }
- charClass = [];
- currentPrefix = null;
- }
- }
-
- },
-
- function generateFile(q) {
- console.log('generating ./twemoji.js');
- createTwemoji(q.re);
- require('./create-dist');
- }
-
-]);
-
-
-
-function createTwemoji(re) {
- fs.writeFileSync(
- file('1/twemoji.js'),
- '/*jslint indent: 2, browser: true, bitwise: true, plusplus: true */\n' +
- 'var twemoji = (' +
- function (
- /*! Copyright Twitter Inc. and other contributors. Licensed under MIT *//*
- https://github.com/twitter/twemoji/blob/gh-pages/LICENSE
- */
-
- // WARNING: this file is generated automatically via
- // `node twemoji-generator.js`
- // please update its `createTwemoji` function
- // at the bottom of the same file instead.
-
- ) {
- 'use strict';
-
- /*jshint maxparams:4 */
-
- var
- // the exported module object
- twemoji = {
-
-
- /////////////////////////
- // properties //
- /////////////////////////
-
- // default assets url, by default will be Twitter Inc. CDN
- base: 'https://twemoji.maxcdn.com/',
-
- // default assets file extensions, by default '.png'
- ext: '.png',
-
- // default assets/folder size, by default "72x72"
- // available via Twitter CDN: 72
- size: '72x72',
-
- // default class name, by default 'emoji'
- className: 'emoji',
-
- // basic utilities / helpers to convert code points
- // to JavaScript surrogates and vice versa
- convert: {
-
- /**
- * Given an HEX codepoint, returns UTF16 surrogate pairs.
- *
- * @param string generic codepoint, i.e. '1F4A9'
- * @return string codepoint transformed into utf16 surrogates pair,
- * i.e. \uD83D\uDCA9
- *
- * @example
- * twemoji.convert.fromCodePoint('1f1e8');
- * // "\ud83c\udde8"
- *
- * '1f1e8-1f1f3'.split('-').map(twemoji.convert.fromCodePoint).join('')
- * // "\ud83c\udde8\ud83c\uddf3"
- */
- fromCodePoint: fromCodePoint,
-
- /**
- * Given UTF16 surrogate pairs, returns the equivalent HEX codepoint.
- *
- * @param string generic utf16 surrogates pair, i.e. \uD83D\uDCA9
- * @param string optional separator for double code points, default='-'
- * @return string utf16 transformed into codepoint, i.e. '1F4A9'
- *
- * @example
- * twemoji.convert.toCodePoint('\ud83c\udde8\ud83c\uddf3');
- * // "1f1e8-1f1f3"
- *
- * twemoji.convert.toCodePoint('\ud83c\udde8\ud83c\uddf3', '~');
- * // "1f1e8~1f1f3"
- */
- toCodePoint: toCodePoint
- },
-
-
- /////////////////////////
- // methods //
- /////////////////////////
-
- /**
- * User first: used to remove missing images
- * preserving the original text intent when
- * a fallback for network problems is desired.
- * Automatically added to Image nodes via DOM
- * It could be recycled for string operations via:
- * $('img.emoji').on('error', twemoji.onerror)
- */
- onerror: function onerror() {
- if (this.parentNode) {
- this.parentNode.replaceChild(createText(this.alt), this);
- }
- },
-
- /**
- * Main method/logic to generate either
tags or HTMLImage nodes.
- * "emojify" a generic text or DOM Element.
- *
- * @overloads
- *
- * String replacement for `innerHTML` or server side operations
- * twemoji.parse(string);
- * twemoji.parse(string, Function);
- * twemoji.parse(string, Object);
- *
- * HTMLElement tree parsing for safer operations over existing DOM
- * twemoji.parse(HTMLElement);
- * twemoji.parse(HTMLElement, Function);
- * twemoji.parse(HTMLElement, Object);
- *
- * @param string|HTMLElement the source to parse and enrich with emoji.
- *
- * string replace emoji matches with
tags.
- * Mainly used to inject emoji via `innerHTML`
- * It does **not** parse the string or validate it,
- * it simply replaces found emoji with a tag.
- * NOTE: be sure this won't affect security.
- *
- * HTMLElement walk through the DOM tree and find emoji
- * that are inside **text node only** (nodeType === 3)
- * Mainly used to put emoji in already generated DOM
- * without compromising surrounding nodes and
- * **avoiding** the usage of `innerHTML`.
- * NOTE: Using DOM elements instead of strings should
- * improve security without compromising too much
- * performance compared with a less safe `innerHTML`.
- *
- * @param Function|Object [optional]
- * either the callback that will be invoked or an object
- * with all properties to use per each found emoji.
- *
- * Function if specified, this will be invoked per each emoji
- * that has been found through the RegExp except
- * those follwed by the invariant \uFE0E ("as text").
- * Once invoked, parameters will be:
- *
- * iconId:string the lower case HEX code point
- * i.e. "1f4a9"
- *
- * options:Object all info for this parsing operation
- *
- * variant:char the optional \uFE0F ("as image")
- * variant, in case this info
- * is anyhow meaningful.
- * By default this is ignored.
- *
- * If such callback will return a falsy value instead
- * of a valid `src` to use for the image, nothing will
- * actually change for that specific emoji.
- *
- *
- * Object if specified, an object containing the following properties
- *
- * callback Function the callback to invoke per each found emoji.
- * base string the base url, by default twemoji.base
- * ext string the image extension, by default twemoji.ext
- * size string the assets size, by default twemoji.size
- *
- * @example
- *
- * twemoji.parse("I \u2764\uFE0F emoji!");
- * // I
emoji!
- *
- *
- * twemoji.parse("I \u2764\uFE0F emoji!", function(iconId, options) {
- * return '/assets/' + iconId + '.gif';
- * });
- * // I
emoji!
- *
- *
- * twemoji.parse("I \u2764\uFE0F emoji!", {
- * size: 72,
- * callback: function(iconId, options) {
- * return '/assets/' + options.size + '/' + iconId + options.ext;
- * }
- * });
- * // I
emoji!
- *
- */
- parse: parse,
-
- /**
- * Given a string, invokes the callback argument
- * per each emoji found in such string.
- * This is the most raw version used by
- * the .parse(string) method itself.
- *
- * @param string generic string to parse
- * @param Function a generic callback that will be
- * invoked to replace the content.
- * This calback wil receive standard
- * String.prototype.replace(str, callback)
- * arguments such:
- * callback(
- * rawText, // the emoji match
- * );
- *
- * and others commonly received via replace.
- */
- replace: replace,
-
- /**
- * Simplify string tests against emoji.
- *
- * @param string some text that might contain emoji
- * @return boolean true if any emoji was found, false otherwise.
- *
- * @example
- *
- * if (twemoji.test(someContent)) {
- * console.log("emoji All The Things!");
- * }
- */
- test: test
- },
-
- // used to escape HTML special chars in attributes
- escaper = {
- '&': '&',
- '<': '<',
- '>': '>',
- "'": ''',
- '"': '"'
- },
-
- // RegExp based on emoji's official Unicode standards
- // http://www.unicode.org/Public/UNIDATA/EmojiSources.txt
- re = /twemoji/,
-
- // avoid runtime RegExp creation for not so smart,
- // not JIT based, and old browsers / engines
- UFE0Fg = /\uFE0F/g,
-
- // avoid using a string literal like '\u200D' here because minifiers expand it inline
- U200D = String.fromCharCode(0x200D),
-
- // used to find HTML special chars in attributes
- rescaper = /[&<>'"]/g,
-
- // nodes with type 1 which should **not** be parsed (including lower case svg)
- shouldntBeParsed = /IFRAME|NOFRAMES|NOSCRIPT|SCRIPT|SELECT|STYLE|TEXTAREA|[a-z]/,
-
- // just a private shortcut
- fromCharCode = String.fromCharCode;
-
- return twemoji;
-
-
- /////////////////////////
- // private functions //
- // declaration //
- /////////////////////////
-
- /**
- * Shortcut to create text nodes
- * @param string text used to create DOM text node
- * @return Node a DOM node with that text
- */
- function createText(text) {
- return document.createTextNode(text);
- }
-
- /**
- * Utility function to escape html attribute text
- * @param string text use in HTML attribute
- * @return string text encoded to use in HTML attribute
- */
- function escapeHTML(s) {
- return s.replace(rescaper, replacer);
- }
-
- /**
- * Default callback used to generate emoji src
- * based on Twitter CDN
- * @param string the emoji codepoint string
- * @param string the default size to use, i.e. "36x36"
- * @return string the image source to use
- */
- function defaultImageSrcGenerator(icon, options) {
- return ''.concat(options.base, options.size, '/', icon, options.ext);
- }
-
- /**
- * Given a generic DOM nodeType 1, walk through all children
- * and store every nodeType 3 (#text) found in the tree.
- * @param Element a DOM Element with probably some text in it
- * @param Array the list of previously discovered text nodes
- * @return Array same list with new discovered nodes, if any
- */
- function grabAllTextNodes(node, allText) {
- var
- childNodes = node.childNodes,
- length = childNodes.length,
- subnode,
- nodeType;
- while (length--) {
- subnode = childNodes[length];
- nodeType = subnode.nodeType;
- // parse emoji only in text nodes
- if (nodeType === 3) {
- // collect them to process emoji later
- allText.push(subnode);
- }
- // ignore all nodes that are not type 1 or that
- // should not be parsed as script, style, and others
- else if (nodeType === 1 && !shouldntBeParsed.test(subnode.nodeName)) {
- grabAllTextNodes(subnode, allText);
- }
- }
- return allText;
- }
-
- /**
- * Used to both remove the possible variant
- * and to convert utf16 into code points.
- * If there is a zero-width-joiner (U+200D), leave the variants in.
- * @param string the raw text of the emoji match
- */
- function grabTheRightIcon(rawText) {
- // if variant is present as \uFE0F
- return toCodePoint(rawText.indexOf(U200D) < 0 ?
- rawText.replace(UFE0Fg, '') :
- rawText
- );
- }
-
- /**
- * DOM version of the same logic / parser:
- * emojify all found sub-text nodes placing images node instead.
- * @param Element generic DOM node with some text in some child node
- * @param Object options containing info about how to parse
- *
- * .callback Function the callback to invoke per each found emoji.
- * .base string the base url, by default twemoji.base
- * .ext string the image extension, by default twemoji.ext
- * .size string the assets size, by default twemoji.size
- *
- * @return Element same generic node with emoji in place, if any.
- */
- function parseNode(node, options) {
- var
- allText = grabAllTextNodes(node, []),
- length = allText.length,
- attrib,
- attrname,
- modified,
- fragment,
- subnode,
- text,
- match,
- i,
- index,
- img,
- rawText,
- iconId,
- 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))
- );
- }
- rawText = match[0];
- iconId = grabTheRightIcon(rawText);
- i = index + rawText.length;
- src = options.callback(iconId, options);
- if (src) {
- img = new Image();
- img.onerror = options.onerror;
- img.setAttribute('draggable', 'false');
- attrib = options.attributes(rawText, iconId);
- for (attrname in attrib) {
- if (
- attrib.hasOwnProperty(attrname) &&
- // don't allow any handlers to be set + don't allow overrides
- attrname.indexOf('on') !== 0 &&
- !img.hasAttribute(attrname)
- ) {
- img.setAttribute(attrname, attrib[attrname]);
- }
- }
- img.className = options.className;
- img.alt = rawText;
- img.src = src;
- modified = true;
- fragment.appendChild(img);
- }
- if (!img) fragment.appendChild(createText(rawText));
- img = null;
- }
- // is there actually anything to replace in here ?
- if (modified) {
- // any text left to be added ?
- if (i < text.length) {
- fragment.appendChild(
- createText(text.slice(i))
- );
- }
- // replace the text node only, leave intact
- // anything else surrounding such text
- subnode.parentNode.replaceChild(fragment, subnode);
- }
- }
- return node;
- }
-
- /**
- * String/HTML version of the same logic / parser:
- * emojify a generic text placing images tags instead of surrogates pair.
- * @param string generic string with possibly some emoji in it
- * @param Object options containing info about how to parse
- *
- * .callback Function the callback to invoke per each found emoji.
- * .base string the base url, by default twemoji.base
- * .ext string the image extension, by default twemoji.ext
- * .size string the assets size, by default twemoji.size
- *
- * @return the string with
replacing all found and parsed emoji
- */
- function parseString(str, options) {
- return replace(str, function (rawText) {
- var
- ret = rawText,
- iconId = grabTheRightIcon(rawText),
- src = options.callback(iconId, options),
- attrib,
- attrname;
- if (src) {
- // recycle the match string replacing the emoji
- // with its image counter part
- ret = '
');
- }
- return ret;
- });
- }
-
- /**
- * Function used to actually replace HTML special chars
- * @param string HTML special char
- * @return string encoded HTML special char
- */
- function replacer(m) {
- return escaper[m];
- }
-
- /**
- * Default options.attribute callback
- * @return null
- */
- function returnNull() {
- return null;
- }
-
- /**
- * Given a generic value, creates its squared counterpart if it's a number.
- * As example, number 36 will return '36x36'.
- * @param any a generic value.
- * @return any a string representing asset size, i.e. "36x36"
- * only in case the value was a number.
- * Returns initial value otherwise.
- */
- function toSizeSquaredAsset(value) {
- return typeof value === 'number' ?
- value + 'x' + value :
- value;
- }
-
-
- /////////////////////////
- // exported functions //
- // declaration //
- /////////////////////////
-
- function fromCodePoint(codepoint) {
- var code = typeof codepoint === 'string' ?
- parseInt(codepoint, 16) : codepoint;
- if (code < 0x10000) {
- return fromCharCode(code);
- }
- code -= 0x10000;
- return fromCharCode(
- 0xD800 + (code >> 10),
- 0xDC00 + (code & 0x3FF)
- );
- }
-
- function parse(what, how) {
- if (!how || typeof how === 'function') {
- how = {callback: how};
- }
- // if first argument is string, inject html
tags
- // otherwise use the DOM tree and parse text nodes only
- 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) {
- // IE6 needs a reset before too
- 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 < unicodeSurrogates.length) {
- c = unicodeSurrogates.charCodeAt(i++);
- if (p) {
- r.push((0x10000 + ((p - 0xD800) << 10) + (c - 0xDC00)).toString(16));
- p = 0;
- } else if (0xD800 <= c && c <= 0xDBFF) {
- p = c;
- } else {
- r.push(c.toString(16));
- }
- }
- return r.join(sep || '-');
- }
-
- }.toString()
- // drop current indentation
- .replace(/^ /gm, '')
- // add the RegExp in the right place
- .replace('re = /twemoji/', 're = /' + re + '/g')
- // add the full license
- .replace('/*! (C) Twitter Inc. */',
- '/*! (C) Twitter Inc. *//*\n' +
- fs.readFileSync(path.join(__dirname, '../../', 'LICENSE')).toString().replace(
- /^./gm, ' '
- ) +
- '\n */'
- ) + '());');
-}
diff --git a/1/utils/preview b/1/utils/preview
deleted file mode 100755
index 40a6e4d3..00000000
--- a/1/utils/preview
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/usr/bin/env node
-
-/*! Copyright Twitter Inc. and other contributors. Licensed under MIT *//*
- https://github.com/twitter/twemoji/blob/gh-pages/LICENSE
-*/
-
-// dependencies
-var fs = require('fs');
-var path = require('path');
-
-function file(which) {
- return path.join(__dirname, '..', which);
-}
-
-fs.readdir(file('../assets'), function (err, files) {
- var page = fs.readFileSync(file('templates/preview.html')).toString().replace(
- '{{emoji-list}}',
- '' + files.map(function (file) {
- return file.replace('.ai', '').split('-').map(function (hex) {
- return '' + hex.toUpperCase() + ';';
- }).join('');
- }).join('\n ')+ ''
- );
- fs.writeFileSync(
- file('test/preview.html'),
- page.replace(
- '{{emoji-options}}',
- JSON.stringify({
- size: 72
- })
- )
- );
- fs.writeFileSync(
- file('test/preview-svg.html'),
- page.replace(
- '{{emoji-options}}',
- JSON.stringify({
- folder: '../svg',
- ext: '.svg',
- base: ''
- })
- )
- );
-});
\ No newline at end of file
diff --git a/1/utils/size b/1/utils/size
deleted file mode 100755
index 4dd4ca67..00000000
--- a/1/utils/size
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/usr/bin/env bash
-
-echo "twemoji.js $(cat 1/twemoji.js | wc -c)"
-echo "twemoji.js gzipped $(gzip -c 1/twemoji.js | wc -c)"
-echo "twemoji.min.js $(cat 1/twemoji.min.js | wc -c)"
-echo "twemoji.min.js gzipped $(gzip -c 1/twemoji.min.js | wc -c)"