use super::super::Renderer;
use crate::render::ProcTemplateComponent;
use crate::render::bibliography::{append_rendered_component, component_starts_new_sentence};
use crate::render::component::render_component_with_format;
use crate::values::RenderContext;
use citum_schema::NoteStartTextCase;
use citum_schema::locale::GeneralTerm;
use citum_schema::options::titles::TextCase;
use citum_schema::template::TemplateComponent;
impl Renderer<'_> {
pub(super) fn apply_sentence_initial_context<F>(
&self,
components: &mut [ProcTemplateComponent],
context: RenderContext,
note_start_text_case: Option<NoteStartTextCase>,
) where
F: crate::render::format::OutputFormat<Output = String>,
{
match context {
RenderContext::Bibliography => {
self.apply_bibliography_sentence_initial_context::<F>(components);
}
RenderContext::Citation => {
self.apply_note_start_sentence_initial_context(components, note_start_text_case);
}
}
}
fn apply_bibliography_sentence_initial_context<F>(
&self,
components: &mut [ProcTemplateComponent],
) where
F: crate::render::format::OutputFormat<Output = String>,
{
let punctuation_in_quote = components
.first()
.and_then(|component| component.config.as_ref())
.is_some_and(|config| config.punctuation_in_quote);
let default_separator = components
.first()
.and_then(|component| component.bibliography_config.as_ref())
.and_then(|bib| bib.separator.as_deref())
.unwrap_or(". ")
.to_string();
let mut entry_output = String::new();
for component in components.iter_mut() {
let rendered = render_component_with_format::<F>(component);
if rendered.is_empty() {
continue;
}
if component_starts_new_sentence(
&entry_output,
&rendered,
&default_separator,
punctuation_in_quote,
) {
component.sentence_initial = true;
self.apply_sentence_initial_transform(component, None);
}
let rendered = render_component_with_format::<F>(component);
append_rendered_component(
&mut entry_output,
&rendered,
&default_separator,
punctuation_in_quote,
);
}
}
fn apply_note_start_sentence_initial_context(
&self,
components: &mut [ProcTemplateComponent],
note_start_text_case: Option<NoteStartTextCase>,
) {
let Some(text_case) = note_start_text_case else {
return;
};
for component in components.iter_mut() {
if !self.is_note_start_term_component(component) {
continue;
}
component.sentence_initial = true;
self.apply_sentence_initial_transform(component, Some(text_case));
break;
}
}
fn apply_sentence_initial_transform(
&self,
component: &mut ProcTemplateComponent,
note_start_text_case: Option<NoteStartTextCase>,
) {
if !component.sentence_initial {
return;
}
let locale = Some(self.locale.locale.as_str());
match &component.template_component {
TemplateComponent::Contributor(_) => {
let case =
crate::values::text_case::resolve_text_case(TextCase::CapitalizeFirst, locale);
if let Some(prefix) = component.prefix.as_mut() {
*prefix = crate::values::text_case::apply_text_case(prefix, case);
} else {
component.value = if component.pre_formatted {
crate::values::text_case::apply_text_case_markup_aware(
&component.value,
case,
)
} else {
crate::values::text_case::apply_text_case(&component.value, case)
};
}
}
TemplateComponent::Group(_) => {
let case =
crate::values::text_case::resolve_text_case(TextCase::CapitalizeFirst, locale);
component.value =
crate::values::text_case::apply_text_case_markup_aware(&component.value, case);
}
TemplateComponent::Term(_) if self.is_note_start_term_component(component) => {
if let Some(case) = note_start_text_case {
component.value = crate::values::text_case::apply_note_start_text_case(
&component.value,
case,
locale,
);
}
}
_ => {}
}
}
fn is_note_start_term_component(&self, component: &ProcTemplateComponent) -> bool {
matches!(
&component.template_component,
TemplateComponent::Term(term) if term.term == GeneralTerm::Ibid
)
}
}