Wire s-expression rendering into live app — blog link-card
- Add setup_sexp_bridge() and load_shared_components() to factory.py so all services get s-expression support automatically - Create shared/sexp/components.py with ~link-card component definition (replaces 5 per-service Jinja link_card.html templates) - Replace blog's link-card fragment handler to use sexp() instead of render_template() — first real s-expression rendered page content Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -10,6 +10,7 @@ from quart import Blueprint, Response, g, render_template, request
|
||||
|
||||
from shared.infrastructure.fragments import FRAGMENT_HEADER
|
||||
from shared.services.navigation import get_navigation_tree
|
||||
from shared.sexp.jinja_bridge import sexp
|
||||
|
||||
|
||||
def register():
|
||||
@@ -57,7 +58,21 @@ def register():
|
||||
|
||||
_handlers["nav-tree"] = _nav_tree_handler
|
||||
|
||||
# --- link-card fragment ---
|
||||
# --- link-card fragment (s-expression rendered) ---
|
||||
def _render_blog_link_card(post, link: str) -> str:
|
||||
"""Render a blog link-card via the ~link-card s-expression component."""
|
||||
published = post.published_at.strftime("%d %b %Y") if post.published_at else None
|
||||
return sexp(
|
||||
'(~link-card :link link :title title :image image'
|
||||
' :icon "fas fa-file-alt" :subtitle excerpt'
|
||||
' :detail published :data-app "blog")',
|
||||
link=link,
|
||||
title=post.title,
|
||||
image=post.feature_image,
|
||||
excerpt=post.custom_excerpt or post.excerpt,
|
||||
published=published,
|
||||
)
|
||||
|
||||
async def _link_card_handler():
|
||||
from shared.services.registry import services
|
||||
from shared.infrastructure.urls import blog_url
|
||||
@@ -73,14 +88,7 @@ def register():
|
||||
parts.append(f"<!-- fragment:{s} -->")
|
||||
post = await services.blog.get_post_by_slug(g.s, s)
|
||||
if post:
|
||||
parts.append(await render_template(
|
||||
"fragments/link_card.html",
|
||||
title=post.title,
|
||||
feature_image=post.feature_image,
|
||||
excerpt=post.custom_excerpt or post.excerpt,
|
||||
published_at=post.published_at,
|
||||
link=blog_url(f"/{post.slug}"),
|
||||
))
|
||||
parts.append(_render_blog_link_card(post, blog_url(f"/{post.slug}")))
|
||||
return "\n".join(parts)
|
||||
|
||||
# Single mode
|
||||
@@ -89,14 +97,7 @@ def register():
|
||||
post = await services.blog.get_post_by_slug(g.s, slug)
|
||||
if not post:
|
||||
return ""
|
||||
return await render_template(
|
||||
"fragments/link_card.html",
|
||||
title=post.title,
|
||||
feature_image=post.feature_image,
|
||||
excerpt=post.custom_excerpt or post.excerpt,
|
||||
published_at=post.published_at,
|
||||
link=blog_url(f"/{post.slug}"),
|
||||
)
|
||||
return _render_blog_link_card(post, blog_url(f"/{post.slug}"))
|
||||
|
||||
_handlers["link-card"] = _link_card_handler
|
||||
|
||||
|
||||
Reference in New Issue
Block a user