-
Notifications
You must be signed in to change notification settings - Fork 20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Visitor holding Value
#53
Comments
For most of this, it seems like we need a "pointer" concept similar to a JSON pointer, which should be totally doable as an additional trait fn.
I'm not following this, why does |
You have a few specific variables available in a loop that require knowing the length and the current index of the item and (not yet implemented in Tera) a variable holding the previous and next item: https://jinja.palletsprojects.com/en/3.0.x/templates/#for |
Hmm, Ok. It may be worth considering switching Is |
Not for Tera at least |
What does fixed-sized list in the context of valuable mean? How does it differ from |
@taiki-e the main difference is that it would not be permitted to have an unknown length. i.e. instead of targeting any |
Actually in template/expression engine we might not use the visitor pattern for all cases. I prefer |
With #59 working with strings, it should work well. |
As long as |
@sunng87 for fast lookups, using |
|
I see. Thank you for clarification. |
As requested on the discord, posting a detailed issue about trying
valuable
for Tera.Background
I am trying to see if valuable could replace
serde_json::Value
for Tera.The goal in a template engine is to find the value the user wants to use in a given context.
Right now, the context in Tera is just
serde_json::Value
, which means we serialise everything even though we don’t really need it. See https://docs.rs/tera/1.10.0/tera/struct.Context.html for examples of Context.In Tera, you need to evaluate expressions based on the context. For example:
{{ get_metadata(path=page.path ~ “image.jpg”) }}
: this concatenates into a single string which is then passed as an argument to a function{% if user.is_admin or data.public %}
: this evaluates the fields truthiness{{ item.price * current_rate | format_currency }}
: this multiplies the value found in the context and then applies a filter on the output{% for result in data.results[user.birth_year] %}
There are more examples on the Tera documentation: https://tera.netlify.app/docs/
If you are familiar with Django/Jinja2/Twig/Liquid this is essentially the same thing.
The way it currently work is the following:
user.birth_year
in the example. If the value is an integer, we assume it’s the index of the array so we don’t change anythingValue
kind: if we’re doing a math operation like*
, we need to make sure both operands resolve to aValue::Number
for example, string concatenation with~
only work onValue::String
and so onWhere valuable comes in
As mentioned, it currently serialises the whole context which can be very costly. For example, rendering a section in a Zola site will clone the content of all the sub-pages if pagination isn’t set up, which can quickly become slow.
The whole Tera cloning the context is actually one of the biggest current perf bottleneck in Zola as you need to clone the content every time you render the page, which can be pretty big considering it’s potentially thousands of HTML pages.
Examples
What I’d like to accomplish is be able to visit the context and extract the
Value
for each identifier. Let’s use https://github.com/tokio-rs/valuable/blob/master/valuable/examples/print.rs as an example data and say that theperson
variable is our context.{{ name }}
The path is
[“name”]
so we only need to visit Structable and Mappable and look for that key{{ addresses.1.city }}
The path is
[“addresses”, 1, “city”]
. We visit Structable/Mappable because it begins with a string and visit the field where it is equal toaddresses
. This is an array so we visit Listable. We know we want to only care about the element at index 1 so we could only visit that one ideally (see #52). Once there, there is onlycity
left to match so we visit in Structable/Mappable again.{% for address in addresses %}
Here we want to iterate on the
Vec<Address>
so I think we just need to visit the addresses and get aVec<Structable>
which we visit in its entirety one by one (since you canbreak
from the loop).The goal
In all cases above we want to get the
Value
corresponding to the path out of thevisit
and pattern match later. Sincevisit
doesn’t return anything, I need to store it on the visitor struct. TheValue
found could be a primitive, a Mappable/Structable (for loops on key values) or not found at all.However I get a lifetime error if I try to assign a
Value
in a small toy example: https://gist.github.com/Keats/150acda601910c5f8a6bd9aceba2ddfd so I’m not sure how I would accomplish that. Is there an example of a visitor holding a Value somewhere?The article at https://tokio.rs/blog/2021-05-valuable specifically mention template engine so I’m wondering if the idea was limited to writing the value to a string buffer or whether it is too limited for Tera.
The text was updated successfully, but these errors were encountered: