liquid_lib/stdlib/blocks/
comment_block.rs

1use std::io::Write;
2
3use liquid_core::parser::BlockElement;
4use liquid_core::Language;
5use liquid_core::Renderable;
6use liquid_core::Result;
7use liquid_core::Runtime;
8use liquid_core::{BlockReflection, ParseBlock, TagBlock, TagTokenIter};
9
10#[derive(Copy, Clone, Debug, Default)]
11pub struct CommentBlock;
12
13impl CommentBlock {
14    pub fn new() -> Self {
15        Self
16    }
17}
18
19impl BlockReflection for CommentBlock {
20    fn start_tag(&self) -> &str {
21        "comment"
22    }
23
24    fn end_tag(&self) -> &str {
25        "endcomment"
26    }
27
28    fn description(&self) -> &str {
29        ""
30    }
31}
32
33impl ParseBlock for CommentBlock {
34    fn parse(
35        &self,
36        mut arguments: TagTokenIter<'_>,
37        mut tokens: TagBlock<'_, '_>,
38        options: &Language,
39    ) -> Result<Box<dyn Renderable>> {
40        // no arguments should be supplied, trying to supply them is an error
41        arguments.expect_nothing()?;
42
43        while let Some(token) = tokens.next()? {
44            // Only needs to parse tags. Expressions and raw text will never have side effects.
45            if let BlockElement::Tag(tag) = token {
46                if tag.name() == self.start_tag() {
47                    // Parses `{% comment %}` tags (in order to allow nesting)
48                    tag.parse(&mut tokens, options)?;
49                } else {
50                    // Other tags are parsed (because of possible side effects, such as in `{% raw %}`)
51                    // But their errors are ignored
52                    let _ = tag.parse(&mut tokens, options);
53                }
54            }
55        }
56
57        tokens.assert_empty();
58        Ok(Box::new(Comment))
59    }
60
61    fn reflection(&self) -> &dyn BlockReflection {
62        self
63    }
64}
65
66#[derive(Copy, Clone, Debug)]
67struct Comment;
68
69impl Renderable for Comment {
70    fn render_to(&self, _writer: &mut dyn Write, _runtime: &dyn Runtime) -> Result<()> {
71        Ok(())
72    }
73}
74
75#[cfg(test)]
76mod test {
77    use super::*;
78
79    use liquid_core::parser;
80    use liquid_core::runtime;
81    use liquid_core::runtime::RuntimeBuilder;
82
83    fn options() -> Language {
84        let mut options = Language::default();
85        options
86            .blocks
87            .register("comment".to_owned(), CommentBlock.into());
88        options
89    }
90
91    fn unit_parse(text: &str) -> String {
92        let options = options();
93        let template = parser::parse(text, &options)
94            .map(runtime::Template::new)
95            .unwrap();
96
97        let runtime = RuntimeBuilder::new().build();
98
99        template.render(&runtime).unwrap()
100    }
101
102    #[test]
103    fn test_comment() {
104        let output = unit_parse("{% comment %} This is a test {% endcomment %}");
105        assert_eq!(output, "");
106    }
107}