1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
use std::fmt::{self, Write};

use crate::ast;

impl fmt::Display for ast::DashIdent {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        for pair in self.0.pairs() {
            pair.value().fmt(f)?;
            if pair.punct().is_some() {
                f.write_char('-')?;
            }
        }
        Ok(())
    }
}

impl fmt::Display for ast::Doctype {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str("<!DOCTYPE html>")
    }
}

impl ast::Value {
    /// An optimization to inline certain values at compile time
    pub fn inlined(&self) -> Option<String> {
        match self {
            // Text literals are always inlined
            ast::Value::Text(text) => Some(text.value()),
            // Braced values are inlined in certain cases
            ast::Value::Braced(expr) => match syn::parse2(expr.clone()) {
                Ok(syn::Expr::Lit(expr_lit)) => match &expr_lit.lit {
                    syn::Lit::Str(str) => Some(str.value()),
                    syn::Lit::Byte(byte) => Some(byte.value().to_string()),
                    syn::Lit::Char(char) => Some(char.value().to_string()),
                    syn::Lit::Int(int) => Some(int.base10_digits().to_string()),
                    syn::Lit::Float(float) => {
                        Some(float.base10_digits().to_string())
                    }
                    syn::Lit::Bool(bool) => Some(bool.value().to_string()),
                    _ => None,
                },
                _ => None,
            },
        }
    }
}

#[cfg(test)]
mod tests {
    use quote::quote;

    use super::*;

    #[test]
    fn fmt_dash_ident() {
        assert_eq!(
            syn::parse2::<ast::DashIdent>(quote! {foo})
                .unwrap()
                .to_string(),
            "foo"
        );
        assert_eq!(
            syn::parse2::<ast::DashIdent>(quote! {foo-bar})
                .unwrap()
                .to_string(),
            "foo-bar"
        );
        assert_eq!(
            syn::parse2::<ast::DashIdent>(quote! {foo-bar-baz})
                .unwrap()
                .to_string(),
            "foo-bar-baz"
        );
    }

    #[test]
    fn fmt_doctype() {
        assert_eq!(ast::Doctype.to_string(), "<!DOCTYPE html>");
    }
}