Giter Site home page Giter Site logo

Can we keep type safety ? about tera HOT 35 CLOSED

keats avatar keats commented on August 25, 2024 2
Can we keep type safety ?

from tera.

Comments (35)

Keats avatar Keats commented on August 25, 2024

Will be even harder if we pass functions instead of custom templatetags

from tera.

untitaker avatar untitaker commented on August 25, 2024

When starting webdev in Rust I thought about having a templating engine that compiles all templates down to normal functions at compiletime. That would solve this issue and also give you compile-time template validation without having to pay the same cost at runtime.

from tera.

untitaker avatar untitaker commented on August 25, 2024

And I realize this idea has been brought up many times before, but so far what I am missing from all of them is everything every other templating library provides:

  • Templates in separate files
  • Bound to the filesystem, so it's easy to include other templates by path relative to basepath
  • Blocks

from tera.

Keats avatar Keats commented on August 25, 2024

The main issue I have with the template -> rust approach is how would it work for use of the library in a self contained way.

For example let's say I make a static website generator like http://gohugo.io/, I want to just use my hugo binary, have some markdown/html files and have the output in the end. If I have to go through a build.rs compilation, this use-case is not possible afaik?

I'm not sure either how it would generate some of the code and I don't see how to give meaningful error reporting.

Either way that's something that needs an answer before adding more code since I don't think we can retrofit type safety after adding more features

from tera.

Keats avatar Keats commented on August 25, 2024

One potential solution would be to have 2 renderers: one typesafe (ie need a build.rs) and one not typesafe that can be used without rust.
Downside is that you would be limited to what is possible in the unsafe mode, ie no rust or random function call which isn't a bad thing in itself.

Not sure if that would work but that's the only idea i've got so far to work in both usecase but it seems like it should be almost 2 different libraries.

from tera.

llogiq avatar llogiq commented on August 25, 2024

If the type system doesn't suffice, we could add one or more lints to ensure safety.

from tera.

Keats avatar Keats commented on August 25, 2024

I'd be interested to hear from people that have experiences with codegen in rust if my plan above is sound or whether it should really be 2 different libraries.

from tera.

Keats avatar Keats commented on August 25, 2024

@untitaker would the plan above be what you had in mind ?

from tera.

untitaker avatar untitaker commented on August 25, 2024

I didn't think about static site generators at all, good point. I think you might be able to define the untyped interface in terms of the typed one, where each type is rust_serialize::json::Json (or serde's equivalent).

You might get away with pretty strong typing even for static site generators, if only the template is dynamically loaded (and not the render context's type).

from tera.

Keats avatar Keats commented on August 25, 2024

The issue is that type safety would require code generation which would need having rust compiler so loading a template dynamically wouldn't work unless I'm missing something.

from tera.

Keats avatar Keats commented on August 25, 2024

Maybe Tera doesn't need to support static sites generators, there are enough of those already

@untitaker @llogiq any idea on what would be the best way to generate code? I have some time next week so planning to work on that a bit. The easiest would be a template file using something like mako/handlebars that I fill I think? Seems much easier than dealing with the AST as well

from tera.

llogiq avatar llogiq commented on August 25, 2024

If you use a build script, you can check arbitrary files by creating the respective source and compiling with -Z no-trans. This allows you to embed proofs in the type system that don't need to appear in the final code

from tera.

untitaker avatar untitaker commented on August 25, 2024

I don't really see the difference in complexity between a macro accepting a path vs a string literal. rust-peg is an example for a syntax extension that supports both, though it uses Rust Nightly APIs instead of Syntex.

On 22 April 2016 23:31:59 CEST, Vincent Prouillet [email protected] wrote:

Maybe Tera doesn't need to support static sites generators, there are
enough of those already

@untitaker @llogiq any idea on what would be the best way to generate
code? I have some time next week so planning to work on that a bit. The
easiest would be a template file using something like mako/handlebars
that I fill I think? Seems much easier than dealing with the AST as
well


You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub:
#24 (comment)

Sent from my Android device with K-9 Mail. Please excuse my brevity.

from tera.

Keats avatar Keats commented on August 25, 2024

I don't get what you mean @untitaker? Also curious of what @mitsuhiko think of a typesafe template engine.

In my mind, you would have the template like now and it would build a .rs file containing functions like render_user_profile (for user/profile.html).
The user would have to specify the types of variables in the template though (ie something like {{ types user=&User friends=Vec<User> }}) so we can build the params for the templates method.
With that in place, we might be able to get rid of serde dependency, but i'm not sure how filters would work without it right now.

from tera.

untitaker avatar untitaker commented on August 25, 2024

@Keats Then I am unsure what you mean with:

Seems much easier than dealing with the AST as well

from tera.

Keats avatar Keats commented on August 25, 2024

Generating the .rs file by building a rust AST with syntex for example

from tera.

Alex-PK avatar Alex-PK commented on August 25, 2024

I am writing exactly a static site generator in Rust, and I got interested in Tera because I dislike handlebars syntax, while I like jinja2/twig syntax.

The same problem with not being able to generate templates at compile time can happen in medium-to-large teams, where templating is done by frontenders. This would also exclude theming for any application, be it web or not. For example: imagine I want to package a rust software like they do with Electron and allow the user to download themes.

I don't think it's a good idea to go "fully static compiled". It would cut off a lot of use cases and a lot of people.

The idea of two renderer seems interesting, but poses the problem of objects' methods, that could be resolved in the compiled version but not in the dynamic one. It wouldn't be much of a problem, though, as if I use the template as dynamic, I will know I won't have objects in there, but just strings/numbers/bools and arrays and hashes of them.

In this mode, the "declaration block" would be completely ignored in the dynamic version and enforced in the static one.

Filters could be an interesting problem. A solution could be just leveraging a ToString or a ToFilterArgument trait in the object, transforming everything to string (possibly a JSON string) before passing it to the filter. This would mimic the Unix pipes behaviour and allow the same filter to work for both static and dynamic templates.

In the end the user writing the template will be aware of the differences, and be able to choose what to use based on the project's requirements.

from tera.

Keats avatar Keats commented on August 25, 2024

Good points.

I'm a bit afraid how complicated it will be to have both typesafe and non-typesafe in the same package though. It would be nice for the end use to be able to use both from the same crate though and the parsing will be almost be the same.

For the object methods, I don't think I would allow it in the typesafe anyway since that would make template logic too complex imo (and my opinion on that can be changed of course).

I think one way to do it would be to have the dynamic templates working and fully featured (currently missing filters and custom fns) and then try to add some codegen on top of that engine.

from tera.

Keats avatar Keats commented on August 25, 2024

Good comment from yesterday's meetup: instead of having

render_user_profile(title, user, friends, theme, blabla)

we could have

render_user_profile(data: UserProfileData)

where the struct would have been generated for us

from tera.

mitsuhiko avatar mitsuhiko commented on August 25, 2024

I thought about the concept of type safe template engines quite a bit. I think one big problem is that a not insignificant reason of why templates are being used is that templates can be user supplied so requiring compilation via rustc seems to be quite inhibitive of this. Unless this can be accomplished without rustc I would recommend just not exploring that area too much.

Object methods turned out to be amazing in Jinja. They allow you to move complexity and logic out of the template code into the application. It might not be completely unreasonable to have methods work in Tera but this might require compiler plugins.

Right now the fact that Tera is limited to JSON is a bit limiting. In particular the problem arrives not being able to differentiate between HTML strings and strings as well as not having a date/time type available.

I feel like this is something that should be explored in detail because categorically rejecting non JSON types and methods will cause problems in the longer term.

from tera.

Keats avatar Keats commented on August 25, 2024

@mitsuhiko how would you handle data without Json? I'll take any good ideas, i'm currently adding filters and it would be nice to keep the types of the args, which I could do by having a HashMap<String, Json> but it makes JSON used in the parser as well.
I could do like Serde and have a Value enum type but I would need to add custom derive to make it on par with Serde, so maybe once macros 1.1 are in.

I came to the same conclusion for typed templates, it's a nice idea but in practice not something I'd need I think.

from tera.

mitsuhiko avatar mitsuhiko commented on August 25, 2024

@Keats i'm toying around with a few things. My thinking is that the best course of action will be to have a custom trait with compiler plugin now that this becomes a possibility.

from tera.

Keats avatar Keats commented on August 25, 2024

@mitsuhiko I came to the same conclusion in #45
For now i implement filters with serde_json but that should be easy to swap out later on

from tera.

mitsuhiko avatar mitsuhiko commented on August 25, 2024

I wonder if it's possible to support methods that way as well in a way.

from tera.

Keats avatar Keats commented on August 25, 2024

https://github.com/djc/askama is using macros 1.1 to get templates compiled to Rust code

from tera.

bitemyapp avatar bitemyapp commented on August 25, 2024

I use http://hackage.haskell.org/package/shakespeare in my day to day work and it's quite lovely. In fact, the only thing I don't like about it is that it's HAML-esque instead of plain HTML like Jinja templates.

One of my favorite things about it was the type-safety. Shakespeare has type-safe templates by default, but it is capable of parsing and rendering templates at runtime by reusing the already-extant code that gets executed at compile-time. This is possible in large part because of Template Haskell, I don't know the state of Rust macros well enough to say whether that is possible in Rust or not.

I would urge you to remember that the best of both worlds does in fact exist and has been done before.

from tera.

Keats avatar Keats commented on August 25, 2024

I'm not against it in principle if you can have both compiled + interpeted but for my own use-cases, I should be able to use templates without Rust/Cargo. That constraint removes many good things a compiled template offer.

Can you run shakespeare templates without having ghc installed? Also how long does templates compilation take on your projects (I'm curious)?

from tera.

bitemyapp avatar bitemyapp commented on August 25, 2024

Can you run shakespeare templates without having ghc installed?

I'm not certain what this question means. Let me turn it around so you understand, "can you render a Jinja2 template without having Python installed?"

The "best of all worlds" as I understood it was being able to have type-safety at compile-time for templates baked into the app, but also have your app be able to accept arbitrary templates as input for rendering at runtime. This is relatively trivial with Hamlet's TH is lifting ordinary Haskell code into the compile time execution environment.

Template compilation is fast as long as the template is quasi-quoted in a Haskell module, which I usually do. You can have templates in separate files, but then it's a touch slower.

from tera.

Keats avatar Keats commented on August 25, 2024

I'm not certain what this question means. Let me turn it around so you understand, "can you render a Jinja2 template without having Python installed?"
Jinja2 no, Go templates yes.

Sorry i wasn't clear, let me give you some of my own current usecases for templates engine:

  1. User defined templates from non-technical users, ie can't ask people to write code in it
  2. Static-site engine: I want a single binary that can compile/live reload templates without anything specific installed

I don't really write any templates in the backend itself these days, except for extending flask-admin or the django admin.

from tera.

bitemyapp avatar bitemyapp commented on August 25, 2024

User defined templates from non-technical users, ie can't ask people to write code in it
Static-site engine: I want a single binary that can compile/live reload templates without anything specific installed

Those are both served by runtime rendering of templates. Presumably they'd be using a static site generator written in Rust, or the web app is written in Rust.

from tera.

Keats avatar Keats commented on August 25, 2024

I'm wondering if there's some miscommunication going on.
Can you create a binary with 0 template in it, give it to someone like me without ghc and let me write templates, have the binary parses all those templates and render them, have 10ms live-reload when I edit them etc?
Shakespeare seems to allow arbitrary Haskell code in its template (according to http://www.yesodweb.com/book/shakespearean-templates#shakespearean-templates_interpolation) so unless it embeds ghc, I don't see how it could possibly read and compile some random templates I'm writing with random data.
I might be missing something though.

Either way, I'm not planning to implement it since I wouldn't really use myself it but if someone wants to try it, I can make anything they need from Tera is available.

from tera.

untitaker avatar untitaker commented on August 25, 2024

BTW https://github.com/djc/askama implements type-safe templates, but doesn't support the static site generator usecase.

Shakespeare appears to be compile-time as well. There is no indication that you can compile templates at runtime without linking ghc.

from tera.

Keats avatar Keats commented on August 25, 2024

@untitaker Askama is pretty close to what you were describing at the beginning of the thread, what are your thoughts on it?

I don't think it would be possible to have a crate working as both interpreted and compiled, since with compiled you end up having to use Rust in the template (https://github.com/djc/askama/blob/master/testing/templates/option.html for example) and Haskell in Hamlet.

from tera.

untitaker avatar untitaker commented on August 25, 2024

from tera.

Keats avatar Keats commented on August 25, 2024

Closing this, that's not going to happen

from tera.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.