Merge branch 'pseudo_context' into explicit_context_priority

This commit is contained in:
Tom Alexander 2020-05-30 12:26:11 -04:00
commit 9bdc398a6d
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE
5 changed files with 56 additions and 12 deletions

View File

@ -21,6 +21,16 @@ pub trait Truthiness {
pub trait Walkable {
fn walk(&self, segment: &str) -> Result<&dyn ContextElement, WalkError>;
/// If an element contains meta information and should not be
/// returned as the final result of a walk, this function should
/// return true.
///
/// For example, the iteration context contains $idx and $len but
/// it should not be the result of a dot-reference like `{.}`.
fn is_pseudo_element(&self) -> bool {
false
}
}
pub trait Renderable {

View File

@ -68,6 +68,10 @@ impl Walkable for IterationContext {
_ => Err(WalkError::CantWalk),
}
}
fn is_pseudo_element(&self) -> bool {
true
}
}
impl CompareContextElement for IterationContext {

View File

@ -103,6 +103,10 @@ impl Walkable for ParametersContext {
OwnedRValue::RVLiteral(literal) => Ok(literal),
}
}
fn is_pseudo_element(&self) -> bool {
true
}
}
impl Clone for ParametersContext {

View File

@ -17,6 +17,7 @@ use crate::renderer::inline_partial_tree::InlinePartialTreeElement;
use crate::renderer::iteration_context::IterationContext;
use crate::renderer::parameters_context::ParametersContext;
use crate::renderer::walking::walk_path;
use std::borrow::Borrow;
use std::collections::HashMap;
#[derive(Clone, Debug)]
@ -813,6 +814,15 @@ impl<'a> DustRenderer<'a> {
Some(new_stack)
}
fn get_index_of_first_non_pseudo_element<'b, B>(breadcrumbs: &'b Vec<B>) -> Option<usize>
where
B: Borrow<dyn ContextElement + 'a>,
{
breadcrumbs
.iter()
.rposition(|b| !(*b).borrow().is_pseudo_element())
}
fn new_breadcrumbs_partial<'b>(
breadcrumbs: &'b Vec<&'b dyn ContextElement>,
explicit_context_breadcrumbs: &'b Vec<&'b dyn ContextElement>,
@ -837,7 +847,10 @@ impl<'a> DustRenderer<'a> {
// 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),
None => new_stack.insert(
Self::get_index_of_first_non_pseudo_element(&new_stack).unwrap_or(0),
ctx,
),
_ => new_stack.push(ctx),
}
});

View File

@ -1,4 +1,5 @@
use crate::renderer::context_element::ContextElement;
use crate::renderer::context_element::Walkable;
use crate::renderer::WalkError;
use std::borrow::Borrow;
@ -34,6 +35,17 @@ where
WalkResult::FullyWalked(output)
}
pub fn get_first_non_pseudo_element<'a, B>(breadcrumbs: &'a Vec<B>) -> Option<&B>
where
B: Borrow<dyn ContextElement + 'a>,
{
breadcrumbs
.iter()
.rev()
.filter(|b| !(*b).borrow().is_pseudo_element())
.next()
}
pub fn walk_path<'a, B, P>(
breadcrumbs: &'a Vec<B>,
path: &Vec<P>,
@ -60,17 +72,18 @@ where
.borrow()
== "."
{
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),
let first_non_pseudo_element = get_first_non_pseudo_element(breadcrumbs);
return match first_non_pseudo_element {
None => Err(WalkError::CantWalk),
Some(current_context) => {
match walk_path_from_single_level(current_context, &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() {