Crystal Slang

Crystal Slang is a lightweight, terse, templating language for Crystal.

Since there's some thing about slang that I haven't been able to find example for in the wild I figured I'd document what I've learned in an organized fashion so I (as well as others) can refer to this when working on Amber projects.

Syntax

The syntax is similar to other templating languages like jade/pug or slim.

doctype html
html
  head
    meta name="viewport" content="width=device-width,initial-scale=1.0"
    title This is a title
    css:
      h1 {color: red;}
      p {color: green;}
    style h2 {color: blue;}
  body
    /! Visible multi-line comment
      span this is wrapped in a comment
    /[if IE]
      p Dat browser is old.
    / Invisible multi-line comment
      span this is wrapped in a comment
    h1 This is a slang file
    h2 This is blue
    input type="checkbox" checked=false
    input type="checkbox" checked=true
    input type="checkbox" checked="checked"
    span#some-id.classname
      #hello.world.world2
        - some_var = "hello world haha"
        span
          span data-some-var=some_var two-attr="fun" and a #{p("hello")}
          span
            span.deep_nested
              p
                | text inside of <p>
              = Process.pid
              | text node
              ' other text node
        span.alongside pid=Process.pid
          custom-tag#with-id pid="#{Process.pid}"
            - ["ah", "oh"].each do |s|
              span = s
    / This is an invisible comment
    #amazing-div some-attr="hello"
    /! This is a visible comment
    script var num1 = 8*4;

    javascript:
      var num2 = 8*3;
      alert("8 * 3 + 8 * 4 = " + (num1 + num2));

Given the context:

some_var = "hello"
strings = ["ah", "oh"]

Compiles to HTML:

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title>This is a title</title>
    <style>
      h1 {color: red;}
      p {color: green;}
    </style>
    <style>h2 {color: blue;}</style>
  </head>
  <body>
    <!--Visible multi-line comment
      <span>this is wrapped in a comment</span>
    -->
    <!--[if IE]>
      <p>Dat browser is old.</p>
    <![endif]-->
    <h1>This is a slang file</h1>
    <h2>This is blue</h2>
    <input type="checkbox"/>
    <input type="checkbox" checked/>
    <input type="checkbox" checked="checked"/>
    <span id="some-id" class="classname">
      <div id="hello" class="world world2">
        <span>
          <span data-some-var="hello world haha" two-attr="fun">and a hello</span>
          <span>
            <span class="deep_nested">
              <p>
                text inside of &lt;p&gt;
              </p>
              #{Process.pid}
              text node
              other text node
            </span>
          </span>
        </span>
        <span class="alongside" pid="#{Process.pid}">
          <custom-tag id="with-id" pid="#{Process.pid}">
            <span>ah</span>
            <span>oh</span>
          </custom-tag>
        </span>
      </div>
    </span>
    <div id="amazing-div" some-attr="hello"></div>
    <!--This is a visible comment-->
    <script>var num1 = 8*4;</script>
    <script>
      var num2 = 8*3;
      alert("8 * 3 + 8 * 4 = " + (num1 + num2));
    </script>
  </body>
</html>

If/Else

If and else's are denoted with the - and content between what would be curly brackets go on the next line following either | or html tag such as span

div
  - if(some_var == 12)
  | It's twelve
  - else
  | It's not twelve

Given the context:

some_var = 12

Compiles to HTML:

<div>It's twelve</div>

Case/When

div
  - case(some_var)
  - when 12
  | It's twelve
  - when 15
  | It's fifteen
  - default
  | Don't know

Given the context:

some_var = 12

Compiles to HTML:

<div>It's twelve!</div>

With Variables

With variables you have to denote = so it knows you're passing a variable.

div
  p This user's name is: 
  span = user.name 

Given the context:

user = User.new
user.name = "jimbo212"

Compiles to HTML:

<div>jimbo212</div>

Shortcodes

For shortcodes it's very similar to how variables are passed, excecpt it's with ==. There's more info about these in the Amber Docs

p
  == link_to("Back", "/books", class: "btn btn-light btn-sm")
  == link_to("Edit", "/books/#{book.id}/edit", class: "btn btn-success btn-sm")

Compiles to HTML:

<div>jimbo212</div>