- What Is Character Sheet Templating?
- The Case Against Pug (and Sheet Templating generally)
- Setting Up The Handlebars Character Sheet Generator
- Basic Templating with Handlebars
- Handlebars Templating: Things Get Complex
- Handlebars Templating: What are Helpers?
- Handlebars Templating: When You Want to Stop Handlebars
- Handlebars Templating: Nesting in All Its Forms
- Handlebars Templating: Handling Generator Errors
- Handlebars Templating: Helpers
- Handlebars Templating: Partials
The next post is going to be very heavy and require knowledge of a lot of features of Handlebars, so we’ll cover that general grounding here. You’ll probably find this to be a very important reference article.
Expressions
The basic method of referring to the output of handlebars is to enclose in double curly brackets, like this {{name}}
. When you have a statement inside double curly brackets, handlebars will look at your data value, and look for a line that begins with that statement. For example, if this is your data file:
{
"system": "Homebrew",
"based-on": "D&D",
"stats": ["strength", "dexterity", "constitution", "intelligence", "wisdom", "charisma"],
"skills": {
"acrobatics": "dexterity",
"arcana": "intelligence",
"athletics": "strength",
"bluff": "charisma",
"diplomacy": "charisma",
"dungeoneering": "wisdom",
"endurance": "constitution",
"heal": "wisdom",
"history": "intelligence",
"insight": "wisdom",
"intimidate": "charisma",
"nature": "wisdom",
"perception": "wisdom",
"religion": "intelligence",
"stealth": "dexterity",
"streetwise": "charisma",
"thievery": "dexterity"
}
}
Code language: JSON / JSON with Comments (json)
The valid data names here are {{system}}
, {{based-on}}
, {{stats}}
and {{skills}}
– those are the words or statements at the beginning of a line. If you include those terms in a HTML file, the program will insert those values.
This example does include some single value data, like {{system}}
and {{based-on}}
. You just need to enter the handlebar expression and know it’s value will always be inserted in the HTML file. So you only need to change it in one place, and when you click Generate
, it will be updated everywhere you have used that expression.
But I think you’ll get most value from arrays and objects, and we’ll see how to do that soon.
Moustaches and Triple-Staches
This kind of expression {{system}}
is called a mustache, because there is a more rudimentary templating language called Mustache that uses these (yes, that misspelling is deliberate), and Handlebars is based on it.
One of the occasional frustrations with handlebars is that any special characters in a mustache are automatically converted into their HTML equivalents: &
becomes &
;. This is called Escaping. There are good reasons for that, but it’s mostly a frustration for us on Roll20. When you see that happening, you can create a triple-stache, like this: {{{system}}}
. When you use three curly brackets, the contents will not be converted – that & remains an &.
For example, if you have "Berserker": "Choose a target – you go Berserk against that target, and it may continue after that target is down.",
and use {{Berserker}}
, that will become "Choose a target – you go Berserk against that target, and it may continue after that target is down."
You probably don’t want that ndash in the middle, and if you use the triple-stash {{{Berserker}}}
, it will be the expected "Choose a target – you go Berserk against that target, and it may continue after that target is down."
Remember this rule – it will save your hair!
Important Note: version 0.6.1 of the handlebars tool automatically blocks escaping of text. This means you always get the text you see and never need to use triple-staches. So remember if this tutorial mentions them, you may not have to use them.
Order Of Operations: Handlebars Goes First
It wouldn’t be Roll20 without an order of operations. When making dice roll macros, it’s often important to understand Roll20’s order of operations. Luckily the order is very simple for Handlebars: It’s handlebars first, and then anything after that.
So you had a select
for race, and you want handlebars to process that race value, you can’t (at least, not easily). This is because handlebars runs first, building the sheet, and then the player picks their race. Any information dependent on that race choice must already be in the sheet.
Luckily you can build data objects and variables to contain any values you want. We’ll show some examples of exactly that in the next post.
The vast majority of the time this order doesn’t matter, but sometimes it does.
Helpers and Block Helpers
Helpers are bits of code that do things. They are basically functions. In native Handlebars, you can build a Helper to do almost anything but you need to know how to build them. In this tool, there’s a fixed, preset list of Helpers and you can use any of them, and you don’t need to know how to build them.
That said, the documentation for using them is often lacking (or completely useless), and you might already need to know how to use them before you can use them!
Helpers fall into two main types. Helpers which are entirely self contained (e.g. {{capitalise "some text"}}
), and those which expect a block ({{#each races}}{{this.race}}{{/each}}
).
Block Helpers start with an {{#something }}
block and end with a {{/something }}
block, while simple Helpers are entirely contained in a mustache {{something }}
.
We’ve already seen the {{#each}}
block helper, which I think is probably the most useful. We’ll look at some more Helpers later.
Inverse Helpers: the Else Block
Inverse Blocks have already been described. When block helpers perform a logical test, and show the block when truthy, you can often include an {{else}}
block to show in all other cases. For example, we have already seen the {{#eq}}
helper:
{{#eq skill stat}}selected{{else}}disabled{{/eq}}
Code language: Handlebars (handlebars)
Nesting Helpers Inside Helpers
Sometimes you need to put a helper inside another helper. You do this with normal parenthesis. If we knew skill or stat could vary in case, we might want to make sure we were always comparing the same thing and thus make the case equal. We could do this:
{{#eq (downcase skill) (downcase stat)}}selected{{else}}disabled{{/eq}}
Code language: Handlebars (handlebars)
In our code, we always know the code is lower case, so we don’t need to do this – but if the case varied, we would need to do this, because Arcane
is not equal to arcane
: case matters.
Stopping Handlebars From Running
There are times you don’t want to run Handlebars code. In Roll20, this occurs whenever you use two or more { brackets, for instance in rolltemplates. For instance, if type &{template:default} {{name=Monster}}
you’ll get an error.
Luckily, Handlebars has the noop block (no operations), and no handlebars processing is done in this block. So you could do this:
{{{{noop}}}}
&{template}{{name=Monster}}
{{{{/noop}}}}
Code language: Markdown (markdown)
or this:
{{{{noop}}}}&{template}{{name=Monster}}{{{{/noop}}}}
Code language: Markdown (markdown)
I generally put all buttons inside their own noop blocks, and the entire contents of any custom rolltemplates inside their own noop block. Notice that this is a block helper that doesn’t start with a # – isn’t coding fun?
Noop
Blocks are handy when you find some code isn’t working properly – just put a noop
block around it till you fix it.
White Space
In webdesign, white space refers to all content that doesn’t actually include anything – spaces, line spaces, and so on. You can remove white space in your code by adding ~ inside a mustache. This removes all white space up to any previous content. This might help improve the look of your code – you can add line breaks, extra spaces, etc., to make your code easier to read, but then when you click that Generate button it is removed.
I’ll show a situation later where this is really useful, but I’m mentioning it here as something you can do, so you know about it. The code might look like this:
<p>
{{~something~}}
</p>
Code language: Handlebars (handlebars)
Assuming {{something}}
was linked to the text “something else”, then clicking the Generate button would give:
<p>something else</p>
Code language: HTML, XML (xml)
The white space has been removed, and the contents of {{something}}
has been grabbed from the data file.
In This File
This article describes a lot of things. Here’s a list.
- What is a mustache?
- triple-stache
- order of operations
- Helpers, Block Helpers, and Nesting Helpers
- the downcase helper
- noop
- Getting Rid of White Space