Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
[![Publish](https://github.com/cogna-dev/x/actions/workflows/publish.yml/badge.svg)](https://github.com/cogna-dev/x/actions/workflows/publish.yml)
[![Document](https://github.com/cogna-dev/x/actions/workflows/document.yml/badge.svg)](https://github.com/cogna-dev/x/actions/workflows/document.yml)
[![MoonBit](https://img.shields.io/badge/MoonBit-ready-8A2BE2)](https://www.moonbitlang.com/)
[![Version](https://img.shields.io/badge/version-v0.1.1-2ea44f)](https://github.com/cogna-dev/x/releases)
[![Version](https://img.shields.io/badge/version-v0.1.3-2ea44f)](https://github.com/cogna-dev/x/releases)

```text
_________ ____ _ _______ ____ _______ _ __
Expand All @@ -30,6 +30,7 @@ Experimental monorepo for real-world [MoonBit](https://www.moonbitlang.com/) pac
|---------|-------------|
| [`cogna-dev/x/hcl`](src/hcl/) | HCL parser built with `cogna-dev/parkit/nom` |
| [`cogna-dev/x/logo`](src/logo/) | Prints the ASCII art for "Cogna" |
| [`cogna-dev/x/mustache`](src/mustache/) | Mustache template renderer with spec-based tests |
| [`cogna-dev/x/sarif`](src/sarif/) | SARIF 2.1.0 static types with JSON encode/decode |

## Development
Expand Down
2 changes: 1 addition & 1 deletion moon.mod.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cogna-dev/x",
"version": "0.1.2",
"version": "0.1.3",
"deps": {
"cogna-dev/parkit": "0.1.1"
},
Expand Down
79 changes: 79 additions & 0 deletions src/mustache/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# `cogna-dev/x/mustache`

[![MoonBit](https://img.shields.io/badge/MoonBit-package-6C47FF)](https://www.moonbitlang.com/)
[![Mustache](https://img.shields.io/badge/template-Mustache-111827)](https://mustache.github.io/)
[![Spec](https://img.shields.io/badge/tests-official%20spec-16A34A)](https://github.com/mustache/spec)
[![Status](https://img.shields.io/badge/status-experimental-F59E0B)](../../README.md)

```text
__ ___ __ __
/ |/ /_ ______/ /_____ _____/ /_ ___
/ /|_/ / / / / __ / __/ // / _ / _ \/ _ \
/_/ /_/\_,_/\_,_/_/\__\_,_/\_,_/\___/\___/
```

Minimal Mustache rendering for MoonBit with practical, spec-driven behavior.

## Features

- Escaped interpolation: `{{name}}`
- Unescaped interpolation: `{{{name}}}`, `{{&name}}`
- Sections and inverted sections: `{{#x}}...{{/x}}`, `{{^x}}...{{/x}}`
- Dotted-name lookup and implicit iterator (`{{.}}`)
- Comments (`{{! ... }}`)
- Partials (`{{>partial}}`)
- Delimiter switching (`{{= <% %> =}}`)

## Usage

### API

```moonbit
pub fn render(template : String, data : Json, partials? : Map[String, String]) -> String
```

### Basic interpolation

```moonbit
let out = @mustache.render(
"Hello, {{subject}}!",
Json::object({ "subject": Json::string("world") }),
)
// out == "Hello, world!"
```

### Sections and dotted names

```moonbit
let template = "{{#person}}{{name}} from {{meta.city}}{{/person}}"
let data = Json::object({
"person": Json::object({
"name": Json::string("Joe"),
"meta": Json::object({ "city": Json::string("Berlin") }),
}),
})
let out = @mustache.render(template, data)
```

### Partials

```moonbit
let template = "{{>card}}"
let data = Json::object({ "title": Json::string("Hello") })
let partials = { "card": "[{{title}}]" }
let out = @mustache.render(template, data, partials=partials)
// out == "[Hello]"
```

## Specification coverage

This package includes tests adapted from official Mustache spec cases:

- interpolation
- sections
- inverted sections
- comments
- delimiters
- partials

Reference: <https://github.com/mustache/spec>
Loading
Loading