Tutorial
The Maraca language is a simple language for defining dynamic (changing) data. This data can be used in various ways, in this tutorial we’ll generate HTML to make a simple todo list app.
Writing data
All data in Maraca is built from text values. Values using only letters and numbers can be written directly. Other characters must either be prefixed with a \, or part of a value surrounded with single quotes.
Code
 
 
 
Values can be built up from multiple adjacent parts, optionally separated by a single space.
Code
 
 
To add structure to our data, we can group multiple values together inside a ‘block’, using square brackets and commas.
Code
 
 
Any value in a block may also have a key, and blocks can be nested.
Code
 
 
Generating HTML
All Maraca does is output changing data, which can be used in all sorts of ways. For this tutorial, we’re using our data to generate HTML (using the maraca-render library).
Maraca blocks map very intuitively to HTML elements:
  • Keyed values => properties
  • Unkeyed values => children
  • A value with a blank key => element type (defaults to div)
CodeHTML
 
 
From now on, when we’re generating HTML we’ll render the output, rather than showing it in code form.
CodeHTML
 
Hello world
Starting the app
To start, let’s outline a very simple, static, version of our app. We’ll add a title, an input for entering new tasks, and a list of tasks.
CodeHTML
 

Todos

Task 1
Task 2
Task 3
Now, let’s start making our app interactive. First we’ll make the input change color when we click and focus it.
For this, we’ll set the focus property of the input to a special type of value that can change over time, which will then automatically update to match the state of the input. We do this by using :~ instead of : when we set the value.
Then, we access this value in another part of our data with @, and use a new ‘round’ type of block, written using parentheses, along with a fallback value, to create an ‘if A then B else C’ statement, written (A, B, => C)" style="font-family: Source Code Pro; font-weight: bold">(A, B, => C). (Round blocks can be used in more general ways, but this is all we need for now.)
Try clicking on the input to see it change color when focused.
CodeHTML
 

Todos

Task 1
Task 2
Task 3
Creating state
Now, let’s say we want to put a line through each task that has been done. So we’ll need some value which holds this information, and then we can use it to set the style of the task. We’ll start with Task 1.
CodeHTML
 

Todos

Task 1
Task 2
Task 3
So where does @done come from? To hold state like this, we use a ‘curly’ block, written using braces, which only returns its (first) unkeyed value, allowing us to create ‘hidden’ keyed values.
CodeHTML
 

Todos

Task 1
Task 2
Task 3
Now, we want this value to toggle when we click on the task.
First, we use :~ again to create values that can change over time, both for the state, and for the mouse property, which will update when the mouse is clicked on the element. The value of @mouse will be a block with a value for each mouse button, so we use a . to access the part we want.
Then, we use the the ‘equals’ (=) and ‘not’ (!) operators, along with a new construct A | B -> C" style="font-family: Source Code Pro; font-weight: bold">A | B -> C, which means ‘when A push B into C’, to watch for the left mouse to be clicked down, and when it is to set the state to its opposite value.
Try clicking on Task 1 to see it in action.
CodeHTML
 

Todos

Task 1
Task 2
Task 3
Transforming blocks
So far, we’ve only added the ‘done’ state to the first task. We could do the same for Task 2 and Task 3 by copying and pasting our code from Task 1 and changing the text, but this isn’t very scalable.
Instead, we can use a ‘transformer’, which takes a block, and creates a new one by transforming each of its values. We write a transformer using =>>, along with a key which lets us access the values from the original block.
CodeValue
 
 
Using this, we can take our list of tasks, and transform each one into a clickable item, expressed exactly as we did for Task 1 above. While we’re at it, let’s improve the user experience by adding a pointer cursor to the tasks, and also highlighting them when hovered.
Try clicking any task and see them each update.
CodeHTML
 

Todos

Task 1
Task 2
Task 3
Updating blocks
Now we’re ready to use our input to add new tasks. First, we’ll turn our list of tasks into a changeable hidden value, so we can access and update it from other parts of our code.
CodeHTML
 

Todos

Task 1
Task 2
Task 3
With that in place, we can combine what we’ve learnt so far to create a hidden value for the new task, attach it to the value property of the input element, watch the keys property for the enter key to be pressed, and when it is add the new task and clear the input.
To create the updated list of tasks, we create a new block, add the newly typed value from the input, and then copy in all the existing tasks, using : without a key, which has this behaviour if the assigned value is a block. (A text value can’t be copied in this way, and as we’ve seen already is just assigned to the blank key.)
Try entering a new task and hitting enter.
CodeHTML
 

Todos

Task 1
Task 2
Task 3
Final app
You may have noticed on the last example that adding a new task resets the ‘done’ state of all the existing tasks. This is because that state is held inside the transformer, so is reset every time the list of tasks changes and the transformer runs.
To fix this, we need to move the ‘done’ state out of the transformer and onto the tasks themselves. See the final code of our app below, noting the changes where the initial tasks are set up, where a new task is added, and where the tasks are transformed into clickable elements.
We can also improve the readability of our code by using double commas to create blank lines in the layout.
Code