2017-10-29 23:19:10 +01:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
#
|
|
|
|
# This is a debugging tool that takes as input a bunch of different
|
|
|
|
# emoji data sources, and outputs a convenient HTML table that can be
|
|
|
|
# used to sanity-check the differences between these different data
|
2020-10-23 02:43:28 +02:00
|
|
|
# sources' decisions about what names to provide to each Unicode
|
2017-10-29 23:19:10 +01:00
|
|
|
# codepoint.
|
|
|
|
import os
|
|
|
|
from typing import Any, Dict, List
|
|
|
|
|
2020-08-07 01:09:47 +02:00
|
|
|
import orjson
|
2020-06-11 00:54:34 +02:00
|
|
|
|
2017-10-29 23:19:10 +01:00
|
|
|
from emoji_names import EMOJI_NAME_MAPS
|
2020-06-11 00:54:34 +02:00
|
|
|
from emoji_setup_utils import EMOJISETS, emoji_is_universal, get_emoji_code
|
2017-10-29 23:19:10 +01:00
|
|
|
|
|
|
|
TOOLS_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
|
|
ZULIP_PATH = os.path.dirname(TOOLS_DIR)
|
2021-02-12 08:20:45 +01:00
|
|
|
EMOJI_MAP_FILE = os.path.join(TOOLS_DIR, "setup", "emoji", "emoji_map.json")
|
2021-02-12 08:19:30 +01:00
|
|
|
UNIFIED_REACTIONS_FILE = os.path.join(
|
2021-02-12 08:20:45 +01:00
|
|
|
ZULIP_PATH, "zerver", "management", "data", "unified_reactions.json"
|
2021-02-12 08:19:30 +01:00
|
|
|
)
|
2021-02-12 08:20:45 +01:00
|
|
|
EMOJI_DATA_FILE = os.path.join(ZULIP_PATH, "node_modules", "emoji-datasource-google", "emoji.json")
|
|
|
|
EMOJI_CACHE = os.path.join(ZULIP_PATH, "static", "generated", "emoji")
|
|
|
|
OUTPUT_FILE = os.path.join(EMOJI_CACHE, "emoji_names_table.html")
|
2017-10-29 23:19:10 +01:00
|
|
|
|
2020-08-07 01:09:47 +02:00
|
|
|
with open(EMOJI_DATA_FILE, "rb") as fp:
|
|
|
|
EMOJI_DATA = orjson.loads(fp.read())
|
|
|
|
with open(UNIFIED_REACTIONS_FILE, "rb") as fp:
|
|
|
|
UNIFIED_REACTIONS_MAP = orjson.loads(fp.read())
|
|
|
|
with open(EMOJI_MAP_FILE, "rb") as fp:
|
|
|
|
EMOJI_MAP = orjson.loads(fp.read())
|
2017-10-29 23:19:10 +01:00
|
|
|
|
|
|
|
EMOJI_IMAGE_TEMPLATE = """
|
2020-07-10 01:57:43 +02:00
|
|
|
<img class="emoji" src="images-{emojiset}-64/{emoji_code}.png" title={emojiset}>
|
2017-10-29 23:19:10 +01:00
|
|
|
"""
|
|
|
|
|
|
|
|
TABLE_ROW_TEMPLATE = """
|
|
|
|
<tr>
|
2020-07-10 01:57:43 +02:00
|
|
|
<td class="new-sorting-info">{sorting_info}</td>
|
|
|
|
<td class="emoji-code">{emoji_code}</td>
|
|
|
|
<td class="emoji-images">{images_html}</td>
|
|
|
|
<td class="zulip-emoji-names">{zulip_names}</td>
|
|
|
|
<td class="iamcal-emoji-names">{iamcal_names}</td>
|
|
|
|
<td class="gemoji-emoji-names">{gemoji_names}</td>
|
|
|
|
<td class="unicode-name">{unicode_name}</td>
|
2017-10-29 23:19:10 +01:00
|
|
|
</tr>
|
|
|
|
"""
|
|
|
|
|
|
|
|
EMOJI_LISTING_TEMPLATE = """
|
|
|
|
<html>
|
|
|
|
<head>
|
|
|
|
<style>
|
2020-07-10 01:57:43 +02:00
|
|
|
{table_css}
|
2017-10-29 23:19:10 +01:00
|
|
|
</style>
|
|
|
|
<title>Zulip emoji names</title>
|
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<table>
|
|
|
|
<thead>
|
|
|
|
<tr>
|
|
|
|
<th class="new-sorting-info">Category</th>
|
|
|
|
<th class="emoji-code">Emoji code</th>
|
|
|
|
<th class="emoji-images">Images</th>
|
|
|
|
<th class="zulip-emoji-names">Zulip</th>
|
|
|
|
<th class="iamcal-emoji-names">Iamcal (Slack)</th>
|
|
|
|
<th class="gemoji-emoji-names">Gemoji (unordered)</th>
|
|
|
|
<th class="unicode-name">Unicode</th>
|
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
2020-07-10 01:57:43 +02:00
|
|
|
{tbody}
|
2017-10-29 23:19:10 +01:00
|
|
|
</tbody>
|
|
|
|
</table>
|
|
|
|
</body>
|
|
|
|
</html>
|
|
|
|
"""
|
|
|
|
|
|
|
|
TABLE_CSS = """
|
|
|
|
.emoji {
|
|
|
|
height: 35px;
|
|
|
|
width: 35px;
|
|
|
|
position: relative;
|
|
|
|
margin-top: -7px;
|
|
|
|
vertical-align: middle;
|
|
|
|
top: 3px;
|
|
|
|
}
|
|
|
|
|
|
|
|
.emoji-images {
|
|
|
|
width: 200px;
|
|
|
|
}
|
|
|
|
|
|
|
|
table, td, th {
|
|
|
|
border: 1px solid black;
|
|
|
|
border-collapse: collapse;
|
|
|
|
}
|
|
|
|
|
|
|
|
td, th {
|
|
|
|
height: 40px;
|
|
|
|
text-align: center;
|
|
|
|
}
|
|
|
|
|
|
|
|
.google {
|
2018-08-25 20:02:38 +02:00
|
|
|
background-image: url('sheet-google-64.png') !important;
|
2017-10-29 23:19:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
.twitter {
|
2018-08-25 20:02:38 +02:00
|
|
|
background-image: url('sheet-twitter-64.png') !important;
|
2017-10-29 23:19:10 +01:00
|
|
|
}
|
|
|
|
"""
|
|
|
|
|
|
|
|
SORTED_CATEGORIES = [
|
2021-02-12 08:20:45 +01:00
|
|
|
"Smileys & Emotion",
|
|
|
|
"People & Body",
|
|
|
|
"Animals & Nature",
|
|
|
|
"Food & Drink",
|
|
|
|
"Activities",
|
|
|
|
"Travel & Places",
|
|
|
|
"Objects",
|
|
|
|
"Symbols",
|
|
|
|
"Flags",
|
|
|
|
"Skin Tones",
|
2017-10-29 23:19:10 +01:00
|
|
|
]
|
|
|
|
|
2020-04-22 01:09:50 +02:00
|
|
|
emoji_code_to_zulip_names: Dict[str, str] = {}
|
|
|
|
emoji_code_to_iamcal_names: Dict[str, str] = {}
|
|
|
|
emoji_code_to_gemoji_names: Dict[str, str] = {}
|
|
|
|
emoji_collection: Dict[str, List[Dict[str, Any]]] = {category: [] for category in SORTED_CATEGORIES}
|
2017-10-29 23:19:10 +01:00
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
|
2017-10-29 23:19:10 +01:00
|
|
|
def generate_emoji_code_to_emoji_names_maps() -> None:
|
|
|
|
# Prepare gemoji names map.
|
2020-04-22 01:09:50 +02:00
|
|
|
reverse_unified_reactions_map: Dict[str, List[str]] = {}
|
2017-10-29 23:19:10 +01:00
|
|
|
for name in UNIFIED_REACTIONS_MAP:
|
|
|
|
emoji_code = UNIFIED_REACTIONS_MAP[name]
|
|
|
|
if emoji_code in reverse_unified_reactions_map:
|
|
|
|
reverse_unified_reactions_map[emoji_code].append(name)
|
|
|
|
else:
|
python: Use trailing commas consistently.
Automatically generated by the following script, based on the output
of lint with flake8-comma:
import re
import sys
last_filename = None
last_row = None
lines = []
for msg in sys.stdin:
m = re.match(
r"\x1b\[35mflake8 \|\x1b\[0m \x1b\[1;31m(.+):(\d+):(\d+): (\w+)", msg
)
if m:
filename, row_str, col_str, err = m.groups()
row, col = int(row_str), int(col_str)
if filename == last_filename:
assert last_row != row
else:
if last_filename is not None:
with open(last_filename, "w") as f:
f.writelines(lines)
with open(filename) as f:
lines = f.readlines()
last_filename = filename
last_row = row
line = lines[row - 1]
if err in ["C812", "C815"]:
lines[row - 1] = line[: col - 1] + "," + line[col - 1 :]
elif err in ["C819"]:
assert line[col - 2] == ","
lines[row - 1] = line[: col - 2] + line[col - 1 :].lstrip(" ")
if last_filename is not None:
with open(last_filename, "w") as f:
f.writelines(lines)
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-04-10 05:23:40 +02:00
|
|
|
reverse_unified_reactions_map[emoji_code] = [name]
|
2017-10-29 23:19:10 +01:00
|
|
|
|
|
|
|
for emoji_code in reverse_unified_reactions_map:
|
2021-02-12 08:19:30 +01:00
|
|
|
emoji_code_to_gemoji_names[emoji_code] = ", ".join(
|
|
|
|
reverse_unified_reactions_map[emoji_code]
|
|
|
|
)
|
2017-10-29 23:19:10 +01:00
|
|
|
|
|
|
|
# Prepare iamcal names map.
|
|
|
|
for emoji_dict in EMOJI_DATA:
|
2018-04-23 15:03:38 +02:00
|
|
|
emoji_code = get_emoji_code(emoji_dict)
|
2017-10-29 23:19:10 +01:00
|
|
|
emoji_code_to_iamcal_names[emoji_code] = ", ".join(emoji_dict["short_names"])
|
|
|
|
|
|
|
|
# Prepare zulip names map.
|
|
|
|
for emoji_code in EMOJI_NAME_MAPS:
|
|
|
|
canonical_name = EMOJI_NAME_MAPS[emoji_code]["canonical_name"]
|
|
|
|
aliases = EMOJI_NAME_MAPS[emoji_code]["aliases"]
|
python: Use trailing commas consistently.
Automatically generated by the following script, based on the output
of lint with flake8-comma:
import re
import sys
last_filename = None
last_row = None
lines = []
for msg in sys.stdin:
m = re.match(
r"\x1b\[35mflake8 \|\x1b\[0m \x1b\[1;31m(.+):(\d+):(\d+): (\w+)", msg
)
if m:
filename, row_str, col_str, err = m.groups()
row, col = int(row_str), int(col_str)
if filename == last_filename:
assert last_row != row
else:
if last_filename is not None:
with open(last_filename, "w") as f:
f.writelines(lines)
with open(filename) as f:
lines = f.readlines()
last_filename = filename
last_row = row
line = lines[row - 1]
if err in ["C812", "C815"]:
lines[row - 1] = line[: col - 1] + "," + line[col - 1 :]
elif err in ["C819"]:
assert line[col - 2] == ","
lines[row - 1] = line[: col - 2] + line[col - 1 :].lstrip(" ")
if last_filename is not None:
with open(last_filename, "w") as f:
f.writelines(lines)
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-04-10 05:23:40 +02:00
|
|
|
names = [canonical_name]
|
2017-10-29 23:19:10 +01:00
|
|
|
names.extend(aliases)
|
|
|
|
emoji_code_to_zulip_names[emoji_code] = ", ".join(names)
|
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
|
2017-10-29 23:19:10 +01:00
|
|
|
def get_sorting_info(category: str, sort_order: int) -> str:
|
|
|
|
return " ".join([category, str(sort_order)])
|
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
|
2017-10-29 23:19:10 +01:00
|
|
|
def get_images_html(emoji_code: str) -> str:
|
2021-02-12 08:20:45 +01:00
|
|
|
images_html = ""
|
2017-10-29 23:19:10 +01:00
|
|
|
for emojiset in EMOJISETS:
|
2020-07-10 01:57:43 +02:00
|
|
|
images_html += EMOJI_IMAGE_TEMPLATE.format(
|
|
|
|
emoji_code=emoji_code,
|
|
|
|
emojiset=emojiset,
|
|
|
|
)
|
2017-10-29 23:19:10 +01:00
|
|
|
|
|
|
|
return images_html
|
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
|
2017-10-29 23:19:10 +01:00
|
|
|
def generate_emoji_collection() -> None:
|
|
|
|
generate_emoji_code_to_emoji_names_maps()
|
|
|
|
# Prepare `emoji_collection`.
|
|
|
|
for emoji_dict in EMOJI_DATA:
|
|
|
|
if not emoji_is_universal(emoji_dict):
|
|
|
|
continue
|
|
|
|
category = emoji_dict["category"]
|
2018-04-23 15:03:38 +02:00
|
|
|
emoji_code = get_emoji_code(emoji_dict)
|
2017-10-29 23:19:10 +01:00
|
|
|
sort_order = emoji_dict["sort_order"]
|
2021-02-12 08:19:30 +01:00
|
|
|
emoji_collection[category].append(
|
|
|
|
{
|
|
|
|
"category": category,
|
|
|
|
"emoji_code": emoji_code,
|
|
|
|
"images_html": get_images_html(emoji_code),
|
|
|
|
"gemoji_names": emoji_code_to_gemoji_names.get(emoji_code, ""),
|
|
|
|
"iamcal_names": emoji_code_to_iamcal_names.get(emoji_code, ""),
|
|
|
|
"zulip_names": emoji_code_to_zulip_names.get(emoji_code, ""),
|
|
|
|
"unicode_name": (emoji_dict["name"] or "").lower(),
|
|
|
|
"sort_order": sort_order,
|
|
|
|
"sorting_info": get_sorting_info(category, sort_order),
|
|
|
|
}
|
|
|
|
)
|
2017-10-29 23:19:10 +01:00
|
|
|
|
|
|
|
# Sort `emoji_collection`.
|
|
|
|
for category in SORTED_CATEGORIES:
|
2021-02-12 08:20:45 +01:00
|
|
|
emoji_collection[category].sort(key=lambda x: x["sort_order"])
|
2017-10-29 23:19:10 +01:00
|
|
|
|
2021-02-12 08:19:30 +01:00
|
|
|
|
2017-10-29 23:19:10 +01:00
|
|
|
def main() -> None:
|
|
|
|
generate_emoji_collection()
|
|
|
|
|
|
|
|
tbody = ""
|
|
|
|
for category in SORTED_CATEGORIES:
|
|
|
|
for emoji_entry in emoji_collection[category]:
|
2020-07-10 01:57:43 +02:00
|
|
|
tbody += TABLE_ROW_TEMPLATE.format(**emoji_entry)
|
2017-10-29 23:19:10 +01:00
|
|
|
|
2021-02-12 08:20:45 +01:00
|
|
|
with open(OUTPUT_FILE, "w") as fp:
|
2021-02-12 08:19:30 +01:00
|
|
|
fp.write(
|
|
|
|
EMOJI_LISTING_TEMPLATE.format(
|
|
|
|
tbody=tbody,
|
|
|
|
table_css=TABLE_CSS,
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
print(
|
|
|
|
"Done! Open http://localhost:9991/static/generated/emoji/emoji_names_table.html "
|
|
|
|
"to view(after starting the dev server)."
|
|
|
|
)
|
2017-10-29 23:19:10 +01:00
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
main()
|