///|
/// A tour through the built-ins, grouped by what they work on. Each block is
/// rendered on its own so the output reads top to bottom; the point is to show
/// the shape of the language and the breadth of what ships, not to build
/// anything in particular. Redundancy here is on purpose.
let text_src =
#|{{ "hello WORLD"|capitalize }}
#|{{ "a-b-c"|replace("-", " ") }}
#|{{ " spaced "|trim }}
#|{{ "a long sentence about the weather"|truncate(20) }}
#|{{ "one two three four five"|wordwrap(10) }}
#|{{ "hi"|center(10) }}
#|{{ "hi"|striptags }}
#|{{ "link"|urlize }}
#|{{ "a"|e }}
///|
let numbers_src =
#|{{ 3.14159|round(2) }}
#|{{ "3.14"|float }}
#|{{ 1234567|filesizeformat }}
#|{{ [3, 1, 2]|sort|list }}
#|{{ [1, 2, 3, 4]|sum }}
#|{{ [1, 2, 3, 4, 5]|batch(2)|list }}
#|{{ [1, 2, 3, 4, 5]|slice(2)|list }}
#|{{ [1, 2, 2, 3]|unique|list }}
#|{{ [1, 2, 3]|random }}
#|{{ {"b": 2, "a": 1}|dictsort|list }}
///|
let lists_src =
#|{{ users|map(attribute="name")|join(", ") }}
#|{{ items|selectattr("shown")|list }}
#|{{ users|groupby("kind")|map(attribute="grouper")|join(", ") }}
#|{{ [1, 2, 3, 4]|reject("odd")|list }}
#|{{ [1, 2, 3, 4]|first }} {{ [1, 2, 3, 4]|last }} {{ [1, 2, 3, 4]|length }}
#|{{ [1, 2, 3]|reverse|list }}
#|{{ {"a": 1}|tojson }}
#|{{ {"q": "a b"}|urlencode }}
#|{{ {"class": "x", "id": 5}|xmlattr }}
///|
let choose_src =
#|{{ missing|default("none") }}
#|{% set ns = namespace(total=0) %}{% for i in [1, 2, 3] %}{% set ns.total = ns.total + i %}{% endfor %}{{ ns.total }}
#|{% if 9 is divisibleby(3) %}yes{% else %}no{% endif %}
#|{% set c = cycler("odd", "even") %}{{ c.next() }}{{ c.next() }}{{ c.next() }}
#|{% set j = joiner(", ") %}{% for x in ["a", "b", "c"] %}{{ j() }}{{ x }}{% endfor %}
#|{{ ok|yesno }} ยท {{ count|pluralize }}
///|
let dates_src =
#|{{ d|date("Y-m-d") }}
#|{{ d|timesince(now) }}
///|
let tests_src =
#|{{ 4 is even }} {{ 9 is divisibleby(3) }} {{ "ab" is iterable }}
#|{{ [1, 2] is sequence }} {{ range is callable }} {{ (""|safe) is escaped }}
#|{% set present = 1 %}{{ present is defined }} {{ missing is undefined }}
#|{{ 7 is number }} {{ "x" is string }} {{ {"a": 1} is mapping }}
#|{{ 3 is integer }} {{ 3.0 is float }} {{ none is none }} {{ true is boolean }}
#|{{ "abc" is lower }} {{ "ABC" is upper }} {{ a is sameas a }}
///|
let globals_src =
#|{{ range(1, 4)|list }} {{ range(0, 10, 2)|list }}
#|{{ dict(a=1, b=2)|items|list }}
#|{{ gettext("Hello") }} {{ _("World") }}
#|{{ lipsum(n=1, min=5, max=8) }}
///|
let statements_src =
#|{% for b in books|sort(attribute='year') %}{{ loop.index }}. {{ b.title }}{% if not loop.last %}; {% endif %}{% endfor %}
#|{% macro field(name, value='') %}{% endmacro %}{{ field('email') }}
#|{% filter upper %}shouted{% endfilter %}
#|{% with total = 3 %}{{ total }}{% endwith %}
#|{% set total = [1, 2, 3]|sum %}{{ total }}
///|
/// Render one section and print it under a heading.
fn show(title : String, source : String, data : Json) -> Unit {
println("## " + title)
println(@moonpug.render(source, data)) catch {
e => println("refused: \{e}")
}
println("")
}
///|
fn main {
try {
show("Text", text_src, @json.parse("{}"))
show("Numbers", numbers_src, @json.parse("{}"))
show(
"Lists and maps",
lists_src,
@json.parse(
"{\"users\":[{\"name\":\"Ada\",\"kind\":\"a\"},{\"name\":\"Grace\",\"kind\":\"b\"},{\"name\":\"Alan\",\"kind\":\"a\"}],\"items\":[{\"shown\":true},{\"shown\":false}]}",
),
)
show(
"Choosing a value",
choose_src,
@json.parse("{\"ok\":true,\"count\":3}"),
)
show(
"Dates",
dates_src,
@json.parse("{\"d\":\"2026-01-01\",\"now\":\"2026-05-04\"}"),
)
show("Tests", tests_src, @json.parse("{}"))
show("Globals", globals_src, @json.parse("{}"))
show(
"Statements",
statements_src,
@json.parse(
"{\"books\":[{\"title\":\"Dune\",\"year\":1965},{\"title\":\"The Hobbit\",\"year\":1937}]}",
),
)
} catch {
e => println("refused: \{e}")
}
}