Layout XML text nodes are now parsed template strings instead of raw text containing {{template tags}}

This commit is contained in:
Keavon Chambers 2020-08-02 23:53:56 -07:00
parent 214c1c09ac
commit 3205e8d274
3 changed files with 31 additions and 22 deletions

View File

@ -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<LayoutComponentNodeOrDefinition>;
#[derive(Debug, Clone, PartialEq)]
pub enum LayoutComponentNode {
Tag(LayoutComponentTag),
Text(String),
Text(Vec<TemplateStringSegment>),
}
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<TemplateStringSegment>) -> 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),
}
}
}

View File

@ -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::<TemplateStringSegment>::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<TemplateStringSegment> {
let mut segments = Vec::<TemplateStringSegment>::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

View File

@ -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);