Skip to content

Instantly share code, notes, and snippets.

@agoose77
Created July 21, 2022 11:56
Show Gist options
  • Save agoose77/6d35a2066c6e9a95ea9538b0ef673706 to your computer and use it in GitHub Desktop.
Save agoose77/6d35a2066c6e9a95ea9538b0ef673706 to your computer and use it in GitHub Desktop.
Sphinx extension to render emojis in XeLaTeX using emojicdn
import requests
import pathlib
import os
import re
from sphinx.util import logging
logger = logging.getLogger(__name__)
def emoji_to_identifier(emoji):
return ord(emoji)
def parse_emoji_whitelist(whitelist):
emoji = []
for entry in whitelist:
from_, _, to = entry.partition(":")
if not to:
to = from_
emoji.extend([
chr(c) for c in range(ord(from_), ord(to)+1)
])
return emoji
def ensure_emoji_cache(cache_path, emoji, style):
for symbol in emoji:
# Find name of emoji
symbol_path = cache_path / f"{emoji_to_identifier(symbol)}.png"
if symbol_path.exists():
continue
logger.info(f"Could not find emoji: {symbol}, downloading...")
# Request from CDN
symbol_quote = requests.utils.quote(symbol)
response = requests.get(
f"https://emojicdn.elk.sh/{symbol_quote}",
params={"style": style}
)
with symbol_path.open("wb") as f:
f.write(response.content)
def update_latex_preamble(cache_path, emoji, config):
include = r"""
\usepackage{newunicodechar}
"""
cache_command = rf"""
\providecommand{{\emojicachepath}}[1]{{{cache_path}/#1}}
"""
emoji_command = r"""
\newcommand{\staticemoji}[1]{%
\bgroup\raisebox{-0.15em}{%
\includegraphics[height=1em]{\emojicachepath{#1}}%
}\egroup%
}
"""
# Translate unicode into \includegraphics commands
declarations = [
rf"\newunicodechar{{{x}}}{{\staticemoji{{{emoji_to_identifier(x)}}}}}"
for x in emoji
]
preamble = include + cache_command + emoji_command + "\n".join(declarations)
config['latex_elements']['preamble'] = config['latex_elements'].get('preamble', '') + preamble
def setup_emoji_cache(app, config):
cache_path = pathlib.Path(config.emoji_cache).absolute()
cache_path.mkdir(exist_ok=True, parents=True)
emoji = parse_emoji_whitelist(config.emoji_whitelist)
ensure_emoji_cache(cache_path, emoji, config.emoji_style)
update_latex_preamble(cache_path, emoji, config)
def setup(app):
app.add_config_value("emoji_whitelist", [], "html", [list])
app.add_config_value("emoji_cache", ".emoji", "html", [str, bytes, os.PathLike])
app.add_config_value("emoji_style", "google", "html", [str])
app.connect('config-inited', setup_emoji_cache)
@agoose77
Copy link
Author

agoose77 commented Jul 21, 2022

Inspired by https://github.com/mreq/xelatex-emoji/

Only supports single-codepoint emoji

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment