Skip to content

Commit

Permalink
Add logo config validation
Browse files Browse the repository at this point in the history
This makes sure for every case/situation there is exactly one logo
defined.
  • Loading branch information
LukasKalbertodt committed Dec 19, 2024
1 parent 6fe4f02 commit 3aa3a60
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 18 deletions.
77 changes: 62 additions & 15 deletions backend/src/config/theme.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{fmt, path::PathBuf};
use std::{collections::HashMap, fmt, path::PathBuf};
use serde::{Deserialize, Serialize};

use super::{color::ColorConfig, translated_string::LangKey};
Expand All @@ -20,9 +20,8 @@ pub(crate) struct ThemeConfig {
///
/// ```
/// logos = [
/// { path = "logo-large.svg", resolution = [425, 182] },
/// { path = "logo-large-en.svg", lang = "en", resolution = [425, 182] },
/// { path = "logo-large-dark.svg", mode = "dark", resolution = [425, 182] },
/// { path = "logo-wide-light.svg", mode = "light", size = "wide", resolution = [425, 182] },
/// { path = "logo-wide-dark.svg", mode = "dark", size = "wide", resolution = [425, 182] },
/// { path = "logo-small.svg", size = "narrow", resolution = [212, 182] },
/// ]
/// ```
Expand All @@ -48,7 +47,7 @@ pub(crate) struct LogoDef {
pub(crate) resolution: LogoResolution,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Hash)]
#[serde(rename_all = "lowercase")]
pub(crate) enum LogoSize {
Wide,
Expand All @@ -61,7 +60,7 @@ impl fmt::Display for LogoSize {
}
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Hash)]
#[serde(rename_all = "lowercase")]
pub(crate) enum LogoMode {
Light,
Expand Down Expand Up @@ -149,24 +148,72 @@ impl ThemeConfig {
}

fn validate_logos(logos: &Vec<LogoDef>) -> Result<(), String> {
#[derive()]
enum LangLogo {
Universal(usize),
LangSpecific(HashMap<LangKey, usize>),
}

let all_modes = [LogoMode::Light, LogoMode::Dark];
let all_sizes = [LogoSize::Wide, LogoSize::Narrow];

let mut cases = HashMap::new();
for logo in logos {
let modes = logo.mode.map(|m| [m]).unwrap_or([LogoMode::Light, LogoMode::Dark]);
let sizes = logo.size.map(|s| [s]).unwrap_or([LogoSize::Wide, LogoSize::Narrow]);
for (i, logo) in logos.iter().enumerate() {
let modes = logo.mode.map(|m| vec![m]).unwrap_or(all_modes.to_vec());
let sizes = logo.size.map(|s| vec![s]).unwrap_or(all_sizes.to_vec());

for mode in modes {
for size in sizes {
for &mode in &modes {
for &size in &sizes {
let key = (mode, size);
let prev = cases.insert(key, &logo.path);
if let Some(prev) = prev {

if let Some(entry) = cases.get_mut(&key) {
let conflicting = match (entry, &logo.lang) {
(LangLogo::LangSpecific(m), Some(lang)) => m.insert(lang.clone(), i),
(LangLogo::LangSpecific(m), None) => m.values().next().copied(),
(LangLogo::Universal(c), _) => Some(*c),
};

if let Some(conflicting) = conflicting {
return Err(format!(
"ambiguous logo definition: \
entry {i} (path: '{curr_path}') conflicts with \
entry {prev_index} (path: '{prev_path}'). \
Both define a {mode} {size} logo, which is only allowed \
if both have different 'lang' keys! Consider adding 'mode' \
or 'size' fields to make entries more specific.",
i = i + 1,
prev_index = conflicting + 1,
curr_path = logo.path.display(),
prev_path = logos[conflicting].path.display(),
));
}
} else {
cases.insert(key, match &logo.lang {
Some(lang) => LangLogo::LangSpecific(HashMap::from([(lang.clone(), i)])),
None => LangLogo::Universal(i),
});
}
}
}
}

// Check that all cases are defined
for mode in all_modes {
for size in all_sizes {
match cases.get(&(mode, size)) {
None => return Err(format!(
"incomplete logo configuration: no {mode} {size} logo defined",
)),
Some(LangLogo::LangSpecific(m)) if !m.contains_key(&LangKey::Default) => {
return Err(format!(
"ambiguous logo definition: "
"incomplete logo configuration: {mode} {size} logo is \
missing `lang = '*'` entry",
));
}
_ => {}
}
}
}


Ok(())
}
5 changes: 2 additions & 3 deletions docs/docs/setup/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -540,9 +540,8 @@
#
# ```
# logos = [
# { path = "logo-large.svg", resolution = [425, 182] },
# { path = "logo-large-en.svg", lang = "en", resolution = [425, 182] },
# { path = "logo-large-dark.svg", mode = "dark", resolution = [425, 182] },
# { path = "logo-wide-light.svg", mode = "light", size = "wide", resolution = [425, 182] },
# { path = "logo-wide-dark.svg", mode = "dark", size = "wide", resolution = [425, 182] },
# { path = "logo-small.svg", size = "narrow", resolution = [212, 182] },
# ]
# ```
Expand Down

0 comments on commit 3aa3a60

Please sign in to comment.