citum_engine/values/
message.rs1use crate::reference::Reference;
13use crate::values::{ComponentValues, ProcHints, ProcValues, RenderOptions};
14use citum_schema::locale::MessageArgs;
15use citum_schema::template::{MessageArgSource, TemplateMessage};
16use std::collections::HashMap;
17
18impl ComponentValues for TemplateMessage {
19 fn values<F: crate::render::format::OutputFormat<Output = String>>(
20 &self,
21 reference: &Reference,
22 hints: &ProcHints,
23 options: &RenderOptions<'_>,
24 ) -> Option<ProcValues<F::Output>> {
25 let mut named = HashMap::with_capacity(self.args.len());
26
27 for (name, source) in &self.args {
28 let value = render_message_arg::<F>(source, reference, hints, options)?;
29 if value.trim().is_empty() {
30 return None;
31 }
32 named.insert(name.clone(), value);
33 }
34
35 let args = MessageArgs {
36 named,
37 ..MessageArgs::default()
38 };
39 let mut value = options.locale.resolve_template_message(
40 &self.message,
41 &args,
42 self.form.as_ref(),
43 self.gender.clone(),
44 )?;
45
46 if crate::values::should_strip_periods(&self.rendering, options) {
47 value = crate::values::strip_trailing_periods(&value);
48 }
49
50 if let Some(tc) = self.rendering.text_case {
51 value = crate::values::text_case::apply_text_case(&value, tc);
52 }
53
54 if value.trim().is_empty() {
55 return None;
56 }
57 let term_backed = self.message.starts_with("term.");
58
59 Some(ProcValues {
60 value,
61 pre_formatted: !term_backed,
62 ..Default::default()
63 })
64 }
65}
66
67fn render_message_arg<F: crate::render::format::OutputFormat<Output = String>>(
68 source: &MessageArgSource,
69 reference: &Reference,
70 hints: &ProcHints,
71 options: &RenderOptions<'_>,
72) -> Option<String> {
73 if let MessageArgSource::Literal { literal } = source {
74 return Some(literal.clone());
75 }
76
77 let component = source.as_template_component()?;
78 if component.rendering().suppress == Some(true) {
79 return None;
80 }
81
82 let values = component.values::<F>(reference, hints, options)?;
83 if values.value.trim().is_empty() {
84 return None;
85 }
86
87 let fmt = F::default();
88 let proc_item = crate::render::ProcTemplateComponent {
89 template_component: component.clone(),
90 template_index: options.current_template_index,
91 value: values.value,
92 prefix: values.prefix,
93 suffix: values.suffix,
94 url: values.url,
95 ref_type: Some(reference.ref_type().clone()),
96 config: Some(options.config.clone()),
97 bibliography_config: options.bibliography_config.clone(),
98 item_language: crate::values::effective_component_language(reference, &component),
99 quote_marks: crate::render::format::QuoteMarks::from(&options.locale.grammar_options),
100 sentence_initial: false,
101 pre_formatted: values.pre_formatted,
102 };
103
104 let rendered = crate::render::render_component_with_format_and_renderer::<F>(
105 &proc_item,
106 &fmt,
107 options.show_semantics,
108 );
109 if rendered.trim().is_empty() {
110 None
111 } else {
112 Some(rendered)
113 }
114}