7 ms·
Maud: A Rust macro for writing HTML
- EugeneOZ 4y agoIt reminds me of how PHP was born...
- IshKebab 4y agoThe main problem with macros like this (aside from being yet another language to learn) is that they don't work nicely with IDEs.
- yakubin 4y agoThey also slow down compilation.
- dustymcp 4y agoIsnt it just easier to have a html file then replace tags inside of that rather than having a new macro language ?
- josephg 4y agoThis also supports conditional expressions and loops: https://maud.lambda.xyz/control-structures.html https://maud.lambda.xyz/control-structures.html
- fredrb 4y agoSo does most templating languages.
- tannhaeuser 4y agoSGML (the markup meta-language once used for describing HTML) has that, but as we're talking the verdict is still out whether that's actually easier [1] ;) But anyway, SGML gives you HTML-aware, context-dependent, injection-free templating (even with hard support for sanitizing user content) in a content authoring workflow independent from a hosting programming language so is in a different ball park. [1]: https://news.ycombinator.com/item?id=31637910 https://news.ycombinator.com/item?id=31637910
- coffeeblack 4y agoShouldn’t it work in any IDE that understands Rust macros?
- msk-lywenn 4y agoIs there any? I don't think there is a real meaning to "understanding rust macros", as they define something completely new.
- tialaramex 4y agoYou can't build an IDE that definitely just "understands Rust macros" since procedural macros in particular are in effect modifying your compiler. Maud is a proc macro. Mara's whichever_compiles! macro for example: https://github.com/m-ou-se/whichever-compiles https://github.com/m-ou-se/whichever-compiles -- that macro is forking your compiler to try out all the branches and throwing away branches which caused a compile error. Clearly your IDE should throw its hands up and say, I don't understand what this does, I give up. In general doing something useful with Rust macros is a more tractable problem for an IDE than say the C pre-processor, because Rust's macros have a stronger syntax, but the proc macro is potentially much too powerful / dangerous to try to evaluate.
- czei002 4y agoTotally agree, macros are the worst Rust feature for me, they are way too powerful and break the tooling, e.g. fmt or language server. https://rust-analyzer.github.io/blog/2021/11/21/ides-and-macros.html https://rust-analyzer.github.io/blog/2021/11/21/ides-and-mac...
- pizza234 4y agoIt ultimately depends on how they're written. println! is a macro, and doesn't "break the tooling". on the other end of the spectrum, using a crate like demonstrate (unit testing) produces hard to understand errors and slows down the IDE. I don't remember experiencing Rust Analyzer crashes for a long time, though (I do remember some in the past).
- tialaramex 4y agoprintln! is only a declarative macro, whereas Maud is a proc macro. The declarative macros aren't too head-twisting for tools, they just expand as declared, this can sometimes have a few surprising effects but generally it is very manageable. Procedural macros have essentially unlimited power and thus are sometimes entirely impossible to analyse.
- pornel 4y agoprintln! depends on a proc macro: https://doc.rust-lang.org/stable/src/core/macros/mod.rs.html#902-907 https://doc.rust-lang.org/stable/src/core/macros/mod.rs.html...
- tialaramex 4y agoI see a built-in there. Are you really seeing a proc macro?
- shepmaster 4y ago> println! is a macro, and doesn't "break the tooling" I like, use, and write macros, but this isn't fully true. For example, recent Rust versions allow writing identifiers directly in the format string: println!("{some_identifier}") However, this breaks rust-analyzer's ability to rename variables [1]. [1]: https://github.com/rust-lang/rust-analyzer/issues/11260# https://github.com/rust-lang/rust-analyzer/issues/11260#
- Grimburger 4y agoMaud is wonderful for small things like a stats page or dashboard. But once you start getting to a few pages it's so much less cognitive overhead to separate concerns out into proper html files/templating. It seems quite daunting to have a large project where all your html is inside rust files and a lot harder to find people who can work on it proficiently.
- Inviz 4y agoI wish it was still the consensus among JS devs. People are putting css into JS files, on top of html
- vonadz 4y agoI think it isn't the consensus anymore because there isn't actually a "correct" solution. It's too subject to personal preference. For example, I prefer having HTML + CSS + JS all in the same file because then I know everything relevant to the component or page I'm working on is right there. I do concede that it can get extremely unwieldy if you don't separate out components though.
- My71staccount 4y agoThere is a correct solution (the one you're not doing)
- vonadz 4y agoSure, just like there's a correct IDE.
- zaarn 4y agoOne of the huge advantages of Maud is that it keeps code and markup close together, so you can do things like having rust control structures determine what markup is used later on (for snippets or widgets, for example). Plus, Maud has a definitive speed advantage from what I've noticed. Sadly, there isn't any great alternative for making performant HTML templates in Rust from what I've seen, a lot of the other HTML templating libs aren't that great comparatively.
- lambda_dn 4y ago
- asplake 4y agoWhat language would you expect a templating capability for Rust programs to be written in?
- pharmakom 4y agoMost languages don’t have macros powerful enough to do this.
- capableweb 4y agoWhat? Outputting HTML is basic enough that most languages don't need to use macros for this. I don't understand why'd you want to use macros with all its problems to generate HTML, when even a simple data structure like "vectors in vectors" would do just fine to generate HTML (ala Reagent in Clojure-land).
- mateuszf 4y agoThat's a bit not fair to languages different than lisp because of their more complicated syntax. Clojure simplicity is just superb in this case.
- capableweb 4y agoArrays/sequences/vectors or a similar implementation of those exists in most languages, lisps are not unique in that way :)
- kamilafsar 4y agoPeople like to hate everything related to JS these days. But when I see libs like these I'm just very grateful for the person(s) who invented JSX [1]. And evenly for MSFT implementing it into TS as a first-class citizen. It's just so much more readable. Scala is the only other language I know of which has some kind of XML/HTML syntax support (scala.xml). (But it looks like it got removed. [2]) [1] https://reactjs.org/docs/introducing-jsx.html https://reactjs.org/docs/introducing-jsx.html [2] https://github.com/scala/scala-xml https://github.com/scala/scala-xml
- mic47 4y agoIIRC php/hack had it before jsx existed: https://docs.hhvm.com/hack/XHP/introduction https://docs.hhvm.com/hack/XHP/introduction https://github.com/phplang/xhp https://github.com/phplang/xhp
- capableweb 4y agoThat's actually the heritage of JSX! XHP was launched in 2010 (https://www.facebook.com/notes/10158791323777200/ https://www.facebook.com/notes/10158791323777200/) The first version of FaxJs (the precursor to React) was launched in 2011, being directly inspired from XHP (https://github.com/jordwalke/FaxJs https://github.com/jordwalke/FaxJs) React was made in 2012 by the same person who made FaxJs, taking the best ideas from FaxJs and creating React. So yeah, JSX actually comes from the idea of XHP :)
- amenghra 4y agohttps://github.com/facebookarchive/xhp-php5-extension https://github.com/facebookarchive/xhp-php5-extension if you are interested in seeing how Marcel initially implemented XHP for PHP. The concept was popular at Facebook, so it made its way into HPHP, HHVM, and later ReactJS.
- nikonikoniko 4y agoI find that very interesting, I have the opposite reaction to JSX. Not wanting to use it has been one of the biggest reasons I have moved into using ClojureScript/Hiccup for front-end applications. I find JSX extremely hard to read and work with and reason about.
- sunfmin 4y agoSimilar thing in Go: https://github.com/theplant/htmlgo https://github.com/theplant/htmlgo
- pornel 4y agoThe difference is that maud does most of the work compile-time, so `html! { div { "foo" } }` compiles into literal "<div>foo</div>" hardcoded in the program, without allocating intermediate HTMLTagBuilder objects.
- hu3 4y agoAnother difference is htmlgo is just plain Go, no macros. So it plays nice with IDEs and other tooling.
- enriquto 4y agoThe given example seems harder to write than the correspondig html. What's the point, then? All these opening and closing quotes are pointless. Why don't write a single string with the verbatim html inside?
- dhosek 4y agoBecause you can do things like have a loop that generates list items, for example?
- pjungwir 4y agoOh this looks great! It reminds me of haml, where it is so much easier to see the structure of your file, and you avoid a whole class of dumb typo bugs. And I'm happy to see this doesn't serialize the arguments into json and back (as Tera does). What is the point of that? Every time I start a new project in Rust/React/Elixir I look for a haml-like templating library. For private JS projects I'm stubbornly using a pug-to-jsx babel plugin, but in other languages I'm mostly out of luck. I have several small Rocket projects now where I'm using Tera (handlebars basically). I'll happily switch them to Maud. Thank you for building this!