From 1fe1d13c600b7dfe421b3b99b833b7d5d1232724 Mon Sep 17 00:00:00 2001 From: Dennis Fink Date: Thu, 23 Jul 2026 00:18:21 +0200 Subject: Add GPX trail maps to blog posts This adds a trail flow block so posts can include attached GPX files as interactive maps with route display, elevation charts, activity summaries, and start/finish markers. The trail assets are loaded only when needed, keeping the shared templates clean while vendoring the Leaflet dependencies required for offline, self-hosted map rendering. --- templates/.djlintrc | 26 +++++++++------- templates/base.html | 31 +++++++++++++++++- templates/blocks/markdown.html | 1 + templates/blocks/trail.html | 71 ++++++++++++++++++++++++++++++++++++++++++ templates/blog-post.html | 10 ++++++ templates/blog.html | 12 +++++++ templates/macros/blog.html | 13 ++++++-- 7 files changed, 149 insertions(+), 15 deletions(-) create mode 100644 templates/blocks/markdown.html create mode 100644 templates/blocks/trail.html (limited to 'templates') diff --git a/templates/.djlintrc b/templates/.djlintrc index 5882faa..75269c1 100644 --- a/templates/.djlintrc +++ b/templates/.djlintrc @@ -1,14 +1,16 @@ { -"blank_line_before_tag": "macro", -"blank_line_after_tag": "endmacro,extends,import,from", -"profile": "jinja", -"format_css": true, -"css": { -"indent_size": 2 -}, -"format_js": true, -"js": { -"indent_size": 2 -}, -"indent": "2" + "blank_line_before_tag": "macro", + "blank_line_after_tag": "endmacro,extends,import,from", + "profile": "jinja", + "format_css": true, + "css": { + "indent_size": 2 + }, + "format_js": true, + "js": { + "indent_size": 2 + }, + "indent": "2", + "max_blank_lines": 0, + "preserve_blank_lines": true } diff --git a/templates/base.html b/templates/base.html index 024907d..99341e7 100644 --- a/templates/base.html +++ b/templates/base.html @@ -75,6 +75,19 @@ type="text/css" href="{{ '/static/css/style.css' | asseturl }}"> {% endblock styles %} + + {% block feature_styles %} + {% if needs_trail_assets | default(false) %} + + + + + {% endif %} + {% endblock feature_styles %} + {% block meta_links %} {% endblock body %} + {% block scripts %} + {% if needs_trail_assets | default(false) %} + + + + + + + + {% endif %} + {% endblock scripts %} + diff --git a/templates/blocks/markdown.html b/templates/blocks/markdown.html new file mode 100644 index 0000000..8ee0a42 --- /dev/null +++ b/templates/blocks/markdown.html @@ -0,0 +1 @@ +{{ this.text }} diff --git a/templates/blocks/trail.html b/templates/blocks/trail.html new file mode 100644 index 0000000..b32b7c1 --- /dev/null +++ b/templates/blocks/trail.html @@ -0,0 +1,71 @@ +{% set trail_gpx = record.attachments.get(this.trail_gpx) if this.trail_gpx else none %} +{% set activity_gpx = record.attachments.get(this.activity_gpx) if this.activity_gpx else none %} +{% if trail_gpx %} + {% set trail_gpx_url = trail_gpx | url(absolute=True, external=False) %} +{% endif %} +{% if activity_gpx %} + {% set activity_gpx_url = activity_gpx | url(absolute=True, external=False) %} +{% endif %} +{% if trail_gpx or activity_gpx %} +
+
Interactive map of the trail
+
+
+ Trail details +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Distance:Time:Overall pace:
Maximum elevation:Minimum elevation:Average elevation:
Ascent:Descent:
Average speed:Maximum speed:
+
+

+ Download the GPX track +

+ +
+
+ + + +
+{% else %} +
+
Interactive map of the trail
+

The interactive trail map could not be loaded.

+
+{% endif %} diff --git a/templates/blog-post.html b/templates/blog-post.html index f5e8bbe..1cb33db 100644 --- a/templates/blog-post.html +++ b/templates/blog-post.html @@ -2,6 +2,16 @@ {% from "macros/blog.html" import render_blog_post %} +{% set features = namespace(trail=false) %} + +{% for block in this.body.blocks %} + {% if block._flowblock == "trail" %} + {% set features.trail = true %} + {% endif %} +{% endfor %} + +{% set needs_trail_assets = features.trail %} + {% block meta %} {{ super() }} diff --git a/templates/blog.html b/templates/blog.html index 4c011a1..3e187cb 100644 --- a/templates/blog.html +++ b/templates/blog.html @@ -2,6 +2,18 @@ {% from "macros/blog.html" import render_blog_index %} +{% set features = namespace(trail=false) %} + +{% for post in this.pagination.items %} + {% for block in post.body.blocks %} + {% if block._flowblock == "trail" %} + {% set features.trail = true %} + {% endif %} + {% endfor %} +{% endfor %} + +{% set needs_trail_assets = features.trail %} + {% block meta %} {{ super() }} diff --git a/templates/macros/blog.html b/templates/macros/blog.html index 7f2ca60..13c2526 100644 --- a/templates/macros/blog.html +++ b/templates/macros/blog.html @@ -19,6 +19,16 @@ {% endmacro %} {% macro render_blog_post(post, show_toc=True) %} + {% set toc = namespace(items=[]) %} + + {% if show_toc and post.render_toc %} + {% for block in post.body.blocks %} + {% if block._flowblock == "markdown" and block.text %} + {% set toc.items = toc.items + (block.text.toc | default([])) %} + {% endif %} + {% endfor %} + {% endif %} +
@@ -68,8 +78,7 @@
{% if show_toc and post.render_toc %} - {% set toc = post.body.toc|default([]) %} - {{ render_toc(toc) }} + {{ render_toc(toc.items) }} {% endif %}
{{ post.body }}
-- cgit v1.3.1