citum_engine/values/
list.rs1use crate::reference::Reference;
12use crate::values::{ComponentValues, ProcHints, ProcValues, RenderOptions};
13use citum_schema::template::{DelimiterPunctuation, TemplateGroup};
14
15impl ComponentValues for TemplateGroup {
16 fn values<F: crate::render::format::OutputFormat<Output = String>>(
18 &self,
19 reference: &Reference,
20 hints: &ProcHints,
21 options: &RenderOptions<'_>,
22 ) -> Option<ProcValues<F::Output>> {
23 let mut has_content = false;
24 let fmt = F::default();
25
26 let mut values = Vec::with_capacity(self.group.len());
28 for item in &self.group {
29 let Some(v) = item.values::<F>(reference, hints, options) else {
30 continue;
31 };
32 if v.value.is_empty() {
33 continue;
34 }
35
36 if !is_term_based(item) {
38 has_content = true;
39 }
40
41 let proc_item = crate::render::ProcTemplateComponent {
43 template_component: item.clone(),
44 template_index: options.current_template_index,
45 value: v.value,
46 prefix: v.prefix,
47 suffix: v.suffix,
48 url: v.url,
49 ref_type: Some(reference.ref_type().clone()),
50 config: Some(options.config.clone()),
51 bibliography_config: options.bibliography_config.clone(),
52 item_language: crate::values::effective_component_language(reference, item),
53 quote_marks: crate::render::format::QuoteMarks::from(
54 &options.locale.grammar_options,
55 ),
56 sentence_initial: false,
57 pre_formatted: v.pre_formatted,
58 };
59
60 let rendered = crate::render::render_component_with_format_and_renderer::<F>(
61 &proc_item,
62 &fmt,
63 options.show_semantics,
64 );
65 if !rendered.is_empty() {
66 values.push(rendered);
67 }
68 }
69
70 if values.is_empty() || !has_content {
71 return None;
72 }
73
74 let default_delimiter = DelimiterPunctuation::Comma;
76 let punctuation = self.delimiter.as_ref().unwrap_or(&default_delimiter);
77 let (script, realization) = crate::values::punctuation_realization_context(
78 crate::values::effective_item_language(reference).as_deref(),
79 options.config.multilingual.as_ref(),
80 );
81 let delimiter = crate::render::format::realize_punctuation(
82 punctuation,
83 script,
84 realization,
85 crate::render::format::PunctuationPosition::Separator,
86 );
87
88 let delimiter = if punctuation.is_semantic() {
89 fmt.text(&delimiter)
90 } else {
91 delimiter.into_owned()
92 };
93
94 Some(ProcValues {
95 value: fmt.join(values, &delimiter),
96 prefix: None,
97 suffix: None,
98 url: None,
99 substituted_key: None,
100 pre_formatted: true,
101 })
102 }
103}
104
105fn is_term_based(component: &citum_schema::template::TemplateComponent) -> bool {
107 use citum_schema::template::TemplateComponent;
108 match component {
109 TemplateComponent::Term(_) => true,
110 TemplateComponent::Message(message) if message.message.starts_with("term.") => true,
111 TemplateComponent::Group(l) => l.group.iter().all(is_term_based),
112 _ => false,
113 }
114}