Day 3 – Merry Cromas

The elves were keen to have an attractive Christmas tree this year. As usual, they wanted to build it with raku, their favourite programming language.

They dug back into the archives of Christmas past and came up with a pretty good way to make a tree – Santa and the Magic Tree. But honestly they felt that it is a bit old fashioned and needs something more dynamic.

HTMXmas

Some more digging and they found some great ideas about using HTMX with raku Cro here and here. This was beginning to look cool. According to Carson Gross – the inventor of HTMX, this was the best present ever – they could move the centre of gravity of web development from front end JavaScript (bleh) back to server side Raku (\o/) and keep their tree dynamic and modern at the same time.

Fragmas

(This is getting beyond a joke … ed.)

One of the coolest things that Carson said (and he said a lot of cool things) was:

Template fragments are a relatively rare Server Side Rendering (SSR) template library feature that allow you to render a fragment or partial bit of the content within a template, rather than the entire template. This feature is very handy in Hypermedia Driven Applications because it allows you to decompose a particular view for partial updates internally without pulling fragments of the template out to separate files for rendering, creating a large number of individual template files.

By keeping all the HTML in a single file, it is also easier to reason about how a feature works. This follows the Locality of Behavior design principle.

Now Cro Template Language already comes with a comprehensive syntax with
Subroutines, Macros and Parts.

But – until now – no fragments were to be found. So the elves wished and wished and Mrs Claus heard their little voices and was sad and spoke to Santa and they lo – they magically appeared! Yes – Fragments in Cro in time for Christmas!

Here’s the Pull Request that was merged 2 weeks ago and here’s the documents. We are still waiting for a new release of Cro (8.9.0?) to push that change to the zef repo. But the elves couldn’t wait so they got it from the GitHub HEAD:

zef install https://github.com/croservices/cro-webapp.git

Tree Me

Let’s see how that looks in practice. First here is the Cro Template file – note the <:fragment svg($_)> tag and also the use of Cro Templates conditionals <?.bauble>

<div hx-target="this" hx-swap="outerHTML">

  <p>Tree Height is 235m</p>
  <p>Tree Area is 8648m^2</p>

  <div hx-target="#svg">
    <button hx-get="/merry_cromas/tree_me">Tree Me</button>
    <button hx-get="/merry_cromas/bauble_up">Bauble Up</button>
    <button hx-get="/merry_cromas/star_bright">Star Bright</button>
    <button hx-get="/merry_cromas/illuminati">Illuminati</button>
  </div>

  <:fragment svg($_)>
  <div id="svg">
    <svg xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" height="768" width="1024">
      <g>
        <!-- Tree -->
        <polygon points="100,50 75,93.30127018922192 125,93.30127018922192" stroke="green" stroke-width="3" fill="green" />
        <polygon points="100,75 62.5,139.9519052838329 137.5,139.9519052838329" stroke="green" stroke-width="3" fill="green" />
        <polygon points="100,100 50,186.60254037844385 150,186.60254037844385" stroke="green" stroke-width="3" fill="green" />
        <rect x="90" y="185" width="20" height="40" stroke="brown" stroke-width="3" fill="brown" />

      <?.baubles>
        <!-- Top Tier -->
        <circle cx="85" cy="80" r="5" fill="red" />
        <circle cx="115" cy="80" r="5" fill="white" />
        <!-- Middle Tier -->
        <circle cx="75" cy="120" r="5" fill="white" />
        <circle cx="100" cy="120" r="5" fill="red" />
        <circle cx="125" cy="120" r="5" fill="white" />
        <!-- Bottom Tier -->
        <circle cx="60" cy="160" r="5" fill="red" />
        <circle cx="100" cy="160" r="5" fill="white" />
        <circle cx="140" cy="160" r="5" fill="red" />
      </?>

      <?.stars>
        <polygon points="100,35 95,45 85,45 93,50 90,60 100,55 110,60 107,50 115,45 105,45" fill="gold" />
      </?>
      </g>
    </svg>
  </div>
  </:>

</div>

And now, in Merry-Cromas.rakumod we specify the Cro Routes that our buttons will use to swap in the appropriate fragment(s) – here is where we specify the data for the conditionals to process as a raku hash using pair syntax, like { :baubles, :stars }.

use Cro::HTTP::Router;
use Cro::WebApp::Template;

sub merry_cromas-routes() is export {

    route {
        template-location 'templates/merry_cromas';

        get -> {
            template 'index.crotmp';
        }

        get -> 'tree_me' {
            template 'index.crotmp', :fragment<svg>, { };
        }

        get -> 'bauble_up' {
            template 'index.crotmp', :fragment<svg>, { :baubles };
        }

        get -> 'star_bright' {
            template 'index.crotmp', :fragment<svg>, { :stars };
        }

        get -> 'illuminati' {
            template 'index.crotmp', :fragment<svg>, { :baubles, :stars };
        }
    }
}

You can see that the Fragment syntax provides a way for the Baubles and the Star to be set in situ within the svg tags rather than hoicked out to a separate file. And yet the get routes can just pick out the fragment they need and, with the help of HTMX, insert it dynamically into the web page.

This is a simple example, and is even more powerful when a website consists of many 100s lines of HTML, CSS and JavaScript. It also minimises the traffic that is send over the wire – fastes, more responsive sites are the result.

Bauble Up

Here’s the final result in action:

Illuminati

The elves have shared all the code, getting started instructions and a working Cro site that you can run locally with just a few commands is provided here for you to enjoy the fun…

https://github.com/librasteve/raku-Cro-Website-Basic

Please remember to have some family time and don’t spend the whole day playing with this new toy!

Merry Cromas to one and all

~librasteve

5 thoughts on “Day 3 – Merry Cromas

  1. I haven’t read any of the doc. I’ve just skimmed the surface by reading this advent article. I know I should go read the doc. But I thought I should let you know my “newbie” / haven’t-yet-read-the-doc perspective about the syntax:

    <:fragment svg($_)> tag and also the use of Cro Templates conditionals <?.bauble>

    I’m struck by the fact that ?.bauble and <?.bauble> would both be valid syntax in the MAIN slang and <?.bauble> would be valid syntax in the Regex slang. In MAIN ?.bauble would be a boolean coercion of the result of a .bauble method call and <?.bauble> would be a list containing the string '?.bauble' as its only element. In Regex it would be a zero length assertion that called the bauble rule. I wonder if any of that is deliberate/meaningful, or whether the familiarity is irrelevant, or, worse, confusing or even misleading. If it’s misleading, then from my newbie perspective my suggestion would be to try to avoid that.

    Similarly, or perhaps conversely, I’m struck by the fact that :fragment svg($_) would NOT be valid syntax in the MAIN slang — it would be a two terms in a row error — and <:fragment svg($_)> would be a list containing two elements, the strings ':fragment' and 'svg($_)'. I wonder if the similarities with corresponding Raku syntax, and/or the fact it would be a two terms in a row error, is accidental. And/or whether switching it to be valid as Raku MAIN slang syntax might be beneficial. I’ve got some ideas about the latter, but will pause here because I may be barking up the wrong tree, and should probably go read the doc!

    Like

  2. Thanks for your comment. I think of `MAIN slang` as just `raku` btw.

    Specifically on the Cro template slang vs. the MAIN slang, I would say that crotmp is intended to echo the raku language in a way that is consistent with, yet differentiated from regular HTML tags.

    So a crotmp tag pair eg `<?.bauble>…</?>` is (i) in angle brackets to show it is tag-like (ie for control rather than content), (ii) unlike an HTML tag begins with a punctuation character, (iii) has an HTML tag-like closer and (iv) has a raku-like way to deference the topic variable – here `.bauble` in the tag echoes a MAIN slang syntax like `given $topic { .bauble }`

    And the echoing of raku extends to the meaning of the control punctuation chars – `?` and `!` being `if` and `else`; `$` being a scalar variable, `@` being an iterator, `:sub` is a `sub`, `&` is a sub call and so on.

    I can understand that too much similarity in slangs may be a source of confusion – but to be honest since crotmp tags are embedded deep in HTML there is no danger of this. And the upside is that that tag design is familiar-ish, always identifiable (for humans and parsers) and easy to remember since you already know that `$` is a scalar and `@` is a list and so on from regular raku.

    I can’t say I understand the purpose of making a template slang that simply embeds regular raku source in HTML – well maybe you are a PHP coder … but that’s not the same use case as a template language. If that is interesting to you then maybe this post https://rakujourney.wordpress.com/2024/09/15/can-raku-replace-php/ will be helpful.

    Like

Leave a reply to librasteve Cancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.