1use std::fmt::Display;
2
3use serde::Serialize;
4
5#[derive(Debug, PartialEq, Serialize, Clone, Eq)]
24pub struct CodeSpan(pub String);
25
26impl CodeSpan {
27 pub fn new<Body: Into<String>>(body: Body) -> Self {
28 CodeSpan(body.into())
29 }
30}
31
32impl Display for CodeSpan {
33 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
34 write!(
35 f,
36 "`{}`",
37 self.0.replace("`", "\\`").replace("\n\n", "\\\n\n")
38 )
39 }
40}
41
42impl From<String> for CodeSpan {
43 fn from(value: String) -> Self {
44 CodeSpan(value)
45 }
46}
47
48#[cfg(test)]
49mod tests {
50 use super::*;
51
52 #[test]
53 fn code_span() {
54 let code_span: CodeSpan = "anything even EOL\ncan be it".to_string().into();
55 assert_eq!(code_span.to_string(), "`anything even EOL\ncan be it`");
56 }
57
58 #[test]
59 fn code_span_with_backtick() {
60 let code_span = CodeSpan::new("anything even EOL\ncan `be` it");
61 assert_eq!(
62 code_span.to_string(),
63 "`anything even EOL\ncan \\`be\\` it`"
64 );
65 }
66
67 #[test]
68 fn code_span_with_terminator() {
69 let code_span = CodeSpan::new("anything even EOL\n\ncan be it\n");
70 assert_eq!(
71 code_span.to_string(),
72 "`anything even EOL\\\n\ncan be it\n`"
73 );
74 }
75}