Skip to content

Commit 432539c

Browse files
authored
Merge pull request #444 from mkantor/feature/publish-source-api
Merge master and add a test for `register_template_source`
2 parents a38fb21 + 46b2cf0 commit 432539c

File tree

25 files changed

+913
-519
lines changed

25 files changed

+913
-519
lines changed

.github/workflows/main.yml

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
name: CI
2+
on:
3+
# Only run when merging to master, or open/synchronize/reopen a PR.
4+
push:
5+
branches:
6+
- master
7+
pull_request:
8+
9+
jobs:
10+
test:
11+
name: Test
12+
runs-on: ${{ matrix.os }}
13+
strategy:
14+
matrix:
15+
build: [stable, beta, nightly, macos, windows]
16+
include:
17+
- build: stable
18+
os: ubuntu-latest
19+
rust: stable
20+
- build: beta
21+
os: ubuntu-latest
22+
rust: beta
23+
- build: nightly
24+
os: ubuntu-latest
25+
rust: nightly
26+
- build: macos
27+
os: macos-latest
28+
rust: stable
29+
- build: windows
30+
os: windows-latest
31+
rust: stable
32+
steps:
33+
- uses: actions/checkout@v2
34+
- uses: actions-rs/toolchain@v1
35+
with:
36+
toolchain: ${{ matrix.rust }}
37+
components: clippy
38+
override: true
39+
- name: Lint
40+
run: cargo clippy --all-features
41+
- name: Build and run tests
42+
run: cargo test --all-features
43+
44+
rustfmt:
45+
name: Rustfmt
46+
runs-on: ubuntu-latest
47+
steps:
48+
- uses: actions/checkout@v2
49+
- uses: actions-rs/toolchain@v1
50+
with:
51+
toolchain: stable
52+
components: rustfmt
53+
override: true
54+
- run: cargo fmt -- --check
55+
56+
msrv:
57+
name: MSRV
58+
runs-on: ubuntu-latest
59+
steps:
60+
- uses: actions/checkout@v2
61+
- uses: actions-rs/toolchain@v1
62+
with:
63+
toolchain: stable
64+
override: true
65+
- run: cargo build --all-features

CHANGELOG.md

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,54 @@
11
# Change Log
22

3-
## [Unreleased](https://github.com/sunng87/handlebars-rust/compare/3.4.0...Unreleased) - ReleaseDate
3+
## [4.0.0](https://github.com/sunng87/handlebars-rust/compare/3.4.0...4.0.0) - 2021-05-25
44

55
* [Added] `dev_mode` for registry: templates and scripts loaded from file are always
66
reloaded when dev mode enabled [#395]
77
* [Added] Registry is now `Clone` [#395]
8-
* [Changed] Updated `rhai` to 0.19.6 and above [#391]
8+
* [Added] New built-in helper `len` [#421]
9+
* [Changed] Updated `rhai` to 0.19 and then 0.20 [#391]
910
* [Changed] `#each` helper now renders else block for non-iterable data [#380]
1011
* [Changed] `TemplateError` and `ScriptError` is now a cause of `RenderError` [#395]
11-
* [Changed] `RenderContext::get_partial` now returns `Option<&Template>`
12+
* [Changed] Empty lines around block helpers are now stripped [#404]
13+
* [Changed] **Breaking** `RenderContext::get_partial` now returns `Option<&Template>`
14+
* [Changed] **Breaking** Capitalize names like `HtmlExpression` and `IoError` based on clippy recommendations [#424]
15+
* [Changed] **Breaking** Improved return type of `call_inner` from `HelperDef` to avoid misleading [#437]
1216
* [Fixed] reference starts with `null`, `true` and `false` were parsed incorrectly [#382]
1317
* [Fixed] dir source path separator bug on windows [#389] [#405]
14-
* [Removed] option to disable source map is removed [#395]
15-
* [Removed] `TemplateFileError` and `TemplateRenderError` are removed and merged into
18+
* [Fixed] stack overflow with nested `@partial-block` [#401]
19+
* [Fixed] value access issue when upper block has a base value [#419]
20+
* [Fixed] escape rules for Json string literal [#423]
21+
* [Fixed] **Breaking** zero-arity subexpressions support [#433]
22+
Zero-arity subexpression no longer resolved as variable. The behaviour is now aligned with handlebarsjs.
23+
* [Removed] **Breaking** option to disable source map is removed [#395]
24+
* [Removed] **Breaking** `TemplateFileError` and `TemplateRenderError` are removed and merged into
1625
`TemplateError` and `RenderError` [#395]
1726

27+
## [3.5.5](https://github.com/sunng87/handlebars-rust/compare/3.5.4...3.5.5) - 2021-05-03
28+
29+
* [Fixed] Panic on reporting invalid tag name [#427]
30+
31+
## [3.5.4](https://github.com/sunng87/handlebars-rust/compare/3.5.3...3.5.4) - 2021-03-27
32+
33+
* [Fixed] Json string literal with escape char [#422]
34+
35+
## [3.5.3](https://github.com/sunng87/handlebars-rust/compare/3.5.2...3.5.3) - 2021-02-20
36+
37+
* [Fixed] value access issue when upper block has a base value [#419]
38+
39+
## [3.5.2](https://github.com/sunng87/handlebars-rust/compare/3.5.1...3.5.2) - 2020-12-29
40+
41+
* [Fixed] allow `/` as trailing separator on Windows, backported from master [#405]
42+
43+
## [3.5.1](https://github.com/sunng87/handlebars-rust/compare/3.5.0...3.5.1) - 2020-10-25
44+
45+
* [Fixed] dir source path separator bug on windows [#389]
46+
47+
## [3.5.0](https://github.com/sunng87/handlebars-rust/compare/3.4.0...3.5.0) - 2020-09-23
48+
49+
* [Changed] `#each` helper now renders else block for non-iterable data [#380]
50+
* [Fixed] reference starts with `null`, `true` and `false` were parsed incorrectly [#382]
51+
1852
## [3.4.0](https://github.com/sunng87/handlebars-rust/compare/3.3.0...3.4.0) - 2020-08-14
1953

2054
* [Added] Debug log that can be turned on by using envlog or other implementation, to trace data resolution during rendering [#369]

Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
[package]
22
name = "handlebars"
3-
version = "4.0.0-alpha.0"
3+
version = "4.0.1-alpha.0"
44
authors = ["Ning Sun <sunng@pm.me>"]
55
description = "Handlebars templating implemented in Rust."
66
license = "MIT"
77
keywords = ["handlebars", "templating", "web"]
8-
categories = ["template-engine"]
8+
categories = ["template-engine", "web-programming"]
99
homepage = "https://github.com/sunng87/handlebars-rust"
1010
repository = "https://github.com/sunng87/handlebars-rust"
1111
documentation = "https://docs.rs/crate/handlebars/"
@@ -28,7 +28,7 @@ pest_derive = "2.1.0"
2828
serde = "1.0.0"
2929
serde_json = "1.0.39"
3030
walkdir = { version = "2.2.3", optional = true }
31-
rhai = { version = "0.19.6", optional = true, features = ["sync", "serde"] }
31+
rhai = { version = "0.20", optional = true, features = ["sync", "serde"] }
3232

3333
[dev-dependencies]
3434
env_logger = "0.8"

README.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,8 @@ book](https://doc.rust-lang.org/book/).
2121
### Quick Start
2222

2323
```rust
24-
extern crate handlebars;
25-
#[macro_use]
26-
extern crate serde_json;
27-
2824
use handlebars::Handlebars;
25+
use serde_json::json;
2926

3027
fn main() -> Result<(), Box<dyn Error>> {
3128
let mut reg = Handlebars::new();
@@ -38,6 +35,7 @@ fn main() -> Result<(), Box<dyn Error>> {
3835
// register template using given name
3936
reg.register_template_string("tpl_1", "Good afternoon, {{name}}")?;
4037
println!("{}", reg.render("tpl_1", &json!({"name": "foo"}))?);
38+
4139
Ok(())
4240
}
4341
```
@@ -80,6 +78,7 @@ and clarify in CHANGELOG.
8078

8179
| Handlebars version range | Minimum Rust version |
8280
| --- | --- |
81+
| ~4.0.0 | 1.45 |
8382
| ~3.0.0 | 1.32 |
8483
| ~2.0.0 | 1.32 |
8584
| ~1.1.0 | 1.30 |
@@ -185,7 +184,7 @@ Handlebars 3.0 can be used in WebAssembly projects.
185184
example](https://github.com/seanmonstar/warp/blob/master/examples/handlebars_template.rs)
186185
* Tower-web: [Built-in](https://github.com/carllerche/tower-web)
187186
* Actix: [handlebars
188-
example](https://github.com/actix/examples/blob/master/template_handlebars/src/main.rs)
187+
example](https://github.com/actix/examples/blob/master/template_engines/handlebars/src/main.rs)
189188
* Tide: [tide-handlebars](https://github.com/No9/tide-handlebars)
190189

191190
### Adopters

examples/partials/template2.hbs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{{#*inline "page"}}
22
<p>Rendered in partial, parent is {{parent}}</p>
33
{{/inline}}
4-
{{> (parent)}}
4+
{{> (lookup this "parent")}}

fuzz/.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
target
3+
corpus
4+
artifacts

fuzz/Cargo.toml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
2+
[package]
3+
name = "handlebars-fuzz"
4+
version = "0.0.0"
5+
authors = ["Automatically generated"]
6+
publish = false
7+
edition = "2018"
8+
9+
[package.metadata]
10+
cargo-fuzz = true
11+
12+
[dependencies]
13+
libfuzzer-sys = "0.4"
14+
15+
[dependencies.handlebars]
16+
path = ".."
17+
18+
# Prevent this from interfering with workspaces
19+
[workspace]
20+
members = ["."]
21+
22+
[[bin]]
23+
name = "render_template_no_data"
24+
path = "fuzz_targets/render_template_no_data.rs"
25+
test = false
26+
doc = false
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#![no_main]
2+
use libfuzzer_sys::fuzz_target;
3+
4+
fuzz_target!(|data: &str| {
5+
let tpl = handlebars::Handlebars::new();
6+
7+
let _ = tpl.render_template(&data, &Vec::<u32>::new());
8+
});

src/context.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -78,19 +78,20 @@ fn parse_json_visitor<'a, 'reg>(
7878
}
7979
None => {
8080
if path_context_depth > 0 {
81-
if let Some(ref context_base_path) = block_contexts
81+
let blk = block_contexts
8282
.get(path_context_depth as usize)
83-
.map(|blk| blk.base_path())
84-
{
85-
extend(&mut path_stack, context_base_path);
83+
.or_else(|| block_contexts.front());
84+
85+
if let Some(base_value) = blk.and_then(|blk| blk.base_value()) {
86+
merge_json_path(&mut path_stack, relative_path);
87+
ResolvedPath::LocalValue(path_stack, base_value)
8688
} else {
87-
// TODO: is this correct behaviour?
88-
if let Some(ref base_path) = block_contexts.front().map(|blk| blk.base_path()) {
89+
if let Some(base_path) = blk.map(|blk| blk.base_path()) {
8990
extend(&mut path_stack, base_path);
9091
}
92+
merge_json_path(&mut path_stack, relative_path);
93+
ResolvedPath::AbsolutePath(path_stack)
9194
}
92-
merge_json_path(&mut path_stack, relative_path);
93-
ResolvedPath::AbsolutePath(path_stack)
9495
} else if from_root {
9596
merge_json_path(&mut path_stack, relative_path);
9697
ResolvedPath::AbsolutePath(path_stack)

src/error.rs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,14 @@ use walkdir::Error as WalkdirError;
1212
use rhai::{EvalAltResult, ParseError};
1313

1414
/// Error when rendering data on template.
15-
#[derive(Debug)]
15+
#[derive(Debug, Default)]
1616
pub struct RenderError {
1717
pub desc: String,
1818
pub template_name: Option<String>,
1919
pub line_no: Option<usize>,
2020
pub column_no: Option<usize>,
2121
cause: Option<Box<dyn Error + Send + Sync + 'static>>,
22+
unimplemented: bool,
2223
}
2324

2425
impl fmt::Display for RenderError {
@@ -93,10 +94,14 @@ impl RenderError {
9394
pub fn new<T: AsRef<str>>(desc: T) -> RenderError {
9495
RenderError {
9596
desc: desc.as_ref().to_owned(),
96-
template_name: None,
97-
line_no: None,
98-
column_no: None,
99-
cause: None,
97+
..Default::default()
98+
}
99+
}
100+
101+
pub(crate) fn unimplemented() -> RenderError {
102+
RenderError {
103+
unimplemented: true,
104+
..Default::default()
100105
}
101106
}
102107

@@ -117,6 +122,11 @@ impl RenderError {
117122

118123
e
119124
}
125+
126+
#[inline]
127+
pub(crate) fn is_unimplemented(&self) -> bool {
128+
self.unimplemented
129+
}
120130
}
121131

122132
quick_error! {
@@ -250,7 +260,7 @@ impl fmt::Display for TemplateError {
250260
quick_error! {
251261
#[derive(Debug)]
252262
pub enum ScriptError {
253-
IOError(err: IOError) {
263+
IoError(err: IOError) {
254264
from()
255265
source(err)
256266
}

0 commit comments

Comments
 (0)