-
Notifications
You must be signed in to change notification settings - Fork 4
/
emoji.py
162 lines (126 loc) · 4.81 KB
/
emoji.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
"""
Emoji extras for Material.
Override the indexes with an extended version that includes short names for Material icons, FontAwesome, etc.
"""
import os
import glob
import copy
import codecs
import functools
import inspect
import material
import pymdownx
from pymdownx.emoji import TWEMOJI_SVG_CDN, add_attriubtes
import xml.etree.ElementTree as etree # noqa: N813
import warnings
from functools import wraps
import logging
log = logging.getLogger('mkdocs')
DEPRECATED = """\
Material emoji logic has been officially moved into mkdocs-material
version 9.4. Please use Material's '{}'
instead of '{}' in your 'mkdocs.yml' file.
```
markdown_extensions:
- pymdownx.emoji:
emoji_index: !!python/name:material.extensions.emoji.twemoji
emoji_generator: !!python/name:material.extensions.emoji.to_svg
```
'mkdocs_material_extensions' is deprecated and will no longer be
supported moving forward. This is the last release.
"""
OPTION_SUPPORT = pymdownx.__version_info__ >= (7, 1, 0)
RESOURCES = os.path.dirname(inspect.getfile(material))
if os.path.exists(os.path.join(RESOURCES, 'templates', '.icons')): # pragma: no cover
RES_PATH = os.path.join(RESOURCES, 'templates', '.icons')
else: # pragma: no cover
RES_PATH = os.path.join(RESOURCES, '.icons')
@functools.lru_cache(maxsize=None)
def log_msg(message):
"""Log message."""
log.warning(message)
def deprecated(message, stacklevel=2, name=None): # pragma: no cover
"""
Raise a `DeprecationWarning` when wrapped function/method is called.
Usage:
@deprecated("This method will be removed in version X; use Y instead.")
def some_method()"
pass
"""
def _wrapper(func):
@wraps(func)
def _deprecated_func(*args, **kwargs):
warnings.warn(
f"'{func.__name__ if name is None else name}' is deprecated.\n{message}",
category=DeprecationWarning,
stacklevel=stacklevel
)
log_msg(message)
return func(*args, **kwargs)
return _deprecated_func
return _wrapper
@deprecated(
DEPRECATED.format('material.extensions.emoji.twemoji', 'materialx.emoji.twemoji'),
name='materialx.emoji.twemoji'
)
def _patch_index(options):
"""Patch the given index."""
icon_locations = options.get('custom_icons', [])[:]
icon_locations.append(RES_PATH)
return _patch_index_for_locations(tuple(icon_locations))
@functools.lru_cache(maxsize=None)
def _patch_index_for_locations(icon_locations):
import pymdownx.twemoji_db as twemoji_db
# Copy the Twemoji index
index = {
"name": 'twemoji',
"emoji": copy.deepcopy(twemoji_db.emoji) if not OPTION_SUPPORT else twemoji_db.emoji,
"aliases": copy.deepcopy(twemoji_db.aliases) if not OPTION_SUPPORT else twemoji_db.aliases
}
# Find our icons
for icon_path in icon_locations:
norm_base = icon_path.replace('\\', '/') + '/'
for result in glob.glob(glob.escape(icon_path.replace('\\', '/')) + '/**/*.svg', recursive=True):
name = ':{}:'.format(result.replace('\\', '/').replace(norm_base, '', 1).replace('/', '-').lstrip('.')[:-4])
if name not in index['emoji'] and name not in index['aliases']:
# Easiest to just store the path and pull it out from the index
index["emoji"][name] = {'name': name, 'path': result}
return index
if OPTION_SUPPORT: # pragma: no cover
def twemoji(options, md):
"""Provide a copied Twemoji index with additional codes for Material included icons."""
return _patch_index(options)
else: # pragma: no cover
def twemoji():
"""Provide a copied Twemoji index with additional codes for Material included icons."""
return _patch_index({})
@deprecated(
DEPRECATED.format('material.extensions.emoji.to_svg', 'materialx.emoji.to_svg'),
1,
name='materialx.emoji.to_svg'
)
def to_svg(index, shortname, alias, uc, alt, title, category, options, md):
"""Return SVG element."""
is_unicode = uc is not None
if is_unicode:
# Handle Twemoji emoji.
svg_path = TWEMOJI_SVG_CDN
attributes = {
"class": options.get('classes', index),
"alt": alt,
"src": "%s%s.svg" % (
options.get('image_path', svg_path),
uc
)
}
if title:
attributes['title'] = title
add_attriubtes(options, attributes)
return etree.Element("img", attributes)
else:
# Handle Material SVG assets.
el = etree.Element('span', {"class": options.get('classes', index)})
svg_path = md.inlinePatterns['emoji'].emoji_index['emoji'][shortname]['path']
with codecs.open(svg_path, 'r', encoding='utf-8') as f:
el.text = md.htmlStash.store(f.read())
return el