aboutsummaryrefslogtreecommitdiffstats
path: root/src/theming
diff options
context:
space:
mode:
Diffstat (limited to 'src/theming')
-rw-r--r--src/theming/hbs.rs35
-rw-r--r--src/theming/hbs/plain.hbs39
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>