Skip to content

Instantly share code, notes, and snippets.

@machty
Last active December 10, 2015 19:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save machty/4481650 to your computer and use it in GitHub Desktop.
Save machty/4481650 to your computer and use it in GitHub Desktop.
Emblem/Emblate: indentation-based templating language targeting Ember Handlebars
Emblem examples:
1) Text / property lookup / helpers
#bar.baz Raw text
#bar.baz
| Raw text
on multiple lines
with {{normal}} Handlebars syntax support
as well as raw <span>HTML</span> support.
<em>Raw HTML support here, too, </em>
strong but you wouldn't want to use that a whole bunch.
#bar = foo
= foo
#bar
= woot
#bar
= someHelper foo
produces:
<div id="bar">Raw text on multiple lines with {{normal}} Handlebars syntax support as well as raw <span>HTML</span> support.<em>Raw HTML support here, too, </em><strong>but you wouldn't want to use that a whole bunch.</strong></div>
<div id="bar">{{foo}}</div>
{{foo}}
<div id="bar">{{woot}}</div>
<div id="bar">{{someHelper foo}}</div>
1a) Non HTML syntactic sugar (NON_HTML_HELPERS=true [enabled by default])
#bar
foo
strong but 'strong' is a recognized HTML tag so it's not treated as a property.
narf
someHelper dude
produces:
<div id="bar">{{foo}}<strong>but 'strong' is a recognized HTML tag so it's not treated as a property.</strong></div>
{{narf}}
{{someHelper dude}}
2) Basic '==' unescaped usage
#bar == foo
#bar
== foo
== foo
produces:
<div id="bar">{{{foo}}}</div>
<div id="bar">{{{foo}}}</div>
{{{foo}}}
3) if/else (this exceptional syntax will probably always be enabled regardless of NON_HTML_HELPERS)
if isTrue
p It was true
else
p It wasn't true
produces:
{{#if isTrue}}<p>It was true</p>{{else}}<p>It wasn't true</p>{{/if}
4) all bare lowercase non-HTML tags treated as HB helpers
each post in posts
h1 = title
4a) Equivalent code if NON_HTML_HELPERS=false
= each post in posts
h1 = title
5) Followup Indentation determines block vs. non-block HB
view App.AwesomeView
view App.AwesomeView
p This overrides AwesomeView's default template.
produces:
{{view App.AwesomeView}}
{{#view App.AwesomeView}}
<p>This overrides AwesomeView's default template.</p>
{{/view}}
4a) Equivalent code if NON_HTML_HELPERS=false
= view App.AwesomeView
= view App.AwesomeView
p This overrides AwesomeView's default template.
6) view insertion with setting properties
view App.AwesomeView contentBinding="whatever"
produces:
{{view App.AwesomeView contentBinding="whatever"}}
7) view insertion shorthand (detected from uppercase first letter, UPPERCASE_ELEMENT_HELPER="view" [default])
App.AwesomeView
produces:
{{view App.AwesomeView}}
8) Variations of (7)
App.AwesomeView contentBinding="woot"
App.AwesomeView = hello
App.AwesomeView
p Overridden template
produces:
{{view App.AwesomeView contentBinding="woot"}}
{{#view App.AwesomeView}}
{{hello}}
{{/view}}
{{#view App.AwesomeView}}
<p>Overridden template</p>
{{/view}}
9) Bigass example (too lazy to generate to result, should be easy enough to figure out)
.container
.row
.span6
App.MenuView
.span6
h1 = name
/ Assume BlurbView has a layout.
App.BlurbView == wysiwyg_description
if loggedIn
p User is logged in!
else
p User ain't logged in!
h2 Last Post
with lastPost
h3 = title
p = body
/ The following syntax is awesome but not a high priority
ul#posts = each posts
li
h4 = title
p = body
10) support for bindAttr
input type="checkbox" disabled=isAdministrator
produces:
<input type="checkbox" {{bindAttr disabled="isAdministrator"}} />
11) support for actions (ACTION_HELPER_ENABLED=true)
button click="submitComment" Submit Comment
button mouseEnter="aboutToClickSubmit" Submit Comment
a click="submitComment post target='view'" Submit Comment
produces:
<button {{action "submitComment"}}>Submit Comment</button>
<button {{action "aboutToClickSubmit" on="mouseEnter"}}>Submit Comment</button>
<a {{action "submitComment" post target="view"}}>Submit Comment</a>
12) Generalized support for in-tag HB tags
button {{action "submitComment"}} Submit Comment
div {{bindAttr class="userIsLoggedIn"}} Something something
produces:
<button {{action "submitComment"}}></button>
<div {{bindAttr class="userIsLoggedIn"}}>Something something</div>
13) unbound helper support (BANG_HELPER="unbound")
p = prop!
produces:
<p>{{unbound prop}}</p>
14) stacked elements (great for bootstrap, other scaffolding frameworks)
instead of writing
.nav
.container
.row
.span4
p Some thing
.span8
p Another thing
you could write
.nav .container .row
.span4
p Some thing
.span8
p Another thing
easier to track indentation, minimize lines this way
14) Syntactic sugar can be disabled (i.e. the above capitalized helpers) in case:
- You're templating for SVG or some other markup language where the assumptions about valid opening tags isn't the same
- Other reasons?
In rake pipeline or sprockets or some node asset pipe, these properties will be configurable.
In html, these properties can be enabled based on the script tag with the un-pre-processed Emblem code
<script type="x-emblem">
p All the code in here will be compiled with all the syntactic sugar enabled.
</script>
<script type="x-raw-emblem">
p All the code in here will be compiled with all the syntactic sugar disabled.
</script>
<script type="x-emblem" data-uppercase-elements-helper="false">
p All the code in here will be compiled with all the syntactic sugar enabled, except uppercase elements helper.
</script>
FAQ
Q: What if I use HB helpers with the same names as HTML elements?
A: You can put a '=' before the helper to force it to be treated as a hb prop/helper lookup. You'd probably also get in the habit of choosing different names for your hb helpers.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment