From 79f52ecdeeb865a39d8c6754c13af0763e6f69c3 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Mon, 25 May 2020 22:50:10 -0400 Subject: [PATCH] Add test for priorities while looping and split the new_breadcrumbs function into two separate new_breadcrumbs functions because sections and partials have different orderings. --- .../explicit_context_setting/README.md | 2 + .../explicit_context_setting/main.dust | 31 ++++++++ src/renderer/renderer.rs | 74 +++++++++++++++++++ 3 files changed, 107 insertions(+) diff --git a/js/test_cases/explicit_context_setting/README.md b/js/test_cases/explicit_context_setting/README.md index 33ab331..99751c6 100644 --- a/js/test_cases/explicit_context_setting/README.md +++ b/js/test_cases/explicit_context_setting/README.md @@ -4,6 +4,8 @@ Partials: Explicit context takes priority over parameters Sections: New context takes priority, then parameters, then explicit +Sections with loops: Loop variables ($idx and $len) take priority over parameters and explicit context + $idx and $len ------------- diff --git a/js/test_cases/explicit_context_setting/main.dust b/js/test_cases/explicit_context_setting/main.dust index eb92a10..2997d29 100644 --- a/js/test_cases/explicit_context_setting/main.dust +++ b/js/test_cases/explicit_context_setting/main.dust @@ -326,3 +326,34 @@ Section vs Partial priority{~n} {pet}{~n} {/some_global} {>priority:explicit pet="snake"/} + +Section vs Partial priority Failed Walk{~n} +======================================={~n} +{#doesnotexist:explicit pet="snake"} + MAIN {pet}{~n} +{:else} + ELSE {pet}{~n} +{/doesnotexist} +{>priority:explicit pet="snake"/} + +Section Loop set $idx as a parameter{~n} +===================================={~n} +{#loop $idx="7"} + $idx is {$idx}{~n} + $len is {$len}{~n} +{/loop} + +Section Loop set $idx in explicit context{~n} +========================================={~n} +{#loop:has_idx} + $idx is {$idx}{~n} + $len is {$len}{~n} +{/loop} + +Section Loop set $idx in explicit context and parameter{~n} +======================================================={~n} +{#loop:has_idx $idx="7"} + $idx is {$idx}{~n} + $len is {$len}{~n} +{/loop} + diff --git a/src/renderer/renderer.rs b/src/renderer/renderer.rs index 3c32be7..d73330c 100644 --- a/src/renderer/renderer.rs +++ b/src/renderer/renderer.rs @@ -785,6 +785,80 @@ impl<'a> DustRenderer<'a> { new_context_element.map(|ctx| new_stack.push(ctx)); Some(new_stack) } + + fn new_breadcrumbs_section<'b>( + breadcrumbs: &'b Vec<&'b dyn ContextElement>, + index_context: Option<&'b dyn ContextElement>, + injected_context: Option<&'b dyn ContextElement>, + explicit_context: &Option>, + new_context_element: Option<&'b dyn ContextElement>, + ) -> Option> { + // If none of the additional contexts are present, return None + // to signal that the original breadcrumbs should be used + // rather than incurring a copy here. + match ( + index_context, + injected_context, + explicit_context, + new_context_element, + ) { + (None, None, None, None) => return None, + _ => (), + } + let mut new_stack = match explicit_context { + Some(_) => Vec::with_capacity(4), + None => breadcrumbs.clone(), + }; + explicit_context.as_ref().map(|path| { + walk_path(breadcrumbs, &path.keys).map(|val| { + if val.is_truthy() { + new_stack.push(val) + } + }); + }); + injected_context.map(|ctx| new_stack.push(ctx)); + new_context_element.map(|ctx| new_stack.push(ctx)); + index_context.map(|ctx| new_stack.push(ctx)); + Some(new_stack) + } + + fn new_breadcrumbs_partial<'b>( + breadcrumbs: &'b Vec<&'b dyn ContextElement>, + explicit_context_breadcrumbs: &'b Vec<&'b dyn ContextElement>, + injected_context: Option<&'b dyn ContextElement>, + explicit_context: &Option>, + ) -> Option> { + // If none of the additional contexts are present, return None + // to signal that the original breadcrumbs should be used + // rather than incurring a copy here. + match (injected_context, explicit_context) { + (None, None) => return None, + _ => (), + }; + let mut new_stack = match explicit_context { + Some(_) => Vec::with_capacity(3), + None => breadcrumbs.clone(), + }; + injected_context.map(|ctx| { + // Special case: when there is no explicit context, the + // injected context gets inserted 1 spot behind the + // current context. Otherwise, the injected context gets + // added after the current context but before the explicit + // context. + match explicit_context { + None => new_stack.insert(std::cmp::max(new_stack.len() - 1, 0), ctx), + _ => new_stack.push(ctx), + } + }); + explicit_context.as_ref().map(|path| { + walk_path(explicit_context_breadcrumbs, &path.keys).map(|val| { + if val.is_truthy() { + new_stack.push(val) + } + }); + }); + Some(new_stack) + } } struct BlockContext<'a> {