citum_engine/render/
org.rs1use super::format::{OutputFormat, QuoteMarks, realize_wrap};
9use crate::values::ScriptClass;
10use citum_schema::template::WrapPunctuation;
11
12#[derive(Default, Clone)]
22pub struct OrgOutputFormat;
23
24impl OutputFormat for OrgOutputFormat {
25 type Output = String;
26
27 fn text(&self, s: &str) -> Self::Output {
28 s.to_string()
29 }
30
31 fn join(&self, items: Vec<Self::Output>, delimiter: &str) -> Self::Output {
32 items.join(delimiter)
33 }
34
35 fn finish(&self, output: Self::Output) -> String {
36 output
37 }
38
39 fn heading(&self, level: u8, content: Self::Output) -> Self::Output {
41 let marks = "*".repeat(level.max(1) as usize);
42 format!("{marks} {content}\n\n")
43 }
44
45 fn emph(&self, content: Self::Output) -> Self::Output {
47 if content.is_empty() {
48 return content;
49 }
50 format!("/{content}/")
51 }
52
53 fn strong(&self, content: Self::Output) -> Self::Output {
55 if content.is_empty() {
56 return content;
57 }
58 format!("*{content}*")
59 }
60
61 fn small_caps(&self, content: Self::Output) -> Self::Output {
63 if content.is_empty() {
64 return content;
65 }
66 format!("~{content}~")
67 }
68
69 fn superscript(&self, content: Self::Output) -> Self::Output {
70 if content.is_empty() {
71 return content;
72 }
73 format!("^{content}^")
74 }
75
76 fn quote(&self, content: Self::Output, marks: &QuoteMarks) -> Self::Output {
77 if content.is_empty() {
78 return content;
79 }
80 let (open, close) = marks.for_depth(0);
82 format!("{open}{content}{close}")
83 }
84
85 fn affix(&self, prefix: &str, content: Self::Output, suffix: &str) -> Self::Output {
86 format!("{prefix}{content}{suffix}")
87 }
88
89 fn inner_affix(&self, prefix: &str, content: Self::Output, suffix: &str) -> Self::Output {
90 format!("{prefix}{content}{suffix}")
91 }
92
93 fn wrap_punctuation(
94 &self,
95 wrap: &WrapPunctuation,
96 content: Self::Output,
97 marks: &QuoteMarks,
98 script: ScriptClass,
99 realization: Option<&citum_schema::options::PunctuationRealization>,
100 ) -> Self::Output {
101 match realize_wrap(wrap, script, realization) {
102 Some((open, close)) => {
103 format!("{}{}{}", self.text(&open), content, self.text(&close))
104 }
105 None => self.quote(content, marks),
106 }
107 }
108
109 fn semantic(&self, _class: &str, content: Self::Output) -> Self::Output {
110 content
112 }
113
114 fn annotation(&self, content: Self::Output) -> Self::Output {
115 if content.is_empty() {
116 return content;
117 }
118 format!(
119 "\n\n#+begin_citum_annotation\n{}\n#+end_citum_annotation",
120 content
121 )
122 }
123
124 fn link(&self, url: &str, content: Self::Output) -> Self::Output {
126 format!("[[{url}][{content}]]")
127 }
128
129 fn entry(
130 &self,
131 _id: &str,
132 content: Self::Output,
133 _url: Option<&str>,
134 _metadata: &super::format::ProcEntryMetadata,
135 ) -> Self::Output {
136 content
137 }
138}
139
140#[cfg(test)]
141#[allow(
142 clippy::unwrap_used,
143 clippy::expect_used,
144 clippy::panic,
145 clippy::indexing_slicing,
146 clippy::todo,
147 clippy::unimplemented,
148 clippy::unreachable,
149 clippy::get_unwrap,
150 reason = "Panicking is acceptable and often desired in tests."
151)]
152mod tests {
153 use super::*;
154
155 #[test]
156 fn test_org_emph() {
157 let fmt = OrgOutputFormat;
158 let result = fmt.emph(fmt.text("italic text"));
159 assert_eq!(result, "/italic text/");
160 }
161
162 #[test]
163 fn test_org_strong() {
164 let fmt = OrgOutputFormat;
165 let result = fmt.strong(fmt.text("bold text"));
166 assert_eq!(result, "*bold text*");
167 }
168
169 #[test]
170 fn test_org_small_caps() {
171 let fmt = OrgOutputFormat;
172 let result = fmt.small_caps(fmt.text("small caps"));
173 assert_eq!(result, "~small caps~");
174 }
175
176 #[test]
177 fn test_org_link() {
178 let fmt = OrgOutputFormat;
179 let result = fmt.link("https://example.com", fmt.text("Example"));
180 assert_eq!(result, "[[https://example.com][Example]]");
181 }
182
183 #[test]
184 fn test_org_empty_content() {
185 let fmt = OrgOutputFormat;
186 let result = fmt.emph(fmt.text(""));
187 assert_eq!(result, "");
188 }
189}