Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Google Closure Templates - head first rendering for the web

Google Closure Templates - head first rendering for the web

The presentation given during fitst meet.js in Gdańsk (javascript barcamp).
It's about why you should use templating engines on the client at all and then focuses on explaining a few things and details about closure templates.

Wojtek Urbański

March 11, 2013
Tweet

More Decks by Wojtek Urbański

Other Decks in Programming

Transcript

  1. A BIT ABOUT ME My name is ( ). I'm

    a front-end developer at / . Wojtek Urbański @wojtiku Spartez Atlassian
  2. JAVASCRIPT TEMPLATING SYSTEMS Mustache.js Handlebars Dust.js jQuery templates _.template Jade

    Haml-js Kite jQuote2 pure jTemplates EJS Eco stencil Nun Kite doT Google Closure Templates
  3. ⇩ var peopleData = [ { firstName: "Kristina", lastName: "Chung",

    speaker: false }, { firstName: "Paige", lastName: "Chen", speaker: false }, { firstName: "Sherri", lastName: "Melton", speaker: true }, { firstName: "Gretchen", lastName: "Hill", speaker: false }, { firstName: "Karen", lastName: "Puckett", speaker: true } ]; <table> <thead> <tr><th>Name</th><th>Surname</th></tr> </thead> <tbody> <tr><td>Kristina</td><td>Chung</td></tr> <tr><td>Paige</td><td>Chen</td></tr> <tr class="speaker"><td>Sherri</td><td>Melton</td></tr> <tr><td>Gretchen</td><td>Hill</td></tr> <tr class="speaker"><td>Karen</td><td>Puckett</td></tr> </tbody> </table>
  4. var rows = ""; var i, len = peopleData.length; if

    (len === 0) { rows = "<tr><td colspan=\"2\">No attendees to list.<td><tr>" } else { for (i = 0; i < len; i++) { rows += "<tr" + ((peopleData[i].speaker) ? "class=\"speaker\"" : "" ) + "><td>" + peopleData[i].firstName + "</td>" + "<td>" + peopleData[i].lastName + "</td></tr>"; } } $("#container").html("<table><thead><tr><th>Name</th><th>Surname</th></tr>" + "</thead><tbody>" + rows + "</tbody></table>");
  5. {namespace meetjs.sample} /** * Prints one person * @param firstName

    * @param lastName * @param speaker Boolean that determines if a person is speaking at the event */ {template .showPerson} <tr{if $speaker} class="speaker"{/if}> <td>{$firstName}</td> <td>{$lastName}</td> </tr> {/template} /** * List people attending meet.js * @param people List of meet.js attendees */ {template .listPeople} <table> <thead><tr><th>Name</th><th>Surname</th></tr></thead> <tbody> {foreach $person in $people} {call .showPerson data="$person" /} {ifempty} <tr><td colspan="2">No attendees to list.</td></tr> {/foreach} </tbody> </table> {/template} $("#container").html(meetjs.sample.listPeople({ people: peopleData });
  6. GOOGLE CLOSURE TEMPLATES Simplicity Logic and display separation Client and

    server side (Javascript and Java) Client-side speed Security (auto-escaping) I18n Code documentation Custom functions Namespacing Expressivnes
  7. SYNTAX - DATA TYPES Type Examples null n u l

    l Boolean f a l s e , t r u e Integer 1 2 3 , - 8 5 7 , 0 x 1 2 3 Float 0 . 5 , 1 2 3 . 0 , 1 0 . 1 e 4 String ' A t l a s s i a n ' , ' ' , ' f o o - b a r ' List [ ] , [ 1 , ' t w o ' , 3 , [ 4 , ' f i v e ' ] ] Map [ : ] , [ ' k e y ' : ' v a l u e ' , ' k e y 2 ' : ' v a l u e 2 ' ] Dot and array notation - $ p e r s o n . n a m e = = $ p e r s o n [ ' n a m e ' ] Null-safe access - $ p e r s o n ? . n a m e | | $ p e r s o n ? [ ' n a m e ' ]
  8. SYNTAX - OPERATORS - (unary) n o t * /

    % + - (binary) < > < = > = = = ! = a n d o r ? : (binary) ? : (ternary)
  9. SYNTAX - COMMANDS { t e m p l a

    t e } { / t e m p l a t e } { < e x p r e s s i o n > } , { p r i n t < e x p r e s s i o n > } { i f < e x p r e s s i o n > } , { e l s e i f } , { e l s e } , { / i f } , { s w i t c h < e x p r e s s i o n > } { f o r e a c h } , { i f e m p t y } , { / f o r e a c h } { f o r } , { / f o r } { s p } , { \ n } , { l b } , { r b } , { n i l } , { l i t e r a l } { / l i t e r a l } { c a l l } , { p a r a m } { l e t }
  10. SYNTAX - FUNCTIONS i s F i r s t

    ( $ v a r ) , i s L a s t ( $ v a r ) , i n d e x ( $ v a r ) in f o r e a c h loop i s N o n n u l l ( v a l u e ) l e n g t h ( l i s t ) f l o o r ( n u m b e r ) , f l o o r ( n u m b e r ) , m i n ( n u m b e r , n u m b e r ), m a x ( n u m b e r , n u m b e r ) there is more you can also define your own!
  11. COMPILATION TO JAVASCRIPT ⇩ {namespace meetjs.sample} /** * Simplest Hello

    world demo * @param name */ {template .helloWorld} <div>Hello from Meet.js, {$name}</div> {/template} // This file was automatically generated from meetjs.soy. // Please don't edit this file by hand. if (typeof meetjs == 'undefined') { var meetjs = {}; } if (typeof meetjs.sample == 'undefined') { meetjs.sample = {}; } meetjs.sample.helloWorld = function(opt_data, opt_ignored) { return '<div>Hello from Meet.js, ' + soy.$$escapeHtml(opt_data.name) + '</ div>'; };
  12. AUTO-ESCAPING implicit by default to HTML escaping { n a

    m e s p a c e c o m . e x a m p l e a u t o e s c a p e = " X X X " } X X X may be t r u e , f a l s e or c o n t e x t u a l disable for a single case with { $ t e m p l a t e D a t a | n o A u t o e s c a p e } sanitized data
  13. AUTO-ESCAPING EXAMPLE + ⇩ {namespace meetjs.sample} /** * @param name

    */ {template .helloWorld autoescape="contextual"} <a href="/Demo?name={$name}" onclick="var x = '{$name}'">{$name}</a> {/template} {“name”: "\"><script>alert(\"x&xx\")</script>"} <a href="/Demo?name=%3E%3Cscript%3Ealert%28%22x%26xx%22%29%3C%2Fscript%3E" onclick="var x = '\x3e\x3cscript\x3ealert(\x22x\x26xx\x22)\x3c\/script\x3e'" > &gt;&lt;script&gt;alert(&quot;x&amp;xx&quot;)&lt;/script&gt; </a>
  14. HOW TO USE You will need to download: S o

    y T o J s S r c C o m p i l e r . j a r — A standalone executable jar file that compiles Closure Templates into efficient JavaScript functions. s o y u t i l s . j s — A library of helper utilities. All JavaScript code that's generated by the template compiler use these utilities. And then compile the template: $ java -jar SoyToJsSrcCompiler.jar --outputPathFormat tpl.js --srcs tpl.soy
  15. THE DARK SIDE Command-line compilation needed Java-like stacktraces Exception in

    thread "main" com.google.template.soy.base.SoySyntaxException: In file meetjs.soy:7, template meetjs.sample.helloWorld: Found references to data keys that are not declared in SoyDoc: [name] at com.google.template.soy.base.SoySyntaxException.createWithoutMetaInfo(So ySyntaxException.java:52) at com.google.template.soy.soytree.SoySyntaxExceptionUtils.createWithNode(S oySyntaxExceptionUtils.java:48) at com.google.template.soy.sharedpasses.CheckSoyDocVisitor.visitTemplateNod e(CheckSoyDocVisitor.java:169) at com.google.template.soy.soytree.AbstractSoyNodeVisitor.visitTemplateBasi cNode(AbstractSoyNodeVisitor.java:157) at com.google.template.soy.soytree.AbstractSoyNodeVisitor.visit(AbstractSoy NodeVisitor.java:65) at com.google.template.soy.soytree.AbstractSoyNodeVisitor.visit(AbstractSoy NodeVisitor.java:55) at com.google.template.soy.basetree.AbstractNodeVisitor.visitChildren(Abstr actNodeVisitor.java:59) at com.google.template.soy.soytree.AbstractSoyNodeVisitor.visitChildren(Abs tractSoyNodeVisitor.java:126) at com.google.template.soy.sharedpasses.CheckSoyDocVisitor.visitSoyNode(Che ckSoyDocVisitor.java:208)
  16. RESOURCES Google Closure Templates official website Grunt task for compiling

    Soy Templates Google Group for Closure Templates Plugins for IntelliJ, Vim, gedit, TextMate, SublimeText... Build for sublime-text
  17. ONE MORE THING... WE ARE LOOKING FOR AWESOME FRONT-END DEVELOPERS

    Visit for details. http://atlassian.com/company/careers/