escaping/src/main.nika

// Prints an HTML table built from a template, with every value escaped.
//
//     nikaia run
//     <table>
//             <tr class="odd"><td>Ada</td><td>fine</td></tr><tr class="even"><td>a&lt;b &amp; c</td>…
//
// Shows: a `dsl html` template, a `<for>` loop inside it, and `html::Raw` for
// markup the program built itself.
//
// A package: `nikaia run` in this directory runs it, and `nikaia test` checks
// what it prints against `tests/` (ADR-269 D13).

use std::html

pub struct Row {
    name: String,
    note: String,
    shade: String,
}

// Every `{…}` hole in a template is escaped, always; there is no way to turn
// that off. A hole is only allowed where escaping is enough: text, or a quoted
// attribute like `class="…"`. In a `<script>` body, an `href` or an unquoted
// attribute the compiler refuses it. The holes need no `f`, and `{{` is a
// literal brace, as in an `f"…"` string.
//
// In `<for r in :rows>`, the colon marks `rows` as a name from the program
// around the template rather than one the template defines.
fn table(rows: Vec[Row]) -> String {
    return dsl html {
        <table>
        <for r in :rows><tr class="{r.shade}"><td>{r.name}</td><td>{r.note}</td></tr></for>
        </table>
    } eod
}

// The one way to put markup into a hole is the type `html::Raw`: its value is
// not escaped again. So the name is escaped first, with `html::escape`, and the
// `<em>` around it survives.
fn emphasised(name: String) -> String {
    let mut built = String()
    built.push_str("<em>")
    built.push_str(ref html::escape(name))
    built.push_str("</em>")
    let markup = html::Raw(built)
    return dsl html {
        <tr class="odd"><td>{name}</td><td>{markup}</td></tr>
    } eod
}

fn main() {
    let rows = [
        Row { name: "Ada", note: "fine", shade: "odd" },
        Row { name: "a<b & c", note: "\"quoted\"", shade: "even" },
        Row { name: "O'Hara", note: "</td> is not a tag here", shade: "odd" },
    ]

    println(f"{table(rows)}")
    println(f"{emphasised("Ada")}")
}

The file itself · all the examples

This site is open source. Improve this page.