128 lines
3.4 KiB
Python
128 lines
3.4 KiB
Python
import re
|
|
# FORCE component registration
|
|
import flask_logic.components
|
|
from flask_logic.registry import COMPONENTS
|
|
|
|
|
|
# ------------------------
|
|
# Content renderer (blocks)
|
|
# ------------------------
|
|
def render_blocks(blocks, context=None):
|
|
html_output = []
|
|
print(COMPONENTS)
|
|
|
|
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
|
|
|
|
def generate_preview(content, max_length=200):
|
|
if isinstance(content, str):
|
|
# old system
|
|
text = re.sub(r"<[^>]+>", "", content) # strip HTML
|
|
return text[:max_length]
|
|
|
|
elif isinstance(content, list):
|
|
# new system
|
|
for block in content:
|
|
if block.get("type") == "text":
|
|
text = re.sub(r"<[^>]+>", "", block.get("value", ""))
|
|
return text[:max_length]
|
|
|
|
return ""
|
|
|
|
# optinal, for images
|
|
def generate_preview_html(content, context=None):
|
|
if isinstance(content, list):
|
|
for block in content:
|
|
if block.get("type") == "text":
|
|
return f"<div class='blog-preview'>{block.get('value')}</div>"
|
|
|
|
elif block.get("type") in COMPONENTS:
|
|
# optional: allow image preview
|
|
render_func = COMPONENTS[block["type"]]["render"]
|
|
kwargs = {k: v for k, v in block.items() if k != "type"}
|
|
return render_func(**kwargs, context=context)
|
|
|
|
elif isinstance(content, str):
|
|
return content[:200]
|
|
|
|
return "" |