From 6e8c7621f1fdf2cf7c9a5511940b94ec33a66289 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Sat, 23 May 2020 23:06:04 -0400 Subject: [PATCH 1/3] It seems paths with a leading dot restrict the scope the below the current context. --- js/test_cases/dot_leading_path/input1.json | 7 +++++++ js/test_cases/dot_leading_path/main.dust | 5 +++++ 2 files changed, 12 insertions(+) create mode 100644 js/test_cases/dot_leading_path/input1.json create mode 100644 js/test_cases/dot_leading_path/main.dust diff --git a/js/test_cases/dot_leading_path/input1.json b/js/test_cases/dot_leading_path/input1.json new file mode 100644 index 0000000..986d7b4 --- /dev/null +++ b/js/test_cases/dot_leading_path/input1.json @@ -0,0 +1,7 @@ +{ + "commander": "Chris", + "names": { + "captain": "Alice", + "first_officer": "Bob" + } +} diff --git a/js/test_cases/dot_leading_path/main.dust b/js/test_cases/dot_leading_path/main.dust new file mode 100644 index 0000000..ada9456 --- /dev/null +++ b/js/test_cases/dot_leading_path/main.dust @@ -0,0 +1,5 @@ +{#names} + Hello {.captain}!{~n} + Hello {.commander}!{~n} + Hello {commander}!{~n} +{/names} From 95dc15f103f46d2e761c8a9759f636c11544d917 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Sat, 23 May 2020 23:12:51 -0400 Subject: [PATCH 2/3] Update parser to preserve the dot and support paths beginning with a dot. --- src/parser/parser.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/parser/parser.rs b/src/parser/parser.rs index 4c0cfd2..c016e7e 100644 --- a/src/parser/parser.rs +++ b/src/parser/parser.rs @@ -263,7 +263,14 @@ fn key(i: &str) -> IResult<&str, &str> { fn path(i: &str) -> IResult<&str, Path> { alt(( map(separated_list1(tag("."), key), |body| Path { keys: body }), - value(Path { keys: Vec::new() }, tag(".")), + map( + tuple((tag("."), separated_list1(tag("."), key))), + |(dot, mut body)| { + body.insert(0, dot); + Path { keys: body } + }, + ), + map(tag("."), |dot| Path { keys: vec![dot] }), ))(i) } @@ -1210,7 +1217,7 @@ mod tests { contents: Some(Body { elements: vec![TemplateElement::TETag(DustTag::DTReference( Reference { - path: Path { keys: vec![] }, + path: Path { keys: vec!["."] }, filters: vec![] } ))] @@ -1238,7 +1245,7 @@ mod tests { IgnoredWhitespace::StartOfLine("\n") ), TemplateElement::TETag(DustTag::DTReference(Reference { - path: Path { keys: vec![] }, + path: Path { keys: vec!["."] }, filters: vec![] })), TemplateElement::TEIgnoredWhitespace( From 50079c6415d6c92844ec60ec094f921ae7091d30 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Sat, 23 May 2020 23:26:00 -0400 Subject: [PATCH 3/3] Add support in the renderer for handling paths containing dot. --- src/renderer/walking.rs | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/renderer/walking.rs b/src/renderer/walking.rs index cc91047..b699254 100644 --- a/src/renderer/walking.rs +++ b/src/renderer/walking.rs @@ -9,7 +9,7 @@ enum WalkResult<'a> { fn walk_path_from_single_level<'a>( context: &'a dyn ContextElement, - path: &Vec<&str>, + path: &[&str], ) -> WalkResult<'a> { if path.is_empty() { return WalkResult::FullyWalked(context); @@ -18,7 +18,6 @@ fn walk_path_from_single_level<'a>( let mut walk_failure = WalkResult::NoWalk; let mut output = context; for elem in path.iter() { - let new_val = output.walk(elem); match output.walk(elem) { Err(WalkError::CantWalk { .. }) => { return walk_failure; @@ -37,6 +36,25 @@ pub fn walk_path<'a>( breadcrumbs: &Vec<&'a dyn ContextElement>, path: &'a Vec<&str>, ) -> Result<&'a dyn ContextElement, WalkError> { + if path.is_empty() { + return Ok(*breadcrumbs + .last() + .expect("Breadcrumbs should never be empty")); + } + if *path.first().expect("Already proved path is not empty") == "." { + return match walk_path_from_single_level( + *breadcrumbs + .last() + .expect("Breadcrumbs should never be empty"), + &path[1..], + ) { + // If no walking was done at all or we partially walked + // then stop trying to find anything because '.' restricts + // us to the current scope + WalkResult::NoWalk | WalkResult::PartialWalk => Err(WalkError::CantWalk), + WalkResult::FullyWalked(new_context) => Ok(new_context), + }; + } for context in breadcrumbs.iter().rev() { match walk_path_from_single_level(*context, path) { // If no walking was done at all, keep looping