use mdbook_preprocessor::PreprocessorContext;
use mdbook_preprocessor::errors::Error;
use serde::Deserialize;
#[derive(Debug, Deserialize, Default)]
pub struct MessageConfig {
pub header: Option<String>,
pub footer: Option<String>,
pub both: Option<String>,
}
#[derive(Debug, Deserialize)]
#[serde(untagged)]
pub enum MarginSetting {
One(String),
Quad(Vec<String>),
Sides {
top: Option<String>,
right: Option<String>,
bottom: Option<String>,
left: Option<String>,
},
}
impl Default for MarginSetting {
fn default() -> Self {
MarginSetting::One("0".to_string())
}
}
#[derive(Debug, Deserialize, Default)]
pub struct MarginConfig {
pub header: Option<MarginSetting>,
pub footer: Option<MarginSetting>,
pub both: Option<MarginSetting>,
}
#[derive(Debug, Deserialize)]
#[serde(untagged)]
pub enum AlignSetting {
One(String),
Split {
header: Option<String>,
footer: Option<String>,
both: Option<String>,
},
}
impl Default for AlignSetting {
fn default() -> Self {
AlignSetting::One("center".to_string())
}
}
#[derive(Debug, Deserialize, Clone, Copy)]
#[serde(rename_all = "lowercase")]
pub enum ContributorsSource {
Git,
File,
Inline,
}
impl Default for ContributorsSource {
fn default() -> Self {
ContributorsSource::Git
}
}
#[derive(Debug, Deserialize, Default)]
pub struct GitInfoConfig {
pub enable: Option<bool>,
pub format: Option<String>,
pub template: Option<String>,
pub header: Option<bool>,
pub footer: Option<bool>,
pub message: Option<MessageConfig>,
#[serde(rename = "font-size")]
pub font_size: Option<String>,
pub separator: Option<String>,
#[serde(rename = "date-format")]
pub date_format: Option<String>,
#[serde(rename = "time-format")]
pub time_format: Option<String>,
pub timezone: Option<String>, pub datetime_format: Option<String>, pub show_offset: Option<bool>,
pub branch: Option<String>,
pub align: Option<AlignSetting>,
pub margin: Option<MarginConfig>,
pub tag: Option<String>,
pub hyperlink: Option<bool>,
pub contributors: Option<bool>,
#[serde(rename = "contributors-title")]
pub contributors_title: Option<String>,
#[serde(rename = "contributors-message")]
pub contributors_message: Option<String>,
#[serde(rename = "contributors-source")]
pub contributors_source: Option<ContributorsSource>,
#[serde(rename = "contributors-file")]
pub contributors_file: Option<String>,
#[serde(rename = "contributors-exclude")]
pub contributors_exclude: Option<Vec<String>>,
#[serde(rename = "contributors-max-visible")]
pub contributors_max_visible: Option<usize>,
}
pub fn load_config(ctx: &PreprocessorContext) -> Result<GitInfoConfig, Error> {
ctx.config
.get::<GitInfoConfig>("preprocessor.gitinfo")?
.ok_or_else(|| Error::msg("Missing or invalid [preprocessor.gitinfo] config"))
}
#[cfg(test)]
mod tests {
use super::*;
use mdbook_preprocessor::{PreprocessorContext, config::Config};
use std::path::PathBuf;
fn ctx(toml_str: &str) -> PreprocessorContext {
let parsed: toml::Value = toml::from_str(toml_str).unwrap();
let mut config = Config::default();
config.set("preprocessor.gitinfo", parsed).unwrap();
PreprocessorContext::new(PathBuf::from("."), config, "html".to_string())
}
#[test]
fn parses_legacy_align() {
let c = load_config(&ctx(r#"align = "left""#)).unwrap();
match c.align.unwrap() {
AlignSetting::One(s) => assert_eq!(s, "left"),
_ => panic!("expected One"),
}
}
#[test]
fn parses_split_align() {
let c = load_config(&ctx(r#"
[align]
both = "center"
header = "left"
"#))
.unwrap();
match c.align.unwrap() {
AlignSetting::Split {
header,
footer,
both,
} => {
assert_eq!(header.as_deref(), Some("left"));
assert_eq!(footer, None);
assert_eq!(both.as_deref(), Some("center"));
}
_ => panic!("expected Split"),
}
}
#[test]
fn message_resolution_parses() {
let c = load_config(&ctx(r#"
[message]
both = "D: {{date}}"
header = "H: {{date}}"
"#))
.unwrap();
assert_eq!(c.message.unwrap().header.unwrap(), "H: {{date}}");
}
}