yamd/nodes/
code_span.rs

1use std::fmt::Display;
2
3use serde::Serialize;
4
5/// # Code span
6///
7/// Any characters except [Terminator](type@crate::lexer::TokenKind::Terminator) surrounded by a
8/// [Backtick](type@crate::lexer::TokenKind::Backtick) of length 1.
9///
10/// Example:
11///
12/// ```text
13/// `anything even EOL
14/// can be it`
15/// ```
16///
17/// HTML equivalent:
18///
19/// ```html
20/// <code>anything even EOL
21/// can be it</code>
22/// ```
23#[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}