render fn

This commit is contained in:
m
2026-03-25 12:42:26 +01:00
parent 0272ec3d07
commit 1c23c05cc7
6 changed files with 145 additions and 15 deletions

24
app.py
View File

@@ -1,7 +1,7 @@
from flask import Flask, render_template, request, redirect, url_for, send_from_directory from flask import Flask, render_template, request, redirect, url_for, send_from_directory
from content.posts import BLOG_POSTS from content.posts import BLOG_POSTS
from flask_logic.logic import get_enriched_post, get_comments_for_post, save_comment from flask_logic.logic import get_enriched_post, get_comments_for_post, save_comment
from flask_logic.renderer import process_post_content, collect_css
# 🌟 IMPORT THE content from separate files. # 🌟 IMPORT THE content from separate files.
from content.posts import BLOG_POSTS from content.posts import BLOG_POSTS
from content.about_text import ABOUT, TITLE from content.about_text import ABOUT, TITLE
@@ -106,6 +106,7 @@ def about():
return render_template('about.html', about_txt = about_txt, blog_title = TITLE) return render_template('about.html', about_txt = about_txt, blog_title = TITLE)
@app.route('/post/<int:post_id>') @app.route('/post/<int:post_id>')
def post_detail(post_id): def post_detail(post_id):
context = {"used_components": set()} context = {"used_components": set()}
@@ -113,28 +114,23 @@ def post_detail(post_id):
post = get_enriched_post(post_id, BLOG_POSTS) post = get_enriched_post(post_id, BLOG_POSTS)
if not post: if not post:
return "Post not found", 404 return "Post not found", 404
comments = get_comments_for_post(post_id) comments = get_comments_for_post(post_id)
context["used_components"].add("image")
context["used_components"].add("code")
processed_content = process_post_content(
post.get('content', ''), context=context
)
#processed_content = render_content(post['content'], context=context) css_files = collect_css(context)
css_files = []
for comp in context["used_components"]:
css_files.append(f"css/components/{comp}.css")
return render_template( return render_template(
"post_detail.html", "post_detail.html",
post=post, post=post,
comments=comments, content=processed_content,
blog_title = TITLE, comments=comments,
blog_title=TITLE,
component_css=css_files component_css=css_files
) )
@app.route('/content/image/<path:filename>') @app.route('/content/image/<path:filename>')
def content_image_files(filename): def content_image_files(filename):
directory = 'content/image' directory = 'content/image'

0
flask_logic/__init__.py Normal file
View File

30
flask_logic/components.py Normal file
View File

@@ -0,0 +1,30 @@
from flask_logic.registry import register_component
@register_component("image", css="css/components/image.css")
def render_image_component(src, caption=None, css_class=None, context=None):
if context:
context["used_components"].add("image")
base_class = "image-container"
full_class = f"{base_class} {css_class}" if css_class else base_class
caption_html = f'<div class="caption">{caption}</div>' if caption else ""
return f"""
<div class="{full_class}">
<img src="/content/image/{src}" alt="{caption or ''}">
{caption_html}
</div>
"""
@register_component("code", css="css/components/code.css")
def render_code_block(value=None, code=None, context=None):
if context:
context["used_components"].add("code")
code = code or value or ""
return f"""
<pre class="code-block"><code>{code}</code></pre>
"""

12
flask_logic/registery.py Normal file
View File

@@ -0,0 +1,12 @@
# component_registry.py
COMPONENTS = {}
def register_component(name, css=None):
def decorator(func):
COMPONENTS[name] = {
"render": func,
"css": css
}
return func
return decorator

92
flask_logic/renderer.py Normal file
View File

@@ -0,0 +1,92 @@
import re
from flask_logic.registry import COMPONENTS
# ------------------------
# Content renderer (blocks)
# ------------------------
def render_blocks(blocks, context=None):
html_output = []
for block in blocks:
block_type = block.get("type")
if block_type == "text":
html_output.append(block.get("value", ""))
elif block_type in COMPONENTS:
render_func = COMPONENTS[block_type]["render"]
# remove "type" before passing kwargs
kwargs = {k: v for k, v in block.items() if k != "type"}
html_output.append(
render_func(**kwargs, context=context)
)
return "\n".join(html_output)
# ------------------------
# Old string renderer (tokens)
# ------------------------
def parse_options(option_string):
options = {}
if not option_string:
return options
parts = option_string.split("|")
for part in parts:
if "=" in part:
key, value = part.split("=", 1)
options[key.strip()] = value.strip()
return options
def render_content(content, context=None):
if not content:
return ""
def replace_image(match):
src = match.group("src").strip()
options = parse_options(match.group("options"))
render_func = COMPONENTS["image"]["render"]
return render_func(
src=src,
caption=options.get("caption"),
css_class=options.get("class"),
context=context
)
pattern = r"\[image:(?P<src>[^\|\]]+)(?:\|(?P<options>[^\]]+))?\]"
return re.sub(pattern, replace_image, content)
# ------------------------
# Unified entry
# ------------------------
def process_post_content(content, context=None):
if isinstance(content, str):
return render_content(content, context=context)
elif isinstance(content, list):
return render_blocks(content, context=context)
return ""
# ------------------------
# CSS collector
# ------------------------
def collect_css(context):
css_files = []
for comp in context["used_components"]:
css = COMPONENTS.get(comp, {}).get("css")
if css:
css_files.append(css)
return css_files

View File

@@ -11,7 +11,7 @@ Simple Blog Template{% endblock %} {% block content %} {% from
<p> <p>
<span class="glyphicon glyphicon-time"></span> Posted on {{ post.date }} <span class="glyphicon glyphicon-time"></span> Posted on {{ post.date }}
</p> </p>
{{ render_post(post) }} {{ content | safe }}
<div class="post-actions"> <div class="post-actions">
<a href="{{ url_for('home') }}" class="btn btn-default btn-custom" <a href="{{ url_for('home') }}" class="btn btn-default btn-custom"
>← Back to Posts</a >← Back to Posts</a