From e44666ad9869afb15fc340eb117d24f969a23ac8 Mon Sep 17 00:00:00 2001
From: julioest tags and joins single newlines with
spaces, so prose flows to the container width. Autolinks
URLs and escapes HTML; preserves XSS protection.
---
news/templatetags/news_tags.py | 24 ++++++++++++++++++++++++
templates/news/v3/detail.html | 3 ++-
2 files changed, 26 insertions(+), 1 deletion(-)
diff --git a/news/templatetags/news_tags.py b/news/templatetags/news_tags.py
index 4aaae85af..87c12d10d 100644
--- a/news/templatetags/news_tags.py
+++ b/news/templatetags/news_tags.py
@@ -1,7 +1,31 @@
+import re
+
from django import template
+from django.template.defaultfilters import urlize
+from django.utils.safestring import mark_safe
register = template.Library()
+_PARAGRAPH_SPLIT = re.compile(r"\n\s*\n+")
+
+
+@register.filter
+def text_paragraphs(value):
+ """Render hard-wrapped plain text as autolinked paragraphs.
+
+ Blank lines become paragraph breaks; single newlines inside a
+ paragraph collapse to spaces so source hard-wrapped at ~80 chars
+ flows naturally to the container width.
+ """
+ if not value:
+ return ""
+ paragraphs = []
+ for chunk in _PARAGRAPH_SPLIT.split(str(value)):
+ text = " ".join(line.strip() for line in chunk.splitlines() if line.strip())
+ if text:
+ paragraphs.append(f" {urlize(text, autoescape=True)}
+
{{ title }}
+
+ {% if author %}
+ {% include "v3/includes/_user_profile.html" with author=author only %}
+ {% endif %}
+
on every soft newline. The new filter splits on
blank lines into
- {{ object.external_url }} + {{ object.external_url }}
{% endif %} {% with body=object.content|default:object.visible_content %} From 29b6a4ed2bfc607e21adcb15769cea9c7b435be7 Mon Sep 17 00:00:00 2001 From: julioest{urlize(text, autoescape=True)}
") + lines = [line.strip() for line in chunk.splitlines() if line.strip()] + if not lines: + continue + if _should_preserve_breaks(lines): + joined = "{joined}
") return mark_safe("\n".join(paragraphs)) From f294e5a4364e0c1f171bc75e055c81bea34f4f63 Mon Sep 17 00:00:00 2001 From: julioest{joined}
") - return mark_safe("\n".join(paragraphs)) - @register.simple_tag(takes_context=True) def can_edit(context, news_item, *args, **kwargs): diff --git a/static/css/v3/post-detail.css b/static/css/v3/post-detail.css index 74a648b7c..5aaf57b4e 100644 --- a/static/css/v3/post-detail.css +++ b/static/css/v3/post-detail.css @@ -113,6 +113,61 @@ overflow-x: auto; } +.post-detail__body ul, +.post-detail__body ol { + padding-left: var(--space-large); + list-style-position: outside; +} + +.post-detail__body ul { + list-style-type: disc; +} + +.post-detail__body ol { + list-style-type: decimal; +} + +.post-detail__body ul ul { + list-style-type: circle; +} + +.post-detail__body ol ol, +.post-detail__body ul ol { + list-style-type: lower-alpha; +} + +.post-detail__body li { + font-family: var(--font-sans); + font-size: var(--font-size-base); + line-height: var(--line-height-loose); +} + +.post-detail__body h1, +.post-detail__body h2, +.post-detail__body h3, +.post-detail__body h4, +.post-detail__body h5, +.post-detail__body h6 { + color: var(--color-text-primary); + font-family: var(--font-display); + font-weight: var(--font-weight-medium); + line-height: var(--line-height-tight); + margin: 0; +} + +.post-detail__body h1 { font-size: var(--font-size-xl); } +.post-detail__body h2 { font-size: var(--font-size-large); } +.post-detail__body h3 { font-size: var(--font-size-medium); } +.post-detail__body h4, +.post-detail__body h5, +.post-detail__body h6 { font-size: var(--font-size-base); } + +.post-detail__body b, +.post-detail__body strong { + color: var(--color-text-primary); + font-weight: var(--font-weight-medium); +} + .post-detail__next, .post-detail__related { display: flex; diff --git a/templates/news/v3/detail.html b/templates/news/v3/detail.html index 2e0babc45..c48dc2e4e 100644 --- a/templates/news/v3/detail.html +++ b/templates/news/v3/detail.html @@ -1,6 +1,6 @@ {% extends "base.html" %} {% load static %} -{% load news_tags %} +{% load wagtailmarkdown %} {% block title %}{{ object.title }}{% endblock %} @@ -56,7 +56,7 @@ {% endif %} {% with body=object.content|default:object.visible_content %} - {% if body %}{{ body|text_paragraphs }}{% endif %} + {% if body %}{{ body|markdown|urlize }}{% endif %} {% endwith %}and that would otherwise break the flex gap rhythm here. --- static/css/v3/post-detail.css | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/static/css/v3/post-detail.css b/static/css/v3/post-detail.css index 5aaf57b4e..00b31231e 100644 --- a/static/css/v3/post-detail.css +++ b/static/css/v3/post-detail.css @@ -68,19 +68,18 @@ gap: var(--space-large); font-size: var(--font-size-base); line-height: var(--line-height-loose); + letter-spacing: var(--letter-spacing-tight); color: var(--color-text-secondary); padding-top: var(--space-xl); border-top: 1px solid var(--color-stroke-weak); } +/* Reset the site-wide `p { @apply py-5 }` from frontend/styles.css + so paragraph rhythm comes from the body's flex `gap`, not from + each
contributing its own 1.25rem of top/bottom padding. */
.post-detail__body p {
padding-top: 0;
padding-bottom: 0;
- font-family: var(--font-sans);
- font-size: var(--font-size-base);
- font-weight: var(--font-weight-regular);
- line-height: var(--line-height-loose);
- letter-spacing: var(--letter-spacing-tight);
}
.post-detail__body a {
@@ -136,12 +135,6 @@
list-style-type: lower-alpha;
}
-.post-detail__body li {
- font-family: var(--font-sans);
- font-size: var(--font-size-base);
- line-height: var(--line-height-loose);
-}
-
.post-detail__body h1,
.post-detail__body h2,
.post-detail__body h3,
@@ -152,7 +145,6 @@
font-family: var(--font-display);
font-weight: var(--font-weight-medium);
line-height: var(--line-height-tight);
- margin: 0;
}
.post-detail__body h1 { font-size: var(--font-size-xl); }
From 666f824fbddd918810e577c8bd236deeef077c80 Mon Sep 17 00:00:00 2001
From: julioest {{ item.title }}
{% endif %}
{% if item.date or item.category or item.tag %}
From 8f234efcd03d147792d823118a9e124e1fdc34ab Mon Sep 17 00:00:00 2001
From: julioest {{ item.title }}
{% endif %}
{% if item.date or item.category or item.tag %}
From 70a710f7c059e83408bd192cefc0da1871782160 Mon Sep 17 00:00:00 2001
From: julioest
+