From 48740ea8cbc8429c407020a699f3422156a268dd Mon Sep 17 00:00:00 2001 From: Kevin Wallace Date: Sat, 5 Nov 2022 03:04:21 -0700 Subject: [PATCH] Allow templates to be overridden in data/templates/ I'd like to customize my instance's theme beyond what's possible with _theme.scss. This patch would allow me to do that, and keep my changes self-contained in data/ without maintaining a local patchset over app/templates/. For utils.html, I've also added scoped blocks around the body of every macro. This allows the macros to be overridden individually in data/templates/utils.html, without copying the whole file. For example, to only override the display of a specific actor's name/icon: {% extends "app/utils.html" %} {% block display_actor %} {% if actor.ap_id == "https://me.example.com" %} {% else %} {{ super() }} {% endif %} {% endblock %} --- app/templates.py | 2 +- app/templates/utils.html | 54 ++++++++++++++++++++++++++++++++++++++++ data/templates/app | 1 + docs/user_guide.md | 4 +++ 4 files changed, 60 insertions(+), 1 deletion(-) create mode 120000 data/templates/app diff --git a/app/templates.py b/app/templates.py index 3415904..283ee44 100644 --- a/app/templates.py +++ b/app/templates.py @@ -38,7 +38,7 @@ from app.utils.highlight import HIGHLIGHT_CSS from app.utils.highlight import highlight _templates = Jinja2Templates( - directory="app/templates", + directory=["data/templates", "app/templates"], trim_blocks=True, lstrip_blocks=True, ) diff --git a/app/templates/utils.html b/app/templates/utils.html index f2f1920..18644a1 100644 --- a/app/templates/utils.html +++ b/app/templates/utils.html @@ -1,168 +1,209 @@ {% macro embed_csrf_token() %} +{% block embed_csrf_token scoped %} +{% endblock %} {% endmacro %} {% macro embed_redirect_url(permalink_id=None) %} +{% block embed_redirect_url scoped %} +{% endblock %} {% endmacro %} {% macro admin_block_button(actor) %} +{% block admin_block_button scoped %}
{{ embed_csrf_token() }} {{ embed_redirect_url() }}
+{% endblock %} {% endmacro %} {% macro admin_unblock_button(actor) %} +{% block admin_unblock_button scoped %}
{{ embed_csrf_token() }} {{ embed_redirect_url() }}
+{% endblock %} {% endmacro %} {% macro admin_follow_button(actor) %} +{% block admin_follow_button scoped %}
{{ embed_csrf_token() }} {{ embed_redirect_url() }}
+{% endblock %} {% endmacro %} {% macro admin_accept_incoming_follow_button(notif) %} +{% block admin_accept_incoming_follow_button scoped %}
{{ embed_csrf_token() }} {{ embed_redirect_url() }}
+{% endblock %} {% endmacro %} {% macro admin_reject_incoming_follow_button(notif) %} +{% block admin_reject_incoming_follow_button scoped %}
{{ embed_csrf_token() }} {{ embed_redirect_url() }}
+{% endblock %} {% endmacro %} {% macro admin_like_button(ap_object_id, permalink_id) %} +{% block admin_like_button scoped %}
{{ embed_csrf_token() }} {{ embed_redirect_url(permalink_id) }}
+{% endblock %} {% endmacro %} {% macro admin_bookmark_button(ap_object_id, permalink_id) %} +{% block admin_bookmark_button scoped %}
{{ embed_csrf_token() }} {{ embed_redirect_url(permalink_id) }}
+{% endblock %} {% endmacro %} {% macro admin_unbookmark_button(ap_object_id, permalink_id) %} +{% block admin_unbookmark_button scoped %}
{{ embed_csrf_token() }} {{ embed_redirect_url(permalink_id) }}
+{% endblock %} {% endmacro %} {% macro admin_pin_button(ap_object_id, permalink_id) %} +{% block admin_pin_button scoped %}
{{ embed_csrf_token() }} {{ embed_redirect_url(permalink_id) }}
+{% endblock %} {% endmacro %} {% macro admin_unpin_button(ap_object_id, permalink_id) %} +{% block admin_unpin_button scoped %}
{{ embed_csrf_token() }} {{ embed_redirect_url(permalink_id) }}
+{% endblock %} {% endmacro %} {% macro admin_delete_button(ap_object) %} +{% block admin_delete_button scoped %}
{{ embed_csrf_token() }}
+{% endblock %} {% endmacro %} {% macro admin_announce_button(ap_object_id, permalink_id=None) %} +{% block admin_announce_button scoped %}
{{ embed_csrf_token() }} {{ embed_redirect_url(permalink_id) }}
+{% endblock %} {% endmacro %} {% macro admin_undo_button(ap_object_id, action="undo", permalink_id=None) %} +{% block admin_undo_button scoped %}
{{ embed_csrf_token() }} {{ embed_redirect_url(permalink_id) }}
+{% endblock %} {% endmacro %} {% macro admin_reply_button(ap_object_id) %} +{% block admin_reply_button scoped %}
+{% endblock %} {% endmacro %} {% macro admin_dm_button(actor_handle) %} +{% block admin_dm_button scoped %}
+{% endblock %} {% endmacro %} {% macro admin_mention_button(actor_handle) %} +{% block admin_mention_button scoped %}
+{% endblock %} {% endmacro %} {% macro admin_profile_button(ap_actor_id) %} +{% block admin_profile_button scoped %}
+{% endblock %} {% endmacro %} {% macro admin_expand_button(ap_object) %} +{% block admin_expand_button scoped %} {# TODO turn these into a regular link and append permalink ID if it's a reply #}
+{% endblock %} {% endmacro %} {% macro display_box_filters(route) %} +{% block display_box_filters scoped %} +{% endblock %} {% endmacro %} {% macro display_tiny_actor_icon(actor) %} +{% block display_tiny_actor_icon scoped %} {{ actor.display_name }}'s avatar +{% endblock %} {% endmacro %} {% macro actor_action(inbox_object, text, with_icon=False) %} +{% block actor_action scoped %}
{% if with_icon %}{{ display_tiny_actor_icon(inbox_object.actor) }}{% endif %} {{ inbox_object.actor.display_name | clean_html(inbox_object.actor) | safe }} @@ -193,9 +238,11 @@ {{ inbox_object.ap_published_at | timeago }}
+{% endblock %} {% endmacro %} {% macro display_actor(actor, actors_metadata={}, embedded=False, with_details=False, pending_incoming_follow_notif=None) %} +{% block display_actor scoped %} {% set metadata = actors_metadata.get(actor.ap_id) %} {% if not embedded %} @@ -306,9 +353,11 @@ {% endif %} +{% endblock %} {% endmacro %} {% macro display_og_meta(object) %} +{% block display_og_meta scoped %} {% if object.og_meta %} {% for og_meta in object.og_meta[:1] %}
@@ -326,10 +375,12 @@
{% endfor %} {% endif %} +{% endblock %} {% endmacro %} {% macro display_attachments(object) %} +{% block display_attachments scoped %} {% for attachment in object.attachments %} {% if object.sensitive and (attachment.type == "Image" or (attachment | has_media_type("image")) or attachment.type == "Video" or (attachment | has_media_type("video"))) %} @@ -368,9 +419,11 @@ {% endif %} {% endfor %} +{% endblock %} {% endmacro %} {% macro display_object(object, likes=[], shares=[], webmentions=[], expanded=False, actors_metadata={}, is_object_page=False) %} +{% block display_object scoped %} {% set is_article_mode = object.is_from_outbox and object.ap_type == "Article" and is_object_page %} {% if object.ap_type in ["Note", "Article", "Video", "Page", "Question"] %}
@@ -663,4 +716,5 @@
{% endif %} +{% endblock %} {% endmacro %} diff --git a/data/templates/app b/data/templates/app new file mode 120000 index 0000000..6a6e8a4 --- /dev/null +++ b/data/templates/app @@ -0,0 +1 @@ +../../app/templates/ \ No newline at end of file diff --git a/docs/user_guide.md b/docs/user_guide.md index e2f1eb6..578bf08 100644 --- a/docs/user_guide.md +++ b/docs/user_guide.md @@ -127,6 +127,10 @@ $secondary-color: #32cd32; See `app/scss/main.scss` to see what variables can be overridden. +#### Custom templates + +If you'd like to customize your instance's theme beyond CSS, you can modify the app's HTML by placing templates in `data/templates` which overwrite the defaults in `app/templates`. + #### Code highlighting theme You can switch to one of the [styles supported by Pygments](https://pygments.org/styles/) by adding a line in `profile.toml`: