Files
LifeFaq/app/services/markdown_render.py
2024-12-16 17:04:06 +01:00

112 lines
3.2 KiB
Python

import markdown
from jinja2 import Environment, DictLoader
# Define Jinja2 custom functions
def img_left_overlay(src):
"""Render an image with overlay."""
return f'''
<div class="img-left-overlay">
<img src="{src}" alt="Overlay Image">
<div class="overlay-text">Overlay Text</div>
</div>
'''
def box(title, content):
"""Render a box component."""
return f'''
<div class="box">
<strong>{title}</strong>
<p>{content}</p>
</div>
'''
def note(content):
"""Render a note component."""
return f'''
<div class="note">
<p>{content}</p>
</div>
'''
def link_to(title, url):
"""Render a box component."""
return f'''
<a href="{url}" target="_blank" rel="noopener noreferrer">{title}</a>
'''
def warning(content):
"""Render a warning component."""
return f'''
<div class="warning">
⚠️ <p>{content}</p>
</div>
'''
def slider(options, images):
"""Render a slider using the provided HTML structure."""
width = options.get("width", 500)
height = options.get("height", 375)
# First image with a <figure> and <figcaption>
first_image_html = f'''
<figure class="relative my-0 slider-bg">
<img src="{images[0]}" width="{width}" height="{height}">
<figcaption class="absolute inset-0 flex flex-col justify-end p-6">
<h1 class="my-0">Fylgja CSS Slider</h1>
</figcaption>
</figure>
'''
## Todo: https://codepen.io/dp_lewis/pen/WNZQzN
# Remaining images as plain <img> tags
other_images_html = "".join([
f'<img src="{img}" width="{width}" height="{height}">' for img in images[1:]
])
# Final combined HTML
return f'''
<main>
<div class="scroll-slider hide-scrollbar">
{first_image_html}
{other_images_html}
</div>
</main>
'''
def create_jinja_environment():
"""Create and configure the Jinja2 environment."""
env = Environment(loader=DictLoader({"base_template": "{{ content | safe }}"}))
env.globals.update({
"img_left_overlay": img_left_overlay,
"box": box,
"note": note,
"warning": warning,
"link_to": link_to,
"slider": slider,
})
return env
def render_markdown_with_jinja(markdown_content: str):
"""
Convert Markdown to HTML and apply Jinja2 rendering for custom tags.
Args:
markdown_content (str): Raw Markdown content.
Returns:
tuple: Rendered HTML content and metadata as a dictionary.
"""
# Step 1: Convert Markdown to HTML and extract metadata
md = markdown.Markdown(extensions=["extra", "nl2br", "meta"])
intermediate_html = md.convert(markdown_content)
metadata = {key: " ".join(value) for key, value in md.Meta.items()} if md.Meta else {}
# Step 2: Pass the resulting HTML with Jinja2 custom tags through Jinja2
env = create_jinja_environment()
template = env.get_template("base_template")
final_html = template.render(content=intermediate_html)
# Step 3: Re-render final_html in Jinja2 for embedded tags like {{ box(...) }}
final_output = env.from_string(final_html).render()
return final_output, metadata