Skip to content

razor_like_templating_proposal

Matěj Štágl edited this page May 21, 2022 · 9 revisions

Templating extension for CLike mode

When this extension is toggled everything is treated as plaintext and outputted to stdout by default.

For transition from plaintext to CLike code @ is used. Expressions are then evaluated and their results pushed to stdout.

To escape an @ symbol, another @ has to be used.

@@Hello
@Hello

Implicit expressions

Start with an @ symbol and are followed by CLike code:

<div>Running for: @os.clock() seconds</div>
<div>Running for: 3.1459 seconds</div>

Except for (meta)function calls & tables indexing, spaces cannot be included. This is an example of such an expression:

@{
    a = 10
}
<div>@a > 0 ? "yes" : "no"</div>

In this example only @a part would be considered as a CLike expression and stdout would be written as:

<div>10 > 0 ? "yes" : "no"</div>

##

Explicit expressions

To allow for expressions where spaces are required, explicit expressions exist. They consist of an @ symbol followed by balanced parenthesis. To execute ternary expression above, the template would need to look like:

@{
    a = 10
}
<div>@(10 > 0 ? "yes" : "no")</div>

This would write to stdout:

<div>yes</div>

Any implicit expression can be written as an explicit expression, hence explicit expressions represent a superset of implicit expressions.

Encoding

By default results of expressions (the last item on stack after interpretation) are not encoded and written as-is. A global table Html exists to control this behavior.

Html might be realized as [MoonSharpModule] but needs to be declared as partial & public so user apps can extend its content.

In default implementation, Html has following methods:

  • Raw -> just a passtrough method

  • Encode -> result is HTML encoded

@Html.Encode("<div>hello</div>")
&lt;div&gt;hello&lt;/div&gt;

Code blocks

Start with an @ symbol and are enclosed by {}. Unlike expressions, code blocks do not render to stdout and are used for side effects / control only.

@{
    tbl = [10, 20, 30]
}

After executing this template, stdout would be empty.

An example of a code block with an arrow function declared and the said function called:

@{
    say = (what) => {
        <div>@what</div>
    }
}
@say("hello")
<div>hello</div>

There are three ways to transition from a code block to plaintext:

  1. transition via <text></text> tag:

    In this type of transition only content of the tag is written to stdout but not the tag itself.

    @{
        a = 10
        <text>
        Value of a is @a
        </text>
    }
    Value of a is 10
  1. transition via any other HTML tag:

    Behaves the same as transition via <text></text> but the tag itself is also written to stdout.

    @{
        a = 10
        <div>
        Value of a is @a
        </div>
    }
    <div>Value of a is 10</div>
  2. line transition:

    Renders rest of the current line as plaintext. To perform line transition @: is used.

    @{
        a = 10
        @:Value of a is @a
    }
    Value of a is 10

Keywords

  1. @if, elseif, else if, else, @switch, @enum

    @if (10 > 5) {
        <div>10 gt 5</div>
    }
    <div>10 gt 5</div>

    elseif, else if & else don't use @ symbol.

    @if (2 > 1) {
        <div>2 > 1</div>
    }
    else {
        <div>2 < 1</div>
    }
    <div>2 > 1</div>
  2. @for, @while, @do

    <ul>
    @for (i in 1..3) {
        <li>@i</li>
    }
    </ul>
    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
    </ul>
    @{
        i = 0
    }
    @do {
        <div>@counter</div>
        i++;
    } while (i < 3)
    <div>0</div>
    <div>1</div>
    <div>2</div>
    @{
        i = 0
    }
    @while (i < 2) {
        <div>@i</div>
        i++
    }
    <div>0</div>
    <div>1</div>
    <div>2</div>
  3. @require

    @require "myModule"
  4. @function

    @function MyFunc(n) {
        <div>@n</div>
    }
    
    @MyFunc(10)
    <div>10</div>

Comments (section added 4/13/22)

Multiline comments can be added via @* *@ and can't be nested. Unlike HTML comments these won't render in the final template and are a shorthand for:

@* My comment *@

=

@{
  /*My comment*/
}

Explicit escape expression (section added 4/20/22)

To allow for easy integration of <script> and <style> tags an explicit escape expression exists. It is similar to the explicit transition but with added bang directly after @ (no whitespace allowed in between).

@! {

}

Any text within an explicit escape transition ignores further control characters @ and treats them as a part of normal text.

@! {
<style>
@media (max-width: 768px) {

}
</style>
}

here @media would normally mean "render content of variable media".

Explicit preprocessor transition (section added 5/18/22)

This transition is inverse to client @: line transition. After @# sequence, the rest of line is parsed as server code, including the # symbol. There is no way to exit from this transition early.

@#define PI 3.14
<div>@PI</div>
<div>3.14</div>