Enum handlebars::ScopedJson
source · pub enum ScopedJson<'reg: 'rc, 'rc> {
Constant(&'reg Json),
Derived(Json),
Context(&'rc Json, Vec<String>),
Missing,
}
Expand description
A JSON wrapper designed for handlebars internal use case
- Constant: the JSON value hardcoded into template
- Context: the JSON value referenced in your provided data context
- Derived: the owned JSON value computed during rendering process
Variants§
Implementations§
source§impl<'reg: 'rc, 'rc> ScopedJson<'reg, 'rc>
impl<'reg: 'rc, 'rc> ScopedJson<'reg, 'rc>
sourcepub fn as_json(&self) -> &Json
pub fn as_json(&self) -> &Json
get the JSON reference
Examples found in repository?
src/json/value.rs (line 33)
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
pub fn render(&self) -> String {
self.as_json().render()
}
pub fn is_missing(&self) -> bool {
matches!(self, ScopedJson::Missing)
}
pub fn into_derived(self) -> ScopedJson<'reg, 'rc> {
let v = self.as_json();
ScopedJson::Derived(v.clone())
}
pub fn context_path(&self) -> Option<&Vec<String>> {
match self {
ScopedJson::Context(_, ref p) => Some(p),
_ => None,
}
}
}
impl<'reg: 'rc, 'rc> From<Json> for ScopedJson<'reg, 'rc> {
fn from(v: Json) -> ScopedJson<'reg, 'rc> {
ScopedJson::Derived(v)
}
}
/// Json wrapper that holds the Json value and reference path information
///
#[derive(Debug)]
pub struct PathAndJson<'reg, 'rc> {
relative_path: Option<String>,
value: ScopedJson<'reg, 'rc>,
}
impl<'reg: 'rc, 'rc> PathAndJson<'reg, 'rc> {
pub fn new(
relative_path: Option<String>,
value: ScopedJson<'reg, 'rc>,
) -> PathAndJson<'reg, 'rc> {
PathAndJson {
relative_path,
value,
}
}
/// Returns relative path when the value is referenced
/// If the value is from a literal, the path is `None`
pub fn relative_path(&self) -> Option<&String> {
self.relative_path.as_ref()
}
/// Returns full path to this value if any
pub fn context_path(&self) -> Option<&Vec<String>> {
self.value.context_path()
}
/// Returns the value
pub fn value(&self) -> &Json {
self.value.as_json()
}
More examples
src/render.rs (line 628)
612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664
pub fn expand<'reg: 'rc, 'rc>(
&'reg self,
registry: &'reg Registry<'reg>,
ctx: &'rc Context,
rc: &mut RenderContext<'reg, 'rc>,
) -> Result<PathAndJson<'reg, 'rc>, RenderError> {
match self {
Parameter::Name(ref name) => {
// FIXME: raise error when expanding with name?
Ok(PathAndJson::new(Some(name.to_owned()), ScopedJson::Missing))
}
Parameter::Path(ref path) => {
if let Some(rc_context) = rc.context() {
let result = rc.evaluate2(rc_context.borrow(), path)?;
Ok(PathAndJson::new(
Some(path.raw().to_owned()),
ScopedJson::Derived(result.as_json().clone()),
))
} else {
let result = rc.evaluate2(ctx, path)?;
Ok(PathAndJson::new(Some(path.raw().to_owned()), result))
}
}
Parameter::Literal(ref j) => Ok(PathAndJson::new(None, ScopedJson::Constant(j))),
Parameter::Subexpression(ref t) => match *t.as_element() {
Expression(ref ht) => {
let name = ht.name.expand_as_name(registry, ctx, rc)?;
let h = Helper::try_from_template(ht, registry, ctx, rc)?;
if let Some(ref d) = rc.get_local_helper(&name) {
call_helper_for_value(d.as_ref(), &h, registry, ctx, rc)
} else {
let mut helper = registry.get_or_load_helper(&name)?;
if helper.is_none() {
helper = registry.get_or_load_helper(if ht.block {
BLOCK_HELPER_MISSING
} else {
HELPER_MISSING
})?;
}
helper
.ok_or_else(|| {
RenderError::new(format!("Helper not defined: {:?}", ht.name))
})
.and_then(|d| call_helper_for_value(d.as_ref(), &h, registry, ctx, rc))
}
}
_ => unreachable!(),
},
}
}
src/partial.rs (line 118)
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
pub fn expand_partial<'reg: 'rc, 'rc>(
d: &Decorator<'reg, 'rc>,
r: &'reg Registry<'reg>,
ctx: &'rc Context,
rc: &mut RenderContext<'reg, 'rc>,
out: &mut dyn Output,
) -> Result<(), RenderError> {
// try eval inline partials first
if let Some(t) = d.template() {
t.eval(r, ctx, rc)?;
}
let tname = d.name();
if rc.is_current_template(tname) {
return Err(RenderError::new("Cannot include self in >"));
}
let partial = find_partial(rc, r, d, tname)?;
if let Some(t) = partial {
// clone to avoid lifetime issue
// FIXME refactor this to avoid
let mut local_rc = rc.clone();
// if tname == PARTIAL_BLOCK
let is_partial_block = tname == PARTIAL_BLOCK;
// add partial block depth there are consecutive partial
// blocks in the stack.
if is_partial_block {
local_rc.inc_partial_block_depth();
} else {
// depth cannot be lower than 0, which is guaranted in the
// `dec_partial_block_depth` method
local_rc.dec_partial_block_depth();
}
let mut block_created = false;
// create context if param given
if let Some(base_path) = d.param(0).and_then(|p| p.context_path()) {
// path given, update base_path
let mut block_inner = BlockContext::new();
*block_inner.base_path_mut() = base_path.to_vec();
// because block is moved here, we need another bool variable to track
// its status for later cleanup
block_created = true;
// clear blocks to prevent block params from parent
// template to be leaked into partials
// see `test_partial_context_issue_495` for the case.
local_rc.clear_blocks();
local_rc.push_block(block_inner);
}
if !d.hash().is_empty() {
// hash given, update base_value
let hash_ctx = d
.hash()
.iter()
.map(|(k, v)| (*k, v.value()))
.collect::<HashMap<&str, &Json>>();
// create block if we didn't (no param provided for partial expression)
if !block_created {
let block_inner = if let Some(block) = local_rc.block() {
// reuse current block information, including base_path and
// base_value if any
block.clone()
} else {
BlockContext::new()
};
local_rc.clear_blocks();
local_rc.push_block(block_inner);
}
// evaluate context within current block, this includes block
// context provided by partial expression parameter
let merged_context = merge_json(
local_rc.evaluate2(ctx, &Path::current())?.as_json(),
&hash_ctx,
);
// update the base value, there must be a block for this so it's
// also safe to unwrap.
if let Some(block) = local_rc.block_mut() {
block.set_base_value(merged_context);
}
}
// @partial-block
if let Some(pb) = d.template() {
local_rc.push_partial_block(pb);
}
// indent
local_rc.set_indent_string(d.indent());
let result = t.render(r, ctx, &mut local_rc, out);
// cleanup
if block_created {
local_rc.pop_block();
}
if d.template().is_some() {
local_rc.pop_partial_block();
}
result
} else {
Ok(())
}
}
sourcepub fn render(&self) -> String
pub fn render(&self) -> String
Examples found in repository?
More examples
src/helpers/mod.rs (line 128)
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
fn call<'reg: 'rc, 'rc>(
&self,
h: &Helper<'reg, 'rc>,
r: &'reg Registry<'reg>,
ctx: &'rc Context,
rc: &mut RenderContext<'reg, 'rc>,
out: &mut dyn Output,
) -> HelperResult {
match self.call_inner(h, r, ctx, rc) {
Ok(result) => {
if r.strict_mode() && result.is_missing() {
Err(RenderError::strict_error(None))
} else {
// auto escape according to settings
let output = do_escape(r, rc, result.render());
out.write(output.as_ref())?;
Ok(())
}
}
Err(e) => {
if e.is_unimplemented() {
// default implementation, do nothing
Ok(())
} else {
Err(e)
}
}
}
}
sourcepub fn is_missing(&self) -> bool
pub fn is_missing(&self) -> bool
Examples found in repository?
More examples
src/helpers/mod.rs (line 124)
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
fn call<'reg: 'rc, 'rc>(
&self,
h: &Helper<'reg, 'rc>,
r: &'reg Registry<'reg>,
ctx: &'rc Context,
rc: &mut RenderContext<'reg, 'rc>,
out: &mut dyn Output,
) -> HelperResult {
match self.call_inner(h, r, ctx, rc) {
Ok(result) => {
if r.strict_mode() && result.is_missing() {
Err(RenderError::strict_error(None))
} else {
// auto escape according to settings
let output = do_escape(r, rc, result.render());
out.write(output.as_ref())?;
Ok(())
}
}
Err(e) => {
if e.is_unimplemented() {
// default implementation, do nothing
Ok(())
} else {
Err(e)
}
}
}
}
pub fn into_derived(self) -> ScopedJson<'reg, 'rc>
sourcepub fn context_path(&self) -> Option<&Vec<String>>
pub fn context_path(&self) -> Option<&Vec<String>>
Trait Implementations§
source§impl<'reg: 'rc, 'rc> Debug for ScopedJson<'reg, 'rc>
impl<'reg: 'rc, 'rc> Debug for ScopedJson<'reg, 'rc>
source§impl<'reg: 'rc, 'rc> From<Value> for ScopedJson<'reg, 'rc>
impl<'reg: 'rc, 'rc> From<Value> for ScopedJson<'reg, 'rc>
source§fn from(v: Json) -> ScopedJson<'reg, 'rc>
fn from(v: Json) -> ScopedJson<'reg, 'rc>
Converts to this type from the input type.