diff --git a/src/layout_abstract_syntax.rs b/src/layout_abstract_syntax.rs index 87be6980..66fd7231 100644 --- a/src/layout_abstract_syntax.rs +++ b/src/layout_abstract_syntax.rs @@ -1,6 +1,7 @@ use crate::layout_abstract_types::*; // AST for a component with info on its definition (from the root element of the XML layout) and a vector of direct child component tags +#[derive(Debug, Clone, PartialEq)] pub struct FlatComponent { // The abstract definition of the root node of the component with attribute parameters pub own_info: LayoutComponentDefinition, @@ -48,7 +49,7 @@ pub type NodeOrDefTree = rctree::Node; #[derive(Debug, Clone, PartialEq)] pub enum LayoutComponentNode { Tag(LayoutComponentTag), - Text(String), + Text(Vec), } impl LayoutComponentNode { @@ -58,7 +59,7 @@ impl LayoutComponentNode { } /// Given some text hanging out in the XML between tags, construct a `LayoutComponentNode` with that text which simply stores the provided `String` - pub fn new_text(text: String) -> Self { + pub fn new_text(text: Vec) -> Self { Self::Text(text) } @@ -67,7 +68,7 @@ impl LayoutComponentNode { pub fn debug_print(&self) { match self { LayoutComponentNode::Tag(tag) => tag.debug_print(), - LayoutComponentNode::Text(text) => println!("================> Text Node: {}", text), + LayoutComponentNode::Text(text) => println!("================> Text Node: {:#?}", text), } } } diff --git a/src/layout_attribute_parser.rs b/src/layout_attribute_parser.rs index 1ff915e7..affff327 100644 --- a/src/layout_attribute_parser.rs +++ b/src/layout_attribute_parser.rs @@ -157,24 +157,7 @@ impl AttributeParser { Some([height]) if height.eq_ignore_ascii_case("height") => TypeValueOrArgument::TypeValue(TypeValue::Dimension(Dimension::Height)), // TemplateString: `? ... {{?}} ...` Some(["`", string, "`"]) => { - let mut segments = Vec::::new(); - let mut is_template = false; - - // Alternate between string and handlebars, always starting wtih string even if empty, and push abstract tokens of non-empty ones to the TemplateString sequence - for part in self.split_by_string_templates_regex.split(string) { - // Push only non-empty template string segments (a String or Argument) - if !part.is_empty() { - // Based on whether we are alternating to a string or template, push the appropriate abstract token - let segment = match is_template { - false => TemplateStringSegment::String(String::from(part)), - true => TemplateStringSegment::Argument(TypeValueOrArgument::VariableArgument(String::from(part))), - }; - segments.push(segment); - } - - // The next iteration will switch from a template to a string or vice versa - is_template = !is_template; - } + let segments = self.parse_text_template_sequence(string); TypeValueOrArgument::TypeValue(TypeValue::TemplateString(segments)) }, @@ -299,6 +282,30 @@ impl AttributeParser { } } + /// Extract {{template tags}} from surrounding text and return a vector alternating between text and the argument + pub fn parse_text_template_sequence(&self, input_text: &str) -> Vec { + let mut segments = Vec::::new(); + let mut is_template = false; + + // Alternate between string and handlebars, always starting wtih string even if empty, and push abstract tokens of non-empty ones to the TemplateString sequence + for part in self.split_by_string_templates_regex.split(input_text) { + // Push only non-empty template string segments (a String or Argument) + if !part.is_empty() { + // Based on whether we are alternating to a string or template, push the appropriate abstract token + let segment = match is_template { + false => TemplateStringSegment::String(String::from(part)), + true => TemplateStringSegment::Argument(TypeValueOrArgument::VariableArgument(String::from(part))), + }; + segments.push(segment); + } + + // The next iteration will switch from a template to a string or vice versa + is_template = !is_template; + } + + segments + } + /// Replace escape characters in an XML string, only supports `&, <, >, ", '` fn unescape_xml(xml: &str) -> String { // Find and replace each escape character, starting with `&` to avoid unescaping other escape sequences diff --git a/src/layout_system.rs b/src/layout_system.rs index fa8a4efb..825e27c5 100644 --- a/src/layout_system.rs +++ b/src/layout_system.rs @@ -317,7 +317,8 @@ impl LayoutSystem { .expect(&format!("Encountered text outside the root tag when parsing XML layout in component: {}", path)[..]); // Construct a text node with the provided text - let abstract_text_node = LayoutComponentNodeOrDefinition::LayoutComponentNode(LayoutComponentNode::new_text(text_string)); + let text_template_sequence = attribute_parser.parse_text_template_sequence(&text_string[..]); + let abstract_text_node = LayoutComponentNodeOrDefinition::LayoutComponentNode(LayoutComponentNode::new_text(text_template_sequence)); // Put the text node in a new tree node let tree_node = rctree::Node::new(abstract_text_node);