Skip to content
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

Tera v2 wishlist/changes #637

Open
Keats opened this issue Jun 3, 2021 · 150 comments
Open

Tera v2 wishlist/changes #637

Keats opened this issue Jun 3, 2021 · 150 comments
Labels

Comments

@Keats
Copy link
Owner

Keats commented Jun 3, 2021

On top of https://github.com/Keats/tera/issues?q=is%3Aopen+is%3Aissue+label%3A%22For+next+major+version%22

Parser

Operator precedence and expressions ✅

Parentheses should work everywhere and precedence should make sense. This is mostly already implemented in a new parser (private for now).

Should something like {{ (get_page(path=“some-page”)).title }} work? Right now it requires going through set which is probably fine imo.

Better error messages ✅

The new parser is hand-written so we can provide detailed error for each type of error. I’m also thinking of spanning all expressions in the AST for better rendering errors but not 100% convinced on that yet, will need to try.

Whitespace management

Do trim_blocks and lstrip_blocks (https://jinja.palletsprojects.com/en/3.0.x/templates/#whitespace-control) by default that can be switched on/off as one thing and not two.

Indexing changes ❔

Right now you can access array indices by doing my_value.0 or my_value[0]. This is in line with Jinja2/Django but it feels a bit weird.

How about allowing only my_value[0] so array index is the same as dict index and more like all programming languages (except tuple access)? The dot syntax doesn’t work when the index is a variable anyway which is probably the main usage of indexing. It would be a big departure from Django/Jinja2 though.

Features

call

https://ttl255.com/jinja2-tutorial-part-5-macros/#call-block is a good example of that feature.
I do find the naming in Jinja2 very confusing though so it would probably be called something different

Investigating valuable ❔

https://tokio.rs/blog/2021-05-valuable
This should avoid an awful lot of cloning and would improve performances a lot. Still not clear whether it will work though.

Improving filters/tests/functions

They should be able to get values from the context implicitely the same way expression do so we don’t have to repeat things like lang=lang in Zola for example.
Maybe a first argument which is something like get_ctx: |key: &str| -> Option<Value>?
It would be nice if there was a way to define the arguments in a better way than the current macros too.
Related issue: #543

Also remove some weird things added to match Jinja2 like #650 (comment)

--

Any feedback / other items you want to change?

@Keats Keats added the question label Jun 3, 2021
@Keats Keats pinned this issue Jun 3, 2021
@KillTheMule
Copy link

Any feedback / other items you want to change?

I'm not yet a tera user, but I gave it a very serious look, because I want runtime templates (using askama for now, which uses compile-time templates). I'm templating latex files, which use brackets (in particular, the curly ones) all over the place, so what I'd need is different delimiters than {{ etc. Is that something you would consider? It would certainly be feasible to restrict this to 2-char delimiters (askama does this, I'm using ~< instead of {{ right now).

@Keats
Copy link
Owner Author

Keats commented Jun 21, 2021

The current parser library doesn't allow passing variables to the lexer and neither does the future lexer library :/
Would adding something [[, [%, [# as equivalent to the curly braces work with Latex?

@KillTheMule
Copy link

Unfortunately, latex also uses [ / ] quite a bit as well, I can't imagine that working except for the most simple documents. I'm pondering trying addition pre/postprocessing steps, but that feels pretty brittle.

@Keats
Copy link
Owner Author

Keats commented Jun 21, 2021

Does it use [[, [%, [# though? Single [/] would be ignored. Otherwise <<, <%, <# but it seems more common to me than squared brackets

@KillTheMule
Copy link

No, [[, [% and [# aren't really used and easily avoided if needed. Is that sufficient, though? Because one could also easily avoid {{ and the like, but other templates libraries if tried (e.g. jinja2) could not deal with the fact that there were single curly braces in the document.

@Keats
Copy link
Owner Author

Keats commented Jun 21, 2021

Tera only cares about {{, {% and {# (and their closing equivalents), a single { or } will not be considered. See #642 for a recent example.

@KillTheMule
Copy link

Huh, that would be awesome. You mention jinja2 in that issue, but I'm pretty sure it did trip over the brackets in the default settings (but jinja2 allows changing the delimiters, so I got it to work). Nevertheless, I'm taking tera for a test-drive tonight, thanks for your time, and thanks for tera!

@KillTheMule
Copy link

After using tera for some time (works nicely, thank you for it!), what I am missing is more fine-grained errors, in particular around rendering a template. When the template has a variable that is missing from the context, the error seems to be a generic Msg type, but I really want to give good feedback to my users (which are very non-technical people, and I cannot assume they speak english), which seems to mean that I have to manually parse the msg string and extract the info that I need. Moreover, if using array variables, it would be great to know which part of the chain was missing (i.e. if using var.field.subfield in a template, and var.field exists, it would be nice to have a possibility to not just show "var.field.subfield missing", but "subfield of var.field missing"... but that's just a shower thought :) A major improvement for me would be to get away from parsing msg strings manually.

@Keats
Copy link
Owner Author

Keats commented Jun 29, 2021

So the next parser has spanned expression pointing to the exact span in the template.
Getting which value didn't exists in an expression like var.field.subfield is a bit more annoying but might be doable. That's a good idea.

@MahaloBay
Copy link

MahaloBay commented Aug 25, 2021

Hi some ideas for v2 :
I believe that there is currently no possibility of negation (or I misread the doc ^^)
For example, i can {% if my_var %} but not {% if !my_var %}, often I found myself having to do {% if my_var %} {%else%} blablabla {% endif %}, same thing in "is containing", i think negation is a good thing to add

EDIT : i search in doc and i find this
image
Maybe i was misread and should using not

@Keats
Copy link
Owner Author

Keats commented Aug 25, 2021

Yep, you have to use not. So {% if not my_var %} and {% if x is not containing(..) %}

@jsha
Copy link
Contributor

jsha commented Oct 13, 2021

Hi! We're starting to use Tera in rustdoc. I like it a lot so far. One thing we're really interested in is performance. Rustdoc generates a lot of HTML in a single run, and there's often a developer waiting to look at the output, so we care a lot about speed. Also, the rustdoc team has put in a lot of effort speeding it up, so we want to make sure the move to templates doesn't slow things down again.

Right now I'm investigating a perf regression after adding a second template. Some themes that come up:

  • malloc and free are responsible for a lot of the regression, suggesting number of allocations might be an issue
  • regex is also fairly big, suggesting get_json_pointer could be sped up (Speed up get_json_pointer #678).
  • BTreeMap::insert shows up high, suggesting that Context::from_serialize is costly.

The valuable crate looks very useful for reducing allocations, and possibly also for replacing the BTreeMap. My thinking is that when the input is a single struct, tera should be able to directly visit each field of the struct by name without building an intermediate BTreeMap of field names -> values.

@Keats
Copy link
Owner Author

Keats commented Oct 13, 2021

We're starting to use Tera in rustdoc.

:o nice!

Performance is the main goal for v2 as well, I'm guessing a lot of allocations you see are from the JSON serialization, which is the bottleneck for Zola as well (minus syntax highlighting). I'm guessing rustdoc is the same (lots of text) that need to be essentially cloned when moving to Value::String.

I have some big hopes for valuable to reduce/remove those allocations but it seems the project stalled a bit.

@jsha
Copy link
Contributor

jsha commented Oct 13, 2021

Has it stalled? Looks like they're planning an initial release as of 8 days ago.

@Keats
Copy link
Owner Author

Keats commented Oct 13, 2021

I am looking at tokio-rs/valuable#59 which would be required for Tera

@KillTheMule
Copy link

One thing I'm wishing for right now was a way to get a template from tera to inspect it. In my case, I can probably just read the file from disc again, but depending on the structure of the program it might be worthwhile to provide something like that (never mind that it might just be faster than reading it again). Maybe a use case would be modifying those on the fly? Or check for certain content? The latter is what I want to do btw.

@Keats
Copy link
Owner Author

Keats commented Oct 14, 2021

You can access a template AST, it's just not visible in the documentation since the AST is not stable.

@Keats
Copy link
Owner Author

Keats commented Nov 5, 2021

It would be nice to have context local functions, it was pulled from v1 due to some breaking changes but it's on the table for v2

@ssendev
Copy link

ssendev commented Dec 19, 2021

I would like to have something like Components from Vue.js which in Tera would probably be macros 2.0.
The difference to current macros being that they not only take arguments but also can have slots blocks.

{% macro user_list(users, user_icon="👤") %}
<ul>
  {% for user in users %}
  <li>
    {% block icon(user_icon, user) %}
      {% if user_icon %}<i class="icon">{{ user_icon }}</i>{% endif %}
    {% endblock %}
    {% block name(user) %}{{ user.name }}{% endblock %}
    {% block default(user) %}<a href="/users/edit/{{user.id}}">Edit</a>{% endblock %}
  </li>
  {% endfor %}
</ul>
{% endmacro %}

{# this uses the default content of all blocks #}
<user-list users="{{users}}"/>
{# rendered #}
<ul><li><i class="icon">👤</i>Aron<a href="/users/edit/1">Edit</a></li></ul>

{# children will be assigned to the default block #}
<user-list users="{{users}}" icon="🧍">
  <span class="disabled">Edit</span>
</user-list>
{# rendered #}
<ul><li><i class="icon">🧍</i>Aron<span class="disabled">Edit</span></li></ul>

{# blocks can be overridden and receive the arguments that are passed #}
<user-list users="{{users}}">
  {% block icon(user_icon, user) %}<i class="icon rounded {{user.color}}">{{user_icon}}</i>{% endblock %}
</user-list>
{# rendered #}
<ul><li><i class="icon rounded red">👤</i>Aron<a href="/users/edit/1">Edit</a></li></ul>

{# when the default block needs arguments it can be called via its name #}
<user-list users="{{users}}">
  {% block default(user) %}<a href="/users/delete/{{user.id}}">Delete</a>{% endblock %}
</user-list>
{# rendered #}
<ul><li><i class="icon">👤</i>Aron<a href="/users/delete/1">Delete</a></li></ul>

{# it would be possible to allow assigning the default block arguments directly but would cause confusion #}
<user-list users="{{users}}" {{ default(user) }}>
  {{ user.name }} {# this works #}
  {% block icon(user_icon) %} {# notice that only the first argument was retrieved #}
    {{ user.name }} {# this doesn't work since user is not defined #}
  {% endblock %}
</user-list>
{# and explicitly calling the default block would still be needed to empty it #}
<user-list users="{{users}}">
  {% block default() %}{% endblock %}
</user-list>
{# rendered #}
<ul><li><i class="icon">👤</i><a href="/users/edit/1">Edit</a></li></ul>

{# shorthand : to avoid {{ }} like in Vue.js and other templating languages might be nice #}
<user-list :users="users">

Using HTML like syntax to call macros might be controversial but I think the result is really neat and leaves the heavy syntax {% %} for control flow more distinct. Syntax wise a similar result could be achieved by leveraging web components but I think the point of server side rendering is to avoid JavaScript which this wouldn't. It's also possible to go all in on web components and make even the macro definitions use HTML syntax via <template> and <slot> but that might be a little too much.

I think this would be a very nice addition to Tera and would allow for seamless use of e.g. Tailwindcss

edit: naming them slot instead of block might still be desirable to avoid ambiguity

@Keats
Copy link
Owner Author

Keats commented Dec 19, 2021

That's extremely unlikely to happen. Tera is not only used for rendering HTML so it can't just change its syntax for one usecase. Something like https://jinja.palletsprojects.com/en/3.0.x/templates/#call is likely to be added though.

@ssendev
Copy link

ssendev commented Dec 19, 2021

Ah of course then that syntax won't fly.

Call is already halfway there but would be improved with the ability to define multiple callers/yield points and to have default content if it's not provided at the call site.

{# the original definition syntax would work but here is an alternate proposal that's closer to call #}
{% macro user_list(users, user_icon="👤") %}
<ul>
  {% for user in users %}
  <li>
    {# a named caller can be defined like this #}
    {{ caller prepend(user) }}
    {# if caller is in {% %} it's a block with default content #}
    {% caller icon(user_icon, user) %}
      {% if user_icon %}<i class="icon">{{ user_icon }}</i>{% endif %}
    {% endcaller %}
    {% caller name(user) %}{{ user.name }}{% endcaller %}
    {% caller(user) %}<a href="/users/edit/{{user.id}}">Edit</a>{% endcaller %}
  </li>
  {% endfor %}
</ul>
{% endmacro %}

{% call(user) user_list(users) %}
  <a href="/users/delete/{{ user.id }}">Delete</a>
{% icon(user_icon, user) %}
  <i class="icon rounded {{ user.color }}">{{ user_icon }}</i>
{% endcall %}
{# rendered #}
<ul><li><i class="icon rounded red">👤</i>Aron<a href="/users/delete/1">Delete</a></li></ul>

To have a library of reusable components macros having these options is extremely useful as can be seen by looking at Vuetify where almost every macro component has multiple callers slots with the most egregious offender probably being v-data-table

@heroin-moose
Copy link

heroin-moose commented Jan 22, 2022

A variant of new() that creates empty Tera instance. For example, I'm writing an application that provides templating. The templates are stored in /usr/share/foobar/templates. However, a user can overwrite them by placing templates to /etc/foobar/templates. In order to keep {% include .. %} working the templates are referenced by relative paths. So basically I need two sets of identically named templates which I obtain by using WalkDir and stripping /etc/foobar/templates and /usr/share/foobar/templates.

@Keats
Copy link
Owner Author

Keats commented Jan 22, 2022

Isn't that Tera::default()?

@heroin-moose
Copy link

Indeed. Thanks, I haven't thought of it.

@rinmyo
Copy link

rinmyo commented Feb 8, 2022

it will be amazing if tera is able to access context. i'm working on KaTeX SSR integration for zola and I really need this feature!

@Keats
Copy link
Owner Author

Keats commented Feb 8, 2022

Yep, accessing the context from filters/functions is definitely something I want to add, partly for Zola as well (so we don't do lang=lang etc)

@Piping
Copy link

Piping commented Feb 18, 2022

is it possible to add a hex function or hex filter to put a number into hex form?

@nulltier
Copy link
Contributor

A note comment about new hand-written parser isn't clear. @Keats are you going to kick off the pest grammar generated parser?

@Keats
Copy link
Owner Author

Keats commented Jun 13, 2024

I've added indent/group_by/filter and made an issue to discuss filters specifically: Keats/tera2#37

@Keats
Copy link
Owner Author

Keats commented Jul 4, 2024

https://github.com/Keats/tera2 now has filters/tests/functions implemented and should be mostly working and is ready for some beta testing.

Next steps are:

  • fixing whatever issues are found (please open issues on the tera2 repo rather than this thread so it's easier to track)
  • add a format filter using the Rust format syntax
  • add filter/tests/fn function compile time checks
  • Easier modification of arrays/maps

And probably some more things like the global macros/macro types/rendering a macro specifically along the way. The macro types can be added later on so it will probably be worked last unless someone wants to implement it.

@uncenter
Copy link
Contributor

Positional arguments is not going to happen, I would use named arguments everywhere in Rust if I could as well.

Is this still the position (pun not intended) on positional arguments? Feels frustrating every time I have a macro/function taking one arg and I have to come up with a name for it. I liked the thought of the first arg or single arg functions being/having positionals?

@Keats
Copy link
Owner Author

Keats commented Sep 15, 2024

Yep still the case

@Pebkac03
Copy link

Pebkac03 commented Sep 19, 2024

One thing that would be nice is the ability to either:

  • Get all variables in a template by adding a method like: get_variables(name) to Tera.
  • Have render produce an error giving all missing variables.

Use case: Building an API in Rust (Axum and tera) where users can get an html-document from a template by specifying the template in the path and field values using headers.

the feature would be useful regardless of performance cost since you could just adapt by either:

  • Checking on each request
  • Checking when template is uploaded and storing separately
  • Adding endpoint for checking (eg. /templates/<template>/info)

@orhun
Copy link
Contributor

orhun commented Sep 19, 2024

Get all variables in a template by adding a method like: get_variables(name) to Tera.

I wrote a function for that in git-cliff in case it helps: https://github.com/orhun/git-cliff/blob/82cc09ff75166b5121f9b446f6ef8216a625c858/git-cliff-core/src/template.rs#L75-L144

@Keats
Copy link
Owner Author

Keats commented Sep 19, 2024

How do you handle branches? Eg if/else?

@orhun
Copy link
Contributor

orhun commented Sep 19, 2024

Not sure if I handle them. I just walk over the AST recursively and fetch anything that looks like a variable.

@Pebkac03
Copy link

Get all variables in a template by adding a method like: get_variables(name) to Tera.

I wrote a function for that in git-cliff in case it helps: https://github.com/orhun/git-cliff/blob/82cc09ff75166b5121f9b446f6ef8216a625c858/git-cliff-core/src/template.rs#L75-L144

Yes it does, is there any reason for a method for Tera with similar functionality to not be implemented that anyone could think of? I feel like it would be useful in many circumstances.

@orhun
Copy link
Contributor

orhun commented Sep 19, 2024

Yeah, I think that'd be pretty nice to have as default.

@Keats
Copy link
Owner Author

Keats commented Sep 19, 2024

is there any reason for a method for Tera with similar functionality to not be implemented that anyone could think of?

You can only know if the output is correct in your own context.

Eg:

{% if a %}
{{ b }}
{% else %}
{{ c }}
{% endif %}

Should it report [a, b, c] even though you might have valid templates where a is not defined in which case you only care about c? Same for a variable used in a for/else branch.
I don't think you can error before rendering a template just based on that

@orhun
Copy link
Contributor

orhun commented Sep 19, 2024

Reporting [a, b, c] would be enough by itself in the context of my use case tbh :)

@Pebkac03
Copy link

Yes, might be better to just add a method to Tera for getting all variables and leaving Tera.render() unchanged. Of course there are cases where not all variables are necessary but I think the scope should, at least initially, be limited to getting all variables of a template and consider changing error behaviour and/or being able to check what is required out of scope

@stellarpower
Copy link

This may have been brought up already, but, I can't think of the right search term.

I'm using Tera from within Zola, and for me it really slows things down always needing to use the {% %} / {{ }} tags to delimit any "code". As well as making it much harder to read.

In jinja, I've previously found it very useful to define my own filters in Python, where I have a more usual programming environment, so it usually makes it easier to implement logic there and expose a new filter than to try and write it within a template. I expect this wouldn't make much sense for Tera, given that it's in Rust, so then some other embedded language would need to be bundled in, and it gets messy.

What would be really nice however, is to be able to write macros in a plain Tera file, without using all the tags, so that it just reads more naturally like other languages. I think that would make working with macros much faster and more pleasant. I expect that might affect parsing, hence mentioning it here and not within Zola, but I may be wrong on that, or maybe it's currently possible an I'm just not using he right keywords in Google.

@Keats
Copy link
Owner Author

Keats commented Oct 11, 2024

I would rather have lua/wasm or similar filters for Zola that users can create than different syntax (how does that even work in practice)?

@stellarpower
Copy link

Lua sounds sensible to me, am sure it would bring up a discussion where different people would prefer a different language, but as it's designed to be embedded and presumably there are easy ways to create rust bindings then sounds like a good option to have.

Either way, it'd still be nice when creating macros to be able to {% include MyMacros.tera %} and have

macro    featureImageURL(page)
    
    # Default to a warning image if the user ha not provided one

    if not page.extra.FeatureImage                                      
        return "https://example.com/NoFeatureImageWarning.jpg"

    else                                                                

        set featureImage = page.extra.FeatureImage                      
        set path         = Macros::pagePath(page = page)                

        if featureImage is starting_with("/")                           
            return featureImage              | safe                   
        else                                                            
            return page.path ~ featureImage  | safe                   
        endif                                                           
    endif                                                               

endmacro featureImageURL

instead of {% include MyMacros.html %} and have

{% macro    featureImageURL(page)             %}

{%     if not page.extra.FeatureImage                                         %}
 	{# Default to a warning image if the user ha not provided one #}
{{         "https://example.com/NoFeatureImageWarning.jpg"   }}

{%     else                                                                   %}

{%         set featureImage = page.extra.FeatureImage                         %}
{%         set path         = Macros::pagePath(page = page)                   %}

{%         if featureImage is starting_with("/")                              %}
{{              featureImage                      | safe                      }}
{%         else                                                               %}
{{              page.path ~ featureImage          | safe                      }}
{%         endif                                                              %}

{%     endif                                                                  %}

{% endmacro featureImageURL                   %}

or

{% macro featureImageURL(page) %}

	{% if not page.extra.FeatureImage %}
 		{# Default to a warning image if user did not provide one #}
		{{ "https://example.com/NoFeatureImageWarning.jpg"   }}

	{% else %}

		{% set featureImage = page.extra.FeatureImage  %}
		{% set path         = Macros::pagePath(page = page) %}

		{% if featureImage is starting_with("/") %}
			{{ featureImage | safe }}
		{% else %}
			{{ page.path ~ featureImage | safe }}
		{% endif %}

	{% endif %}

{% endmacro featureImageURL %}

If we're not actually rendering a template right now, I just find it a lot of extra typing and visual noise that makes it harder for my eye to scan and for my mind to read the code. I have no idea how lisp users survive because I just cannot scan more than three closing brackets of the same type in one go!

@Keats
Copy link
Owner Author

Keats commented Oct 11, 2024

Your example is a very narrow version of a macro. How would you have a macro used to template some Python code without delimiters? Like something that actually has text like return, if, else etc. I mean without even that part, I find the first snippet much worse to read than the 3rd one

@stellarpower
Copy link

Well, possibly not the best use-case for that kind of macro. I'm trying to build a simple site, the macros are there to implement logic and then maybe they have one line rendering the actual content, so the chances of needing to render a keyword or something that looks like code are minimal. I'd expect someone wouldn't want to use the idea if they were. I keep the macros separate from the templates if I can, and if they could return values back to the template rather than render, then personally I'd find that preferable. Having used a number of templating tools I find that's usually where the friction comes in. One is injecting logic into content and the other is injecting content into logic. The way they expand, the scoping rules, include paths, etc. all makes sense in the context of content but are different from their equivalents in most programming languages. I've found it best if there's a way to keep those boundaries separated and the interface as thin as possible. E.g. if I wanted to promote some blog posts to the top of the page based on some tags and how popular they are, it's best to run through manipulating a list of hashmaps to get them in the order, and then let the template decide what to do with those. So I definitely wouldn't complain to having an embedded lua interpreter, doing away with most of the macros and a number of the filters altogether and instead just working in a programming language to achieve things and sending that back up to the template to render.

But either way, I lost a good 20 minutes yesterday wondering what had gone wrong because after needing to copy and paste several times (this was the workaround for sorting, so it was quite a bit longer than the above), my eye simply didn't scan the difference between {{ and {# and that the final line where I actually produced what I needed was commented out, rather than broken and producing an empty list. I'm also having to lint the rendered HTML carefully, because I get massive amounts of whitespace inbetween the braces of the statements, say in the href for an anchor. And then not having single-line comments and then needing to uncomment my comments to comment out whole sections of a macro without causing them to be nested when it doesn't build. For me it's very time-consuming, had much the same experience with Jekyll, Jinja, etc.

@azemlya
Copy link

azemlya commented Oct 14, 2024

Maybe I don't understand something, but why read the raw text of the templates? There are also a bunch of extensions with syntax highlighting Jinja2. For example, VS Code with the extension Better Jinja or Sublime Text is able to highlight the syntax well. Why break your eyes?

@Keats
Copy link
Owner Author

Keats commented Oct 18, 2024

Any thoughts on Keats/tera2#51 ?

@stellarpower
Copy link

stellarpower commented Oct 19, 2024

Maybe I don't understand something, but why read the raw text of the templates? There are also a bunch of extensions with syntax highlighting Jinja2. For example, VS Code with the extension Better Jinja or Sublime Text is able to highlight the syntax well. Why break your eyes?

Syntax highlighting helps, it doesn't always fire up or work properly in my IDE. But the need to type the braces is still an inconvenience and clutters things for me, whatever colour they might be.

I think components make sense, as more of a frontend thing, and then if logic can be somewhat separated then that seems a logical way of approaching it to me. I guess up to now Tera may be emulating the behaviour/ethos of other templating engines that largely work in the same way, but moving away significantly from the way they do things could lead to something better. As mentioned - personally would rather implement e.g. complex sorting programmatically and have that separate from the HTML/UI elements/whatever format is being templated that decide how to display each data item. If embedded Lua is on the table, then it could even be taken as something like each Component is a class and move away from a more text-based expansion approach. Its constructor takes an optional body and some typed arguments and perhaps then the macro call instead also becomes e.g. {{ MyComponent("Hell oworld", 1, 100) }} to insert one i the document there. Or for a body something like

{% MyComponent("Hell oworld", 1, 100) %}
    Body is here
{% end %}

@uncenter
Copy link
Contributor

Syntax highlighting helps, it doesn't always fire up or work properly in my IDE. But the need to type the braces is still an inconvenience and clutters things for me, whatever colour they might be.

FYI I've been working on a Tera-specific Tree-sitter grammar for Neovim/Helix editors if that helps: https://github.com/uncenter/tree-sitter-tera. Planning to make a TextMate version (VS Code and Sublime Text) version at some point in the future once I finish up documenting the Tree-sitter version.

@stellarpower
Copy link

Thanks! If it works in VS Code I will likely take a look some time in the future.

@uncenter
Copy link
Contributor

uncenter commented Oct 22, 2024

Thanks! If it works in VS Code I will likely take a look some time in the future.

As I said originally it only works with Neovim/Helix (and Zed too actually) as it is a Tree-sitter grammar, which VSCode doesn't support. Working on a new TextMate grammar for VS Code right now but it isn't complete or public yet. I can let you know once I finish it, hopefully later this week :)

@stellarpower
Copy link

Yep, that's what I meant. I'll keep an eye out, if you end up creating one :D

@uncenter
Copy link
Contributor

Yep, that's what I meant. I'll keep an eye out, if you end up creating one :D

Now public at https://github.com/uncenter/vscode-tera. Please create issues if you encounter any weird behavior, I'd be happy to fix. Still haven't added embedded HTML support, on my todo though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests