From ad736978592373ff97e994e276708fea021d397c Mon Sep 17 00:00:00 2001 From: Stuart Maxwell Date: Tue, 12 Nov 2024 22:25:40 +1300 Subject: [PATCH] Move markdown rendering into separate module --- src/djpress/app_settings.py | 27 ++++++++++++++------------- src/djpress/markdown_renderer.py | 18 ++++++++++++++++++ src/djpress/models/post.py | 4 +++- src/djpress/utils.py | 26 +++++++++++++++----------- tests/test_utils.py | 13 ++++++++++++- 5 files changed, 62 insertions(+), 26 deletions(-) create mode 100644 src/djpress/markdown_renderer.py diff --git a/src/djpress/app_settings.py b/src/djpress/app_settings.py index e941c05..34683da 100644 --- a/src/djpress/app_settings.py +++ b/src/djpress/app_settings.py @@ -2,24 +2,25 @@ # DJPress settings DJPRESS_SETTINGS = { - "TRUNCATE_TAG": ("", str), - "CACHE_CATEGORIES": (True, bool), - "CACHE_RECENT_PUBLISHED_POSTS": (False, bool), - "RECENT_PUBLISHED_POSTS_COUNT": (20, int), - "MARKDOWN_EXTENSIONS": ([], list), - "MARKDOWN_EXTENSION_CONFIGS": ({}, dict), - "BLOG_TITLE": ("My DJ Press Blog", str), - "BLOG_DESCRIPTION": ("", str), - "POST_READ_MORE_TEXT": ("Read more...", str), - "POST_PREFIX": ("{{ year }}/{{ month }}/{{ day }}", str), "ARCHIVE_ENABLED": (True, bool), "ARCHIVE_PREFIX": ("", str), - "CATEGORY_ENABLED": (True, bool), - "CATEGORY_PREFIX": ("category", str), "AUTHOR_ENABLED": (True, bool), "AUTHOR_PREFIX": ("author", str), + "BLOG_DESCRIPTION": ("", str), + "BLOG_TITLE": ("My DJ Press Blog", str), + "CACHE_CATEGORIES": (True, bool), + "CACHE_RECENT_PUBLISHED_POSTS": (False, bool), + "CATEGORY_ENABLED": (True, bool), + "CATEGORY_PREFIX": ("category", str), + "MARKDOWN_EXTENSION_CONFIGS": ({}, dict), + "MARKDOWN_EXTENSIONS": ([], list), + "MARKDOWN_RENDERER": ("djpress.markdown_renderer.default_renderer", str), + "MICROFORMATS_ENABLED": (True, bool), + "POST_PREFIX": ("{{ year }}/{{ month }}/{{ day }}", str), + "POST_READ_MORE_TEXT": ("Read more...", str), + "RECENT_PUBLISHED_POSTS_COUNT": (20, int), "RSS_ENABLED": (True, bool), "RSS_PATH": ("rss", str), - "MICROFORMATS_ENABLED": (True, bool), "THEME": ("default", str), + "TRUNCATE_TAG": ("", str), } diff --git a/src/djpress/markdown_renderer.py b/src/djpress/markdown_renderer.py new file mode 100644 index 0000000..7cd00bf --- /dev/null +++ b/src/djpress/markdown_renderer.py @@ -0,0 +1,18 @@ +"""Default Markdown renderer for Djpress.""" + +import markdown + +from djpress.conf import settings as djpress_settings + + +def default_renderer(markdown_text: str) -> str: + """Return the Markdown text as HTML.""" + md = markdown.Markdown( + extensions=djpress_settings.MARKDOWN_EXTENSIONS, + extension_configs=djpress_settings.MARKDOWN_EXTENSION_CONFIGS, + output_format="html", + ) + html = md.convert(markdown_text) + md.reset() + + return html diff --git a/src/djpress/models/post.py b/src/djpress/models/post.py index 057a431..9b8fce5 100644 --- a/src/djpress/models/post.py +++ b/src/djpress/models/post.py @@ -13,10 +13,12 @@ from djpress.conf import settings as djpress_settings from djpress.exceptions import PageNotFoundError, PostNotFoundError from djpress.models import Category -from djpress.utils import render_markdown +from djpress.utils import get_markdown_renderer logger = logging.getLogger(__name__) +render_markdown = get_markdown_renderer() + PUBLISHED_POSTS_CACHE_KEY = "published_posts" diff --git a/src/djpress/utils.py b/src/djpress/utils.py index b11a135..79276c3 100644 --- a/src/djpress/utils.py +++ b/src/djpress/utils.py @@ -1,24 +1,28 @@ """Utility functions that are used in the project.""" -import markdown from django.contrib.auth.models import User from django.template.loader import TemplateDoesNotExist, select_template from django.utils import timezone +from django.utils.module_loading import import_string from djpress.conf import settings as djpress_settings -def render_markdown(markdown_text: str) -> str: - """Return the Markdown text as HTML.""" - md = markdown.Markdown( - extensions=djpress_settings.MARKDOWN_EXTENSIONS, - extension_configs=djpress_settings.MARKDOWN_EXTENSION_CONFIGS, - output_format="html", - ) - html = md.convert(markdown_text) - md.reset() +def get_markdown_renderer() -> callable: + """Get the configured markdown renderer function. - return html + Returns: + callable: The markdown renderer function. + """ + renderer_path = djpress_settings.MARKDOWN_RENDERER + + try: + return import_string(renderer_path) + except ImportError as exc: + from django.core.exceptions import ImproperlyConfigured + + msg = f"Could not import markdown renderer '{renderer_path}': {exc}" + raise ImproperlyConfigured(msg) from exc def get_author_display_name(user: User) -> str: diff --git a/tests/test_utils.py b/tests/test_utils.py index 5334676..0b953c4 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,10 +1,13 @@ import pytest -from djpress.utils import get_author_display_name, render_markdown, get_template_name +from djpress.utils import get_author_display_name, get_markdown_renderer, get_template_name from django.contrib.auth.models import User from django.template.loader import TemplateDoesNotExist +render_markdown = get_markdown_renderer() + + # create a parameterized fixture for a test user with first name, last name, and username @pytest.fixture( params=[ @@ -48,6 +51,14 @@ def test_get_author_display_name(test_user): assert display_name == user_name +def test_render_markdown_does_not_exist(settings): + settings.DJPRESS_SETTINGS["MARKDOWN_RENDERER"] = "djpress.not_exists" + from django.core.exceptions import ImproperlyConfigured + + with pytest.raises(ImproperlyConfigured): + get_markdown_renderer() + + def test_render_markdown_basic(): markdown_text = "# Heading\n\nThis is some **bold** text. And this is *italic*.\n\nAnd a paragraph." html = render_markdown(markdown_text)