From da798d1a94503228afbc1b3232a6184a97692dab Mon Sep 17 00:00:00 2001 From: David Lesieur Date: Fri, 27 Dec 2024 18:07:21 -0500 Subject: [PATCH 1/2] Let user select Typogrify filters to omit (#3436). --- docs/settings.rst | 9 +++- pelican/readers.py | 17 +++++-- pelican/settings.py | 1 + pelican/tests/test_readers.py | 84 +++++++++++++++++++++++++++++++++++ 4 files changed, 107 insertions(+), 4 deletions(-) diff --git a/docs/settings.rst b/docs/settings.rst index b442451a2..8ee69e944 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -288,7 +288,14 @@ Basic settings A list of tags for Typogrify to ignore. By default Typogrify will ignore ``pre`` and ``code`` tags. This requires that Typogrify version 2.0.4 or - later is installed + later is installed. + +.. data:: TYPOGRIFY_OMIT_FILTERS = [] + + A list of Typogrify filters to skip. Allowed values are: ``'amp'``, + ``'smartypants'``, ``'caps'``, ``'initial_quotes'``, ``'widont'``. By + default, no filter is omitted (in other words, all filters get applied). This + setting requires that Typogrify version 2.0.8 or later is installed. .. data:: TYPOGRIFY_DASHES = 'default' diff --git a/pelican/readers.py b/pelican/readers.py index 59aa7ca33..182194fe1 100644 --- a/pelican/readers.py +++ b/pelican/readers.py @@ -648,11 +648,22 @@ def read_file( smartypants.Attr.default |= smartypants.Attr.w def typogrify_wrapper(text): - """Ensures ignore_tags feature is backward compatible""" + """Ensure compatibility with older versions of Typogrify. + + The 'TYPOGRIFY_IGNORE_TAGS' and/or 'TYPOGRIFY_OMIT_FILTERS' + settings will be ignored if the installed version of Typogrify + doesn't have the corresponding features.""" try: - return typogrify(text, self.settings["TYPOGRIFY_IGNORE_TAGS"]) + return typogrify( + text, + self.settings["TYPOGRIFY_IGNORE_TAGS"], + **{f: False for f in self.settings["TYPOGRIFY_OMIT_FILTERS"]}, + ) except TypeError: - return typogrify(text) + try: + typogrify(text, self.settings["TYPOGRIFY_IGNORE_TAGS"]) + except TypeError: + return typogrify(text) if content: content = typogrify_wrapper(content) diff --git a/pelican/settings.py b/pelican/settings.py index 69120058a..1fb0b2111 100644 --- a/pelican/settings.py +++ b/pelican/settings.py @@ -149,6 +149,7 @@ def load_source(name: str, path: str) -> ModuleType: "ARTICLE_PERMALINK_STRUCTURE": "", "TYPOGRIFY": False, "TYPOGRIFY_IGNORE_TAGS": [], + "TYPOGRIFY_OMIT_FILTERS": [], "TYPOGRIFY_DASHES": "default", "SUMMARY_END_SUFFIX": "…", "SUMMARY_MAX_LENGTH": 50, diff --git a/pelican/tests/test_readers.py b/pelican/tests/test_readers.py index 68938a83a..7db503d0c 100644 --- a/pelican/tests/test_readers.py +++ b/pelican/tests/test_readers.py @@ -409,6 +409,90 @@ def test_typogrify_summary(self): except ImportError: return unittest.skip("need the typogrify distribution") + def test_typogrify_ignore_filters(self): + try: + # typogrify should be able to ignore user specified filters. + page = self.read_file( + path="article_with_code_block.rst", + TYPOGRIFY=True, + TYPOGRIFY_OMIT_FILTERS=["amp"], + ) + expected = ( + "

An article with some code

\n" + '
'
+                'x'
+                ' &'
+                ' y\n
\n' + "

A block quote:

\n
\nx " + "& y
\n" + "

Normal:\nx & y

\n" + ) + self.assertEqual(page.content, expected) + + page = self.read_file( + path="article.rst", + TYPOGRIFY=True, + TYPOGRIFY_OMIT_FILTERS=["smartypants"], + ) + expected = ( + '

THIS is some content. ' + "With some stuff to "typogrify"...

\n" + '

Now with added support for TLA.

\n' + ) + self.assertEqual(page.content, expected) + + page = self.read_file( + path="article.rst", + TYPOGRIFY=True, + TYPOGRIFY_OMIT_FILTERS=["caps"], + ) + expected = ( + "

THIS is some content. " + "With some stuff to “typogrify”…

\n" + '

Now with added support for TLA.

\n' + ) + self.assertEqual(page.content, expected) + + page = self.read_file( + path="article.rst", + TYPOGRIFY=True, + TYPOGRIFY_OMIT_FILTERS=["initial_quotes"], + ) + expected = ( + '

THIS is some content. ' + "With some stuff to “typogrify”…

\n" + '

Now with added support for TLA.

\n' + ) + self.assertEqual(page.content, expected) + + page = self.read_file( + path="article.rst", + TYPOGRIFY=True, + TYPOGRIFY_OMIT_FILTERS=["widont"], + ) + expected = ( + '

THIS is some content. ' + "With some stuff to " + "“typogrify”…

\n

Now with added " + 'support for ' + 'TLA.

\n' + ) + self.assertEqual(page.content, expected) + + page = self.read_file( + path="article.rst", + TYPOGRIFY=True, + TYPOGRIFY_OMIT_FILTERS=["this-filter-does-not-exists"], + ) + self.assertRaises(TypeError) + except ImportError: + return unittest.skip("need the typogrify distribution") + except TypeError: + return unittest.skip("need typogrify version 2.0.8 or later") + def test_typogrify_ignore_tags(self): try: # typogrify should be able to ignore user specified tags, From 82dd2e80ea26f4e681e92cd808515c405ac234d9 Mon Sep 17 00:00:00 2001 From: David Lesieur Date: Tue, 7 Jan 2025 14:51:20 -0500 Subject: [PATCH 2/2] Update required Typogrify version for 'TYPOGRIFY_OMIT_FILTERS' setting. --- docs/settings.rst | 2 +- pelican/tests/test_readers.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/settings.rst b/docs/settings.rst index 8ee69e944..72c72fb1e 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -295,7 +295,7 @@ Basic settings A list of Typogrify filters to skip. Allowed values are: ``'amp'``, ``'smartypants'``, ``'caps'``, ``'initial_quotes'``, ``'widont'``. By default, no filter is omitted (in other words, all filters get applied). This - setting requires that Typogrify version 2.0.8 or later is installed. + setting requires that Typogrify version 2.1.0 or later is installed. .. data:: TYPOGRIFY_DASHES = 'default' diff --git a/pelican/tests/test_readers.py b/pelican/tests/test_readers.py index 7db503d0c..0524efd16 100644 --- a/pelican/tests/test_readers.py +++ b/pelican/tests/test_readers.py @@ -491,7 +491,7 @@ def test_typogrify_ignore_filters(self): except ImportError: return unittest.skip("need the typogrify distribution") except TypeError: - return unittest.skip("need typogrify version 2.0.8 or later") + return unittest.skip("need typogrify version 2.1.0 or later") def test_typogrify_ignore_tags(self): try: