Hacker News new | past | comments | ask | show | jobs | submit login
LuaX: A Lua Dialect with JSX (bvisness.me)
190 points by goranmoomin 8 months ago | hide | past | favorite | 83 comments



The project itself seems fine, and clearly works for the author.

But I'm never quite sure why people insist that you cannot do web dev the old school ways of HTML files with a little PHP or other scripting. All of that still works just fine. So when people say they wrote an entirely new system because they miss being able to stay simple like in ye olde days... I'm not sure I understand the connection.


You are correct. The minimum needed to generate dynamic HTML is a string builder, not a fancy framework.

Frameworks exist for Software at Scale (TM). Big Corp has a revolving door of developers and they need cookie cutter tools that isolate the damage a "bad" developer can cause. If you're a solo developer or a small company, then this digital bureaucracy is unnecessary.


I couldn't disagree more. I work on a very small team, and our current projects use big modern JS frameworks. Our productivity has never been higher. I absolutely hate having to touch old projects, that I had to build from much lower level APIs.


Your "very small team" of under 5 developers is still what React, et al. target.

Developers leave about every two years. Engineering management want to use technologies that allow for resource flexibility, and those libraries are designed to attract both parties. You, and management, for different reasons.


The component model is a very powerful technique for keeping large amounts of complex code maintainable. I worked in large amounts of tricky jQuery before the component model and I would never wish to go back.

JSX works well for a component approach because you’re expressing the component in a fully functional programming language. Doing a lot of that work tends to make the developer quite capable in Javascript.


> the minimum needed to generate dynamic HTML is a string builder

Ah, the sweet sweet nostalgia of XSS


If you want a reason, go look at the Gitea project. They use Go templates, which are a lot like PHP. Depending on your definition, it could be "just fine." But also, you get a lot of issues that remain unsolved, such as the 77 comments in [1]. User interfaces are not meant to be handled on the backend in my opinion. When you try to do that, you get issues unless it's a system that's designed for doing the exact same computations on the frontend too (isomorphic like NextJS).

[1] https://github.com/go-gitea/gitea/issues/5937


Exactly.

> When I started out, you could just copy HTML files up to your server and you had a website. It was magical! And PHP made it even better; you could just throw in a little snippet of server-side code and you had a dynamic page.

Well, you can still very much do this. Sure, it's not bleeding edge, but large chunks of the web (even newer sites) still do it this way and rely on PHP or sinilar server side languages.


If you want to handle complex client-side state, you will soon reinvent an inferior react or vue. Not every app is a simple CRUD app that can be summarized by a series of GET and POST requests.


Depends on the project, no?

Could build Figma or Google Sheets "with HTML files with a little PHP or other scripting?" I don't see how either app could be developed without significant amounts of "scripting" (i.e. code running in the browser and on the server).


JSX is useful not just for advanced string interpolation but for representing/generation of tree alike structures / literals in PL. JSX is not only about HTML but XML too.

I don't know how JSX is made in LuaX but in my QuickJS fork [1] JSX allows to generate as tree literals as procedure calls (JSX(tag,props,kids)) that can be used for various purposes - DOM population, VDOM generation, HTML/XML string composition, etc.

And being embedded into a compiler JSX a) prevents common mistakes like non-closed tags and b) effective internalization ( translation happens at compile time once ).

[1] JSX implementation for QuickJS : https://gitlab.com/c-smile/quickjspp/-/blob/master/quickjs-j...


Great job! I will take a look. I am also trying to geylt my head around mithriljs


The only thing I liked about React was JSX. This is a great idea.


Is it really? I’m using mithril with hyperscript and m-snippet to save some shift-typing and its native structure feels much better than html-like, especially when flow-control and multiple attributes kick in.

Wrt $subj, Lua has even better thing - Lua table, which can hold both kv-pairs and indexed items. With function environments that could allow something like:

  function comp:render()
    return div {
      class = "foo",
      input {
        type = "text",
        disabled = true,
        value = self.value,
      }
    }
  end
That’s what Lua was made for. Idk why I would “<choose><jsx></jsx></choose>” over “choose { lua }”.


> That’s what Lua was made for. Idk why I would “<choose><jsx></jsx></choose>” over “choose { lua }”.

React was made for web developers. Most web developers know HTML already. Many of them probably know Lua too, but not as widespread as HTML-knowledge.

JSX is basically HTML in JavaScript, so it's easy because it's familiar. The reason for JSX is to make DOM creation in JS more like DOM creation in HTML.


You need to invent and build non-trivial systems to compile JSX, while you only need a couple lines to make a mithril.js style hyperscript h() without the need for a compiler, and you get variables, loops / array maps etc for free since you're writing normal JS.


Sure, I'm not arguing for everyone to use JSX (I personally use Reagent/Hiccup in ClojureScript most of the time, which are just built-in vectors (arrays) basically).

I'm just explaining to someone why people chose JSX in favor of X, when they come from a HTML/CSS/JS background.


Yeah that's fair! Everyone has their own way to do stuff


In my opinion, HTML and XML would benefit from being a Lua table with Lua strings too.


My opinion is that most developers would be better off if they just started using lisp-like languages instead. Use Fennel if you really have to use Lua.


Lisps are much more loaded with implicitness around all sorts of brackets, which makes them non-friendly for semi-programmers. This is less important in our usual industry that is motivated to hide as much as possible behind a paywall, but I’m a strong follower of “anyone wielding a keyboard should be able to program” ideology.

That said, historically lisps are the most featureful runtime-wise. It’s a real shame we hide behind our complexity but collectively chicken out before really powerful concepts lisps introduced.


Awesome WM has nested GTK widgets similar to what you describe, a testament to the flexibility of Lua's uber table.


Because you’ll have to switch context each time you look into browser developer tools, MDN docs, etc.


Browsers have no support for JSX, nor is it documented at MDN.


Let me clarify: React team could choose any syntax of JSX, or even have no syntax and use nested data structures. They've chosen HTML-like syntax for developer convenience. My first experience with React was through ClojureScript and Om (back in 2014), and I can tell you that constantly translating back and forth between 2 vastly different syntaxes hurts.


Worse thing is that html snippets are not directly pasteable into your code. For this I wrote me html-to-m tool which I can run on a visual selection in vim with a hotkey. There is a web-based one, but I find its formatting too awful to use.


If copy pasting is that important to you, I don't think you're a good developer.


This has the downside of mixing properties/attrributes with children.

So, in `div`, `class` is a property, but `input` that immediately follows is a child of the component


Ironically, this is a case where one of Lua's most controversial features comes in handy. Tables can be initialized with both named and sequential members. In this case, "class" is a named member and the `input` element is sequential.


I think gp meant that they can be reordered in a way that is hard to reason about, e.g. {…many-children…, class=""}, putting attributes away from a tag.


Yup. That's what I'm thinking about.

It's a similar issue as CSS nesting, by the way :) I'm not saying it's inherently bad, it's just it could be confusing. But could probably solved by a linter: put attributes at the top, nested children at the bottom


How would that look in lua with a custom function or class instead of div, input, etc?

To me JSX and hyperscript are both about the same thing. JSX gets compiled to a bunch of createElement calls that looks just like hyperscript. I prefer the look of JSX over hyperscript.


The same way as in jsx

  div {…}
  Comp {…}
  Ns.Comp {…}


I’m loving using hyperscript in my projects.


Man that’s my least favorite thing about react :/


Is that because you want presentation to be separated? Or some other reason?


Interestingly the authors comparison language (PHP) has a facebook-created offshoot that supports this exact syntax, XHP[0].

[0] https://docs.hhvm.com/hack/XHP/introduction


If I remember correctly, XHP was the precursor to JSX.


They also made XHP-JS, though it seems inactive. Maybe that was the interim solution?

https://engineering.fb.com/2015/07/09/open-source/announcing...

https://github.com/hhvm/xhp-js


Talking about html rendering is very similar to a domain I've been thinking about: configs.

Lua can be trivially sandboxed. Throw in a parser for acquiring metadata (dependencies) and you have a full blown config language in a few hundred LoC

https://github.com/civboot/civlua/tree/main/luck

I love Lua


Wow great job!

I also hate (well, dislike) static website builders... so I built my own based on markdown, with an embedded Scheme-like template language. But this is much nicer as you turned things around and made the website basically a Lua program that happens to output HTML.

Do you have support for stuff like syntax highlighting for code samples, table-of-contents "widgets" and so on?


No - in fact, I spent about three hours manually syntax highlighting all the code examples in the post!

At some point maybe I’ll make syntax highlighting for my editor, but it’s not a super high priority for me.


I've built a lua-based markdown which is more sane (from a programmer's PoV) than markdown but still concise

https://github.com/civboot/civlua/tree/main/cxt

I'm planning on supporting syntax highlighting. I could imagine creating a cxx that does what LuaX is doing, except it would support rendering to the command line as well as html.

Want to team up?


FWIW the textadept lexer can return everything well defined and supports everything, the rest is just styling.


Cool project and if it works for you and you're happy, that's all what counts.

When I read the article, I was thinking that Go templates were used wrong. I was thinking there must be a way to define the template so you inject the content and don't need to define the start and the end of the html, but instead yield a block of other html as some kind of argument. I was trying to look it up, but couldn't find documentation on this. Maybe the author is right and I'm wrong.

And I was wondering why the author isn't using something like Templ [0], which is kind of JSX with Go as hosting language. Probably because it needs the preprocessor / compile step?

[0] https://github.com/a-h/templ


In some cases you can use the block system in Go templates, but it is extremely sad. I actually made a proposal for an extension to Go templates that would make the “component” workflow a little easier[1], and used it on my site before switching to LuaX, but at the end of the day I don’t like switching languages and I don’t like recompiling my site while I’m writing. Go templates are fundamentally not what I wanted.

[1] https://github.com/golang/go/issues/54748


> I don’t know what the future holds for LuaX. It’s not ready for other people to use, and I’m not sure it will ever be.

I hope he decides to open source it.


It is actually open-source already if you know where to look, but heads up that it’s not documented for public use (and as mentioned, I cut some corners on the parser). https://github.com/bvisness/bvisness.me/blob/main/bhp/transp...


Same here.

I share the frustration of template systems being separate from the rest of your code, let alone your language.

IME, JSX and Hiccup are the best approaches to 'HTML in your functions'.

Having this for Lua would be great; its a wonderful scripting language.


I don’t know anything about Lua other than I want to try it out because of redbean [1]. Wonder if this project can work with that?

[1] https://redbean.dev/


This is really cool! For a long time I've been thinking about writing something very similar, but for building World of Warcraft addons. It'd be basically the same thing, combining Lua and JSX but with the addition of a React-like API for the game's events. I haven't got around to it yet (probably never will at this rate) but I'm definitely going to look at this project for inspiration if I ever find the time.


I think this is a solid choice if you want both template engine and plugin system. I wish someday https://soupault.app adopt this.


This is a strange article. I think the relevant part is "Because I like it", which is absolutely fine, that seems like a fun project. But whatever problem he's identified has already been solved in many different other ways.


JSX is a very nice way to build XML/HTML content, and when you need it programmatically it makes all the difference vs string soup.

It's similar with languages will permit fluent SQL-like syntax mixed with general purpose programming.

Bridging these realms into a single integrated programming environment should be celebrated. There's no reason our ecosystem is so fragmented.

Lua shares many aspects with JS, but also does async programming in a much better way than JS, because it was adapted for games, where many things happen concurrently and not in a blocking way. The syntax is also clear and more minimal, like Python is.

I'm working on a hobby language (who isn't!) which combines many aspects from Erlang, JS, JSX, LISP, SmallTalk etc. and while Erlang is my model fo runtime concurrency, Lua is my model for syntax concurrency (that is no red/blue separation: every function is implicitly sync or async depending on how you call it). I think projects like these are a good thing for our industry.

Enough divergence, it's time for convergence!


> It's similar with languages will permit fluent SQL-like syntax mixed with general purpose programming.

Other than t-sql and plpgsql, can you give an example of languages with native SQL syntax? I've been thinking about building a toy language like that and haven't found anything not native to a database engine.



Or even better, VB.NET, since it has both LINQ and XML literals.


Is your language available in some form? I would be curious to check it out. Are you running on top of BEAM given that you're using Erlang as a concurrency base?


I didn’t like any of the other solutions I’d seen! And besides, you’re talking about someone who hosts a yearly Wheel Reinvention Jam… https://handmade.network/jam/2023


Interesting. There have also been talks and prototypes in the Luau community of creating a preprocessor to convert a JSX-like syntax to Luau/Lua, as JSX has gained popularity alongside transpiling TSX to Luau/Lua, as it's a much better syntax for writing code for Luau/Lua UI libraries than `React.createElement({}, {})` etc.


Just a random question that came to my mind when browsing the example: How do you make sure the slug is unique in a system like this?


As with PHP, that’s outside this part of the system. My personal site looks up paths in the filesystem like old-school PHP, but you could also do some kind of “routing” definitions if you wanted, like…new-school PHP.


It would have been nice if LuaX was written in Lua.

Forking Pallene (https://github.com/pallene-lang/pallene) would introduce: - Types - LuaX -> Lua - LuaX -> C


JSX on the server doesn't make sense to me.

It makes sense in the browser because it was made to mimic the dom api. But the interface between the browser and server is text.

When using jsx in the server you're extremely limited. You cannot just use any html tag unless the framework has a specific solution for it.


As I said in the article, JSX is distinct from frameworks like React. The interface between the browser and server is HTML; LuaX allows me to author that HTML in a more structural way before sending it to the browser.

Also I can totally use any tag I want. LuaX powers the RSS feed of my site too, with all its `atom:link` and `pubDate` and `guid` tags. It doesn't care about the names of tags, only the structure.


Can you write script and style tags?

Usually this is where JSX implementations fail.


> When using jsx in the server you're extremely limited. You cannot just use any html tag unless the framework has a specific solution for it.

Doesn't look like that's the case in OP's solution, where HTML tags are transformed into Lua tables. I guess then there's some code that turns the lua tables into the html text to be sent to the client


The main argument (“I hate static sites”) can be more efficiently (dynamic page, guaranteed fast response, mainstream tech) addressed by deploying normal JavaScript jsx on the edge.


> The problem is that no preprocessor-style template language actually allows you to manipulate the HTML as data.

Lisp works great for this sort of thing.


Everytime I see JSX I think of E4X, which is a now defunct standard that contributed to JS having for(of) instead of for each() :-/


I use haserl,htmx with lua for simple dynamic sites, would love to play with this,is the code available somewhere?


I'd love to see how you're using these tools


nothing magic, haserl is like a light-weight php template that mix dynamic script with static html, lua does the scripting(shell script works too), again, for simple use cases they worked like a charm.


Hmm. OK, but I'd rather have seen this done in Fennel (with s-exps it would look pretty seamless).


This could be done in Fennel very trivially.


Very cool. Support for manipulating the headers that are output would be nice on the TODO list.


I see the author here made a common copyright notice mistake.

Us developers as a group seem to hold the belief that updating the copyright dates manually is bad or wrong.

But AIUI, the copyright should be more than a simple "today.getYear()" call. If you first published the page in 2020, then the copyright should reflect that.

If instead, when we delete the 2020 and auto update it to _currentYear_ dynamically, we have removed the claim to have published it earlier. So if there is a copyright issue where another site copied some content but left the copyright year as say 2021, now from a first glance it would have the more senior copyright claim.

What you would want is something that generates a copyright notice like "Copyright 2020-2023". See here for more examples: https://www.websitepolicies.com/blog/copyright-notice


I'm not a lawyer, but my understanding has always been that the copyright notice isn't required at all. If you get into a dispute over the ownership of something, you just need a way to prove you're the actual copyright owner. I don't see how a small line of text on the page will help you do that (especially since you can arbitrarily change it whenever you want).

I keep mine up to date on my sites just because it's basically a staple of modern web design. Not having it would be weird, and having it out of date would probably confuse people.


Yeah, the git history will back me up in any actual copyright dispute. I just have the date in the footer to keep my website from looking old and stale.


Git history is as strong as evidence as a copyright string. One can forge a repo with dates they need and upload it to github. With a well-versed arbiter you’ll probably end up looking at internet archives.


I wonder if some of that is because many off the shelf dynamic templates do the current year thing so that end users (initially) see the correct date. Sort of cargo culting from that pattern?


Or just don't update it.


> now from a first glance it would have the more senior copyright claim.

So what? What matters is authorship, not the date at which it was published on this or that website. Even if a website copies your text, no matter the date, that is still your text and still copyright infringement no matter what if you didn't license this text to them.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: