rshtml_core 0.5.0

RsHtml: A Template Engine for Seamless HTML and Rust Integration.
Documentation
use crate::Node;
use crate::error::E;
use crate::parser::{IParser, RsHtmlParser, Rule};
use crate::position::Position;
use pest::error::Error;
use pest::iterators::{Pair, Pairs};
use std::iter::Peekable;

pub struct RustExprParser;

impl IParser for RustExprParser {
    fn parse(parser: &mut RsHtmlParser, pair: Pair<Rule>) -> Result<Node, Box<Error<Rule>>> {
        let pair_span = pair.as_span();
        let position = Position::from(&pair);

        let mut inner_pairs = pair.into_inner().peekable();
        let mut clauses: Vec<(String, Position, Vec<Node>)> = Vec::new();

        let consume_whitespaces = |inner_p: &mut Peekable<Pairs<Rule>>| {
            while let Some(p) = inner_p.peek() {
                if p.as_rule() == Rule::WHITESPACE {
                    inner_p.next();
                } else {
                    break;
                }
            }
        };

        while inner_pairs.peek().is_some() {
            let head_pair = inner_pairs
                .next_if(|p| p.as_rule() == Rule::rust_expr_head)
                .ok_or(
                    E::mes(format!(
                        "Internal Error: rust_expr expected a head, found {:?}",
                        inner_pairs.peek().map(|p| p.as_rule())
                    ))
                    .span(pair_span),
                )?;

            let head_position = Position::from(&head_pair);
            let head = head_pair.as_str().trim().to_string();

            consume_whitespaces(&mut inner_pairs);

            let template_pair = inner_pairs
                .next_if(|p| p.as_rule() == Rule::inner_template)
                .ok_or(
                    E::mes(format!(
                        "Internal Error: rust_expr missing inner_template for head: '{head}'"
                    ))
                    .span(pair_span),
                )?;

            let body_nodes = parser.build_nodes_from_pairs(template_pair.into_inner())?;

            clauses.push((head.clone(), head_position, body_nodes));

            consume_whitespaces(&mut inner_pairs);
        }

        if clauses.is_empty() {
            return Err(E::mes("Internal Error: rust_expr parsed with no clauses").span(pair_span));
        }

        Ok(Node::RustExpr(clauses, position))
    }
}