bheisler / tinytemplate Goto Github PK
View Code? Open in Web Editor NEWA small, lightweight template engine
License: Apache License 2.0
A small, lightweight template engine
License: Apache License 2.0
Hey!
The documentation mentions the following:
Although it is possible to use TinyTemplate with template strings loaded at runtime, this is not recommended.
What is the reason behind this? I am currently looking for a fast and rather lightweight templating engine that allows branching as well and after tinkering around with this crate, it seems to work perfectly.
Now, the template can use the syntax {{ call template_name with child_of_context }}
for render template_name
with child_of_context
.
Can it call the template with context which is not the child but itself?
And, for it, why don't you add the syntax {{ call template_name }}
?
Is this project abandoned? Any active forks?
It looks like path traversal currently uses serde_json::Value::get, which supports both string keys for maps and numeric keys for arrays. However, TinyTemplate only invokes the string lookup, so any lookup on an array will fail; this is particularly a hassle for tuples, which serde_json::Value represents as arrays.
This can be fixed by attempting to parse the path element as a usize and using that for value lookup if name lookup fails; doing it only on name lookup failure means that any situations where a map is being constructed with string keys that happen to be parseable as usize will continue to work.
I have a PR ready if this approach sounds reasonable :)
I have a value set to r#"I said "hello" "#
substituited into
let str = r#"{value}"#;
I get
let str = r#"I said "hello""#;
Reproduction:
fn main() {
let data = "{#}";
let mut tpl = tinytemplate::TinyTemplate::new();
let _ = tpl.add_template("template", data);
}
Gives
thread 'main' panicked at 'begin <= end (2 <= 1) when slicing `{#}`', /home/jess/.cargo/registry/src/github.com-1ecc6299db9ec823/tinytemplate-1.2.1/src/compiler.rs:59:31
stack backtrace:
0: rust_begin_unwind
at /rustc/952fdf2a1119affa1b37bcacb0c49cf9f0168ac8/library/std/src/panicking.rs:515:5
1: core::panicking::panic_fmt
at /rustc/952fdf2a1119affa1b37bcacb0c49cf9f0168ac8/library/core/src/panicking.rs:92:14
2: core::str::slice_error_fail
3: core::str::traits::<impl core::slice::index::SliceIndex<str> for core::ops::range::Range<usize>>::index
at /rustc/952fdf2a1119affa1b37bcacb0c49cf9f0168ac8/library/core/src/str/traits.rs:214:21
4: core::str::traits::<impl core::ops::index::Index<I> for str>::index
at /rustc/952fdf2a1119affa1b37bcacb0c49cf9f0168ac8/library/core/src/str/traits.rs:64:9
5: tinytemplate::compiler::TemplateCompiler::compile
at /home/jess/.cargo/registry/src/github.com-1ecc6299db9ec823/tinytemplate-1.2.1/src/compiler.rs:59:31
6: tinytemplate::template::Template::compile
at /home/jess/.cargo/registry/src/github.com-1ecc6299db9ec823/tinytemplate-1.2.1/src/template.rs:124:27
7: tinytemplate::TinyTemplate::add_template
at /home/jess/.cargo/registry/src/github.com-1ecc6299db9ec823/tinytemplate-1.2.1/src/lib.rs:189:24
8: scratchPpQmmMhHJ::main
at ./main.rs:6:13
9: core::ops::function::FnOnce::call_once
at /rustc/952fdf2a1119affa1b37bcacb0c49cf9f0168ac8/library/core/src/ops/function.rs:227:5
I'll make a PR to add the fuzzing harness I used to find this, so you can run it yourself with cargo-fuzz
.
This line should probably be "not[space]" and not "not":
Line 74 in 141836d
Ran into issue where trying to use below template code:
{{ if notes -}} "{notes}" {{- else -}} ##f {{- endif }}
Hi,
TinyTemplate looks ideal for a use-case I have.
The problem is, that I will not generate HTML, so the default formatter that does HTML escaping is a big problem for me (I don't want to add " | unescaped" to every value usage).
Is there a way to change the default formatter?
I looked at the source code and it seems this is not possible. But I'm a Rust beginner, so maybe I'm missing something.
I have a vector of structures, which I want to format. Unfortunately I can't access the root element to loop over it: {{ for item in ??? }} {item.field} {{ endfor }}
. Is it possible? What template should I write?
I have an HTML template to display resource objects, however I have some global context as well.
In JavaScript I would just merge the objects but that is not as easy in a typed language such as Rust.
What is the best way to use multiple context objects with a single template?
Is the project dead?
Just asking...
Anybody aware of good alternatives?
Currently, to use the crate with the @last error fixed, you need to specify the dependency as git repository.
I think it'd be useful to be able to loop over an integer value, as well as the existing array functionality.
Example:
Context:
{
depth: 3,
text: "Test"
}
Template:
"{{ for i in depth }}\t{{ endfor }} {text}"
Thank you for your crate!
I tried to use it and cargo/rustc didn't seem to find the Serialize
trait. I then tried to copy your example in the README.md and it also failed to compile (i did add the dependencies you mentioned):
Updating crates.io index
Compiling proc-macro2 v1.0.18
Compiling ryu v1.0.5
Compiling serde v1.0.114
Compiling unicode-xid v0.2.1
Compiling syn v1.0.33
Compiling serde_json v1.0.56
Compiling itoa v0.4.6
Compiling serde_derive v1.0.114
Compiling quote v1.0.7
Compiling tinytemplate v1.1.0
Compiling tttest v0.1.0 (/tmp/tttest)
error[E0463]: can't find crate for `serde`
--> src/main.rs:8:10
|
8 | #[derive(Serialize)]
| ^^^^^^^^^ can't find crate
|
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
For more information about this error, try `rustc --explain E0463`.
error: could not compile `tttest`.
To learn more, run the command again with --verbose.
I assume that serde_derive
does not contain the Traits necessary to compile this, so instead of depending on serde_derive
, the README should use serde = { version = "1.0", features = ["derive"] }
, as written in serdes documentation. It then follows that the example code should use
use serde::Serialize;
instead of
#[macro_use]
extern crate serde_derive;
the distributed crate for tinytemplate appears to have almost all files marked as executable:
$ wget -O - -q 'https://crates.io/api/v1/crates/tinytemplate/1.2.1/download' | tar tvz
-rwxrwxrwx 1000/1000 1249 2021-01-03 14:00 tinytemplate-1.2.1/.github/workflows/ci.yml
-rwxrwxrwx 1000/1000 30 2019-01-26 09:01 tinytemplate-1.2.1/.gitignore
-rwxrwxrwx 1000/1000 1912 2021-03-03 18:56 tinytemplate-1.2.1/CHANGELOG.md
-rwxrwxrwx 1000/1000 2629 2019-01-26 09:01 tinytemplate-1.2.1/CONTRIBUTING.md
-rwxrwxrwx 1000/1000 596 2021-03-03 18:56 tinytemplate-1.2.1/Cargo.toml.orig
-rw-r--r-- 0/0 1183 1969-12-31 19:00 tinytemplate-1.2.1/Cargo.toml
-rwxrwxrwx 1000/1000 10847 2019-01-26 09:01 tinytemplate-1.2.1/LICENSE-APACHE
-rwxrwxrwx 1000/1000 1057 2019-01-26 09:01 tinytemplate-1.2.1/LICENSE-MIT
-rwxrwxrwx 1000/1000 4724 2021-01-03 15:43 tinytemplate-1.2.1/README.md
-rwxrwxrwx 1000/1000 1469 2019-01-26 09:01 tinytemplate-1.2.1/benches/benchmarks.rs
-rwxrwxrwx 1000/1000 27364 2021-01-03 15:28 tinytemplate-1.2.1/src/compiler.rs
-rwxrwxrwx 1000/1000 7313 2021-03-03 18:54 tinytemplate-1.2.1/src/error.rs
-rwxrwxrwx 1000/1000 3382 2021-01-03 15:28 tinytemplate-1.2.1/src/instruction.rs
-rwxrwxrwx 1000/1000 8460 2021-01-03 14:53 tinytemplate-1.2.1/src/lib.rs
-rwxrwxrwx 1000/1000 6721 2021-01-03 14:53 tinytemplate-1.2.1/src/syntax.rs
-rwxrwxrwx 1000/1000 33095 2021-01-03 15:37 tinytemplate-1.2.1/src/template.rs
-rw-r--r-- 0/0 74 1969-12-31 19:00 tinytemplate-1.2.1/.cargo_vcs_info.json
$
typically, source code files are not marked as executable.
On debian systems, this causes executable-not-elf-or-script lintian warnings for the rust-tinytemplate-dev
package.
I'm not sure how you're generating the crates for tinytemplate, but it looks like they could be generated in a way that avoids setting the execute bit on each source file.
This line
Line 322 in cff1932
Some(float) => float != 0.0,
Since a number should be truthy if it is not equal to 0.
$ find ~/.cargo/ -perm /002
/home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tinytemplate-1.2.1/.github/workflows/ci.yml
/home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tinytemplate-1.2.1/.gitignore
/home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tinytemplate-1.2.1/CHANGELOG.md
/home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tinytemplate-1.2.1/CONTRIBUTING.md
/home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tinytemplate-1.2.1/Cargo.toml.orig
/home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tinytemplate-1.2.1/LICENSE-APACHE
/home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tinytemplate-1.2.1/LICENSE-MIT
/home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tinytemplate-1.2.1/README.md
/home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tinytemplate-1.2.1/benches/benchmarks.rs
/home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tinytemplate-1.2.1/src/compiler.rs
/home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tinytemplate-1.2.1/src/error.rs
/home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tinytemplate-1.2.1/src/instruction.rs
/home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tinytemplate-1.2.1/src/lib.rs
/home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tinytemplate-1.2.1/src/syntax.rs
/home/user/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tinytemplate-1.2.1/src/template.rs
This indicates that this crate has world writable permissions. This has been fixed in cargo (CVE-2023-38497), but that will not help for people using older versions of rust than 1.71.1 (e.g. stuck on old versions provided by their Linux distro, etc).
As such, it would be beneficial to fix this in the package as well.
my template:
{{< hint [info] >}}
TKTK
{{< /hint >}}
I don't want the {{
to be parsed by tinytemplate, it's for another parser
I want to use TinyTemplate for an Actix Web application, but I run into problems making my TinyTemplate object lazy_static because it does not have the Sync trait. Is it possible to add that or is there a technical reason for that? I could understand that a mutable TinyTemplate object could add a template while another thread calls the render function but why can't two threads use the render function at the same time when they have non-mut reference? Is it recommended to just recreate a new TinyTemplate object every time render()
is used or is it faster to reuse the same object and add some synchronization code? Or should I clone the object once for each CPU core and use some kind of pool? Is it possible to share a pointer to just the render() function and use that in a thread safe manner?
Sorry if those are basic questions, I'm still new to Rust, but TinyTemplate works very well for my use case but right now I recreate the TinyTemplate every time I need it and wonder if I'm doing it wrong.
I'm not sure if this is specific to the file I was working with or if it applies to all file that use curly braces, but I wanted to bring it up anyway.
It seems TinyTemplate uses just opening and closing curly braces { } to denote places to insert values into the template file.
I'm working on a project that generates a JavaScript project workspace and needs to insert some values into a few default JS files. However, when I try to use a JS file as a template, the TinyTemplate errors out, telling me that a matching curly brace is missing.
I have some JS like this:
const myObj = {
projectName: "{project_name}"
};
TinyTemplate should insert the value of project_name into this JS object, but TinyTemplate sees the opening brace of myObj as as signaling the start of an injection point for the templating engine and then breaks when it sees the first opening brace of the actual injection point.
Personally, I'd love to use TinyTemplate for my project because I really only need minimal templating capabilities so other options would bloat out my app unnecessarily. Are there any plans in the future to make TinyTemplate compatible with JavaScript files and other formats that use curly braces extensively?
Adding a template with an escaped opening curly brace, \{
, causes a panic by core::str::slice_error_fail
originating from tinytemplate::compiler::TemplateCompiler::compile
.
Minimal test case:
use tinytemplate::TinyTemplate;
static TEMPLATE: &str = r#"hello \{world}"#;
fn main() {
let mut tt = TinyTemplate::new();
tt.add_template("template", TEMPLATE).expect("Unable to add template");
}
The panic isn't caused by expect
, as shown in the backtrace.
Backtrace:
thread 'main' panicked at 'byte index 8 is out of bounds of `{world}`', src/libcore/str/mod.rs:2010:9
stack backtrace:
0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
at src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:39
1: std::sys_common::backtrace::_print
at src/libstd/sys_common/backtrace.rs:70
2: std::panicking::default_hook::{{closure}}
at src/libstd/sys_common/backtrace.rs:58
at src/libstd/panicking.rs:200
3: std::panicking::default_hook
at src/libstd/panicking.rs:215
4: std::panicking::rust_panic_with_hook
at src/libstd/panicking.rs:478
5: std::panicking::continue_panic_fmt
at src/libstd/panicking.rs:385
6: rust_begin_unwind
at src/libstd/panicking.rs:312
7: core::panicking::panic_fmt
at src/libcore/panicking.rs:85
8: core::str::slice_error_fail
at src/libcore/str/mod.rs:0
9: tinytemplate::compiler::TemplateCompiler::compile
10: tinytemplate::TinyTemplate::add_template
11: test_case::main
12: std::rt::lang_start::{{closure}}
13: std::panicking::try::do_call
at src/libstd/rt.rs:49
at src/libstd/panicking.rs:297
14: __rust_maybe_catch_panic
at src/libpanic_unwind/lib.rs:87
15: std::rt::lang_start_internal
at src/libstd/panicking.rs:276
at src/libstd/panic.rs:388
at src/libstd/rt.rs:48
16: main
17: __libc_start_main
18: _start
This has been tested on both cargo 1.34.0 (6789d8a0a 2019-04-01)
and cargo 1.36.0-nightly (759b6161a 2019-05-06)
.
right now I'm using
{ thing }
to print a variable, but this is colliding with LaTeX blocks in my text. Is it possible to change that to something like
<[ thing ]>
I try to use custom formatter with index like this: { @index | my_formtter }
.
When I try to render the template it fails with the following message
Failed to find value '@index' from path '@index'.
If I remove formatter everything works as expected.
Thank you for this very nice project. I love the simple and low-dependency philosophy.
Somewhat not in that vein: what would you think about supporting iteration over maps/objects? Currently iteration is restricted to arrays. Following the standard syntax in other templating languages, it could look something like this:
{{ for key, value in guests }}
The key is {key} and the value is {value}
{{ endfor }}
I poked around the code to see what the implementation would be like, and I think it would be straightforward (I would do it):
We would add a new instruction similar to PushIterationContext
. Perhaps PushObjectIterationContext(Path<'template>, &'template str, &'template str)
where the enum payload is (path to the map, key variable name, value variable name).
In the compiler, the parse_for
function would be changed to split the key name on ,
, and then construct either a array iteration spec (no commas), an object iteration spec (1 comma) or an error (2 or more commas).
The new instruction would have to be implemented in template.rs
. This would follow array iteration, probably with a new ContextElement
.
When compiling a project that uses criterion
, which has tinytemplate
as a dependency, I get this compilation error when cargo tries to build it:
error: unknown `doc` attribute `Hidden`
--> <SNIP>/tinytemplate-1.2.0/src/error.rs:44:11
|
44 | #[doc(Hidden)]
| ^^^^^^
error: aborting due to previous error
error: could not compile `tinytemplate`
To learn more, run the command again with --verbose.
warning: build failed, waiting for other jobs to finish...
error: build failed
My version of Cargo is cargo 1.52.0-nightly (572e20153 2021-02-24)
.
Hello
I tried to use tinytemplate to create powershell script.
However, unlike HTML, ps scripts use braces everywhere.
Do you think it would be possible to add a way to change to another pair ?
regards
TinyTemplate converts the context structure to serde_json::Value
internally so that it can look up values by string keys. This introduces a dependency on serde_json
even though we don't really do any JSON serialization. If TinyTemplate had its own version of Value
which could be constructed by a custom serde
serializer, we could drop serde_json
and only depend on serde
.
This is not a high priority for Criterion.rs (which depends on serde_json
anyway). I would be happy to accept a pull request though.
My project contains a large number of {}/{{}}-like strings (such as in CSS or FreeMarker), and I can't escape them all with .
Is there a way to customize the placeholder symbols, for example, I want to use <%xxxxxx%> instead of {xxxxxx}, so I don't have to modify existing files?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.