Tags map directly to the DOM tag with that name. If the tag is omitted it is assumed to be a div
.
h1
span
input
div
Ids begin with #
just like the CSS selector for them. If a tag has an id it must be before any classes. An element can have zero or one id.
The tag may be omitted and assumed to be a div
.
#main
#hero
nav#nav
form#my-form
Classes begin with a .
just like the CSS selector for them. An element can have zero or more classes.
img.avatar
a.button
button.primary
.tool.eraser
Content that appears after an element treated as the text content of the element.
ul
li A
li List
li of
li Items
Blocks of text content can be nested using the "plain" filter.
.content
:plain
Hello this is some
nested text content
It sure is!
Attributes are declared inside (...)
, just like regular HTML attributes. Multiple attributes are separated by spaces.
form(action="/login")
input(type="text" value=@name)
button(click=@accept) Ok!
Attributes have a shorthand notation when the name is the same as the method:
input(@value)
button(@click) Radical!
If attributes are present they must occur after any ids or classes.
button#primary.flat(click=@activate) Activate
The structure of a document is determined by the nesting.
nav
a.home Home
a.about About
Unbuffered code is evaluated but it's result is not included in the output. You may use it to declare variables or for regular CoffeeScript control flow.
.main
- if @loggedIn
a Log Out
- else
a Log In
Buffered code begins with an =
. It can be inline or nested. The code is evaluated at runtime and it is converted into a string and inserted as text content. If the method is an observable or a function that depends on other observable the content will be updated when any of the observable dependencies change.
.person
.name
= @first
= @last
You can insert CoffeeScript or JavaScript code or verbatim text using filters.
coffeescript:
alert "cool"
javascript:
alert("hey");
textarea
verbatim:
.example
This will end up as text in the text area is is