diff --git a/peterbecom/api/test_blogitem.py b/peterbecom/api/test_blogitem.py index 598035387..f1b66e764 100644 --- a/peterbecom/api/test_blogitem.py +++ b/peterbecom/api/test_blogitem.py @@ -234,3 +234,66 @@ def test_edit_blogitem(admin_client): assert response.status_code == 200 blogitem.refresh_from_db() assert blogitem.proper_keywords == ["three", "four"] + + +sample_markdown = """ +# Header 1 + +Textblock 1 + +## Header *2* + +Textblock 2 + +### Header `three` + +Moo boo + +## 2 Headers + +foo muu +""" + + +@pytest.mark.django_db +def test_edit_blogitem_markdown_render(admin_client): + blogitem = BlogItem.objects.create( + oid="hello-world", + title="Hello World", + pub_date=timezone.now(), + proper_keywords=["one", "two"], + display_format="markdown", + text=sample_markdown, + ) + url = reverse("api:blogitem", args=["hello-world"]) + + cat1 = Category.objects.create(name="Code") + response = admin_client.post( + url, + json.dumps( + { + "title": "New title", + "oid": "new-oid", + "summary": "New summary", + "keywords": "three \n four ", # ["three ", " four "], + "pub_date": json_datetime(timezone.now()), + "categories": [cat1.id], + "text": sample_markdown, + "display_format": "markdown", + } + ), + content_type="application/json", + ) + assert response.status_code == 200 + blogitem.refresh_from_db() + + html = blogitem.text_rendered + + assert ( + '

Header 1

' + in html + ) + assert ( + '

2 Headers

' + in html + ) diff --git a/peterbecom/plog/utils.py b/peterbecom/plog/utils.py index bc4d00f62..e6f2ae13d 100644 --- a/peterbecom/plog/utils.py +++ b/peterbecom/plog/utils.py @@ -18,6 +18,7 @@ from django.core.exceptions import ValidationError from django.core.validators import validate_email from django.utils import timezone +from markdown.extensions.toc import slugify as toc_slugify # https://github.com/vzhou842/profanity-check is probably better but it requires # scikit-learn or whatever it's called. @@ -27,6 +28,13 @@ from .gfm import gfm +def custom_toc_slugify(value: str, separator: str, unicode: bool = False) -> str: + s = toc_slugify(value, separator, unicode) + if s[0].isdigit(): + s = "h-" + s + return s + + def blog_post_url(oid, page=None): if page and page != 1: return f"/plog/{oid}/p{page}" @@ -223,7 +231,22 @@ def highlighter(m): return found text = _markdown_pre_regex.sub(matcher, text) - html = markdown.markdown(gfm(text), extensions=["markdown.extensions.tables"]) + html = markdown.markdown( + gfm(text), + extensions=[ + "tables", + "toc", + ], + extension_configs={ + "toc": { + "anchorlink": True, + "permalink": False, + "baselevel": 2, + "toc_depth": 3, + "slugify": custom_toc_slugify, + } + }, + ) html = html.replace("
", "
")
 
     # Markdown leaves a strange whitespace before the end of the paragraph.