SlideShare a Scribd company logo
1 of 75
Juicer
一个 Javascript 模板引擎の实现与优化



            流火 @ TaobaoUED
            Blog: http://benben.cc
var json={
    name:"liuhuo",
    blog:"ued.taobao.com"
};
var json={
               name:"liuhuo",
               blog:"ued.taobao.com"
           };




<span class="name">流火 (blog: ued.taobao.com)</span>
var json={
                        name:"liuhuo",
                        blog:"ued.taobao.com"
                    };




        <span class="name">流火 (blog: ued.taobao.com)</span>




var html;
html='<span class="name">'+json.name+' (blog: '+json.blog+')</span>';
function sub(str,data) {
    return str
        .replace(/{(.*?)}/igm,function($,$1) {
            return data[$1]?data[$1]:$;
        });
}
var tpl='<span class="name">{name} (blog: {blog})</span>';

var html=sub(tpl,json);
YUI.Lang.sub
JSON   Template
JSON   Template
JSON   Template
        Engine    Template
JSON   Template
        Engine    Template
JSON   Template
        Engine    Template
JSON   Template
        Engine    Template




         HTML
       Fragment
water     juicer     fruits




JSON    Template
         Engine    Template




          HTML
        Fragment
doT      yayaTemplate
    ejs
             Mustache
                             artTemplate
nTenjin
                    Kissy template
   micro template

   ...
               jQuery tmpl
“如无必要,勿增实体”
Entia non sunt multiplicanda praeter
necessitatem.
Security
Security
 XSS escape
Security
          XSS escape




Syntax
Security
                        XSS escape




 Syntax
easy to write & read
Security
                        XSS escape




 Syntax                              Performance
easy to write & read
Security
                        XSS escape




 Syntax                              Performance
easy to write & read                 as faster as you can
Security
                        XSS escape




 Syntax                              Performance
easy to write & read                 as faster as you can




                Error Handling
Security
                        XSS escape




 Syntax                              Performance
easy to write & read                 as faster as you can




                Error Handling
                        robustness
Security
                        XSS escape




 Syntax                              Performance
easy to write & read                 as faster as you can




                Error Handling
                        robustness
Syntax
<ul>                                               <ul>                                            <ul>
    {{#list}}                                          {@each data.list as it,k}                       {{#each list as it,k}}
        {{#show}}                                          {@if it.show}                                   {{#if it.show}}
            <li>{{name}} (index: {{index}})</li>               <li>${it.name} (index: ${k})</li>               <li>{{it.name}} (index: {{k}})</li>
        {{/show}}                                          {@/if}                                          {{/if}}
    {{/list}}                                          {@/each}                                        {{/each}}
    {{#blah}}                                          {@each data.blah as it}                         {{#each blah as it}}
        <li>                                               <li>                                            <li>
            num: {{num}}                                       num: ${it.num}                                  num: {{it.num}}
            ...                                                {@if it.num==3}                                 {{#if it.num==3}}
            {{#inner}}                                             {@each it.inner as it2}                         {{#each it.inner as it2}}
                <li>{{time}}</li>                                      <li>${it2.time}</li>                            <li>{{it2.time}}</li>
            {{/inner}}                                             {@/each}                                        {{/each}}
            ...                                                {@/if}                                          {{/if}}
        </li>                                              </li>                                           </li>
    {{/blah}}                                          {@/each}                                        {{/each}}
</ul>                                              </ul>                                           </ul>

<ul>                                                                      <ul>
    <% for(var i=0;i<list.length;i++) { %>                                    <?js for(var i=0;i<it.list.length;i++) { ?>
        <% if(list[i].show) { %>                                                  <?js if(it.list[i].show) { ?>
            <li><%= list[i].name %> (index: <%= i %>)</li>                            <li>${it.list[i].name} (index: ${i})</li>
        <% } %>                                                                   <?js } ?>
    <% } %>                                                                   <?js } ?>
    <% for(var i=0;i<blah.length;i++) { %>                                    <?js for(var i=0;i<it.blah.length;i++) { ?>
        <li>                                                                      <li>
            num: <%= blah[i].num %>                                                   num: ${it.blah[i].num}
            <% if(blah[i].num==3) { %>                                                <?js if(it.blah[i].num==3) { ?>           
                <% for(var j=0;j<blah[i].inner.length;j++) { %>                           <?js for(var j=0;j<it.blah[i].inner.length;j++) { ?>
                    <li><%= blah[i].inner[j].time %></li>                                     <li>${it.blah[i].inner[j].time}</li>
                <% } %>                                                                   <?js } ?>
            <% } %>                                                                   <?js } ?>
        </li>                                                                     </li>
    <% } %>                                                                   <?js } ?>
</ul>                                                                     </ul>
JSON
var data={
    list:[
        {name:'liuhuo',show:true},
        {name:'benben',show:false},
        {name:'taobao',show:true}
    ],
    blah:[
        {num:1},
        {num:2},
        {num:3,inner:[
            {'time':'15:00'},
            {'time':'16:00'},
            {'time':'17:00'},
            {'time':'18:00'}
        ]},
        {num:4}
    ]
};
JSON                                  EXPECTED RESULT
var data={                            <ul>
    list:[                                <li>liuhuo (index: 0)</li>
        {name:'liuhuo',show:true},        <li>benben (index: 1)</li>
        {name:'benben',show:false},       <li>taobao (index: 2)</li>
        {name:'taobao',show:true}         <li>num: 1</li>
    ],                                    <li>num: 2</li>
    blah:[                                <li>num: 3</li>
        {num:1},                          <li>15:00</li>
        {num:2},                          <li>16:00</li>
        {num:3,inner:[                    <li>17:00</li>
            {'time':'15:00'},             <li>18:00</li>
            {'time':'16:00'},             <li>num: 4</li>
            {'time':'17:00'},         </ul>
            {'time':'18:00'}
        ]},
        {num:4}
    ]
};
<ul>
    {@each data.list as it,k}
        {@if it.show}
            <li>${it.name} (index: ${k})</li>
        {@/if}
    {@/each}
    {@each data.blah as it}
        <li>
            num: ${it.num}
            {@if it.num==3}
                {@each it.inner as it2}
                    <li>${it2.time}</li>
                {@/each}
            {@/if}
        </li>
    {@/each}
</ul>




         using juicer
          http://jsfiddle.net/paulguo/LpvwH/1/
<ul>
    {{#each list as it,index}}
        {{#if it.show}}
            <li>{{it.name}} (index: {{index}})</li>
        {{/if}}
    {{/each}}
    {{#each blah as it}}
        <li>
            num: {{it.num}}
            {{#if it.num==3}}
                {{#each it.inner as it2}}
                    <li>{{it2.time}}</li>
                {{/each}}
            {{/if}}
        </li>
    {{/each}}
</ul>




          using kissy
          http://jsfiddle.net/paulguo/yLg4Y/1/
<ul>
    {{#list}}
        {{#show}}
            <li>{{name}} (index: {{index}})</li>
        {{/show}}
    {{/list}}
    {{#blah}}
        <li>
            num: {{num}}
            {{#inner}}
                <li>{{time}}</li>
            {{/inner}}
        </li>
    {{/blah}}
</ul>




    using mustache
          http://jsfiddle.net/paulguo/VCH9k/1/
<ul>
    <% for(var i=0;i<list.length;i++) { %>
        <% if(list[i].show) { %>
            <li><%= list[i].name %> (index: <%= i %>)</li>
        <% } %>
    <% } %>
    <% for(var i=0;i<blah.length;i++) { %>
        <li>
            num: <%= blah[i].num %>
            <% if(blah[i].num==3) { %>           
                <% for(var j=0;j<blah[i].inner.length;j++) { %>
                    <li><%= blah[i].inner[j].time %></li>
                <% } %>
            <% } %>
        </li>
    <% } %>
</ul>




               using micro
                http://jsfiddle.net/paulguo/KsDhC/1/
<ul>
    <?js for(var i=0;i<it.list.length;i++) { ?>
        <?js if(it.list[i].show) { ?>
            <li>${it.list[i].name} (index: ${i})</li>
        <?js } ?>
    <?js } ?>
    <?js for(var i=0;i<it.blah.length;i++) { ?>
        <li>
            num: ${it.blah[i].num}
            <?js if(it.blah[i].num==3) { ?>           
                <?js for(var j=0;j<it.blah[i].inner.length;j++) { ?>
                    <li>${it.blah[i].inner[j].time}</li>
                <?js } ?>
            <?js } ?>
        </li>
    <?js } ?>
</ul>




               using nTenjin
                  http://jsfiddle.net/paulguo/W7eVV/1/
Performance
Performance




              http://jsperf.com/javascript-template-engine/11
Performance
 test result without
       escape.
Performance
 test result without
       escape.
Performance
    test result without
          escape.




http://juicer.name/speedtest
Security
var json={
" output:'<script>alert("XSS");</script>'
};
Security
var json={
" output:'<script>alert("XSS");</script>'
};




document.write
Security
var json={
" output:'<script>alert("XSS");</script>'
};




document.write                        $(node).html()
Security
var json={
" output:'<script>alert("XSS");</script>'
};




document.write                        $(node).html()

juicer.to_html('${output}',json);
//输出:&lt;script&gt;alert("XSS");&lt;/script&gt;


juicer.to_html('$${output}',json);
//输出:<script>alert("XSS");</script>
template
compile
template             reusable function
compile
template             reusable function
                           compiled template
compile                             render
template             reusable function                  html code
                           compiled template
var json={
    list:[
        {name:"benben"},
        {name:"liuhuo"}
    ]
};

var tpl='{@each data.list as value,key}$${value.name}{@/each}';
var compiled_tpl=juicer.compile(tpl,{errorhandling:false});
function anonymous(data) {
    var data = data || {};
    var out = '';
    out += '';
    for (var i0 = 0, l = data.list.length; i0 < l; i0++) {
        var value = data.list[i0];
        var key = i0;
        out += '';
        out += ((value.name));
        out += '';
    }
    out += '';
    return out;
}
Several Optimization Point
Several Optimization Point




                using += instead of array.push
Browser string optimizations have changed the string
concatenation picture.
Firefox was the first browser to optimize string concatenation. Beginning with
version 1.0, the array technique is actually slower than using the plus operator
in all cases. Other browsers have also optimized string concatenation, so
Safari, Opera, Chrome, and Internet Explorer 8 also show better performance
using the plus operator. Internet Explorer prior to version 8 didn’t have such an
optimization, and so the array technique is always faster than the plus operator.



— Writing Efficient JavaScript: Chapter 7 – Even Faster Websites
The V8 javascript engine (used in Google Chrome) uses this code
to do string concatenation:




// ECMA-262, section 15.5.4.6
function StringConcat() {
  if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
    throw MakeTypeError("called_on_null_or_undefined", ["String.prototype.concat"]);
  }
  var len = %_ArgumentsLength();
  var this_as_string = TO_STRING_INLINE(this);
  if (len === 1) {
    return this_as_string + %_Arguments(0);
  }
  var parts = new InternalArray(len + 1);
  parts[0] = this_as_string;
  for (var i = 0; i < len; i++) {
    var part = %_Arguments(i);
    parts[i + 1] = TO_STRING_INLINE(part);
  }
  return %StringBuilderConcat(parts, len + 1, "");
}
Several Optimization Point




                             avoid using with {}
var person = {                        The with construct introduces an extra scope for
    name: "Nicholas",                 the script engine to search through whenever a
    age: 30                           variable is referenced. This alone produces a
};                                    minor performance decrease. However, the
                                      contents of that scope are not known at compile
function displayInfo(){               time, meaning that the compiler cannot optimize
    var count = 5;                    for it, in the same way as it can with normal scopes
    with(person){                     (such as those created by functions).
        alert(name + " is " + age);
        alert("Count is " + count);
    }
}

displayInfo();
Several Optimization Point




                  cache the compiled template.
1 循环 {@each}…{@/each}

2 判断 {@if}…{@else if}…{@else}…{@/if}

3 变量(支持函数)${varname|function}

4 注释 {# comment here}
a demo, then docs.
          http://juicer.name
Juicer Docs

juicer is a high-performance lightweight javascript template engine, the benefits of using juicer is that you
can seperate your data and the html structure. it can also running on node.js environment.



the name of juicer
if the data is fruit, the template compared to water, through the juicer will be able to put them mixed into
html code.



import juicer.js
<script type="text/javascript" src="juicer-min.js"></script>



* License

juicer is published under the apache license and hosted on github. if you find errors or typos please file an
issueor a pull request on the repository.
* API

> compile and render the template with given data immediately.

juicer.to_html(tpl,data,options);


> only compile the template, it'll return a reusable function for the given `template`.

var tpl=juicer.compile(tpl,options);


> render the complied template with given data.

var tpl=juicer.compile(tpl,options);
var html=tpl.render(data);


Options

{
"   cache:true/false,
"   loose:false/true,
    errorhandling:true/false
}


cache in the options means that whether cache the pre-compiled templates.
* Syntax

a. ${var}
using ${} to evaluating expressions and functions.

${data.name}

${data.name|function}


let's use a demo to illustrate this usage.

var json={
"   name:'benben',
"   age:23
};


var inc=function(number) {
"   return number+1;
};


//it'll be 'benben'
juicer.to_html('${data.name}',json);

//it'll be 24
juicer.to_html('${data.age|inc}',json);
{@each data.list as it,k}
    <span class=”{@if k+2>data.list.length}notdot{@/if}”>...</span>
{@/each}
http://taobao.com/s?q=%E6%B7%98%E5%AE%9D




                                                  json={
                                                      query:’淘宝’,
                                                      ...
                                                  }




http://taobao.com/s?q=${query|encodeURIComponent}
escape/unescape

it is noteworthy that, for security reasons, ${output} will do escape to the output, if you
do not want it to be escaped, you can use $${output} to avoid this. for example:

var json={
"   value:'<strong>juicer</strong>'
};


var escapetpl='${data.value}';

var unescapetpl='$${data.value}';


juicer.to_html(escapetpl,json); //it'll be '&lt;strong&gt;juicer&lt;/strong&gt;'

juicer.to_html(unescapetpl,json); //it'll be '<strong>juicer</strong>'
b. {@each} ... {@/each}


when you need iterate a list, you can use `each` like this.


{@each data.list as item}
"   ${item.prop}
{@/each}



you can also get the index while eaching.


{@each data.list as item,index}
"   ${item.prop}
"   ${index} //index
{@/each}
c. {@if} ... {@else} ... {else if} ... {@/if}


you can also use if-else if you need.


{@each data.list as item,index}
"   {@if index===3}
"   "    the index is 3, the value is ${item.prop}
"   {@else}
"   "    the index is not 3, the value is ${item.prop}
"   {@/if}
{@/each}



d. {# comment}


you can also write comments in the template code to facilitate future management.


{# some comment here}
* running on the Node.js environment


bash:   npm install juicer
var juicer=require('juicer');

var html=juicer.to_html(tpl,data,options);
juicer.to_html(
         ‘${data.end}’,
Q&A      {end:‘thanks!’}
      );




              http://juicer.name

More Related Content

What's hot

Rediscovering JavaScript: The Language Behind The Libraries
Rediscovering JavaScript: The Language Behind The LibrariesRediscovering JavaScript: The Language Behind The Libraries
Rediscovering JavaScript: The Language Behind The Libraries
Simon Willison
 
Юрий Буянов «Squeryl — ORM с человеческим лицом»
Юрий Буянов «Squeryl — ORM с человеческим лицом»Юрий Буянов «Squeryl — ORM с человеческим лицом»
Юрий Буянов «Squeryl — ORM с человеческим лицом»
e-Legion
 
ApacheCon NA11 - Apache Celix, Universal OSGi?
ApacheCon NA11 - Apache Celix, Universal OSGi?ApacheCon NA11 - Apache Celix, Universal OSGi?
ApacheCon NA11 - Apache Celix, Universal OSGi?
abroekhuis
 
JQuery In Rails
JQuery In RailsJQuery In Rails
JQuery In Rails
Louie Zhao
 

What's hot (20)

Rediscovering JavaScript: The Language Behind The Libraries
Rediscovering JavaScript: The Language Behind The LibrariesRediscovering JavaScript: The Language Behind The Libraries
Rediscovering JavaScript: The Language Behind The Libraries
 
Potential Friend Finder
Potential Friend FinderPotential Friend Finder
Potential Friend Finder
 
Mobile Database Persistence
Mobile Database PersistenceMobile Database Persistence
Mobile Database Persistence
 
An Elephant of a Different Colour: Hack
An Elephant of a Different Colour: HackAn Elephant of a Different Colour: Hack
An Elephant of a Different Colour: Hack
 
Devs for Leokz e 7Masters - WTF Oriented Programming
Devs for Leokz e 7Masters - WTF Oriented ProgrammingDevs for Leokz e 7Masters - WTF Oriented Programming
Devs for Leokz e 7Masters - WTF Oriented Programming
 
Using Templates to Achieve Awesomer Architecture
Using Templates to Achieve Awesomer ArchitectureUsing Templates to Achieve Awesomer Architecture
Using Templates to Achieve Awesomer Architecture
 
Mongo db mug_2012-02-07
Mongo db mug_2012-02-07Mongo db mug_2012-02-07
Mongo db mug_2012-02-07
 
Юрий Буянов «Squeryl — ORM с человеческим лицом»
Юрий Буянов «Squeryl — ORM с человеческим лицом»Юрий Буянов «Squeryl — ORM с человеческим лицом»
Юрий Буянов «Squeryl — ORM с человеческим лицом»
 
Gta v savegame
Gta v savegameGta v savegame
Gta v savegame
 
Jquery
JqueryJquery
Jquery
 
RubyBarCamp “Полезные gems и plugins”
RubyBarCamp “Полезные gems и plugins”RubyBarCamp “Полезные gems и plugins”
RubyBarCamp “Полезные gems и plugins”
 
Elastic tire demo
Elastic tire demoElastic tire demo
Elastic tire demo
 
JQuery
JQueryJQuery
JQuery
 
ApacheCon NA11 - Apache Celix, Universal OSGi?
ApacheCon NA11 - Apache Celix, Universal OSGi?ApacheCon NA11 - Apache Celix, Universal OSGi?
ApacheCon NA11 - Apache Celix, Universal OSGi?
 
Therapeutic refactoring
Therapeutic refactoringTherapeutic refactoring
Therapeutic refactoring
 
DataMapper @ RubyEnRails2009
DataMapper @ RubyEnRails2009DataMapper @ RubyEnRails2009
DataMapper @ RubyEnRails2009
 
Javascript & jQuery: A pragmatic introduction
Javascript & jQuery: A pragmatic introductionJavascript & jQuery: A pragmatic introduction
Javascript & jQuery: A pragmatic introduction
 
Beginner workshop to angularjs presentation at Google
Beginner workshop to angularjs presentation at GoogleBeginner workshop to angularjs presentation at Google
Beginner workshop to angularjs presentation at Google
 
JQuery In Rails
JQuery In RailsJQuery In Rails
JQuery In Rails
 
php plus mysql
php plus mysqlphp plus mysql
php plus mysql
 

Similar to Juicer javascript template engine

JSON(JavaScript Object Notation)
JSON(JavaScript Object Notation)JSON(JavaScript Object Notation)
JSON(JavaScript Object Notation)
Raghu nath
 
JQuery do dia-a-dia Gustavo Dutra
JQuery do dia-a-dia Gustavo DutraJQuery do dia-a-dia Gustavo Dutra
JQuery do dia-a-dia Gustavo Dutra
Tchelinux
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
Dmitry Buzdin
 
Ruby Language - A quick tour
Ruby Language - A quick tourRuby Language - A quick tour
Ruby Language - A quick tour
aztack
 

Similar to Juicer javascript template engine (20)

Automatically Spotting Cross-language Relations
Automatically Spotting Cross-language RelationsAutomatically Spotting Cross-language Relations
Automatically Spotting Cross-language Relations
 
Broadleaf Presents Thymeleaf
Broadleaf Presents ThymeleafBroadleaf Presents Thymeleaf
Broadleaf Presents Thymeleaf
 
iRODS Rule Language Cheat Sheet
iRODS Rule Language Cheat SheetiRODS Rule Language Cheat Sheet
iRODS Rule Language Cheat Sheet
 
Lettering js
Lettering jsLettering js
Lettering js
 
JSON(JavaScript Object Notation)
JSON(JavaScript Object Notation)JSON(JavaScript Object Notation)
JSON(JavaScript Object Notation)
 
jQuery - Introdução
jQuery - IntroduçãojQuery - Introdução
jQuery - Introdução
 
JQuery do dia-a-dia Gustavo Dutra
JQuery do dia-a-dia Gustavo DutraJQuery do dia-a-dia Gustavo Dutra
JQuery do dia-a-dia Gustavo Dutra
 
My First Ruby
My First RubyMy First Ruby
My First Ruby
 
WTF Oriented Programming, com Fabio Akita
WTF Oriented Programming, com Fabio AkitaWTF Oriented Programming, com Fabio Akita
WTF Oriented Programming, com Fabio Akita
 
JQuery Flot
JQuery FlotJQuery Flot
JQuery Flot
 
Lab final
Lab finalLab final
Lab final
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
 
ScalikeJDBC Tutorial for Beginners
ScalikeJDBC Tutorial for BeginnersScalikeJDBC Tutorial for Beginners
ScalikeJDBC Tutorial for Beginners
 
CAVE Overview
CAVE OverviewCAVE Overview
CAVE Overview
 
jQuery: Tips, tricks and hints for better development and Performance
jQuery: Tips, tricks and hints for better development and PerformancejQuery: Tips, tricks and hints for better development and Performance
jQuery: Tips, tricks and hints for better development and Performance
 
Elm: give it a try
Elm: give it a tryElm: give it a try
Elm: give it a try
 
“Insulin” for Scala’s Syntactic Diabetes
“Insulin” for Scala’s Syntactic Diabetes“Insulin” for Scala’s Syntactic Diabetes
“Insulin” for Scala’s Syntactic Diabetes
 
Swift Sequences & Collections
Swift Sequences & CollectionsSwift Sequences & Collections
Swift Sequences & Collections
 
Ruby Language - A quick tour
Ruby Language - A quick tourRuby Language - A quick tour
Ruby Language - A quick tour
 
Rails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript Using CoffeeScript, Backbone.js and JasmineRails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
 

Recently uploaded

Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
vu2urc
 

Recently uploaded (20)

2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 

Juicer javascript template engine

  • 1.
  • 2. Juicer 一个 Javascript 模板引擎の实现与优化 流火 @ TaobaoUED Blog: http://benben.cc
  • 4. var json={     name:"liuhuo",     blog:"ued.taobao.com" }; <span class="name">流火 (blog: ued.taobao.com)</span>
  • 5. var json={     name:"liuhuo",     blog:"ued.taobao.com" }; <span class="name">流火 (blog: ued.taobao.com)</span> var html; html='<span class="name">'+json.name+' (blog: '+json.blog+')</span>';
  • 6.
  • 7. function sub(str,data) { return str .replace(/{(.*?)}/igm,function($,$1) { return data[$1]?data[$1]:$; }); }
  • 8. var tpl='<span class="name">{name} (blog: {blog})</span>'; var html=sub(tpl,json);
  • 10. JSON Template
  • 11. JSON Template
  • 12. JSON Template Engine Template
  • 13. JSON Template Engine Template
  • 14. JSON Template Engine Template
  • 15. JSON Template Engine Template HTML Fragment
  • 16. water juicer fruits JSON Template Engine Template HTML Fragment
  • 17.
  • 18. doT yayaTemplate ejs Mustache artTemplate nTenjin Kissy template micro template ... jQuery tmpl
  • 19.
  • 20. “如无必要,勿增实体” Entia non sunt multiplicanda praeter necessitatem.
  • 21.
  • 24. Security XSS escape Syntax
  • 25. Security XSS escape Syntax easy to write & read
  • 26. Security XSS escape Syntax Performance easy to write & read
  • 27. Security XSS escape Syntax Performance easy to write & read as faster as you can
  • 28. Security XSS escape Syntax Performance easy to write & read as faster as you can Error Handling
  • 29. Security XSS escape Syntax Performance easy to write & read as faster as you can Error Handling robustness
  • 30. Security XSS escape Syntax Performance easy to write & read as faster as you can Error Handling robustness
  • 31. Syntax <ul> <ul> <ul>     {{#list}}     {@each data.list as it,k}     {{#each list as it,k}}         {{#show}}         {@if it.show}         {{#if it.show}}             <li>{{name}} (index: {{index}})</li>             <li>${it.name} (index: ${k})</li>             <li>{{it.name}} (index: {{k}})</li>         {{/show}}         {@/if}         {{/if}}     {{/list}}     {@/each}     {{/each}}     {{#blah}}     {@each data.blah as it}     {{#each blah as it}}         <li>         <li>         <li>             num: {{num}}             num: ${it.num}             num: {{it.num}}             ...             {@if it.num==3}             {{#if it.num==3}}             {{#inner}}                 {@each it.inner as it2}                 {{#each it.inner as it2}}                 <li>{{time}}</li>                     <li>${it2.time}</li>                     <li>{{it2.time}}</li>             {{/inner}}                 {@/each}                 {{/each}}             ...             {@/if}             {{/if}}         </li>         </li>         </li>     {{/blah}}     {@/each}     {{/each}} </ul> </ul> </ul> <ul> <ul>     <% for(var i=0;i<list.length;i++) { %>     <?js for(var i=0;i<it.list.length;i++) { ?>         <% if(list[i].show) { %>         <?js if(it.list[i].show) { ?>             <li><%= list[i].name %> (index: <%= i %>)</li>             <li>${it.list[i].name} (index: ${i})</li>         <% } %>         <?js } ?>     <% } %>     <?js } ?>     <% for(var i=0;i<blah.length;i++) { %>     <?js for(var i=0;i<it.blah.length;i++) { ?>         <li>         <li>             num: <%= blah[i].num %>             num: ${it.blah[i].num}             <% if(blah[i].num==3) { %>                        <?js if(it.blah[i].num==3) { ?>                            <% for(var j=0;j<blah[i].inner.length;j++) { %>                 <?js for(var j=0;j<it.blah[i].inner.length;j++) { ?>                     <li><%= blah[i].inner[j].time %></li>                     <li>${it.blah[i].inner[j].time}</li>                 <% } %>                 <?js } ?>             <% } %>             <?js } ?>         </li>         </li>     <% } %>     <?js } ?> </ul> </ul>
  • 33. JSON EXPECTED RESULT var data={ <ul>     list:[     <li>liuhuo (index: 0)</li>         {name:'liuhuo',show:true},     <li>benben (index: 1)</li>         {name:'benben',show:false},     <li>taobao (index: 2)</li>         {name:'taobao',show:true}     <li>num: 1</li>     ],     <li>num: 2</li>     blah:[     <li>num: 3</li>         {num:1},     <li>15:00</li>         {num:2},     <li>16:00</li>         {num:3,inner:[     <li>17:00</li>             {'time':'15:00'},     <li>18:00</li>             {'time':'16:00'},     <li>num: 4</li>             {'time':'17:00'}, </ul>             {'time':'18:00'}         ]},         {num:4}     ] };
  • 34.
  • 35. <ul>     {@each data.list as it,k}         {@if it.show}             <li>${it.name} (index: ${k})</li>         {@/if}     {@/each}     {@each data.blah as it}         <li>             num: ${it.num}             {@if it.num==3}                 {@each it.inner as it2}                     <li>${it2.time}</li>                 {@/each}             {@/if}         </li>     {@/each} </ul> using juicer http://jsfiddle.net/paulguo/LpvwH/1/
  • 36. <ul>     {{#each list as it,index}}         {{#if it.show}}             <li>{{it.name}} (index: {{index}})</li>         {{/if}}     {{/each}}     {{#each blah as it}}         <li>             num: {{it.num}}             {{#if it.num==3}}                 {{#each it.inner as it2}}                     <li>{{it2.time}}</li>                 {{/each}}             {{/if}}         </li>     {{/each}} </ul> using kissy http://jsfiddle.net/paulguo/yLg4Y/1/
  • 37. <ul>     {{#list}}         {{#show}}             <li>{{name}} (index: {{index}})</li>         {{/show}}     {{/list}}     {{#blah}}         <li>             num: {{num}}             {{#inner}}                 <li>{{time}}</li>             {{/inner}}         </li>     {{/blah}} </ul> using mustache http://jsfiddle.net/paulguo/VCH9k/1/
  • 38. <ul>     <% for(var i=0;i<list.length;i++) { %>         <% if(list[i].show) { %>             <li><%= list[i].name %> (index: <%= i %>)</li>         <% } %>     <% } %>     <% for(var i=0;i<blah.length;i++) { %>         <li>             num: <%= blah[i].num %>             <% if(blah[i].num==3) { %>                            <% for(var j=0;j<blah[i].inner.length;j++) { %>                     <li><%= blah[i].inner[j].time %></li>                 <% } %>             <% } %>         </li>     <% } %> </ul> using micro http://jsfiddle.net/paulguo/KsDhC/1/
  • 39. <ul>     <?js for(var i=0;i<it.list.length;i++) { ?>         <?js if(it.list[i].show) { ?>             <li>${it.list[i].name} (index: ${i})</li>         <?js } ?>     <?js } ?>     <?js for(var i=0;i<it.blah.length;i++) { ?>         <li>             num: ${it.blah[i].num}             <?js if(it.blah[i].num==3) { ?>                            <?js for(var j=0;j<it.blah[i].inner.length;j++) { ?>                     <li>${it.blah[i].inner[j].time}</li>                 <?js } ?>             <?js } ?>         </li>     <?js } ?> </ul> using nTenjin http://jsfiddle.net/paulguo/W7eVV/1/
  • 41. Performance http://jsperf.com/javascript-template-engine/11
  • 42. Performance test result without escape.
  • 43. Performance test result without escape.
  • 44. Performance test result without escape. http://juicer.name/speedtest
  • 48. Security var json={ " output:'<script>alert("XSS");</script>' }; document.write $(node).html() juicer.to_html('${output}',json); //输出:&lt;script&gt;alert("XSS");&lt;/script&gt; juicer.to_html('$${output}',json); //输出:<script>alert("XSS");</script>
  • 50. compile template reusable function
  • 51. compile template reusable function compiled template
  • 52. compile render template reusable function html code compiled template
  • 53. var json={     list:[         {name:"benben"},         {name:"liuhuo"}     ] }; var tpl='{@each data.list as value,key}$${value.name}{@/each}'; var compiled_tpl=juicer.compile(tpl,{errorhandling:false});
  • 54. function anonymous(data) {     var data = data || {};     var out = '';     out += '';     for (var i0 = 0, l = data.list.length; i0 < l; i0++) {         var value = data.list[i0];         var key = i0;         out += '';         out += ((value.name));         out += '';     }     out += '';     return out; }
  • 56. Several Optimization Point using += instead of array.push
  • 57.
  • 58. Browser string optimizations have changed the string concatenation picture. Firefox was the first browser to optimize string concatenation. Beginning with version 1.0, the array technique is actually slower than using the plus operator in all cases. Other browsers have also optimized string concatenation, so Safari, Opera, Chrome, and Internet Explorer 8 also show better performance using the plus operator. Internet Explorer prior to version 8 didn’t have such an optimization, and so the array technique is always faster than the plus operator. — Writing Efficient JavaScript: Chapter 7 – Even Faster Websites
  • 59. The V8 javascript engine (used in Google Chrome) uses this code to do string concatenation: // ECMA-262, section 15.5.4.6 function StringConcat() {   if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {     throw MakeTypeError("called_on_null_or_undefined", ["String.prototype.concat"]);   }   var len = %_ArgumentsLength();   var this_as_string = TO_STRING_INLINE(this);   if (len === 1) {     return this_as_string + %_Arguments(0);   }   var parts = new InternalArray(len + 1);   parts[0] = this_as_string;   for (var i = 0; i < len; i++) {     var part = %_Arguments(i);     parts[i + 1] = TO_STRING_INLINE(part);   }   return %StringBuilderConcat(parts, len + 1, ""); }
  • 60. Several Optimization Point avoid using with {}
  • 61.
  • 62. var person = { The with construct introduces an extra scope for name: "Nicholas", the script engine to search through whenever a age: 30 variable is referenced. This alone produces a }; minor performance decrease. However, the contents of that scope are not known at compile function displayInfo(){ time, meaning that the compiler cannot optimize var count = 5; for it, in the same way as it can with normal scopes with(person){ (such as those created by functions). alert(name + " is " + age); alert("Count is " + count); } } displayInfo();
  • 63. Several Optimization Point cache the compiled template.
  • 64. 1 循环 {@each}…{@/each} 2 判断 {@if}…{@else if}…{@else}…{@/if} 3 变量(支持函数)${varname|function} 4 注释 {# comment here}
  • 65. a demo, then docs. http://juicer.name
  • 66. Juicer Docs juicer is a high-performance lightweight javascript template engine, the benefits of using juicer is that you can seperate your data and the html structure. it can also running on node.js environment. the name of juicer if the data is fruit, the template compared to water, through the juicer will be able to put them mixed into html code. import juicer.js <script type="text/javascript" src="juicer-min.js"></script> * License juicer is published under the apache license and hosted on github. if you find errors or typos please file an issueor a pull request on the repository.
  • 67. * API > compile and render the template with given data immediately. juicer.to_html(tpl,data,options); > only compile the template, it'll return a reusable function for the given `template`. var tpl=juicer.compile(tpl,options); > render the complied template with given data. var tpl=juicer.compile(tpl,options); var html=tpl.render(data); Options { " cache:true/false, " loose:false/true, errorhandling:true/false } cache in the options means that whether cache the pre-compiled templates.
  • 68. * Syntax a. ${var} using ${} to evaluating expressions and functions. ${data.name} ${data.name|function} let's use a demo to illustrate this usage. var json={ " name:'benben', " age:23 }; var inc=function(number) { " return number+1; }; //it'll be 'benben' juicer.to_html('${data.name}',json); //it'll be 24 juicer.to_html('${data.age|inc}',json);
  • 69. {@each data.list as it,k} <span class=”{@if k+2>data.list.length}notdot{@/if}”>...</span> {@/each}
  • 70. http://taobao.com/s?q=%E6%B7%98%E5%AE%9D json={ query:’淘宝’, ... } http://taobao.com/s?q=${query|encodeURIComponent}
  • 71. escape/unescape it is noteworthy that, for security reasons, ${output} will do escape to the output, if you do not want it to be escaped, you can use $${output} to avoid this. for example: var json={ " value:'<strong>juicer</strong>' }; var escapetpl='${data.value}'; var unescapetpl='$${data.value}'; juicer.to_html(escapetpl,json); //it'll be '&lt;strong&gt;juicer&lt;/strong&gt;' juicer.to_html(unescapetpl,json); //it'll be '<strong>juicer</strong>'
  • 72. b. {@each} ... {@/each} when you need iterate a list, you can use `each` like this. {@each data.list as item} " ${item.prop} {@/each} you can also get the index while eaching. {@each data.list as item,index} " ${item.prop} " ${index} //index {@/each}
  • 73. c. {@if} ... {@else} ... {else if} ... {@/if} you can also use if-else if you need. {@each data.list as item,index} " {@if index===3} " " the index is 3, the value is ${item.prop} " {@else} " " the index is not 3, the value is ${item.prop} " {@/if} {@/each} d. {# comment} you can also write comments in the template code to facilitate future management. {# some comment here}
  • 74. * running on the Node.js environment bash: npm install juicer var juicer=require('juicer'); var html=juicer.to_html(tpl,data,options);
  • 75. juicer.to_html( ‘${data.end}’, Q&A {end:‘thanks!’} ); http://juicer.name

Editor's Notes

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n
  51. \n
  52. \n
  53. \n
  54. \n
  55. \n
  56. \n
  57. \n
  58. \n
  59. \n
  60. \n
  61. \n
  62. \n
  63. \n
  64. \n
  65. \n
  66. \n
  67. \n
  68. \n
  69. \n
  70. \n
  71. \n
  72. \n
  73. \n
  74. \n
  75. \n
  76. \n
  77. \n
  78. \n
  79. \n
  80. \n
  81. \n
  82. \n
  83. \n
  84. \n
  85. \n
  86. \n
  87. \n
  88. \n
  89. \n
  90. \n
  91. \n
  92. \n
  93. \n
  94. \n
  95. \n
  96. \n
  97. \n