Coder Social home page Coder Social logo

Comments (33)

brycefisher avatar brycefisher commented on May 18, 2024

rust-mustache is pretty decent.

I'm not sure about making this middleware. Do mean create a new piece of middleware that acts as the templating engine?

I'm familiar with how Express does this for NodeJs. The developer configures Express to pass through res.render() invocations to the templating engine. The developer also supplies template director(y|ies). Do you plan to create something similar?

from iron.

reem avatar reem commented on May 18, 2024

This is tricky, because we'd like the method to be implemented on Response but access some form of app-global configuration - you'd set up the templating by adding a Middleware with some options on it like the templating engine and template directories, but I'm not sure how that information gets to res.render.

This are good thoughts to be having, but I'm not sure what the answer is.

from iron.

brycefisher avatar brycefisher commented on May 18, 2024

I just realized that Mixins would make Middleware an ideal way to provide a replaceable templating engine. Sorry I'm a little slow on the uptake.

Perhaps, we could establish a convention that a particular Alloy entry (maybe something like a Vec of Path objects) contains the directories for whatever template engine Middleware is used. There could be a Hashmap in Alloy for per-engine app-wide configuration settings.

A third part of the convention could be that a piece of middleware acting as the render engine would provide a res.render() method via Mixins.

How does that strike your fancy?

from iron.

reem avatar reem commented on May 18, 2024

I think it's cleaner to just provide a Templating trait that any template engine could implement, then you provide an instance of that trait to the templating middleware and it uses that for res.render. My main concern is that res.render would have no access to the Alloy and therefore no access to any configuration.

This is solvable by placing a second Alloy in Response, but I'm not sure if that's the way to go. I think there is a better, more general way to do app-wide configuration than this, but I'm not sure how yet.

Maybe the best way would be to add a global-configuration Alloy on each Iron instance - then provide a &-reference to the app in both request and response? This is fast but also quite convenient, and could in fact be made memory efficient by storing the global Alloy behind an Arc, so it is not cloned for each request.

from iron.

brycefisher avatar brycefisher commented on May 18, 2024

Yes! That's essentially what express does with app.set(key, value) and app.get(key). Is no other way to provide config, other than in fn arguments?

It seems like there may be other app-wide configuration needs that may come along anyway -- there should a simple app-wide in memory data-store ready to go.

from iron.

reem avatar reem commented on May 18, 2024

I'm only concerned that adding a reference to the app in Request and Response makes testing trickier - right now I've managed to create a small mocking library for Request and Response that does not have to resort to unsafe anywhere (https://github.com/reem/iron-test) but an app reference may make that trickier.

from iron.

brycefisher avatar brycefisher commented on May 18, 2024

Ugh -- that would suck. Hmmm, maybe we could check for an environmental variable (IRON_VIEWS) and fallback to a default directory for templates (./views). I'm not sure if I'm in love with this idea, but it should prevent any unsafe could or references back to Iron in res or req...

I saw that repo. I'm super excited to play with that.

from iron.

reem avatar reem commented on May 18, 2024

There's way too much of std::mem::unitialized in our tests right now, so that would be great to fix.

I'd really rather not fall back to an environment variable. Maybe, instead of a global persistent reference to Iron, we could just have a global persistent reference to some sort of global preferences object that only coincidentally happens to be stored on Iron.

I think that we'll find, however, that there may be a need for a general-purpose Alloy-like structure on Response.

from iron.

brycefisher avatar brycefisher commented on May 18, 2024

Yeah, relying only on environment variables is wrong.

from iron.

reem avatar reem commented on May 18, 2024

I think there needs to be a dedicated way to immutably access shared global configuration. More thoughts to come.

from iron.

reem avatar reem commented on May 18, 2024

I think the solution is to include a config: Arc<AnyMap> in both Request and Response. This allows easy global configuration and is pretty easy to mock in tests.

from iron.

brycefisher avatar brycefisher commented on May 18, 2024

I think this is the most ergonomic solution. Would it make any difference if the config is accessed in Response or Request? It feels wrong to provide the same information in two places, but I can't think of any particular problems with this idea.

from iron.

reem avatar reem commented on May 18, 2024

I think providing access to config in both places is perfectly fine.

from iron.

reem avatar reem commented on May 18, 2024

The configuration problem is mostly solved through the Read variant in Persistent and the interface it exposes.

from iron.

Valve avatar Valve commented on May 18, 2024

I don't know if this question is relevant, just curious if it's possible to compile a view as part of the build process. For example there is play! framework for Scala, where views are normal scala files, statically checked and compiled by the scala compiler (https://playframework.com/documentation/2.3.x/ScalaTemplates). I wonder if it's possible to do the same in Rust.

from iron.

reem avatar reem commented on May 18, 2024

You can definitely do this with a syntax extension, or even without one if you are willing to lose a bit of expressiveness. However, I think that's probably the domain of a templating engine, not this middleware.

from iron.

aochagavia avatar aochagavia commented on May 18, 2024

it could be interesting to look at the way Nickel has implemented mustache support

from iron.

reem avatar reem commented on May 18, 2024

@aochagavia They have done much of the work that we'd like to do, but I'd much rather be templating engine agnostic and support a richer interface - notably nickels .render only allows HashMap<&'static str, &'static str> which means that you can't render a template with dynamic data, like from a database.

from iron.

allan-simon avatar allan-simon commented on May 18, 2024

as someone was noting for scala, in cppcms , a webframework in C++ (so in the same segment of "compiled language") the use template file , that get compiles into C++

basically the idea is that your template file is converted into a C++ class + a name , which is then added to a hashmap, then in your "controller" methods you just do

 render(content_structure,  "name_of_the_template")

content_structure being a plain struct, with the data you want to render in your template.

The advantage I see to this approach is

  • possibility to add dynamic data
  • compile time check, (the same as people of the posgresql rust library have created a compile time check of the SQL statement)
  • performance (as it's only compiled once)
  • still possible for corner case to inject "raw" rust code
    If that seems interesting, I can provide more details on how it is implemented as I've been working with this templating system quite extensively (and would interested to re implement it in Iron)

http://cppcms.com/wikipp/en/page/cppcms_1x_templates_gen
http://cppcms.com/wikipp/en/page/cppcms_1x_templates_comm

from iron.

brycefisher avatar brycefisher commented on May 18, 2024

@allan-simon sounds like this would really put us ahead of the node / ruby / python community by really leveraging all the best parts of rustc.

from iron.

reem avatar reem commented on May 18, 2024

Agreed. There could be some really cool work to be done in making a crazy syntax extensions for creating templates.

from iron.

allan-simon avatar allan-simon commented on May 18, 2024

I've finished a side project of mine these last days, and I've started today to take a look at syntax extensions, I will soon create a "toy" repository on my github to keep track on my progress on comprehension of "how to create complex syntax extensions" , so that at the end I could use to have a tutorial on how the machinery work, so that we don’t end up with an unmaintainable extension.

I will keep you updated on my progress for this, though I think it's going to take me at least a week or two before getting a "beginning of proof of concept", but things will get faster after a good grasp on this.

from iron.

reem avatar reem commented on May 18, 2024

@allan-simon I also just recently started learning about syntax extensions. If you want an example of a (hopefully) well written one: https://github.com/reem/stainless

from iron.

allan-simon avatar allan-simon commented on May 18, 2024

@reem Perfect it will help a lot.

from iron.

allan-simon avatar allan-simon commented on May 18, 2024

Hello, just to keeps you updated, using your stainless extension and brain_fuck macro, I've started a toy html template extension and now i'm able to generate function to output html and to mix rust code in it

https://bpaste.net/show/62c46adedcb2

right now I have 2 tags

  • <% template name() %> which generate a function "name() -> String"
  • <% rust xxxxxx %> that permits to "inject" rust code inside a template, I've first implemented this one because it was IMHO the most complex one (the others will follow the same logic as <% template %>, and it will permit to have "workarounds" waiting for me to implement more specific tags (like <% if %> etc.

other things are treated as html and added to the output buffer returned by string

Right now I'm still making myself clear about what i want, and I will tell you when I got something that reflect my idea of the templating engine I want, so that we can start discussing about making change on it

from iron.

reem avatar reem commented on May 18, 2024

@allan-simon I think it would probably be best to adopt an existing templating standard and possibly just make changes to it, rather than starting from scratch.

The most ideal situation is that I can create static or const templates which are aware of the types they must be passed to be rendered, then I can get nice type errors if I try to pass incompatible things as the pieces of the template.

from iron.

allan-simon avatar allan-simon commented on May 18, 2024

actually as said, I'm basing the syntax/concept fully on the one of the "cppcms" framework, (which I think was also based on an existing one, as vim was able to put a nice syntaxic coloration) as I think it's closer to what I'm doing (i.e template transformed into native code at compilation time)

and yup as you said, the goal is to have the same garanty in the template as we have in rust, i.e if it compiles then you're sure it works (i.e syntax checking / type checking etc.)

from iron.

sunng87 avatar sunng87 commented on May 18, 2024

Hi, I have talked with @reem in IRC but also want to update here. I have been working on a handlebars template engine for rust and I'm going to create an iron middleware for integration.

By far, the handlebars-rust project is almost finished and should support most of handlebars features, helper customization and template inheritance. I'm now working on the middleware. Since it's still difficult to compile iron against rust nightly, I may still need several days for it.

As discussed with @reem, we will create a new Template struct contains template name and data you want to render. Template will implement Modifier for Response, so users can call response.set(template). The information will be stored in extensions and processed by middleware. I'm also going to keep it easy to test. So users can test their handlers by retrieving data from extensions (in test function).

from iron.

sunng87 avatar sunng87 commented on May 18, 2024

To answer some questions above, handlebars is a widely used template syntax created by Yokuda Hatz (yes, it's who made cargo also) originally in javascript. In handlebars-rust, there is a tricky point that you have to make the data implements ToJson so we can render it. Because in handlebars, there's if/else, each and some other custom flow controls, data are not only for rendering, but also to control rendering. So I can't just use a "Show" trait or String/&str type for it. Lucky enough, most common data structure implements ToJson, so we can use it without (too much) pain.

from iron.

reem avatar reem commented on May 18, 2024

Just a note, but its Yehuda Katz, aka wycats. :)

from iron.

sunng87 avatar sunng87 commented on May 18, 2024

Oh, sorry for wycats.

from iron.

sunng87 avatar sunng87 commented on May 18, 2024

The middleware handlebars-iron is done and available from crates.io

from iron.

untitaker avatar untitaker commented on May 18, 2024

I think this can be closed since handlebars-iron seems to work fairly well.

from iron.

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.