Layout XML text nodes are now parsed template strings instead of raw text containing {{template tags}}
This commit is contained in:
parent
214c1c09ac
commit
3205e8d274
|
|
@ -1,6 +1,7 @@
|
||||||
use crate::layout_abstract_types::*;
|
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
|
// 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 {
|
pub struct FlatComponent {
|
||||||
// The abstract definition of the root node of the component with attribute parameters
|
// The abstract definition of the root node of the component with attribute parameters
|
||||||
pub own_info: LayoutComponentDefinition,
|
pub own_info: LayoutComponentDefinition,
|
||||||
|
|
@ -48,7 +49,7 @@ pub type NodeOrDefTree = rctree::Node<LayoutComponentNodeOrDefinition>;
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum LayoutComponentNode {
|
pub enum LayoutComponentNode {
|
||||||
Tag(LayoutComponentTag),
|
Tag(LayoutComponentTag),
|
||||||
Text(String),
|
Text(Vec<TemplateStringSegment>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LayoutComponentNode {
|
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`
|
/// 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)
|
Self::Text(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -67,7 +68,7 @@ impl LayoutComponentNode {
|
||||||
pub fn debug_print(&self) {
|
pub fn debug_print(&self) {
|
||||||
match self {
|
match self {
|
||||||
LayoutComponentNode::Tag(tag) => tag.debug_print(),
|
LayoutComponentNode::Tag(tag) => tag.debug_print(),
|
||||||
LayoutComponentNode::Text(text) => println!("================> Text Node: {}", text),
|
LayoutComponentNode::Text(text) => println!("================> Text Node: {:#?}", text),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -157,24 +157,7 @@ impl AttributeParser {
|
||||||
Some([height]) if height.eq_ignore_ascii_case("height") => TypeValueOrArgument::TypeValue(TypeValue::Dimension(Dimension::Height)),
|
Some([height]) if height.eq_ignore_ascii_case("height") => TypeValueOrArgument::TypeValue(TypeValue::Dimension(Dimension::Height)),
|
||||||
// TemplateString: `? ... {{?}} ...`
|
// TemplateString: `? ... {{?}} ...`
|
||||||
Some(["`", string, "`"]) => {
|
Some(["`", string, "`"]) => {
|
||||||
let mut segments = Vec::<TemplateStringSegment>::new();
|
let segments = self.parse_text_template_sequence(string);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
TypeValueOrArgument::TypeValue(TypeValue::TemplateString(segments))
|
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 `&, <, >, ", '`
|
/// Replace escape characters in an XML string, only supports `&, <, >, ", '`
|
||||||
fn unescape_xml(xml: &str) -> String {
|
fn unescape_xml(xml: &str) -> String {
|
||||||
// Find and replace each escape character, starting with `&` to avoid unescaping other escape sequences
|
// Find and replace each escape character, starting with `&` to avoid unescaping other escape sequences
|
||||||
|
|
|
||||||
|
|
@ -317,7 +317,8 @@ impl LayoutSystem {
|
||||||
.expect(&format!("Encountered text outside the root tag when parsing XML layout in component: {}", path)[..]);
|
.expect(&format!("Encountered text outside the root tag when parsing XML layout in component: {}", path)[..]);
|
||||||
|
|
||||||
// Construct a text node with the provided text
|
// 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
|
// Put the text node in a new tree node
|
||||||
let tree_node = rctree::Node::new(abstract_text_node);
|
let tree_node = rctree::Node::new(abstract_text_node);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue