diff --git a/timezones/app_settings.py b/timezones/app_settings.py
index 74f6c8f..ef8a3a8 100644
--- a/timezones/app_settings.py
+++ b/timezones/app_settings.py
@@ -13,7 +13,6 @@
# AA Time Zones
from timezones import __title__
-from timezones.helper.static_files import calculate_integrity_hash
logger = LoggerAddTag(my_logger=get_extension_logger(name=__name__), prefix=__title__)
@@ -26,30 +25,3 @@ def allianceauth_discordbot_active():
"""
return apps.is_installed("aadiscordbot")
-
-
-class IntegrityHash:
- """
- Integrity hashes for static files
- """
-
- logger.debug("Calculating integrity hashes for static files")
-
- # CSS
- CSS = {"timezones.min.css": calculate_integrity_hash("css/timezones.min.css")}
-
- # JavaScript
- JS = {"timezones.min.js": calculate_integrity_hash("js/timezones.min.js")}
-
- # External Libraries
- EXTERNAL_LIBS = {
- "jquery.timeago.min.js": calculate_integrity_hash(
- "libs/jquery-timeago/1.6.7/jquery.timeago.min.js"
- ),
- "moment-timezone-with-data-1970-2030.min.js": calculate_integrity_hash(
- "libs/moment-timezone/0.5.36/moment-timezone-with-data-1970-2030.min.js"
- ),
- "weather-icons.min.css": calculate_integrity_hash(
- "libs/weather-icons/2.0.10/css/weather-icons.min.css"
- ),
- }
diff --git a/timezones/helper/static_files.py b/timezones/helper/static_files.py
index da3f6d7..9388885 100644
--- a/timezones/helper/static_files.py
+++ b/timezones/helper/static_files.py
@@ -3,9 +3,11 @@
"""
# Standard Library
-import base64
-import hashlib
import os
+from pathlib import Path
+
+# Third Party
+from sri import Algorithm, calculate_integrity
# Alliance Auth
from allianceauth.services.hooks import get_extension_logger
@@ -24,6 +26,8 @@ def calculate_integrity_hash(relative_file_path: str) -> str:
"""
Calculates the integrity hash for a given static file
+ :param self:
+ :type self:
:param relative_file_path: The file path relative to the `aa-timezones/timezones/static/timezones` folder
:type relative_file_path: str
:return: The integrity hash
@@ -31,14 +35,6 @@ def calculate_integrity_hash(relative_file_path: str) -> str:
"""
file_path = os.path.join(AA_TIMEZONES_STATIC_DIR, relative_file_path)
-
- logger.debug(f"Calculating integrity hash for file: {file_path}")
-
- with open(file=file_path, encoding="utf-8") as static_file:
- file_hash = hashlib.sha512()
-
- content = static_file.read()
- file_hash.update(content.encode("utf-8"))
- integrity_hash = f"sha512-{base64.b64encode(file_hash.digest()).decode()}"
+ integrity_hash = calculate_integrity(Path(file_path), Algorithm.SHA512)
return integrity_hash
diff --git a/timezones/templates/timezones/bundles/aa-timezones-css.html b/timezones/templates/timezones/bundles/aa-timezones-css.html
index b013d3e..24f8272 100644
--- a/timezones/templates/timezones/bundles/aa-timezones-css.html
+++ b/timezones/templates/timezones/bundles/aa-timezones-css.html
@@ -1,8 +1,3 @@
{% load timezones %}
-
+{% timezones_static 'css/timezones.min.css' %}
diff --git a/timezones/templates/timezones/bundles/aa-timezones-js.html b/timezones/templates/timezones/bundles/aa-timezones-js.html
index c50e06d..3ab5ef4 100644
--- a/timezones/templates/timezones/bundles/aa-timezones-js.html
+++ b/timezones/templates/timezones/bundles/aa-timezones-js.html
@@ -1,7 +1,3 @@
{% load timezones %}
-
+{% timezones_static 'js/timezones.min.js' %}
diff --git a/timezones/templates/timezones/bundles/jquery-timeago-js.html b/timezones/templates/timezones/bundles/jquery-timeago-js.html
index 3432a52..f734fcb 100644
--- a/timezones/templates/timezones/bundles/jquery-timeago-js.html
+++ b/timezones/templates/timezones/bundles/jquery-timeago-js.html
@@ -1,8 +1,3 @@
-{% load static %}
{% load timezones %}
-
+{% timezones_static 'libs/jquery-timeago/1.6.7/jquery.timeago.min.js' %}
diff --git a/timezones/templates/timezones/bundles/moment-timezone-js.html b/timezones/templates/timezones/bundles/moment-timezone-js.html
index 20fbb4f..04e0f4c 100644
--- a/timezones/templates/timezones/bundles/moment-timezone-js.html
+++ b/timezones/templates/timezones/bundles/moment-timezone-js.html
@@ -1,8 +1,3 @@
-{% load static %}
{% load timezones %}
-
+{% timezones_static 'libs/moment-timezone/0.5.36/moment-timezone-with-data-1970-2030.min.js' %}
diff --git a/timezones/templates/timezones/bundles/weather-icons-css.html b/timezones/templates/timezones/bundles/weather-icons-css.html
index 65f68cf..ba12353 100644
--- a/timezones/templates/timezones/bundles/weather-icons-css.html
+++ b/timezones/templates/timezones/bundles/weather-icons-css.html
@@ -1,9 +1,3 @@
-{% load static %}
{% load timezones %}
-
+{% timezones_static 'libs/weather-icons/2.0.10/css/weather-icons.min.css' %}
diff --git a/timezones/templatetags/timezones.py b/timezones/templatetags/timezones.py
index 69b8f40..b4e9b90 100644
--- a/timezones/templatetags/timezones.py
+++ b/timezones/templatetags/timezones.py
@@ -2,54 +2,73 @@
Versioned static URLs to break browser caches when changing the app version
"""
+# Standard Library
+import os
+
# Django
from django.template.defaulttags import register
from django.templatetags.static import static
+from django.utils.safestring import mark_safe
+
+# Alliance Auth
+from allianceauth.services.hooks import get_extension_logger
+
+# Alliance Auth (External Libs)
+from app_utils.logging import LoggerAddTag
# AA Time Zones
-from timezones import __version__
-from timezones.app_settings import IntegrityHash
+from timezones import __title__, __version__
+from timezones.helper.static_files import calculate_integrity_hash
+
+logger = LoggerAddTag(my_logger=get_extension_logger(__name__), prefix=__title__)
@register.simple_tag
-def timezones_static(path: str) -> str:
+def timezones_static(relative_file_path: str) -> str | None:
"""
Versioned static URL
- :param path: Path to the static file relative to the static folder
- :type path: str
+ :param relative_file_path: The file path relative to the `aa-timezones/timezones/static/timezones` folder
+ :type relative_file_path: str
:return: Versioned static URL
:rtype: str
"""
- static_url = static(path)
- versioned_url = static_url + "?v=" + __version__
+ logger.debug(f"Getting versioned static URL for: {relative_file_path}")
- return versioned_url
+ file_type = os.path.splitext(relative_file_path)[1][1:]
+ logger.debug(f"File extension: {file_type}")
-@register.simple_tag
-def timezones_static_integrity_hash(
- static_file_type: str, relative_file_path: str
-) -> str:
- """
- Returns the integrity hash for a file
+ # Only support CSS and JS files
+ if file_type not in ["css", "js"]:
+ raise ValueError(f"Unsupported file type: {file_type}")
- :param static_file_type: The type of static file
- :type static_file_type: str
- :param relative_file_path: The file path relative to the `aa-timezones/timezones/static/timezones` folder
- :type relative_file_path: str
- :return: Integrity hash
- :rtype: str
- """
+ integrity_hash = calculate_integrity_hash(relative_file_path)
+ static_file_path = os.path.join("timezones", relative_file_path)
+ static_url = static(static_file_path)
+
+ # Versioned URL for CSS and JS files
+ # Add version query parameter to break browser caches when changing the app version
+ # Do not add version query parameter for libs as they are already versioned through their file path
+ versioned_url = (
+ static_url
+ if relative_file_path.startswith("libs/")
+ else static_url + "?v=" + __version__
+ )
- if static_file_type == "css":
- return IntegrityHash.CSS.get(relative_file_path)
+ # Return the versioned URL with integrity hash for CSS
+ if file_type == "css":
+ logger.debug(f"Integrity hash for {relative_file_path}: {integrity_hash}")
- if static_file_type == "js":
- return IntegrityHash.JS.get(relative_file_path)
+ return mark_safe(
+ f''
+ )
- if static_file_type == "lib":
- return IntegrityHash.EXTERNAL_LIBS.get(relative_file_path)
+ # Return the versioned URL with integrity hash for JS files
+ if file_type == "js":
+ return mark_safe(
+ f''
+ )
- raise ValueError(f"Unsupported static file type: {static_file_type}")
+ return None
diff --git a/timezones/tests/test_templatetags.py b/timezones/tests/test_templatetags.py
index 7629b24..9a2deef 100644
--- a/timezones/tests/test_templatetags.py
+++ b/timezones/tests/test_templatetags.py
@@ -25,13 +25,12 @@ def test_versioned_static(self):
context = Context({"version": __version__})
template_to_render = Template(
- "{% load timezones %}"
- "{% timezones_static 'timezones/css/timezones.min.css' %}"
+ "{% load timezones %}" "{% timezones_static 'css/timezones.min.css' %}"
)
rendered_template = template_to_render.render(context)
- self.assertInHTML(
- needle=f'/static/timezones/css/timezones.min.css?v={context["version"]}',
- haystack=rendered_template,
+ self.assertIn(
+ member=f'/static/timezones/css/timezones.min.css?v={context["version"]}',
+ container=rendered_template,
)