{"_id":"dali","_rev":"25-0c43b4bcf06f7bc6fcd38df305a50d0d","name":"dali","description":"Surreal templating for server and browser","dist-tags":{"latest":"1.0.3"},"versions":{"1.0.1":{"name":"dali","description":"Surreal templating for server and browser","version":"1.0.1","homepage":"https://github.com/masyl/Dali","repository":{"type":"git","url":"git://github.com/masyl/Dali.git"},"author":{"name":"Mathieu Sylvain","email":"mathieu@ti-coco.com","url":"https://github.com/masyl"},"main":"index.js","directories":{"lib":"."},"scripts":{"test":"vows"},"engines":{"node":">= v0.4.0"},"dependencies":{},"devDependencies":{},"_id":"dali@1.0.1","_engineSupported":true,"_npmVersion":"1.0.1rc5","_nodeVersion":"v0.4.3","_defaultsLoaded":true,"dist":{"shasum":"de2ac8a3470cd88b3e2474f21935335fe3a32cab","tarball":"https://registry.npmjs.org/dali/-/dali-1.0.1.tgz","integrity":"sha512-W2LNwLmEp7g5I1rSjvWaQbzH6ZNCb0+WIBbAcBlviT+jjvH7UDN44yVAhJrtACjSALFe7uhmvWZu2CfZ6bAaWg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBxAhKmABqO3G89Nb3a0sj8RgzRNMinYa1D9nl3S9cr9AiAnXqbgDD0glFxzgCupSA6WoOHIsSq+Jaj5XoLwjO87EA=="}]}},"1.0.2":{"name":"dali","description":"Surreal templating for server and browser","version":"1.0.2","homepage":"https://github.com/masyl/Dali","repository":{"type":"git","url":"git://github.com/masyl/Dali.git"},"author":{"name":"Mathieu Sylvain","email":"mathieu@ti-coco.com","url":"https://github.com/masyl"},"main":"index.js","directories":{"lib":"."},"scripts":{"test":"vows"},"engines":{"node":">= v0.4.0"},"dependencies":{},"devDependencies":{},"_id":"dali@1.0.2","_engineSupported":true,"_npmVersion":"1.0.1rc5","_nodeVersion":"v0.4.3","_defaultsLoaded":true,"dist":{"shasum":"8e00d69a408c618a358644a403e510e1893162af","tarball":"https://registry.npmjs.org/dali/-/dali-1.0.2.tgz","integrity":"sha512-x4AZSZwFoSLFD7cVY/p7u6Jm873r7z57U+LDdwKlEg0jlpFf/GPneFUJCnFeYw6ne89cTgTdMaUyzdoR6lHoNA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD9GA8Tw0sJEwJqE3osCGtb/B47mDq7H4n4ixvZ57tPhAIgQTRoOubetX7NvnDIoYmfPOW5BMTyyerqbMnU9rQlIUw="}]}},"1.0.3":{"name":"dali","description":"Surreal templating for server and browser","version":"1.0.3","homepage":"https://github.com/masyl/Dali","keywords":["dali","templating","engine","mustache"],"repository":{"type":"git","url":"git://github.com/masyl/Dali.git"},"author":{"name":"Mathieu Sylvain","email":"mathieu@ti-coco.com","url":"https://github.com/masyl"},"main":"src/index.js","directories":{"lib":"lib","test":"test"},"scripts":{"test":"vows","start":"node server.js"},"engines":{"node":">= v0.6.0"},"dependencies":{},"devDependencies":{"vows":">= v0.6.2","eyes":"latest","express":">= v2.5.0","http-proxy":">= v0.8.0","node-static":">= v0.5.0"},"_npmUser":{"name":"masyl","email":"mathieu@ti-coco.com"},"_id":"dali@1.0.3","optionalDependencies":{},"_engineSupported":true,"_npmVersion":"1.1.0-3","_nodeVersion":"v0.6.10","_defaultsLoaded":true,"dist":{"shasum":"8507a0e7df0b5909bc8154484ad42d9285d9452d","tarball":"https://registry.npmjs.org/dali/-/dali-1.0.3.tgz","integrity":"sha512-mYWhAA1iU0wDcCPBJ3MSUprUQUyrSCr17r+ZoAMMzyr556kOIbhw2OhOJ3gHN6WQVs2TsAbOIo1UppVvU0QrRg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBQyFLrlSRgrkVKID2d0D8q4I1zOAw3D1XMRWWBr3OXEAiAVUoCKo9o2hKNTGM2LxXWxWa2Bcl7162B7uw0Lw7j0HQ=="}]},"readme":"Dali - Surreal Templating\n=========================\n\n__Version:__\n1.0\n\n__Author:__\n_Mathieu Sylvain_ - 2010-2011\n\n__License:__\nThis work is in the Public Domain. To view a copy of the public domain\ncertification, visit [http://creativecommons.org/licenses/publicdomain/](http://creativecommons.org/licenses/publicdomain/)\nor send a letter to Creative Commons, 171 Second Street, Suite 300,\nSan Francisco, California, 94105, USA.\n\n__Distribution:__\nThe Dali engine is available for Download and for collaborations at : [https://github.com/masyl/Dali](https://github.com/masyl/Dali)\n\nIntroduction\n------------\n\nDali is templating engine for javascript. It can run on the client in any browser and on servers such as [node.js](http://nodejs.org/).\n\nDali has the following characteristics:\n\n* It's fast (bechmarks to come, but try the samples and see)\n* A simple and consistent tag syntax\n* Allows for logic-less templating\n* A rich set of tags and filters\n* Exstensible through custom tags and filters\n* Extensive ability for code reuse\n* Dynamic template loading and inheritance\n* Verbose error handling\n* Access to full javasript expressions as arguments\n* Includes a lightweight MVC api\n* An extensive set of samples in a live-testing tool\n* The code is released in the public domain\n* The code is documented and testable\n* The code is available for the community on GitHub\n\n\nUsing the library\n-----------------\n\nDali is packaged as a single javascript file which can be loaded either as a script tag in the browser, or as a CommonJS module using the \"require\" method. Simply download the latest stable release from GitHub and add it to your project like this:\n\n\t<script src=\"libs/dali/dali.js\"></script>\n\nor in [node.js](http://nodejs.org/) like this:\n\n\tvar Dali = require(__dirname +\"/libs/dali\");\n\nAltough optionnal, Dali will automatically detect the presence of jQuery and add the \"dali\" namespace inside jQuery.\n\nDali has no CSS and no other dependencies, and we do not have any CDN hosting available for now.\n\nOnce loaded, the librabry adds two object in the global scope:\n\n* The \"Dali\" constructor _(uppercase \"D\")_\n* The \"dali\" instance. _(lowercase \"d\")_\n\nFor most scenarios, you should simply start using dali immediatly with the global dali instance.\n\n\tvar helloWorldData = {label: \"Hello world!\"};\n\tvar helloWorldTemplate = dali.add(\"sample\", \"<div>{{out item.label /}}</div>\");\n\tvar output = helloWorldTemplate.render(helloWorldData)\n\nBut if you need either a custom dali instance or a dali instance resrained to a particular application scope, you can simply create a new instance like this:\n\n\tfunction someWidget() {\n\t\tvar privateDali = new Dali();\n\t};\n\n### Secondary API's\n\nDali also comes with a few lightweight API's to help you build apps. The is the MVC api, and the App api. Samples are available for both.\n\nNote that the secondary API require the core Dali api and that the App api require the MVC api.\n\n\t<script src=\"libs/dali/dali.mvc.js\"></script>\n\t<script src=\"libs/dali/dali.app.js\"></script>\n\n\n### Storing templates\n\nThere are two recommended techniques for storing your templates:\n\n* Inside script tags and delivered inline with you html page\n* Inside external resouces such as \"templateABC.dali.html\" files and load them with ajax\n\nIf you place dali templates inside script tags, make sure you use the \"text/x-dali-template\" type. Like this:\n\n\t<script id=\"templateABC\" type=\"text/x-dali-template\">\n \t\t<div>\n\t\t\tDescription: {{out item.vehicle.description /}}\n\t\t</div>\n\t</script>\n\nBoth methods give the same ouput and have similar restrictions, but their performance cost is very different. Adding a script tag is very fast and effective for small application and limits the number of HTTP requests, but loading templates in Ajax is a better solution for large application where the total weight of all templates is too much to load at first.\n\nOnce a template is loaded, it will be refered by its Id and should not need to be reloaded or recompiled.\n\nIf your curious about the mechanis of template compilation, you can jump to the \"under the hood\" section.\n\n---\n\nTag Notation\n------------\n\nThe syntax of Dali revolves mostly around the tag notation.\n\nThis notation has been choses because it is simple to understand, easy to remember and allows for great flexibility.\n\nThe basic constructs are :\n\nAn open \"out\" tag:\n\n\t{{out}}\n\t\t<span>Some text!</span>\n\t{{endout}}\n\nA self-closing tag with arguments:\n\n\t{{out \"<span>Some text!</span>\" /}}\n\nA tag with additionnal alternate tags:\n\n\t{{if vars.count > 1 }}\n\t\tis bigger than 1\n\t{{if-not}}\n\t\tis NOT bigger than 1\n\t{{endif}}\n\nTags with a filter:\n\n\t{{out \"This will be in uppercase!\" >> uppercase /}}\n\n\t{{out >> uppercase}}\n\t\tThis will also be in uppercase!\n\t{{endout}}\n\nA tag with linefeeds and whitespaces:\n\n\t{{ out\n\t\t\"Some text to output in uppercase!\"\n\t\t>> uppercase\n\t/}}\n\n\n\n### Comments and commenting-out tags\n\n\nComment are usefull both for adding usefull information in your templates without being rendered.\n\nBut the Dali approach to commenting also allows you to comment-out your code quickly during development for doing tests or disabling features temporarilly.\n\nComment are triggered by the \"#\" symbol, and its behavior depends on where you place it.\n\nComments for documentation:\n\n\t{{#\n\t\tYou can add multi-line comments anywhere...\n\t\ttheir content is innert, so they will not\n\t\tbe parsed or evaluated.\n\t/}}\n\nCommenting out a whole tag (argument, main block and all alternate tags):\n\n\t{{#if a > 1 }}\n\t\tSome text to output!\n\t{{if-not}}\n\t\tOr maybe not...\n\t{{endif}}\n\nCommenting out only a tags content (while still parse its arguments and alternate tags):\n\n\t{{out \"This will output\" #}}\n\t\tBut this will not\n\t{{endout}}\n\nCommenting out only an alternate tag:\n\n\t{{#if 2 > 1 }}\n\t\tThis will surely output\n\t{{if-not #}}\n\t\tBut this will not.\n\t{{endif}}\n\n\nNote: When you comment-out a tag, it will be \"completely ignored\", meaning that it will not even be present in the compiled template.\n\n\n### Tag arguments and the execution scope\n\n\nMost tags support arguments. Arguments are written immediatly after the name of the tag. Multiple arguments are separated by commas.\n\n\t{{var \"varNameGoesHere\", \"var value goes here...\" /}}\n\n\t{{out vars.someVar, 5 + 3, \"some test!\" /}}\n\nNote that elements after the \">>\" prefix used for filter will not be part of your arguments. For example, here we have only 1, 2 and 3 as arguments:\n\n\t{{out 1, 2, 3 >> void /}}\n\nArgument are evaluated as javascript expressions. When these arguments are evaluation during the rendering process, they have acces to the global scope of you application and to some objects specific to the rendering.\n\nThese objects are:\n\n* __env__ : The environment object, which contains the overall execution context and global variables.\n* __vars__ : All the variables defined during the rendering process. (See the var tag)\n* __item__ : The current data being rendered. This will change when you use the \"each\" tag.\n* __loop__ : A status object which informs you on where ou are in a \"each\" loop. (first item, last item, etc)\n* __dali__ : A reference to the dali instance.\n\nNote that these expressions are prone to the same types of errors as any other javascript code, so make sure you account for most usage scenarios and handle empty values.\n\n\n### Global scope vs Environment variables\n\n\nHaving access to the global scope of you app or document doesnt mean its a good idea to use it. It is tempting to just access everything globally and not worry too much, but this will make you template harder to reuse and is an error prone approach.\n\nInstead, it is recommended that you pass your helper function and various variables into the environment object. This guaranties that all the dependencies of your templates are well understood and well managed.\n\nHere is a sample scenario:\n\n\t[code sample goes here....]\n\n---\n\nFilters:\n--------\n\nA common feature of templating languages, is the notion of filters. In Dali, filter are used to transform the output of tag after they have been rendered. Filter can be used on every tags and alternate tags.\n\nThe rule is simple, filters follow the same \"name followed by arguments\" syntax as tags, but they are separated from the tag by the \">>\" marker. Here is a few examples:\n\nA basic filter:\n\n\t{{out \"Some text in lowercase!\" >> uppercase /}}\n\nA filter on an alternate tag:\n\n\t{{if abc = true}}\n\t\tYEAH!\n\t{{if-not >> uppercase}}\n\t\t{{out vars.errorMessage /}\n\t{{endif}}\n\nA custom filter with two argument:\n\n\t{{out \"Firstname\" >> wrapWith \"[\", \"]\" /}}\n\nTwo chained filters:\n\n\t{{out item.title >> trim >> lowercase /}}\n\n\n### Built-in fiters\n\nHere is the list of built-in filters supplied in Dali:\n\n* __void__ : Intercept and cancels the output of a tag. The tag still executes, but it has not output.\n* __trim__ : Will remove whitespaces before and after the content.\n* __uppercase__ : Transform the output in lowecase\n* __lowercase__ : Transform the ouput in uppercase\n\n### Creatin Custom Filters\n\nWhile this first version of Dali comes with few filters, you can easilly define you own customs filters.\n\nCreating a custom filter is very simple. It is a simple function which outputs a string. This function can take in any number of arguments and the input is passed as the _this_ object. Simply register the functions you need like this:\n\n\tDali.register({\n\t\tFilters: {\n\t\t\t\"h1\": function(args) {\n\t\t\t\treturn \"<h1>\" + this + \"</h1>\";\n\t\t\t},\n\t\t\t\"replace\": function(args) {\n\t\t\t\treturn \"\".replace.apply(this, args);\n\t\t\t}\n\t\t}\n\t});\n\n\n\n\n---\n\nTags:\n-----\n\n\tout / raw\n\tvar\n\tif (else, not)\n\teach\n\t\tloop object\n\t\t\t\t\t\t\"empty\": [],\n\t\t\t\t\t\t\"single\": [],\n\t\t\t\t\t\t\"begin\": [],\n\t\t\t\t\t\t\"end\": [],\n\t\t\t\t\t\t\"first\": [],\n\t\t\t\t\t\t\"odd\": [],\n\t\t\t\t\t\t\"between\": [],\n\t\t\t\t\t\t\"last\": []\n\ttemplate\n\trender\n\tload\n\n---\n\nCreating custom tags\n--------------------\n\nHere is how simple custom tag is built (explanations will follow):\n\n\n\talertTag = new Dali.Tag(\"alert\", function(data, _args, env, block, alternateBlocks) {\n\t\tvar args = _args();\n\t\talert(args.join(\", \"));\n\t\treturn \"\";\n\t}, {})\n\n\tDali.register({\n\t\tTags: {\n\t\t\t\"alert\": alertTag\n\t\t}\n\t});\n\nThis \"alert\" tag will trigger an alert dialog that shows the values of the tags argument, separated by commas.\n\nNote that before using the arguments, you must first call the \"_args\" argument as a function to evaluate their values.\n\nAfter created the tag with the Dali.Tag constructor, you simply register it with the \"Dali.register\" method.\n\nTo see more complexe examples of tags that process block content, you can browse the Dali source code on GitHub.\n\n---\n\nTemplate inheritance\n--------------------\n\nWhile many templating engines support partials and macros, very few have achieved true template inheritance.\n\nDali achieves this elegantly with a combination of the render tag and the template tag.\n\nIn the dali sample you will find a situation where a page is rendered by a basePage template which is in turn renderd in an html5 page template.\n\nThis scenario is in comparable to the complex templating found in server langauges.\n\n__See \"Template inheritance\" in the Dali Samples__\n\n---\n\n\nErrors Handling\n-----------------\n\nIn Dali, a special care given to providing clear and verbose error messages. Since errors can come from many different sources, Dali uses the standard javascript exception handling methods for bubbling out errors. This means that a template that fails will output a true javascript error with a relevant message and description.\n\nThis means that for your apps to be robust, you should wrap dali operations inside try/catch statements, like this:\n\n\ttry {\n\t\ttemplateABC.render(data);\n\t} catch (err) {\n\t\tshowDefaultErrorMessage(err.name, err.message);\n\t}\n\nIn future versions, error handling might provide more subtulties, but this method will always be available and is totally future proof.\n\nYou can browse the samples for the full list of possible errors and a way to try to test more template failure scenarios.\n\n---\n\nMVC api\n-------\n\nTo come... see samples.\n\n\n---\n\n\nSample MVC Mobile App\n---------------------\n\nAlong side the Dali api, there is a sample mobile application that is used to showcase how it can greatly simplify writing mobile apps. It combines jQuery Mobile, Dali and the Dali MVC api.\n\nThis sample is available to download and contribute to on GitHub at [https://github.com/masyl/jquery.mobile.mvc](https://github.com/masyl/jquery.mobile.mvc). And you can sample it online at [http://masyl.github.com/jquery.mobile.mvc/](http://masyl.github.com/jquery.mobile.mvc/).\n\n---\n\nUnder the hood\n--------------\n\nWhen a template is loaded, it will go through a three step process, in the following order:\n\n* Source is analysed and parser into a tree structure\n* This tree structure is used to generate a function in javascript code\n* The javascript code is compiled into a native object by using the \"Function\" constructor.\n\nAll this happens in the blink of an eye and should not affect your applications performance.\n\nFuture plans for optimization include:\n\n* Option of running the template directly with the tree structure instead of relying on the \"Function\" constructor. This will allow cases where you are not allowed to use the \"Function\" constructor.\n* Fetching and rendering templates only on demand instead of at load time.\n* Caching templates\n* Sanitizing helpers (utilities to remove JS from inputs)\n\n__Note on code safety:__\nSince we use the \"_Function_\" constructor for generating the template and evaluating expression, you should be carefull to sanitize any user input and use contributed content to prevent script injection for malicious purposes.\n\n\n\n\n\n\n","maintainers":[{"name":"masyl","email":"mathieu@ti-coco.com"}]}},"maintainers":[{"name":"masyl","email":"mathieu@ti-coco.com"}],"time":{"modified":"2022-06-14T08:27:42.519Z","created":"2011-04-30T15:44:24.411Z","1.0.1":"2011-04-30T15:44:24.592Z","1.0.2":"2011-05-02T03:45:12.868Z","1.0.3":"2012-03-11T19:31:27.680Z"},"author":{"name":"Mathieu Sylvain","email":"mathieu@ti-coco.com","url":"https://github.com/masyl"},"repository":{"type":"git","url":"git://github.com/masyl/Dali.git"}}