diff options
Diffstat (limited to 'src/theming')
-rw-r--r-- | src/theming/hbs.rs | 35 | ||||
-rw-r--r-- | src/theming/hbs/plain.hbs | 39 |
2 files changed, 74 insertions, 0 deletions
diff --git a/src/theming/hbs.rs b/src/theming/hbs.rs new file mode 100644 index 0000000..73c72ae --- /dev/null +++ b/src/theming/hbs.rs @@ -0,0 +1,35 @@ +use std::sync::LazyLock; + +use handlebars::*; +use reqwest::StatusCode; + +use crate::CONFIG; + +static INTERNAL_THEMES: &[(&str, &str)] = &[("plain", include_str!("hbs/plain.hbs"))]; + +static HANDLEBARS: LazyLock<Handlebars> = LazyLock::new(|| { + let mut hb = Handlebars::new(); + handlebars_helper!(url_encode: |s: String| urlencoding::encode(&s)); + + hb.register_helper("url-encode", Box::new(url_encode)); + + for (key, fulltext) in INTERNAL_THEMES { + log::info!("Registering internal theme `{key}`"); + hb.register_template_string(key, fulltext).unwrap(); + } + hb.set_dev_mode(CONFIG.theme_debug); + + if let Some(themes_dir) = CONFIG.theme_dir.as_ref() { + log::info!("Registering theme dir `{themes_dir}`"); + hb.register_templates_directory(&CONFIG.theme_ext, themes_dir.as_ref()).unwrap(); + } + + hb +}); + +pub fn render_theme(name: &str, ctx: &crate::ctx::Ctx) -> Option<Result<String, StatusCode>> { + let templ = HANDLEBARS.get_template(name)?; + let ctx = Context::wraps(ctx).unwrap(); + let render = templ.renders(&HANDLEBARS, &ctx, &mut RenderContext::new(Some(&name.into()))).map_err(|_| StatusCode::INTERNAL_SERVER_ERROR); + Some(render) +} diff --git a/src/theming/hbs/plain.hbs b/src/theming/hbs/plain.hbs new file mode 100644 index 0000000..975d6c5 --- /dev/null +++ b/src/theming/hbs/plain.hbs @@ -0,0 +1,39 @@ +<!doctype html> +<html lang="en" style="margin: 20px; overflow: hidden;"> + <head> + <meta charset="UTF-8"/> + <title>{{#if error}}Error!{{else}}@{{user.name}}'s Last.fm Stats{{/if}}</title> + <style>{{#if font.css}}{{{font.css}}}{{/if}}</style> + <style> + {{#if (eq query.dark null)}} + :root { --b: black; color: black; background-color: white; } + {{else}} + :root { --b: white; color: white; background-color: black; } + a:visited { color: pink } + a { color: cyan; } + {{/if}} + * { font-size: {{#if font}}17px{{else}}{{#if font.scale}}calc(20px * {{font.scale}}){{else}}20px{{/if}}{{/if}}; } + {{#if (or font.name font.css)}} + * { font-family: '{{#if font.name}}{{font.name}}{{/if}}' } + {{/if}} + p { margin: 0px; padding: 0px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } + </style> + </head> + <body> + {{#if error}} + <p style="white-space: unset;">{{error}}</p> + {{else}} + <a style="float: left;" target="_blank" href="{{scrobble.url}}"><img src="{{scrobble.image_url}}" style="height: 80px; border: solid var(--b) 4px; margin: 2px;" /></a> + <p><a target="_blank" href="{{user.url}}">@{{user.name}}</a>{{#if scrobble.now_playing}} + is scrobbling{{else}}'s last scrobble was + {{/if}} + </p><p> + <i><b><a target="_blank" href="{{scrobble.url}}">{{scrobble.name}}</a></b></i> + </p><p> + {{#if scrobble.album}}from <i><b>{{scrobble.album}}</b></i>{{/if}} + </p><p> + by <b><a target="_blank" href="{{scrobble.artist.url}}">{{scrobble.artist.name}}</a></b>. + </p> + {{/if}} + </body> +</html> |