The modern DSL (Design Sub-Language) for describing UI trees.
Sakko is a bracket-based markup language that compiles to component trees. Write concise, readable markup. Get a structured AST. Use it with Sazami, build your own renderer, or create something entirely different.
<card {
heading: "Hello, world"
text: "This compiles to an AST."
button: "Get Started"
}>
That is the entire source. Sakko tokenizes it, parses it, and produces a structured AST. The AST can then be transformed into anything: Sazami web components, React VNodes, JSON, you name it.
Here is a more complex example:
<player {
card(row center) {
coverart(round): "album.jpg"
details {
text(bold): "Midnight City"
text(dim): "M83"
}
controls {
icon-btn: previous
icon-btn(accent large): play
icon-btn: next
}
}
}>
npm install @nisoku/sakkoimport { parseSakko, tokenize } from "@nisoku/sakko";
// Tokenize source to tokens (useful for debugging)
const tokens = tokenize('button(accent): Click me');
// Parse to AST
const ast = parseSakko(`
<card {
heading: "Hello"
button: "Click"
}>
`);
console.log(ast);
// {
// type: 'root',
// name: 'card',
// children: [
// { type: 'inline', name: 'heading', modifiers: [], value: 'Hello' },
// { type: 'inline', name: 'button', modifiers: [], value: 'Click' }
// ]
// }The parser produces one of four node types:
| Type | Fields | Description |
|---|---|---|
root |
name, modifiers?, children |
Top-level container |
element |
name, modifiers?, children |
Block element with children |
inline |
name, modifiers?, value |
Leaf element with text value |
list |
items |
Comma-separated group |
Modifiers are either flags or key-value pairs:
{ type: 'flag', value: 'accent' }
{ type: 'pair', key: 'cols', value: '3' }Every Sakko document has one root block wrapped in angle brackets:
<page {
...children
}>
Elements with children use curly braces:
card {
heading: "Title"
text: "Description"
}
Elements without children use a colon:
text: Hello world
button(accent): Click me
icon: play
Parenthesized flags or key-value pairs after the element name:
button(primary large): Submit
grid(cols 3 gap medium): [...]
card(row center curved): { ... }
input(placeholder "Email"): ""
Comma-separated elements in square brackets:
row: [button: A, button: B, button: C]
Single-line comments with //:
// This is a comment
card {
text: Hello // inline comment
}
Build/ Library source code
src/
parser/ Tokenizer and parser
types/ TypeScript type definitions
tests/ Tests
Examples/ Example .sako files
Docs/ Documentation (powered by DocMD)
cd Buildnpm installnpm testnpm run build| Document | Summary |
|---|---|
| Language Reference | Full Sakko syntax guide |
| API Reference | Public API surface |
cd Docs
npm install
npm run dev