Struct handlebars::Decorator

source ·
pub struct Decorator<'reg, 'rc> { /* private fields */ }
Expand description

Render-time Decorator data when using in a decorator definition

Implementations§

Returns helper name

Examples found in repository?
src/render.rs (line 864)
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
    fn eval<'reg: 'rc, 'rc>(
        &'reg self,
        registry: &'reg Registry<'reg>,
        ctx: &'rc Context,
        rc: &mut RenderContext<'reg, 'rc>,
    ) -> Result<(), RenderError> {
        match *self {
            DecoratorExpression(ref dt) | DecoratorBlock(ref dt) => {
                let di = Decorator::try_from_template(dt, registry, ctx, rc)?;
                match registry.get_decorator(di.name()) {
                    Some(d) => d.call(&di, registry, ctx, rc),
                    None => Err(RenderError::new(format!(
                        "Decorator not defined: {:?}",
                        dt.name
                    ))),
                }
            }
            _ => Ok(()),
        }
    }
More examples
Hide additional examples
src/partial.rs (line 50)
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(())
    }
}

Returns all helper params, resolved within the context

Returns nth helper param, resolved within the context

Examples found in repository?
src/decorators/inline.rs (line 11)
10
11
12
13
14
15
16
17
18
19
fn get_name<'reg: 'rc, 'rc>(d: &Decorator<'reg, 'rc>) -> Result<String, RenderError> {
    d.param(0)
        .ok_or_else(|| RenderError::new("Param required for decorator \"inline\""))
        .and_then(|v| {
            v.value()
                .as_str()
                .map(|v| v.to_owned())
                .ok_or_else(|| RenderError::new("inline name must be string"))
        })
}
More examples
Hide additional examples
src/partial.rs (line 78)
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(())
    }
}

Returns hash, resolved within the context

Examples found in repository?
src/partial.rs (line 93)
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(())
    }
}

Return hash value of a given key, resolved within the context

Returns the default inner template if any

Examples found in repository?
src/decorators/inline.rs (line 32)
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
    fn call<'reg: 'rc, 'rc>(
        &self,
        d: &Decorator<'reg, 'rc>,
        _: &'reg Registry<'reg>,
        _: &'rc Context,
        rc: &mut RenderContext<'reg, 'rc>,
    ) -> DecoratorResult {
        let name = get_name(d)?;

        let template = d
            .template()
            .ok_or_else(|| RenderError::new("inline should have a block"))?;

        rc.set_partial(name, template);
        Ok(())
    }
More examples
Hide additional examples
src/partial.rs (line 31)
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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
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
fn find_partial<'reg: 'rc, 'rc: 'a, 'a>(
    rc: &'a RenderContext<'reg, 'rc>,
    r: &'reg Registry<'reg>,
    d: &Decorator<'reg, 'rc>,
    name: &str,
) -> Result<Option<Cow<'a, Template>>, RenderError> {
    if let Some(partial) = rc.get_partial(name) {
        return Ok(Some(Cow::Borrowed(partial)));
    }

    if let Some(tpl) = r.get_or_load_template_optional(name) {
        return tpl.map(Option::Some);
    }

    if let Some(tpl) = d.template() {
        return Ok(Some(Cow::Borrowed(tpl)));
    }

    Ok(None)
}

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(())
    }
}
Examples found in repository?
src/partial.rs (line 135)
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(())
    }
}

Trait Implementations§

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Should always be Self
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.