#[cfg(feature = "schema")]
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(JsonSchema))]
#[serde(rename_all = "kebab-case")]
pub enum TextCase {
Title,
Sentence,
SentenceApa,
SentenceNlm,
CapitalizeFirst,
Lowercase,
Uppercase,
AsIs,
}
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(JsonSchema))]
#[serde(untagged)]
pub enum TitlesConfigEntry {
Preset(crate::presets::TitlePreset),
Explicit(Box<TitlesConfig>),
}
impl Default for TitlesConfigEntry {
fn default() -> Self {
TitlesConfigEntry::Explicit(Box::default())
}
}
impl TitlesConfigEntry {
pub fn resolve(&self) -> TitlesConfig {
match self {
TitlesConfigEntry::Preset(preset) => preset.config(),
TitlesConfigEntry::Explicit(config) => *config.clone(),
}
}
}
#[derive(Debug, Default, PartialEq, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(JsonSchema))]
#[serde(rename_all = "kebab-case")]
pub struct TitlesConfig {
#[serde(default, skip_serializing_if = "HashMap::is_empty")]
pub type_mapping: HashMap<String, String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub component: Option<TitleRendering>,
#[serde(skip_serializing_if = "Option::is_none")]
pub monograph: Option<TitleRendering>,
#[serde(skip_serializing_if = "Option::is_none")]
pub container_monograph: Option<TitleRendering>,
#[serde(skip_serializing_if = "Option::is_none")]
pub periodical: Option<TitleRendering>,
#[serde(skip_serializing_if = "Option::is_none")]
pub serial: Option<TitleRendering>,
#[serde(skip_serializing_if = "Option::is_none")]
pub default: Option<TitleRendering>,
#[serde(skip_serializing_if = "Option::is_none")]
pub custom: Option<HashMap<String, serde_json::Value>>,
#[serde(
flatten,
default,
skip_serializing_if = "std::collections::BTreeMap::is_empty"
)]
#[cfg_attr(feature = "schema", schemars(skip))]
pub unknown_fields: std::collections::BTreeMap<String, serde_yaml::Value>,
}
#[derive(Debug, Default, PartialEq, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(JsonSchema))]
#[serde(rename_all = "kebab-case")]
pub struct TitleRendering {
#[serde(skip_serializing_if = "Option::is_none")]
pub text_case: Option<TextCase>,
#[serde(skip_serializing_if = "Option::is_none")]
pub emph: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub quote: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub strong: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub small_caps: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub prefix: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub suffix: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub locale_overrides: Option<HashMap<String, TitleRendering>>,
#[serde(
flatten,
default,
skip_serializing_if = "std::collections::BTreeMap::is_empty"
)]
#[cfg_attr(feature = "schema", schemars(skip))]
pub unknown_fields: std::collections::BTreeMap<String, serde_yaml::Value>,
}
impl TitleRendering {
pub fn to_rendering(&self) -> crate::template::Rendering {
crate::template::Rendering {
text_case: self.text_case,
emph: self.emph,
quote: self.quote,
strong: self.strong,
small_caps: self.small_caps,
prefix: self.prefix.clone(),
suffix: self.suffix.clone(),
..Default::default()
}
}
pub fn locale_override(&self, language: Option<&str>) -> Option<&TitleRendering> {
let overrides = self.locale_overrides.as_ref()?;
let language = language?;
overrides.get(language).or_else(|| {
language
.split('-')
.next()
.and_then(|tag| overrides.get(tag))
})
}
}