use hayagriva::archive::ArchivedStyle;
use hayagriva::citationberg::{
CitationFormat as CslCitationFormat, IndependentStyle, StyleCategory,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum CitationContentType {
#[default]
Numeric,
Label,
AuthorDate,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum CitationRendering {
#[default]
Bracketed,
Superscript,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct CitationFormat {
pub content: CitationContentType,
pub rendering: CitationRendering,
}
pub trait CitationStyle {
fn citation_format(&self) -> CitationFormat;
}
#[derive(Debug, Clone, Copy)]
pub struct StyleInfo {
pub aliases: &'static [&'static str],
pub archived: ArchivedStyle,
pub format: CitationFormat,
}
impl CitationStyle for StyleInfo {
fn citation_format(&self) -> CitationFormat {
self.format
}
}
static STYLE_REGISTRY: &[StyleInfo] = &[
StyleInfo {
aliases: &["ieee"],
archived: ArchivedStyle::InstituteOfElectricalAndElectronicsEngineers,
format: CitationFormat {
content: CitationContentType::Numeric,
rendering: CitationRendering::Bracketed,
},
},
StyleInfo {
aliases: &["vancouver"],
archived: ArchivedStyle::Vancouver,
format: CitationFormat {
content: CitationContentType::Numeric,
rendering: CitationRendering::Bracketed,
},
},
StyleInfo {
aliases: &["acm", "association-for-computing-machinery"],
archived: ArchivedStyle::AssociationForComputingMachinery,
format: CitationFormat {
content: CitationContentType::Numeric,
rendering: CitationRendering::Bracketed,
},
},
StyleInfo {
aliases: &["acs", "american-chemical-society"],
archived: ArchivedStyle::AmericanChemicalSociety,
format: CitationFormat {
content: CitationContentType::Numeric,
rendering: CitationRendering::Bracketed,
},
},
StyleInfo {
aliases: &["ama", "american-medical-association"],
archived: ArchivedStyle::AmericanMedicalAssociation,
format: CitationFormat {
content: CitationContentType::Numeric,
rendering: CitationRendering::Bracketed,
},
},
StyleInfo {
aliases: &["springer-basic"],
archived: ArchivedStyle::SpringerBasic,
format: CitationFormat {
content: CitationContentType::Numeric,
rendering: CitationRendering::Bracketed,
},
},
StyleInfo {
aliases: &["cell"],
archived: ArchivedStyle::Cell,
format: CitationFormat {
content: CitationContentType::Numeric,
rendering: CitationRendering::Bracketed,
},
},
StyleInfo {
aliases: &["elsevier-vancouver"],
archived: ArchivedStyle::ElsevierVancouver,
format: CitationFormat {
content: CitationContentType::Numeric,
rendering: CitationRendering::Bracketed,
},
},
StyleInfo {
aliases: &["nature"],
archived: ArchivedStyle::Nature,
format: CitationFormat {
content: CitationContentType::Numeric,
rendering: CitationRendering::Superscript,
},
},
StyleInfo {
aliases: &["vancouver-superscript"],
archived: ArchivedStyle::VancouverSuperscript,
format: CitationFormat {
content: CitationContentType::Numeric,
rendering: CitationRendering::Superscript,
},
},
StyleInfo {
aliases: &["alphanumeric"],
archived: ArchivedStyle::Alphanumeric,
format: CitationFormat {
content: CitationContentType::Label,
rendering: CitationRendering::Bracketed,
},
},
StyleInfo {
aliases: &["apa", "american-psychological-association"],
archived: ArchivedStyle::AmericanPsychologicalAssociation,
format: CitationFormat {
content: CitationContentType::AuthorDate,
rendering: CitationRendering::Bracketed,
},
},
StyleInfo {
aliases: &["chicago-author-date"],
archived: ArchivedStyle::ChicagoAuthorDate,
format: CitationFormat {
content: CitationContentType::AuthorDate,
rendering: CitationRendering::Bracketed,
},
},
StyleInfo {
aliases: &["chicago-notes"],
archived: ArchivedStyle::ChicagoNotes,
format: CitationFormat {
content: CitationContentType::AuthorDate,
rendering: CitationRendering::Bracketed,
},
},
StyleInfo {
aliases: &["mla", "modern-language-association"],
archived: ArchivedStyle::ModernLanguageAssociation,
format: CitationFormat {
content: CitationContentType::AuthorDate,
rendering: CitationRendering::Bracketed,
},
},
StyleInfo {
aliases: &["mla8", "modern-language-association-8"],
archived: ArchivedStyle::ModernLanguageAssociation8,
format: CitationFormat {
content: CitationContentType::AuthorDate,
rendering: CitationRendering::Bracketed,
},
},
StyleInfo {
aliases: &["harvard", "harvard-cite-them-right"],
archived: ArchivedStyle::HarvardCiteThemRight,
format: CitationFormat {
content: CitationContentType::AuthorDate,
rendering: CitationRendering::Bracketed,
},
},
StyleInfo {
aliases: &["springer-basic-author-date"],
archived: ArchivedStyle::SpringerBasicAuthorDate,
format: CitationFormat {
content: CitationContentType::AuthorDate,
rendering: CitationRendering::Bracketed,
},
},
StyleInfo {
aliases: &["elsevier-harvard"],
archived: ArchivedStyle::ElsevierHarvard,
format: CitationFormat {
content: CitationContentType::AuthorDate,
rendering: CitationRendering::Bracketed,
},
},
];
pub fn find_style_info(name: &str) -> Option<&'static StyleInfo> {
let name_lower = name.to_lowercase();
STYLE_REGISTRY
.iter()
.find(|info| info.aliases.iter().any(|&alias| alias == name_lower))
}
pub fn supported_style_aliases() -> impl Iterator<Item = &'static str> {
STYLE_REGISTRY.iter().map(|info| info.aliases[0])
}
#[cfg(test)]
pub fn all_registry_styles() -> impl Iterator<Item = &'static StyleInfo> {
STYLE_REGISTRY.iter()
}
#[cfg(test)]
pub fn registry_style_count() -> usize {
STYLE_REGISTRY.len()
}
#[cfg(test)]
pub fn format_style_list() -> String {
let mut numeric = Vec::new();
let mut superscript = Vec::new();
let mut label = Vec::new();
let mut author_date = Vec::new();
for style in STYLE_REGISTRY {
let name = style.aliases[0];
match (style.format.content, style.format.rendering) {
(CitationContentType::Numeric, CitationRendering::Superscript) => {
superscript.push(name);
}
(CitationContentType::Numeric, CitationRendering::Bracketed) => {
numeric.push(name);
}
(CitationContentType::Label, _) => {
label.push(name);
}
(CitationContentType::AuthorDate, _) => {
author_date.push(name);
}
}
}
format!(
"Numeric styles: {}\n\
Superscript styles: {}\n\
Label styles: {}\n\
Author-date styles: {}",
numeric.join(", "),
superscript.join(", "),
label.join(", "),
author_date.join(", ")
)
}
#[derive(Debug, Clone, Copy)]
pub struct DetectedStyleFormat {
format: CitationFormat,
}
impl CitationStyle for DetectedStyleFormat {
fn citation_format(&self) -> CitationFormat {
self.format
}
}
pub fn detect_style_format(style: &IndependentStyle) -> DetectedStyleFormat {
let csl_format = style.info.category.iter().find_map(|cat| match cat {
StyleCategory::CitationFormat { format } => Some(*format),
StyleCategory::Field { .. } => None,
});
let content = match csl_format {
Some(CslCitationFormat::Numeric) => CitationContentType::Numeric,
Some(CslCitationFormat::Label) => CitationContentType::Label,
_ => CitationContentType::AuthorDate,
};
DetectedStyleFormat {
format: CitationFormat {
content,
rendering: CitationRendering::Bracketed, },
}
}