rshtml_core 0.1.0

RsHtml: A Template Engine for Seamless HTML and Rust Integration.
Documentation
use crate::Node;
use crate::node::{RustBlockContent, TextBlockItem, TextLineItem};
use crate::parser::{IParser, RsHtmlParser, Rule};
use crate::traits::IsEscaped;
use pest::error::{Error, ErrorVariant};
use pest::iterators::{Pair, Pairs};

pub struct RustBlockParser;

impl IParser for RustBlockParser {
    fn parse(_: &mut RsHtmlParser, pair: Pair<Rule>) -> Result<Node, Box<Error<Rule>>> {
        Ok(Node::RustBlock(Self::build_rust_block_contents(pair.into_inner())?))
    }
}

impl RustBlockParser {
    fn build_rust_block_contents(pairs: Pairs<Rule>) -> Result<Vec<RustBlockContent>, Box<Error<Rule>>> {
        let mut content_parts = Vec::new();
        for inner_pair in pairs {
            match inner_pair.as_rule() {
                Rule::text_line_directive => {
                    content_parts.push(Self::build_text_line(inner_pair));
                }
                Rule::text_block_tag => {
                    content_parts.push(Self::build_text_block(inner_pair));
                }
                Rule::rust_code => {
                    content_parts.push(RustBlockContent::Code(inner_pair.as_str().to_string()));
                }
                Rule::nested_block => {
                    let nested_contents = Self::build_rust_block_contents(inner_pair.into_inner())?;
                    content_parts.push(RustBlockContent::NestedBlock(nested_contents));
                }
                rule => {
                    return Err(Box::new(Error::new_from_span(
                        ErrorVariant::CustomError {
                            message: format!("Internal Error: Unexpected rule {:?} inside rust block content", rule),
                        },
                        inner_pair.as_span(),
                    )));
                }
            }
        }
        Ok(content_parts)
    }

    fn build_text_line(inner_pair: Pair<Rule>) -> RustBlockContent {
        let mut items = Vec::new();

        for item_pair in inner_pair.into_inner() {
            match item_pair.as_rule() {
                Rule::rust_expr_simple => {
                    let item_pair_str = item_pair.as_str();
                    items.push(TextLineItem::RustExprSimple(item_pair_str.escaped_or_raw(), item_pair_str.is_escaped()));
                }
                Rule::text_line => {
                    let text = item_pair.as_str().replace("@@", "@");
                    if !text.is_empty() {
                        items.push(TextLineItem::Text(text));
                    }
                }
                _ => {
                    eprintln!("Warning: Unexpected rule in text_block: {:?}", item_pair.as_rule());
                }
            }
        }

        RustBlockContent::TextLine(items)
    }

    fn build_text_block(inner_pair: Pair<Rule>) -> RustBlockContent {
        let mut items = Vec::new();

        for item_pair in inner_pair.into_inner() {
            match item_pair.as_rule() {
                Rule::rust_expr_simple => {
                    let item_pair_str = item_pair.as_str();
                    items.push(TextBlockItem::RustExprSimple(item_pair_str.escaped_or_raw(), item_pair_str.is_escaped()));
                }
                Rule::text_block => {
                    let text = item_pair.as_str().replace("@@", "@");
                    if !text.is_empty() {
                        items.push(TextBlockItem::Text(text));
                    }
                }
                _ => {
                    eprintln!("Warning: Unexpected rule in text_block: {:?}", item_pair.as_rule());
                }
            }
        }

        RustBlockContent::TextBlock(items)
    }
}