Move home/post detail/like rendering from Python to .sx defcomps

- Home page: inline shared helpers, render_to_sx("blog-home-main")
- Post detail: new ~blog-post-detail-content defcomp with data from service
- Like toggle: call render_to_sx("market-like-toggle-button") directly
- Add post_meta_data() and post_detail_data() to BlogPageService

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-04 09:24:55 +00:00
parent f2910ad767
commit d7f9afff8e
4 changed files with 177 additions and 11 deletions

View File

@@ -355,6 +355,78 @@ class BlogPageService:
"sumup_configured": sumup_configured,
}
def post_meta_data(self, post, base_title):
"""Compute SEO meta tag values from post dict."""
import re
from quart import request as req
is_public = post.get("visibility") == "public"
is_published = post.get("status") == "published"
email_only = post.get("email_only", False)
robots = "index,follow" if (is_public and is_published and not email_only) else "noindex,nofollow"
desc = (post.get("meta_description") or post.get("og_description") or
post.get("twitter_description") or post.get("custom_excerpt") or
post.get("excerpt") or "")
if not desc and post.get("html"):
desc = re.sub(r'<[^>]+>', '', post["html"])
desc = desc.replace("\n", " ").replace("\r", " ").strip()[:160]
image = (post.get("og_image") or post.get("twitter_image") or post.get("feature_image") or "")
canonical = post.get("canonical_url") or (req.url if req else "")
post_title = post.get("meta_title") or post.get("title") or ""
page_title = f"{post_title} \u2014 {base_title}" if post_title else base_title
og_title = post.get("og_title") or page_title
tw_title = post.get("twitter_title") or page_title
is_article = not post.get("is_page")
return {
"robots": robots, "page_title": page_title, "desc": desc,
"canonical": canonical,
"og_type": "article" if is_article else "website",
"og_title": og_title, "image": image,
"twitter_card": "summary_large_image" if image else "summary",
"twitter_title": tw_title,
}
def post_detail_data(self, post, user, rights, csrf, blog_url_base):
"""Serialize post detail view data for ~blog-post-detail-content defcomp."""
slug = post.get("slug", "")
is_admin = rights.get("admin") if isinstance(rights, dict) else getattr(rights, "admin", False)
user_id = getattr(user, "id", None) if user else None
# Tags and authors
tags = []
for t in (post.get("tags") or []):
name = t.get("name") or getattr(t, "name", "")
fi = t.get("feature_image") or getattr(t, "feature_image", None)
tags.append({"name": name, "src": fi or "", "initial": name[:1] if name else ""})
authors = []
for a in (post.get("authors") or []):
name = a.get("name") or getattr(a, "name", "")
img = a.get("profile_image") or getattr(a, "profile_image", None)
authors.append({"name": name, "image": img or ""})
return {
"slug": slug,
"is_draft": post.get("status") == "draft",
"publish_requested": post.get("publish_requested", False),
"can_edit": is_admin or (user_id is not None and post.get("user_id") == user_id),
"edit_href": f"{blog_url_base}/{slug}/admin/edit/",
"is_page": bool(post.get("is_page")),
"has_user": bool(user),
"liked": post.get("is_liked", False),
"like_url": f"{blog_url_base}/{slug}/like/toggle/",
"csrf": csrf,
"custom_excerpt": post.get("custom_excerpt") or "",
"tags": tags,
"authors": authors,
"feature_image": post.get("feature_image"),
"html_content": post.get("html", ""),
"sx_content": post.get("sx_content", ""),
}
async def preview_data(self, session, *, slug=None, **kw):
"""Build preview data with prettified/rendered content."""
from quart import g