{"_id":"caveman","_rev":"11-8934ec03f2a07e96207a170ee3e9820a","name":"caveman","description":"A fast JS templating engine.","dist-tags":{"latest":"0.1.6"},"versions":{"0.1.0":{"name":"caveman","description":"Fast JS template engine","author":{"name":"Andrew Childs"},"version":"0.1.0","main":"caveman.js","scripts":{"test":"./node_modules/jasmine-node/bin/jasmine-node --coffee --color --verbose ./spec"},"keywords":["caveman","javascript","template","html"],"repository":{"type":"git","url":"https://github.com/andrewchilds/caveman.git"},"dependencies":{"jasmine-node":"1.13.1"},"homepage":"https://github.com/andrewchilds/caveman","bugs":{"url":"https://github.com/andrewchilds/caveman/issues"},"license":"MIT","_id":"caveman@0.1.0","dist":{"shasum":"e49976046b7346a1223b5d8ea416248b4a394d7a","tarball":"https://registry.npmjs.org/caveman/-/caveman-0.1.0.tgz","integrity":"sha512-/HwjiY6ANujE2h0o/0pIn4ABH1vASJ3ogDaYWBegyMahpf4lwedWR4Qnn3A3a5gEwsUsLjzHbv+KlAb+IOYRxg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCgwiIMdQb8icT5WtrZSt2VlKd/uKCbSW3FBCQ66fUHXgIgcqF79lbvxvVFe8uKS1BeEdYe5wnWLoBMeBkthoHhgYA="}]},"_from":"./","_npmVersion":"1.3.21","_npmUser":{"name":"andrewchilds","email":"ac@glomerate.com"},"maintainers":[{"name":"andrewchilds","email":"ac@glomerate.com"}]},"0.1.1":{"name":"caveman","description":"A fast JS templating engine.","author":{"name":"Andrew Childs"},"version":"0.1.1","main":"caveman.js","scripts":{"test":"./node_modules/jasmine-node/bin/jasmine-node --coffee --color --verbose ./spec"},"keywords":["caveman","javascript","template","html"],"repository":{"type":"git","url":"https://github.com/andrewchilds/caveman.git"},"dependencies":{"jasmine-node":"1.13.1"},"homepage":"https://github.com/andrewchilds/caveman","bugs":{"url":"https://github.com/andrewchilds/caveman/issues"},"license":"MIT","_id":"caveman@0.1.1","dist":{"shasum":"35f488a69247e2f7e84a2c36a4113460eab145cc","tarball":"https://registry.npmjs.org/caveman/-/caveman-0.1.1.tgz","integrity":"sha512-Jfg0hTUJaUZ2Xec9fAz3eTz/maADHgB68xKE+noKtDW6vPmgAIOj+D5vi9mys/mb5M1nTIZwTEnWzEi2eaRRow==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC+o1CwWsLAvwa3RfRm+1MiX7NY9/oUle1jg31/02w5SwIhAKNVT/pj1unSye+gDGSGBKvwLznXSyWr3JYiz6IEgCKk"}]},"_from":".","_npmVersion":"1.3.21","_npmUser":{"name":"andrewchilds","email":"ac@glomerate.com"},"maintainers":[{"name":"andrewchilds","email":"ac@glomerate.com"}]},"0.1.3":{"name":"caveman","description":"A fast JS templating engine.","author":{"name":"Andrew Childs"},"version":"0.1.3","main":"caveman.js","scripts":{"test":"./node_modules/jasmine-node/bin/jasmine-node --coffee --color --verbose ./spec"},"keywords":["caveman","javascript","template","html"],"repository":{"type":"git","url":"https://github.com/andrewchilds/caveman.git"},"dependencies":{"jasmine-node":"1.13.1"},"homepage":"https://github.com/andrewchilds/caveman","bugs":{"url":"https://github.com/andrewchilds/caveman/issues"},"license":"MIT","_id":"caveman@0.1.3","dist":{"shasum":"3c5fed5359b68135ed0954bca5f57f7264f0accb","tarball":"https://registry.npmjs.org/caveman/-/caveman-0.1.3.tgz","integrity":"sha512-q0CbaV/jmmiVWNMj11gD5wUZ6p+vZtD3umQuHBMTmGqsgUepLRwKR2OLajeTKkph/6VL8ppabT2zQt5tc+Bb4A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDWVDdgt8WU1dBNOJK8o7NPcKVP0RXixJSwbbccSqTYOgIhAO3KpgtfNpkzdxuGQH43f/Eheuy0a7cORX0K9GP5QMNS"}]},"_from":".","_npmVersion":"1.3.21","_npmUser":{"name":"andrewchilds","email":"ac@glomerate.com"},"maintainers":[{"name":"andrewchilds","email":"ac@glomerate.com"}]},"0.1.4":{"name":"caveman","description":"A fast JS templating engine.","author":{"name":"Andrew Childs"},"version":"0.1.4","main":"caveman.js","scripts":{"test":"./node_modules/jasmine-node/bin/jasmine-node --coffee --color --verbose ./spec"},"keywords":["caveman","javascript","template","html"],"repository":{"type":"git","url":"git+https://github.com/andrewchilds/caveman.git"},"devDependencies":{"jasmine-node":"1.13.1"},"homepage":"https://github.com/andrewchilds/caveman","bugs":{"url":"https://github.com/andrewchilds/caveman/issues"},"license":"MIT","gitHead":"262e67010c2ada0f672c87df025b8e6f32585b44","_id":"caveman@0.1.4","_shasum":"7554addc201426c67bf915b580935745ac094a7f","_from":".","_npmVersion":"3.3.12","_nodeVersion":"5.1.0","_npmUser":{"name":"andrewchilds","email":"ac@glomerate.com"},"maintainers":[{"name":"andrewchilds","email":"ac@glomerate.com"}],"dist":{"shasum":"7554addc201426c67bf915b580935745ac094a7f","tarball":"https://registry.npmjs.org/caveman/-/caveman-0.1.4.tgz","integrity":"sha512-IeYeJq/rsGObA0YFVwrzuKIxxVVbf+pMSOKTw0MmM9XeESpKrSvlk/Xg/cZ4ZSeexpaqLerOlFgg2MZNNZKzig==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCw5Uschz9ZFOogRaLuaaqF2e661HWQUXOPBgpx84aqzwIgFeF3eaUMX3eKJyu/T90acXhhXdFBVOrjteeHkLWHbDQ="}]}},"0.1.5":{"name":"caveman","description":"A fast JS templating engine.","author":{"name":"Andrew Childs"},"version":"0.1.5","main":"caveman.js","scripts":{"test":"./node_modules/jasmine-node/bin/jasmine-node --coffee --color --verbose ./spec"},"keywords":["caveman","javascript","template","html"],"repository":{"type":"git","url":"git+https://github.com/andrewchilds/caveman.git"},"devDependencies":{"jasmine-node":"1.13.1"},"homepage":"https://github.com/andrewchilds/caveman","bugs":{"url":"https://github.com/andrewchilds/caveman/issues"},"license":"MIT","gitHead":"6a26fb4d49968496094db7ea728cbae316278f02","_id":"caveman@0.1.5","_shasum":"7dd7b424c74846235ccffe732b1448464d3b3c8f","_from":".","_npmVersion":"3.3.12","_nodeVersion":"5.1.0","_npmUser":{"name":"andrewchilds","email":"ac@glomerate.com"},"maintainers":[{"name":"andrewchilds","email":"ac@glomerate.com"}],"dist":{"shasum":"7dd7b424c74846235ccffe732b1448464d3b3c8f","tarball":"https://registry.npmjs.org/caveman/-/caveman-0.1.5.tgz","integrity":"sha512-/6Ko7Pilh8bsSVn0et4f2nH0xZ+k7wH8q4mLBWVR9yMlOi1YZDge2TB6rXow/hlxjJqyN7f6Kf/0vmMT83L2jA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGAXaOgg3wj5BtxwFEwg2Dn1kNZPiqYR9OP5EMv5qQxAAiEA/HpNPeW6f+KZBIzx+K4mmkGy82RvKGjoBLrQ8QKK6Hc="}]},"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/caveman-0.1.5.tgz_1466609198872_0.5744362375698984"}},"0.1.6":{"name":"caveman","description":"A fast JS templating engine.","author":{"name":"Andrew Childs"},"version":"0.1.6","main":"caveman.js","scripts":{"test":"./node_modules/jasmine-node/bin/jasmine-node --coffee --color --verbose ./spec"},"keywords":["caveman","javascript","template","html"],"repository":{"type":"git","url":"git+https://github.com/andrewchilds/caveman.git"},"devDependencies":{"jasmine-node":"1.13.1"},"homepage":"https://github.com/andrewchilds/caveman","bugs":{"url":"https://github.com/andrewchilds/caveman/issues"},"license":"MIT","gitHead":"ae23ded8cf1a22ecb6e2c901d7b56a91397ef61e","_id":"caveman@0.1.6","_shasum":"0678838a4089adb797ed79092c352f523e6d525c","_from":".","_npmVersion":"3.3.12","_nodeVersion":"5.1.0","_npmUser":{"name":"andrewchilds","email":"ac@glomerate.com"},"maintainers":[{"name":"andrewchilds","email":"ac@glomerate.com"}],"dist":{"shasum":"0678838a4089adb797ed79092c352f523e6d525c","tarball":"https://registry.npmjs.org/caveman/-/caveman-0.1.6.tgz","integrity":"sha512-XIwMxCLOdhqtCDJoZ4XoE5tPgpE/yJLH6PQuQxEiZQ6rCbnyjRdlU8GYhso3+0OItDhlrA9cNQ35fOEE9pTs4A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDmGHVB4eWd3M7zTR5JOq+W/7IIfAMK+iirADiw7YQ2aAiEAwm/R9O6XuNfMkF2ck0Wj06GGBQZJj8FY1+O7IsOMZgo="}]},"_npmOperationalInternal":{"host":"packages-16-east.internal.npmjs.com","tmp":"tmp/caveman-0.1.6.tgz_1466618074340_0.7689310463611037"}}},"readme":"&nbsp;\n\n![Caveman](http://i.imgur.com/MPGs04C.png)\n\n-----\n\n![Travis](https://travis-ci.org/andrewchilds/caveman.png?branch=master)\n\nCaveman is a 1kb JS templating engine, written for long-running single-page applications that render tens of thousands of DOM elements at a time.\n\nCaveman's markup language is built using an extensible macro system, which allows for arbitrary script execution, explicit logic, and partials. The library is lightweight (1kb compressed), has no dependencies, adds a single `Caveman` variable to the global namespace, and seems from [initial benchmark tests](#benchmarks) to be very fast, nearly as fast as native JS concatenation.\n\n## Installation\n\n```sh\nnpm install caveman\n```\n\n```sh\nbower install caveman\n```\n\n## Usage Examples\n\n### 1. Client-side Compilation & Rendering\n\nThis is an easy setup, but it's not as fast as precompiling your templates on the server (see below). This example assumes jQuery already exists on the page.\n\n```html\n<script src=\"/path/to/caveman.js\"></script>\n<script class=\"caveman-template\" data-name=\"blogPosts\" type=\"text/x-template\">\n<div class=\"posts\">\n  {{- for d.posts }}\n    {{- render blogPost }}\n  {{- end }}\n</div>\n</script>\n<script class=\"caveman-template\" data-name=\"blogPost\" type=\"text/x-template\">\n<div class=\"post\">\n  <h2>{{d.title}}</h2>\n  <div class=\"article\">{{d.article}}</div>\n</div>\n</script>\n<script>\n$(function () {\n\n  // Compile and register all templates using jQuery and the data-name attribute:\n  $('.caveman-template').each(function () {\n    Caveman.register($(this).data('name'), $(this).html());\n  });\n\n  // Rendering\n  var data = {\n    posts: [\n      { title: 'My Second Awesome Blog Post', article: '...' },\n      { title: 'My First Awesome Blog Post', article: '...' }\n    ]\n  };\n  var html = Caveman.render('blogPosts', data);\n  document.getElementById('content').innerHTML = html;\n\n});\n</script>\n<div id=\"content\"></div>\n```\n\n### 2. Server-side Compilation, Client-side Rendering\n\nAssuming a node application with templates in `app/views/templates/*.html` and generated assets in `public/bundled`.\n\n1. Using Grunt and [grunt-caveman](https://github.com/andrewchilds/grunt-caveman), configure your Caveman task:\n\n    ```js\n    grunt.initConfig({\n      caveman: {\n        compile: {\n          src: ['app/views/templates/*.html'],\n          dest: 'public/bundled/templates.js'\n        }\n      }\n    });\n\n    grunt.loadNpmTasks('grunt-caveman');\n    ```\n\n2. Run Grunt to generate your `templates.js` file. Partials will be named according to their file names, without the \".html\" extension.\n\n3. You should now have a Caveman template registry ready to go on the client-side:\n\n    ```html\n    <script src=\"/path/to/caveman.js\"></script>\n    <script src=\"/bundled/templates.js\"></script>\n    <script>\n      var myTemplateData = { foo: [1, 2, 3], bar: true };\n      var html = Caveman.render('myTemplateName', myTemplateData);\n      document.getElementById('foo').innerHTML = html;\n    </script>\n    ```\n\n### 3. Server-side Compilation and Rendering\n\nYou can also use Caveman for static site generation. Let's assume you have your caveman templates in `./templates` and generated assets in `./public`. Using Grunt and [grunt-caveman](https://github.com/andrewchilds/grunt-caveman), configure your Caveman task like so:\n\n```js\ngrunt.initConfig({\n  caveman: {\n    compile: {\n      src: ['templates/*.html'],\n      render: {\n        // 'homePage' equates to templates/homePage.html\n        'homePage': 'public/index.html',\n        'aboutPage': 'public/about/index.html',\n        'contactPage': 'public/contact/index.html'\n      }\n    }\n  }\n});\n\ngrunt.loadNpmTasks('grunt-caveman');\n```\n\n## Concepts\n\n### Escaping\n\nCaveman does not escape input by default, but you can enable that by setting `Caveman.options.escapeByDefault = true`. If you want to escape an individual string, you can do that with the `escape` macro:\n\n```html\n<div>{{- escape d.html }}</div>\n```\n\n### Scope\n\nCaveman doesn't use `with` blocks or do any scope lookup under the hood. Data is passed in to a Caveman template as the argument `d`, so instead of `{{foo}}` you use `{{d.foo}}`. Within `for` and `each` blocks, the scope of `d` becomes block-level, as illustrated here:\n\n```html\n<div class=\"posts\">\n  {{- for d.posts as post }}\n    <h2>{{post.title}}</h2>\n    {{- for post.images }}\n      <!-- d is now block level. -->\n      <img src=\"{{d.src}}\" alt=\"{{d.alt}}\" />\n    {{- end }}\n    <!-- Scope of d is restored. -->\n    {{- for post.images as image }}\n      <!-- The scope of d is unaffected since we're using `for as`. -->\n      <img src=\"{{image.src}}\" alt=\"{{image.alt}}\" />\n      <!-- We can still reference anything further up the scope chain: -->\n      {{d.posts[0].images[0].src}}\n    {{- end }}\n    {{- each post.images[0] }}\n      <!-- d is now block-level. -->\n      {{_key}}: {{d}}\n    {{- end }}\n    {{- each post.images[0] as attr }}\n      <!-- The scope of d is unaffected since we're using `each as`. -->\n      {{_key}}: {{attr}}\n      <!-- We can still reference anything further up the scope chain: -->\n      {{d.posts[0].images[0].src}}\n    {{- end }}\n  {{- end }}\n</div>\n```\n\n### Custom Macros\n\nMacros can be added or modified quite easily, even after templates are compiled. For example, a \"tableClass\" macro that adds zebra stripes and \"first\" and \"last\" classes, depending on where it is in the array:\n\n```js\nCaveman.addMacro('tableClass', {\n  find: /^tableClass$/,\n  replace: \"str += (_i % 2 ? 'even' : 'odd');\" +\n    \"if (_i === 0) { str += ' first'; }\" +\n    \"if (_i === _len - 1) { str += ' last'; }\"\n});\n\ndata = {\n  rows: [\n    { text: 'a' }\n    { text: 'b' }\n    { text: 'c' }\n  ]\n}\n\nCaveman(template, data)\n```\n\n```html\n<!-- template -->\n<table>\n  {{- for d.rows as row }}\n    <tr class=\"{{- tableClass }}\">\n      <td>{{_i}}: {{row.text}}</td>\n    </tr>\n  {{- end }}\n</table>\n\n<!-- rendered HTML -->\n<table>\n  <tr class=\"odd first\">\n    <td>0: a</td>\n  </tr>\n  <tr class=\"even\">\n    <td>1: b</td>\n  </tr>\n  <tr class=\"odd last\">\n    <td>2: c</td>\n  </tr>\n</table>\n```\n\n### Arbitrary Script Execution\n\n```js\nCaveman(template, {\n  rows: [1, 2, 3]\n});\n```\n\n```html\n<!-- template -->\n{{- for d.rows }}\n  <div>{{d}} x {{d}} = {{- print d * d }}</div>\n{{- end }}\n\n<!-- rendered HTML -->\n<div>1 x 1 = 1</div>\n<div>2 x 2 = 4</div>\n<div>3 x 3 = 9</div>\n```\n\n## Interpolation Behavior\n\n```html\n<!-- exampleTemplate.html -->\nstring: {{d.strings}}\nempty string: {{d.emptyString}}\nboolean false: {{d.booleanFalse}}\nboolean true: {{d.booleanTrue}}\nnull: {{d.nullValue}}\nundefined: {{d.undefinedValue}}\nfloats: {{d.floats}}\nintegers: {{d.ints}}\nzero: {{d.zero}}\narrays (bracket notation): {{d.arrays[2]}}\narrays of objects (dot and bracket notation): {{d.arraysOfObjects[1].b}}\n```\n\n```js\nCaveman.render('exampleTemplate', {\n  strings: \"123\",\n  emptyString: '',\n  booleanFalse: false,\n  booleanTrue: true,\n  nullValue: null,\n  undefinedValue: undefined,\n  floats: 123.12,\n  ints: 1234,\n  zero: 0,\n  arrays: [1, 2, 3, 4]\n  arraysOfObjects: [\n    { a: 1, b: 2, c: 3 },\n    { a: 1, b: 2, c: 3 }\n  ]\n});\n```\n\n```html\n<!-- rendered HTML -->\nstring: 123\nempty string:\nboolean false: false\nboolean true: true\nnull:\nundefined:\nfloats: 123.12\nintegers: 1234\nzero: 0\narrays (bracket notation): 3\narrays of objects (dot and bracket notation): 2\n```\n\n## Macro Documentation\n\n#### {{- if *expression* }}\n#### {{- unless *expression* }}\n#### {{- else }}\n#### {{- else if *expression* }}\n#### {{- end }}\n\n```html\n<div class=\"posts\">\n  {{- for d.posts as post }}\n    {{- unless post.hidden }}\n      <h2>{{post.title}}</h2>\n      {{- if post.comments.length > 0 }}\n        {{- for post.comments as comment }}\n          <div class=\"comment\">{{comment.text}}</div>\n        {{- end }}\n      {{- else }}\n        <div>No comments!</div>\n      {{- end }}\n    {{- end }}\n  {{- end }}\n</div>\n```\n\nThe `if`, `unless`, and `end` macros have shortcuts, respectively:\n\n#### {{? *expression* }}\n#### {{^ *expression* }}\n#### {{/}}\n\n-----\n\n#### {{- for *array* }}\n#### {{- for *array* as *obj* }}\n\nThe `for` macro iterates through arrays. These variables are available in the block scope:\n\n* `_i` = the current index of the for loop, starting with zero\n* `_len` = the length of the for loop.\n\n```js\nvar data = {\n  users: [\n    { name: 'Jimmy', email: 'jimmy@gmail.com' },\n    { name: 'Ralph', email: 'ralph@gmail.com' }\n  ]\n};\nCaveman(template, data);\n```\n\n```html\n<!-- template -->\n<div class=\"users\">\n  {{- for d.users as user }}\n    <div class=\"user\">\n      <label>Name</label> <strong>{{user.name}}</strong>\n      <label>Email</label> <a href=\"mailto:{{user.email}}\">{{user.email}}</a>\n    </div>\n  {{- end }}\n</div>\n\n<!-- rendered HTML -->\n<div class=\"users\">\n  <div class=\"user\">\n    <label>Name</label> <strong>Jimmy</strong>\n    <label>Email</label> <a href=\"mailto:jimmy@gmail.com\">jimmy@gmail.com</a>\n  </div>\n  <div class=\"user\">\n    <label>Name</label> <strong>Ralph</strong>\n    <label>Email</label> <a href=\"mailto:ralph@gmail.com\">ralph@gmail.com</a>\n  </div>\n</div>\n```\n\n-----\n\n#### {{- each *obj* }}\n#### {{- each *obj* as *attr* }}\n\n`each` is meant for iterating through object properties, using a closure instead of a for loop. The `_key` variable is available in the block scope.\n\n```js\ndata = {\n  cars: [\n    {\n      make: 'Volvo',\n      model: '245s',\n      year: 1976,\n    },\n    {\n      make: 'Saab',\n      model: '900s',\n      year: 1985\n    }\n  ]\n};\n```\n\n```html\n<!-- template -->\n{{- for d.cars as car }}\n  <div class=\"car\">\n    {{- each car as attribute }}\n      <div>{{_key}}: {{attribute}}</div>\n    {{- end }}\n  </div>\n{{- end }}\n\n<!-- rendered HTML -->\n<div class=\"car\">\n  <div>make: Volvo</div>\n  <div>model: 245s</div>\n  <div>year: 1976</div>\n</div>\n<div class=\"car\">\n  <div>make: Saab</div>\n  <div>model: 900s</div>\n  <div>year: 1984</div>\n</div>\n```\n\n-----\n\n#### {{- with *a.b.c.obj* }}\n#### {{- with *a.b.c.obj* as *obj* }}\n\n`with` allows you to scope an object to `d` (or to a named variable using `with foo as bar`) within a block.\n\n```html\n<!-- template -->\n{{- for d.posts as post }}\n  {{- with post.author as author }}\n    <h2>{{author.name}}</h2>\n  {{- end }}\n{{- end }}\n```\n\n-----\n\n#### {{- print *expression* }}\n\n`print` writes the expression's returned value. The `_i` character is the current index of the array. `d` is the current value, which happens to be a string.\n\n```html\n<!-- template -->\n{{- for d.rows }}\n  <div>{{d}} x {{d}} = {{- print d * d }}</div>\n{{- end }}\n\n<!-- rendered HTML -->\n<div>1 x 1 = 1</div>\n<div>2 x 2 = 4</div>\n<div>3 x 3 = 9</div>\n```\n\n-----\n\n#### {{- log *expression* }}\n\nWrites {expression} to console.log.\n\n```js\n{{- log x.y.z }}\n```\n\n-----\n\n#### {{- render *partialName* }}\n#### {{- render *partialName* *context* }}\n\nRenders partial {name} using optional {scope}.\n\nCompiled templates should be registered using the `Caveman.register` method so they can be used as partials.\n\n```js\nCaveman.register('emailList', emailList)\nCaveman.register('emailLink', emailLink)\n\nvar data = {\n  emails: [\n    { email: 'jimmy@gmail.com', name: 'Jimmy' },\n    { email: 'ralph@gmail.com', name: 'Ralph', className: 'active' },\n    { email: 'joe@gmail.com', name: 'Joe' }\n  ]\n};\nCaveman.render('emailList', data);\n```\n\n```html\n<!-- \"emailList\" template -->\n{{- for d.emails }}\n  <div class=\"user\">{{- render emailLink }}</div>\n{{- end }}\n\n<!-- \"emailLink\" template -->\n<a href=\"mailto:{{d.email}}\" class=\"{{d.className}}\">{{d.name}}</a>\n\n<!-- rendered HTML -->\n<div class=\"user\">\n  <a href=\"mailto:jimmy@gmail.com\" class=\"\">Jimmy</a>\n</div>\n<div class=\"user\">\n  <a href=\"mailto:ralph@gmail.com\" class=\"active\">Ralph</a>\n</div>\n<div class=\"user\">\n  <a href=\"mailto:joe@gmail.com\" class=\"\">Joe</a>\n</div>\n```\n\n-----\n\n#### {{// *comment* }}\n\nAllows comments in a template without being included in the rendered output.\n\n```js\nvar template = 'Foo {{// This is a comment. }} bar';\n\nCaveman.register('commentExample', template);\nCaveman.render('commentExample');\n```\n\n```html\nFoo  bar\n```\n\n-----\n\n#### {{- escape *expression* }}\n\nPrevent HTML/JS from being evaluated. You can enable this behavior globally by setting `Caveman.options.escapeByDefault = true`.\n\n```js\nvar data = {\n  html: '<script>alert(\"HELLO!\");</script> & \\''\n};\nvar template = '{{- escape d.html }}';\n\nCaveman.register('escapeExample', template);\nCaveman.render('escapeExample', data);\n```\n\n```html\n&lt;script&gt;alert(&quot;HELLO!&quot;);&lt;/script&gt; &amp; &#39;\n```\n\n-----\n\n#### {{- unescape *expression* }}\n\nAllow HTML/JS to be evaluated, even if `Caveman.options.escapeByDefault` was already set to `true`.\n\n```js\nvar data = {\n  html: '<script>alert(\"HELLO!\");</script> & \\''\n};\nvar template = '{{- unescape d.html }}';\n\nCaveman.register('unescapeExample', template);\nCaveman.render('unescapeExample', data);\n```\n\n```html\n<script>alert(\"HELLO!\");</script> & '\n```\n\n## Method Reference\n\n#### Caveman\n\nReturns either a compiled template function, or the rendered HTML if data is passed in. The latter approach should not be used in production as the compiled template is not cached.\n\n```js\nCaveman(template) // returns compiled template function\nCaveman(template, data) // returns rendered HTML\n```\n\n-----\n\n#### Caveman.compile(*template*)\n\nReturns a compiled template string. If you're sending pre-compiled templates to the client, you should use this method, otherwise you don't really need to use this. If you're compiling templates on the client-side, you should just use `Caveman.register` and `Caveman.render`.\n\n```js\nvar template = '{{- for d.users as user }}<span>{{user.name}}</span>{{- end }}'\nvar compiled = Caveman.compile(template);\n\nCaveman.register('userNames', compiled);\n```\n\n-----\n\n#### Caveman.register(*templateName*, *uncompiledTemplateString*)\n#### Caveman.register(*templateName*, *compiledTemplateFunction*)\n\nRegister a partial {name} using template {template}, allowing it to be used later on with `Caveman.render`. Accepts both compiled and uncompiled templates.\n\n```js\nvar template = '{{- for d.users as user }}<span>{{user.name}}</span>{{- end }}'\nCaveman.register('userNames', template);\n```\n\n-----\n\n#### Caveman.render(*templateName*, *data*)\n\nRender a compiled template {name} using {data}.\n\n```js\nvar data = {\n  users: [ { name: 'Mario' }, { name: 'Luigi' } ]\n}\nCaveman.render('userNames', data);\n// > \"<span>Mario</span><span>Luigi</span>\"\n```\n\n-----\n\n#### Caveman.addMacro(*macroName*, *macroDefinition*)\n\nAdds or updates a macro {macroName} with macro {macro}. Macros are objects with the following keys:\n\n* find: Required. The regex to test the str against.\n* replace: Required. A string or function that returns a replacement expression.\n* blockEnd: Optional. If this is a block, what should be added during the matching {{- end }} macro.\n* prefix: Optional. If anything needs to be added at the beginning of the compiled template.\n* shortcut: Optional. Define a shortcut syntax for this macro.\n\nAll existing macros are defined using this method, for example:\n\n```js\nCaveman.addMacro('if', {\n  find: /^if /,\n  replace: function (str) {\n    return str.replace(/^if (.*)/, 'if ($1) {');\n  },\n  blockEnd: '}',\n  shortcut: {\n    find: /^\\?\\s?/,\n    replace: function (str) {\n      return str.replace(/^\\?\\s?(.*)/, '- if $1');\n    }\n  }\n});\n\nCaveman.addMacro('print', {\n  find: /^print /,\n  replace: function (str) {\n    return str.replace(/^print (.*)/, 'str += ($1);');\n  }\n});\n```\n\n-----\n\n## Options\n\nTo use custom tags (e.g. ERB-style tags), override these two options before compiling your templates:\n\n```js\nCaveman.options.openTag = '<%'; // defaults to '{{'\nCaveman.options.closeTag = '%>'; // defaults to '}}'\n```\n\nRemove indentation by shrink wrapping your templates:\n\n```js\nCaveman.options.shrinkWrap = true; // defaults to false\n```\n\nAutomatically escape all input:\n\n```js\nCaveman.options.escapeByDefault = true; // defaults to false\n```\n\n## Benchmarks\n\nIf you only look at [pure rendering](http://jsperf.com/js-templating-performance/5) performance, Caveman shows a dramatic performance gain over Hogan, Handlebars and Lodash:\n\n![benchmark-without-dom](http://i.imgur.com/7wKwTwJ.png)\n\nHowever a more [real-world test](http://jsperf.com/js-templating-performance/4) that includes DOM manipulation shows a more modest improvement:\n\n![benchmark-with-dom](http://i.imgur.com/28xpRTv.png)\n\nYMMV.\n\n## Running the test suite\n\n```sh\nnpm test\n```\n\n## License\n\nMIT. Copyright &copy; 2016 Andrew Childs\n","maintainers":[{"name":"andrewchilds","email":"ac@glomerate.com"}],"time":{"modified":"2022-06-13T05:42:27.987Z","created":"2014-02-23T04:58:24.928Z","0.1.0":"2014-02-23T04:58:24.928Z","0.1.1":"2014-07-02T21:32:30.623Z","0.1.3":"2014-07-03T02:31:11.601Z","0.1.4":"2015-12-01T16:56:08.689Z","0.1.5":"2016-06-22T15:26:41.473Z","0.1.6":"2016-06-22T17:54:36.457Z"},"readmeFilename":"README.md","homepage":"https://github.com/andrewchilds/caveman","keywords":["caveman","javascript","template","html"],"repository":{"type":"git","url":"git+https://github.com/andrewchilds/caveman.git"},"author":{"name":"Andrew Childs"},"bugs":{"url":"https://github.com/andrewchilds/caveman/issues"},"license":"MIT"}