tools (common/template): expose theme settings to the template:
- `css`: additional sheets rendered after the regular css files (can be used for a dark theme) - `html_data_theme`: copied to the <html> data-theme attribute - `themes_items`: theme selector entries (theme, label, icon) - fix missing parenthesis in `is_file`
This commit is contained in:
parent
da20bba2ab
commit
099b107c29
1 changed files with 63 additions and 2 deletions
|
|
@ -26,7 +26,7 @@ import os.path
|
|||
from pathlib import Path
|
||||
import re
|
||||
import time
|
||||
from typing import List, Optional, Tuple, Union
|
||||
from typing import List, NotRequired, Optional, Tuple, TypedDict, Union
|
||||
from xml.sax.saxutils import quoteattr
|
||||
|
||||
from babel import support
|
||||
|
|
@ -374,6 +374,12 @@ class Environment(jinja2.Environment):
|
|||
return super(Environment, self).get_template(name, parent, globals)
|
||||
|
||||
|
||||
class ThemeItem(TypedDict):
|
||||
theme: str
|
||||
label: str
|
||||
icon: NotRequired[str]
|
||||
|
||||
|
||||
class Renderer:
|
||||
|
||||
def __init__(self, host, front_url_filter=None, trusted=False, private=False):
|
||||
|
|
@ -440,7 +446,7 @@ class Renderer:
|
|||
"settings": {},
|
||||
}
|
||||
theme_settings = p / "settings.json"
|
||||
if theme_settings.is_file:
|
||||
if theme_settings.is_file():
|
||||
try:
|
||||
with theme_settings.open() as f:
|
||||
settings = json.load(f)
|
||||
|
|
@ -656,6 +662,26 @@ class Renderer:
|
|||
except KeyError:
|
||||
raise exceptions.NotFound(f"no theme found for {site_name}")
|
||||
|
||||
def _get_themes_items(self, site: str) -> list[ThemeItem] | None:
|
||||
"""Build the theme selector items from the site themes.
|
||||
|
||||
Get items for every theme with a "label" in its settings.
|
||||
@param site: site name ("" for the default site)
|
||||
@return: the items, sorted by label, None if empty
|
||||
"""
|
||||
themes = self.sites_themes.get(site, {})
|
||||
items: list[ThemeItem] = []
|
||||
for name, data in themes.items():
|
||||
settings = data["settings"]
|
||||
if "label" not in settings:
|
||||
continue
|
||||
item = ThemeItem(theme=name, label=settings["label"])
|
||||
if "icon" in settings:
|
||||
item["icon"] = settings["icon"]
|
||||
items.append(item)
|
||||
items.sort(key=lambda item: item["label"])
|
||||
return items or None
|
||||
|
||||
def get_static_path(
|
||||
self, template_data: TemplateData, filename: str, settings: Optional[dict] = None
|
||||
) -> Optional[TemplateData]:
|
||||
|
|
@ -1180,6 +1206,38 @@ class Renderer:
|
|||
if css_contents:
|
||||
kwargs["css_content" + suffix] = "\n".join(css_contents)
|
||||
|
||||
# extra css sheets from theme settings are rendered after the regular css files in
|
||||
# base.html so they can override them
|
||||
css_links = []
|
||||
html_data_theme = None
|
||||
themes_items = None
|
||||
# template_data.site is None for absolute template paths
|
||||
if template_data.site is not None:
|
||||
theme_settings = self.sites_themes[template_data.site][template_data.theme][
|
||||
"settings"
|
||||
]
|
||||
html_data_theme = theme_settings.get("html_data_theme")
|
||||
themes_items = self._get_themes_items(template_data.site)
|
||||
for entry in theme_settings.get("css", []):
|
||||
css_path = self.get_static_path(
|
||||
template_data, entry["file"], theme_settings
|
||||
)
|
||||
if css_path is None:
|
||||
log.warning(
|
||||
_("theme css file {file!r} not found, skipping").format(
|
||||
file=entry["file"]
|
||||
)
|
||||
)
|
||||
continue
|
||||
link = {
|
||||
"rel": "stylesheet",
|
||||
"type": "text/css",
|
||||
"href": self.get_front_url(css_path),
|
||||
}
|
||||
if entry.get("media"):
|
||||
link["media"] = entry["media"]
|
||||
css_links.append(link)
|
||||
|
||||
scripts_handler = ScriptsHandler(self, template_data)
|
||||
self.set_locale(locale)
|
||||
|
||||
|
|
@ -1190,6 +1248,9 @@ class Renderer:
|
|||
media_path=media_path,
|
||||
css_files=css_files,
|
||||
css_files_noscript=css_files_noscript,
|
||||
css_links=css_links,
|
||||
html_data_theme=html_data_theme,
|
||||
themes_items=themes_items,
|
||||
locale=self._locale,
|
||||
locales=self.locales,
|
||||
gidx=Indexer(),
|
||||
|
|
|
|||
Loading…
Reference in a new issue