Merge branch 'helper_sep' into render
This commit is contained in:
commit
b35874f19e
23
js/test_cases/helpers_first/input1.json
Normal file
23
js/test_cases/helpers_first/input1.json
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"people": [
|
||||||
|
{
|
||||||
|
"name": "Alice",
|
||||||
|
"pet": "cat"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Bob",
|
||||||
|
"pet": "dog"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Chris",
|
||||||
|
"pet": "lizard"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"toys": [
|
||||||
|
"ball",
|
||||||
|
"bone"
|
||||||
|
],
|
||||||
|
"scalar": 7,
|
||||||
|
"name": "global name",
|
||||||
|
"pet": "global pet"
|
||||||
|
}
|
29
js/test_cases/helpers_first/main.dust
Normal file
29
js/test_cases/helpers_first/main.dust
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
Tags inside a first{~n}
|
||||||
|
==================={~n}
|
||||||
|
{#people}
|
||||||
|
{name}{@first petname="fluffy"},{pet}{petname}{/first}
|
||||||
|
{/people}{~n}
|
||||||
|
|
||||||
|
first inside a scalar{~n}
|
||||||
|
====================={~n}
|
||||||
|
{#scalar}
|
||||||
|
{name}{@first petname="fluffy"},{pet}{petname}{/first}
|
||||||
|
{/scalar}{~n}
|
||||||
|
|
||||||
|
Nested first inside another non-array section{~n}
|
||||||
|
============================================={~n}
|
||||||
|
{#people}
|
||||||
|
{#toys}
|
||||||
|
{name}'s pet {pet} plays with a {.}{@first}, {/first}
|
||||||
|
{/toys}
|
||||||
|
{/people}{~n}
|
||||||
|
|
||||||
|
Else block inside a first{~n}
|
||||||
|
========================={~n}
|
||||||
|
{#people}
|
||||||
|
{name}{@first},{pet}{petname}{:else}elseblock{/first}
|
||||||
|
{/people}{~n}
|
||||||
|
|
||||||
|
Sep outside any section{~n}
|
||||||
|
======================={~n}
|
||||||
|
{@first}first is printed outside any section{/first}
|
23
js/test_cases/helpers_last/input1.json
Normal file
23
js/test_cases/helpers_last/input1.json
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"people": [
|
||||||
|
{
|
||||||
|
"name": "Alice",
|
||||||
|
"pet": "cat"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Bob",
|
||||||
|
"pet": "dog"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Chris",
|
||||||
|
"pet": "lizard"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"toys": [
|
||||||
|
"ball",
|
||||||
|
"bone"
|
||||||
|
],
|
||||||
|
"scalar": 7,
|
||||||
|
"name": "global name",
|
||||||
|
"pet": "global pet"
|
||||||
|
}
|
29
js/test_cases/helpers_last/main.dust
Normal file
29
js/test_cases/helpers_last/main.dust
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
Tags inside a last{~n}
|
||||||
|
=================={~n}
|
||||||
|
{#people}
|
||||||
|
{name}{@last petname="fluffy"},{pet}{petname}{/last}
|
||||||
|
{/people}{~n}
|
||||||
|
|
||||||
|
last inside a scalar{~n}
|
||||||
|
===================={~n}
|
||||||
|
{#scalar}
|
||||||
|
{name}{@last petname="fluffy"},{pet}{petname}{/last}
|
||||||
|
{/scalar}{~n}
|
||||||
|
|
||||||
|
Nested last inside another non-array section{~n}
|
||||||
|
============================================{~n}
|
||||||
|
{#people}
|
||||||
|
{#toys}
|
||||||
|
{name}'s pet {pet} plays with a {.}{@last}, {/last}
|
||||||
|
{/toys}
|
||||||
|
{/people}{~n}
|
||||||
|
|
||||||
|
Else block inside a last{~n}
|
||||||
|
========================{~n}
|
||||||
|
{#people}
|
||||||
|
{name}{@last},{pet}{petname}{:else}elseblock{/last}
|
||||||
|
{/people}{~n}
|
||||||
|
|
||||||
|
Sep outside any section{~n}
|
||||||
|
======================={~n}
|
||||||
|
{@last}last is printed outside any section{/last}
|
23
js/test_cases/helpers_sep/input1.json
Normal file
23
js/test_cases/helpers_sep/input1.json
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"people": [
|
||||||
|
{
|
||||||
|
"name": "Alice",
|
||||||
|
"pet": "cat"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Bob",
|
||||||
|
"pet": "dog"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Chris",
|
||||||
|
"pet": "lizard"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"toys": [
|
||||||
|
"ball",
|
||||||
|
"bone"
|
||||||
|
],
|
||||||
|
"scalar": 7,
|
||||||
|
"name": "global name",
|
||||||
|
"pet": "global pet"
|
||||||
|
}
|
29
js/test_cases/helpers_sep/main.dust
Normal file
29
js/test_cases/helpers_sep/main.dust
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
Tags inside a sep{~n}
|
||||||
|
================={~n}
|
||||||
|
{#people}
|
||||||
|
{name}{@sep petname="fluffy"},{pet}{petname}{/sep}
|
||||||
|
{/people}{~n}
|
||||||
|
|
||||||
|
sep inside a scalar{~n}
|
||||||
|
==================={~n}
|
||||||
|
{#scalar}
|
||||||
|
{name}{@sep petname="fluffy"},{pet}{petname}{/sep}
|
||||||
|
{/scalar}{~n}
|
||||||
|
|
||||||
|
Nested sep inside another non-array section{~n}
|
||||||
|
==========================================={~n}
|
||||||
|
{#people}
|
||||||
|
{#toys}
|
||||||
|
{name}'s pet {pet} plays with a {.}{@sep}, {/sep}
|
||||||
|
{/toys}
|
||||||
|
{/people}{~n}
|
||||||
|
|
||||||
|
Else block inside a sep{~n}
|
||||||
|
======================={~n}
|
||||||
|
{#people}
|
||||||
|
{name}{@sep},{pet}{petname}{:else}elseblock{/sep}
|
||||||
|
{/people}{~n}
|
||||||
|
|
||||||
|
Sep outside any section{~n}
|
||||||
|
======================={~n}
|
||||||
|
{@sep}sep is printed outside any section{/sep}
|
@ -41,6 +41,9 @@ pub enum DustTag<'a> {
|
|||||||
DTHelperLessThan(ParameterizedBlock<'a>),
|
DTHelperLessThan(ParameterizedBlock<'a>),
|
||||||
DTHelperGreaterThanOrEquals(ParameterizedBlock<'a>),
|
DTHelperGreaterThanOrEquals(ParameterizedBlock<'a>),
|
||||||
DTHelperLessThanOrEquals(ParameterizedBlock<'a>),
|
DTHelperLessThanOrEquals(ParameterizedBlock<'a>),
|
||||||
|
DTHelperSep(ParameterizedBlock<'a>),
|
||||||
|
DTHelperFirst(ParameterizedBlock<'a>),
|
||||||
|
DTHelperLast(ParameterizedBlock<'a>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
@ -240,6 +243,18 @@ fn dust_tag(i: &str) -> IResult<&str, DustTag> {
|
|||||||
parameterized_block("{@", &tag_to_path("lt")),
|
parameterized_block("{@", &tag_to_path("lt")),
|
||||||
DustTag::DTHelperLessThan,
|
DustTag::DTHelperLessThan,
|
||||||
),
|
),
|
||||||
|
map(
|
||||||
|
parameterized_block("{@", &tag_to_path("sep")),
|
||||||
|
DustTag::DTHelperSep,
|
||||||
|
),
|
||||||
|
map(
|
||||||
|
parameterized_block("{@", &tag_to_path("first")),
|
||||||
|
DustTag::DTHelperFirst,
|
||||||
|
),
|
||||||
|
map(
|
||||||
|
parameterized_block("{@", &tag_to_path("last")),
|
||||||
|
DustTag::DTHelperLast,
|
||||||
|
),
|
||||||
))(i)
|
))(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,5 +160,35 @@ fn extract_inline_partials_from_tag<'a, 'b>(
|
|||||||
Some(body) => extract_inline_partials_from_body(blocks, &body),
|
Some(body) => extract_inline_partials_from_body(blocks, &body),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
DustTag::DTHelperSep(parameterized_block) => {
|
||||||
|
match ¶meterized_block.contents {
|
||||||
|
None => (),
|
||||||
|
Some(body) => extract_inline_partials_from_body(blocks, &body),
|
||||||
|
};
|
||||||
|
match ¶meterized_block.else_contents {
|
||||||
|
None => (),
|
||||||
|
Some(body) => extract_inline_partials_from_body(blocks, &body),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
DustTag::DTHelperFirst(parameterized_block) => {
|
||||||
|
match ¶meterized_block.contents {
|
||||||
|
None => (),
|
||||||
|
Some(body) => extract_inline_partials_from_body(blocks, &body),
|
||||||
|
};
|
||||||
|
match ¶meterized_block.else_contents {
|
||||||
|
None => (),
|
||||||
|
Some(body) => extract_inline_partials_from_body(blocks, &body),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
DustTag::DTHelperLast(parameterized_block) => {
|
||||||
|
match ¶meterized_block.contents {
|
||||||
|
None => (),
|
||||||
|
Some(body) => extract_inline_partials_from_body(blocks, &body),
|
||||||
|
};
|
||||||
|
match ¶meterized_block.else_contents {
|
||||||
|
None => (),
|
||||||
|
Some(body) => extract_inline_partials_from_body(blocks, &body),
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ use crate::parser::template;
|
|||||||
use crate::parser::Body;
|
use crate::parser::Body;
|
||||||
use crate::parser::DustTag;
|
use crate::parser::DustTag;
|
||||||
use crate::parser::Filter;
|
use crate::parser::Filter;
|
||||||
|
use crate::parser::OwnedLiteral;
|
||||||
use crate::parser::PartialNameElement;
|
use crate::parser::PartialNameElement;
|
||||||
use crate::parser::Path;
|
use crate::parser::Path;
|
||||||
use crate::parser::Special;
|
use crate::parser::Special;
|
||||||
@ -20,6 +21,7 @@ use crate::renderer::inline_partial_tree::InlinePartialTreeElement;
|
|||||||
use crate::renderer::iteration_context::IterationContext;
|
use crate::renderer::iteration_context::IterationContext;
|
||||||
use crate::renderer::parameters_context::ParametersContext;
|
use crate::renderer::parameters_context::ParametersContext;
|
||||||
use crate::renderer::walking::walk_path;
|
use crate::renderer::walking::walk_path;
|
||||||
|
use std::borrow::Borrow;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@ -644,11 +646,178 @@ impl<'a> DustRenderer<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
DustTag::DTHelperSep(parameterized_block) => {
|
||||||
|
let new_breadcrumbs = self.new_breadcrumbs_partial(
|
||||||
|
breadcrumbs,
|
||||||
|
breadcrumbs,
|
||||||
|
None,
|
||||||
|
¶meterized_block.explicit_context,
|
||||||
|
);
|
||||||
|
|
||||||
|
let index = self.get(breadcrumbs, &vec!["$idx"]);
|
||||||
|
let len = self.get(breadcrumbs, &vec!["$len"]);
|
||||||
|
match (index, len) {
|
||||||
|
(Err(_), _) | (_, Err(_)) => {
|
||||||
|
return self.render_maybe_body(
|
||||||
|
¶meterized_block.contents,
|
||||||
|
new_breadcrumbs.as_ref().unwrap_or(breadcrumbs),
|
||||||
|
blocks,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
(Ok(index_resolved), Ok(len_resolved)) => {
|
||||||
|
// Iteration contexts use OwnedLiteral::LPositiveinteger
|
||||||
|
let index_cast = index_resolved
|
||||||
|
.get_context_element_reference()
|
||||||
|
.to_any()
|
||||||
|
.downcast_ref::<OwnedLiteral>();
|
||||||
|
let len_cast = len_resolved
|
||||||
|
.get_context_element_reference()
|
||||||
|
.to_any()
|
||||||
|
.downcast_ref::<OwnedLiteral>();
|
||||||
|
match (index_cast, len_cast) {
|
||||||
|
(
|
||||||
|
Some(OwnedLiteral::LPositiveInteger(index_number)),
|
||||||
|
Some(OwnedLiteral::LPositiveInteger(len_number)),
|
||||||
|
) => {
|
||||||
|
if *index_number == len_number - 1 {
|
||||||
|
return Ok("".to_owned());
|
||||||
|
} else {
|
||||||
|
return self.render_maybe_body(
|
||||||
|
¶meterized_block.contents,
|
||||||
|
new_breadcrumbs.as_ref().unwrap_or(breadcrumbs),
|
||||||
|
blocks,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => return Ok("".to_owned()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DustTag::DTHelperFirst(parameterized_block) => {
|
||||||
|
let new_breadcrumbs = self.new_breadcrumbs_partial(
|
||||||
|
breadcrumbs,
|
||||||
|
breadcrumbs,
|
||||||
|
None,
|
||||||
|
¶meterized_block.explicit_context,
|
||||||
|
);
|
||||||
|
|
||||||
|
let index = self.get(breadcrumbs, &vec!["$idx"]);
|
||||||
|
match index {
|
||||||
|
Err(_) => return Ok("".to_owned()),
|
||||||
|
Ok(index_resolved) => {
|
||||||
|
// Iteration contexts use OwnedLiteral::LPositiveinteger
|
||||||
|
let index_cast = index_resolved
|
||||||
|
.get_context_element_reference()
|
||||||
|
.to_any()
|
||||||
|
.downcast_ref::<OwnedLiteral>();
|
||||||
|
match index_cast {
|
||||||
|
Some(OwnedLiteral::LPositiveInteger(index_number)) => {
|
||||||
|
if *index_number != 0 {
|
||||||
|
return Ok("".to_owned());
|
||||||
|
} else {
|
||||||
|
return self.render_maybe_body(
|
||||||
|
¶meterized_block.contents,
|
||||||
|
new_breadcrumbs.as_ref().unwrap_or(breadcrumbs),
|
||||||
|
blocks,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => return Ok("".to_owned()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DustTag::DTHelperLast(parameterized_block) => {
|
||||||
|
let new_breadcrumbs = self.new_breadcrumbs_partial(
|
||||||
|
breadcrumbs,
|
||||||
|
breadcrumbs,
|
||||||
|
None,
|
||||||
|
¶meterized_block.explicit_context,
|
||||||
|
);
|
||||||
|
|
||||||
|
let index = self.get(breadcrumbs, &vec!["$idx"]);
|
||||||
|
let len = self.get(breadcrumbs, &vec!["$len"]);
|
||||||
|
match (index, len) {
|
||||||
|
(Err(_), _) | (_, Err(_)) => return Ok("".to_owned()),
|
||||||
|
(Ok(index_resolved), Ok(len_resolved)) => {
|
||||||
|
// Iteration contexts use OwnedLiteral::LPositiveinteger
|
||||||
|
let index_cast = index_resolved
|
||||||
|
.get_context_element_reference()
|
||||||
|
.to_any()
|
||||||
|
.downcast_ref::<OwnedLiteral>();
|
||||||
|
let len_cast = len_resolved
|
||||||
|
.get_context_element_reference()
|
||||||
|
.to_any()
|
||||||
|
.downcast_ref::<OwnedLiteral>();
|
||||||
|
match (index_cast, len_cast) {
|
||||||
|
(
|
||||||
|
Some(OwnedLiteral::LPositiveInteger(index_number)),
|
||||||
|
Some(OwnedLiteral::LPositiveInteger(len_number)),
|
||||||
|
) => {
|
||||||
|
if *index_number != len_number - 1 {
|
||||||
|
return Ok("".to_owned());
|
||||||
|
} else {
|
||||||
|
return self.render_maybe_body(
|
||||||
|
¶meterized_block.contents,
|
||||||
|
new_breadcrumbs.as_ref().unwrap_or(breadcrumbs),
|
||||||
|
blocks,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => return Ok("".to_owned()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok("".to_owned())
|
Ok("".to_owned())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Read a value from the context tree
|
||||||
|
pub fn get<P>(
|
||||||
|
&'a self,
|
||||||
|
breadcrumbs: &'a Vec<BreadcrumbTreeElement<'a>>,
|
||||||
|
name: &Vec<P>,
|
||||||
|
) -> Result<IceResult<'a>, WalkError>
|
||||||
|
where
|
||||||
|
P: Borrow<str>,
|
||||||
|
{
|
||||||
|
let val =
|
||||||
|
walk_path(breadcrumbs, name).map(|ice| ice.into_context_element(self, breadcrumbs));
|
||||||
|
match val {
|
||||||
|
Ok(Some(ice_result)) => Ok(ice_result),
|
||||||
|
Ok(None) => Err(WalkError::CantWalk),
|
||||||
|
Err(walk_error) => Err(walk_error),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read a value from the parameters context
|
||||||
|
///
|
||||||
|
/// Returns None if the key is not present at all
|
||||||
|
pub fn tap<P>(
|
||||||
|
&'a self,
|
||||||
|
breadcrumbs: &'a Vec<BreadcrumbTreeElement<'a>>,
|
||||||
|
parameters: &'a ParametersContext<'a>,
|
||||||
|
name: &P,
|
||||||
|
) -> Option<Result<IceResult<'a>, WalkError>>
|
||||||
|
where
|
||||||
|
P: Borrow<str>,
|
||||||
|
{
|
||||||
|
if !parameters.contains_key(name.borrow()) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let val = parameters
|
||||||
|
.walk("key")
|
||||||
|
.map(|ice| ice.into_context_element(self, breadcrumbs));
|
||||||
|
match val {
|
||||||
|
Ok(Some(ice_result)) => Some(Ok(ice_result)),
|
||||||
|
Ok(None) => Some(Err(WalkError::CantWalk)),
|
||||||
|
Err(walk_error) => Some(Err(walk_error)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn new_breadcrumbs_section<'b>(
|
fn new_breadcrumbs_section<'b>(
|
||||||
&'b self,
|
&'b self,
|
||||||
breadcrumbs: &'b Vec<BreadcrumbTreeElement<'b>>,
|
breadcrumbs: &'b Vec<BreadcrumbTreeElement<'b>>,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user