Skip to content

Commit 659b4d9

Browse files
authored
Add new strict option in the emoji extension (#2488)
* Add new strict option in the emoji extension * Add emoji test for strict mode and twemoji not pointing to latest ver. * Remove unnecessary function
1 parent a994065 commit 659b4d9

7 files changed

Lines changed: 3959 additions & 3853 deletions

File tree

docs/src/markdown/about/changelog.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## 10.12
4+
5+
- **NEW**: Emoji: Add a new `strict` option that will raise an exception if an emoji is used whose name has changed,
6+
removed, or never existed.
7+
- **FIX**: Emoji: Emoji links should be generated such that they point to the new CDN version.
8+
39
## 10.11.2
410

511
- **FIX**: SuperFences: Fix a regression where certain patterns could cause a hang.

docs/src/markdown/extensions/emoji.md

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -500,17 +500,22 @@ Option | Type | Default | Description
500500
--------------------------- | ---------- | -------------------- | -----------
501501
`emoji_index` | function | `emojione` index | A function that returns the index to use when parsing `:short_name:` syntax. See [Default Emoji Indexes](#default-emoji-indexes) to see the provided indexes.
502502
`emoji_generator` | function | `to_png` generator | A function that takes the emoji info and constructs the desired emoji output. See [Default Emoji Generators](#default-emoji-generators) to see the provided generators.
503-
`title` | string | `#!py3thon 'short'` | Specifies the title format that is fed into the emoji generator function. Can either be `long` which is the long description of the emoji, `short` which is the short name (`:short:`), or `none` which will simply pass `None`.
504-
`alt` | string | `#!py3thon 'unicode'` | Specifies the format for the alt value that is passed to the emoji generator function. If `alt` is set to `short`, the short name will be passed to the generator. If `alt` is set to `unicode` the Unicode characters are passed to the generator. Lastly, if `alt` is set to `html_entity`, the Unicode characters are passed encoded as HTML entities.
505-
`remove_variation_selector` | bool | `#!py3thon False` | Specifies whether variation selectors should be removed from Unicode alt. Currently, only `fe0f` is removed as it is the only one presently found in the current emoji sets.
506-
`options` | dictionary | `#!py3thon {}` | Options that are specific to emoji generator functions. Supported parameters can vary from function to function.
503+
`title` | string | `#!python 'short'` | Specifies the title format that is fed into the emoji generator function. Can either be `long` which is the long description of the emoji, `short` which is the short name (`:short:`), or `none` which will simply pass `None`.
504+
`alt` | string | `#!python 'unicode'` | Specifies the format for the alt value that is passed to the emoji generator function. If `alt` is set to `short`, the short name will be passed to the generator. If `alt` is set to `unicode` the Unicode characters are passed to the generator. Lastly, if `alt` is set to `html_entity`, the Unicode characters are passed encoded as HTML entities.
505+
`remove_variation_selector` | bool | `#!python False` | Specifies whether variation selectors should be removed from Unicode alt. Currently, only `fe0f` is removed as it is the only one presently found in the current emoji sets.
506+
`options` | dictionary | `#!python {}` | Options that are specific to emoji generator functions. Supported parameters can vary from function to function.
507+
`strict` | bool | `#!python False` | Raise an exception if an emoji is used whose name is not found in the database.
507508

508509
/// new | New 7.1
509510
`options` is now shared between index and generator functions opposed to being passed to the generator function
510511
only. The generator and/or index function should decide which of the arguments are relevant for its usage and parse
511512
accordingly.
512513
///
513514

515+
/// new | New 10.12
516+
Added `strict` mode.
517+
///
518+
514519
/// tip | Legacy GitHubEmoji Emulation
515520
The Emoji extension was actually created to replace the now retired GitHubEmoji extension. Emoji was written to be
516521
much more flexible. If you have a desire to configure the output to be like the legacy GitHubEmoji extension, you

pymdownx/__meta__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,5 +185,5 @@ def parse_version(ver, pre=False):
185185
return Version(major, minor, micro, release, pre, post, dev)
186186

187187

188-
__version_info__ = Version(10, 11, 2, "final")
188+
__version_info__ = Version(10, 12, 0, "final")
189189
__version__ = __version_info__._get_canonical()

pymdownx/emoji.py

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"""
2525
from markdown import Extension
2626
from markdown.inlinepatterns import InlineProcessor
27+
from markdown.postprocessors import Postprocessor
2728
from markdown import util as md_util
2829
import xml.etree.ElementTree as etree
2930
import inspect
@@ -35,8 +36,8 @@
3536
UNICODE_VARIATION_SELECTOR_16 = 'fe0f'
3637
EMOJIONE_SVG_CDN = 'https://cdnjs.cloudflare.com/ajax/libs/emojione/2.2.7/assets/svg/'
3738
EMOJIONE_PNG_CDN = 'https://cdnjs.cloudflare.com/ajax/libs/emojione/2.2.7/assets/png/'
38-
TWEMOJI_SVG_CDN = 'https://cdn.jsdelivr.net/gh/jdecked/twemoji@15.0.3/assets/svg/'
39-
TWEMOJI_PNG_CDN = 'https://cdn.jsdelivr.net/gh/jdecked/twemoji@15.0.3/assets/72x72/'
39+
TWEMOJI_SVG_CDN = 'https://cdn.jsdelivr.net/gh/jdecked/twemoji@15.1.0/assets/svg/'
40+
TWEMOJI_PNG_CDN = 'https://cdn.jsdelivr.net/gh/jdecked/twemoji@15.1.0/assets/72x72/'
4041
GITHUB_UNICODE_CDN = 'https://github.githubassets.com/images/icons/emoji/unicode/'
4142
GITHUB_CDN = 'https://github.githubassets.com/images/icons/emoji/'
4243
NO_TITLE = 'none'
@@ -52,6 +53,13 @@
5253
Please update your custom index accordingly.
5354
"""
5455

56+
MSG_BAD_EMOJI = """
57+
Emoji Extension (strict mode): The following emoji were detected and either had
58+
their name change, were removed, or have never existed.
59+
60+
{}
61+
"""
62+
5563

5664
def add_attributes(options, attributes):
5765
"""Add additional attributes from options."""
@@ -226,7 +234,7 @@ def to_alt(index, shortname, alias, uc, alt, title, category, options, md):
226234
class EmojiPattern(InlineProcessor):
227235
"""Return element of type `tag` with a text attribute of group(2) of an `InlineProcessor`."""
228236

229-
def __init__(self, pattern, config, md):
237+
def __init__(self, pattern, config, strict_mode, md):
230238
"""Initialize."""
231239

232240
InlineProcessor.__init__(self, pattern, md)
@@ -240,6 +248,8 @@ def __init__(self, pattern, config, md):
240248
self.remove_var_sel = config['remove_variation_selector']
241249
self.title = title if title in VALID_TITLE else NO_TITLE
242250
self.generator = config['emoji_generator']
251+
self.strict = config['strict']
252+
self.strict_cache = strict_mode
243253

244254
def _set_index(self, index):
245255
"""Set the index."""
@@ -336,10 +346,30 @@ def handleMatch(self, m, data):
336346
self.options,
337347
self.md
338348
)
349+
elif self.strict:
350+
self.strict_cache.add(shortname)
339351

340352
return el, m.start(0), m.end(0)
341353

342354

355+
class EmojiAlertPostprocessor(Postprocessor):
356+
"""Post processor to strip out unwanted content."""
357+
358+
def __init__(self, strict_cache, md):
359+
"""Initialize."""
360+
361+
self.strict_cache = strict_cache
362+
363+
def run(self, text):
364+
"""Strip out ids and classes for a simplified HTML output."""
365+
366+
if len(self.strict_cache):
367+
raise RuntimeError(
368+
MSG_BAD_EMOJI.format('\n'.join([f'- {x}' for x in sorted(self.strict_cache)]))
369+
)
370+
return text
371+
372+
343373
class EmojiExtension(Extension):
344374
"""Add emoji extension to Markdown class."""
345375

@@ -371,21 +401,35 @@ def __init__(self, *args, **kwargs):
371401
False,
372402
"Remove variation selector 16 from unicode. - Default: False"
373403
],
404+
'strict': [
405+
False,
406+
"When enabled, if an emoji with a missing name is detected, an exception will be raised."
407+
],
374408
'options': [
375409
{},
376410
"Emoji options see documentation for options for github and emojione."
377411
]
378412
}
379413
super().__init__(*args, **kwargs)
380414

415+
def reset(self):
416+
"""Reset."""
417+
418+
self.strict_cache.clear()
419+
381420
def extendMarkdown(self, md):
382421
"""Add support for emoji."""
383422

423+
md.registerExtension(self)
424+
384425
config = self.getConfigs()
385426

386427
util.escape_chars(md, [':'])
387428

388-
md.inlinePatterns.register(EmojiPattern(RE_EMOJI, config, md), "emoji", 75)
429+
self.strict_cache = set()
430+
md.inlinePatterns.register(EmojiPattern(RE_EMOJI, config, self.strict_cache, md), "emoji", 75)
431+
if config['strict']:
432+
md.postprocessors.register(EmojiAlertPostprocessor(self.strict_cache, md), "emoji-alert", 50)
389433

390434

391435
###################

0 commit comments

Comments
 (0)