{"id":21891401,"url":"https://github.com/pitpik/schnauzer","last_synced_at":"2025-06-29T09:03:44.847Z","repository":{"id":40760615,"uuid":"89849761","full_name":"PitPik/Schnauzer","owner":"PitPik","description":"Fast and tiny template rendering engine using templates similar to Mustage or Handlebars","archived":false,"fork":false,"pushed_at":"2025-01-27T18:38:08.000Z","size":1354,"stargazers_count":6,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-06-05T19:02:27.600Z","etag":null,"topics":["handlebars","javascript-library","mustache","partials","rendering","template"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/PitPik.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2017-04-30T12:36:19.000Z","updated_at":"2025-01-27T18:38:12.000Z","dependencies_parsed_at":"2025-01-20T09:29:04.081Z","dependency_job_id":"73c0ff62-40a2-46da-819f-99406f8ba3fc","html_url":"https://github.com/PitPik/Schnauzer","commit_stats":null,"previous_names":[],"tags_count":35,"template":false,"template_full_name":null,"purl":"pkg:github/PitPik/Schnauzer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PitPik%2FSchnauzer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PitPik%2FSchnauzer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PitPik%2FSchnauzer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PitPik%2FSchnauzer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/PitPik","download_url":"https://codeload.github.com/PitPik/Schnauzer/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PitPik%2FSchnauzer/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262566830,"owners_count":23329681,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["handlebars","javascript-library","mustache","partials","rendering","template"],"created_at":"2024-11-28T12:35:20.322Z","updated_at":"2025-06-29T09:03:44.830Z","avatar_url":"https://github.com/PitPik.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":" ![coverage](https://img.shields.io/badge/version-3\u0026#46;0\u0026#46;1-blue) ![coverage](https://img.shields.io/badge/dependencies-0-green) ![coverage](https://img.shields.io/badge/minified-11\u0026#46;13KB-blue) ![coverage](https://img.shields.io/badge/gzipped-~4\u0026#46;89KB-blue)\n\n# {{schnauzer.js}} - Handlebars templates with JavaScript\n\nSchanuzer parses and renderes Handlebars templates. It lets you build **semantic templates** effectively with no frustration.\n\nSchanuzer is largely compatible with Mustache and Handlebars templates. In most cases it is possible to swap out Mustache or Handlebars with Schanuzer and continue using your current templates. Schnauzer aims to be 100% compatible to Handlebars although there are some differences in how helpers work and Schnauzer is a Klass to be initialized.\n\nSchanuzer is also very small and fast. It has the power of Handlebars but is almost the size of Mustage (11.13KB minified, ~4.89KB compressed) and therefore also perfectly suitable for mobile applications.\nRendering with Schnauzer is about ~33% faster than Handlebars, and parsing is around as fast as rendering although you can still precompile your templates (serveside and pass them to your app/page as a simple JSON).\n\n## Where to use schnauzer.js?\n\nYou can use schnauzer.js to render templates anywhere you can use JavaScript. This includes web browsers (even Internet Explorer), server-side environments such as [node](http://nodejs.org/), and [CouchDB](http://couchdb.apache.org/) views.\n\nschnauzer.js ships with support for both the [CommonJS](http://www.commonjs.org/) module API and the [Asynchronous Module Definition](https://github.com/amdjs/amdjs-api/wiki/AMD) API, or AMD.\n\n### Dynamic rendering, keeps your template alive.\n\nSchnauzer has 3 optional functions `renderHook()`, `loopHelper()` and `evaluationHook()` that get triggered with every single template tag/loop iteration so the template can be kept alive after the initial rendering.\nWith those functions it's possible to keep track of all the rendered variables and helpers by including a special character `%` in front of variables that need to be observed. This way, when used in the DOM, it's possible to overwrite parts of the rendered template after it was first rendered without having to re-render the whole template.\nThis is perfect for developing MVC like libraries/frameworks that need to partially update HTML on the fly.\nThose hooks have no influence in rendering performance when not defined.\n\n* * *\n\n## Usage\n\nBelow is a quick example how to use schnauzer.js:\n\n```js\nvar template = `\n  \u003cp\u003eHello, my name is {{name}}.\n    I am from {{hometown}}.\n    I have {{kids.length}} kids:\u003c/p\u003e\n  \u003cul\u003e\n    {{#kids}}\u003cli\u003e{{name}} is {{age}}\u003c/li\u003e{{/kids}}\n  \u003c/ul\u003e\n`;\nvar viewModel = {\n  \"name\": \"Tim\",\n  \"hometown\": \"Somewhere, CA\",\n  \"kids\": [\n    { \"name\": \"Jimmy\", \"age\": \"7\" },\n    { \"name\": \"Sally\", \"age\": \"4\" }\n  ]\n};\nvar result = new Schnauzer(template).render(viewModel);\n\n// Would render:\n// \u003cp\u003eHello, my name is Tim. I am from Somewhere, CA. I have 2 kids:\u003c/p\u003e\n// \u003cul\u003e\n//   \u003cli\u003eJimmy is 7\u003c/li\u003e\n//   \u003cli\u003eSally is 4\u003c/li\u003e\n// \u003c/ul\u003e\n```\n\nIn this example `Schnauzer()` is initialised with the template as first argument (options would be the second optional argument) and `render()` that takes one parameter: the `viewModel` object that contains the data and code needed to render the template.\n\n## API\n\n```js\nnew Schnauzer(\n  templateOrOptions?: String | { [key: String]: any },\n  options?: {\n    entityMap: { // characters to be escaped\n      '\u0026': '\u0026amp;',\n      '\u003c': '\u0026lt;',\n      '\u003e': '\u0026gt;',\n      '\"': '\u0026quot;',\n      \"'\": '\u0026#39;',\n      '/': '\u0026#x2F;',\n      '`': '\u0026#x60;',\n      '=': '\u0026#x3D;'\n    },\n    escapeHTML: true, // if false, Schnauzer renders like all tags are set to {{{ }}}\n    helpers: { [name: String]: Function }, // short-cut for registerHelper()\n    partials: { [name: String]: String | [] }, // short-cut for registerPartial()\n    self: 'self', // name of initial (main) partial\n    limitPartialScope: true, // sets limiting of scope inside partials (like in HBS)\n    strictArguments: true, // sets arguments from a helper automatically to !helper\n  }\n)\n.render(data: { [key: String]: any }, extraData: any): string\n.parse(text: String): [] // returns a partial for re-cycling, re-usage in other instance\n.registerHelper(name: String, func: Function): void\n.unregisterHelper(name: String): void\n.registerPartial(name: String, html: String | []): [] // parsed tree\n.unregisterPartial(name: String): void\n```\n`parse()` is only needed if the template was not passed to `new Schnauzer()` in the first place. This might be handy if you're not sure if this template will ever be used and still a string and not a precompiled partial tree so you can save parsing time...\n\nIn `render(data, extraData)` you can pass some extra data source needed for parsing your template. If the renderer doesn't find the required data in `data` then it looks inside `extraData`.\nThis can be very helpful if you have, for example, an array of links to render where the root of the link is always the same (stored in extraModel) but the rest of the link is different (stored in the view model). So you don't have to put the root inside evey item of the array.\n\n```js\nvar data = {\n  links: [{\n     link: 'link1',\n     text: 'My first link',\n  }, {\n     link: 'link2',\n     text: 'My second link'\n  }]\n}\nvar extraData = {\n  root: './some/path'\n}\n\nvar output = new Schnauzer('{{#links}}\u003ca href=\"{{root}}/{{link}}\"\u003e{{text}}\u003c/a\u003e{{/links}}')\n   .render(data, extraData);\n```\n\n### Even faster helpers\n\nWhen using helpers with a simple output and no `options` are needed, you can name your helper with the prefix `$` (like `$myHelper`) so that it skips building the `options` and renders therefore faster.\n\n## Precompiling Templates\nSchnauzer allows templates to be precompiled and included as a JSON tree rather than the Schnauzer template allowing for faster startup time.\n\n```js\nvar template = `\n  {{#*inline 'myInlinePartial'}}\n    {{foo}} ...\n  {{/inline}}\n\n  {{\u003e myInlinePartial}}\n  {{\u003e another bar='bar text'}}\n`;\nvar schnauzer = new Schnauzer(template, {\n  partials: { another: 'Simple {{bar}}' }\n});\n```\nThis would produce 3 partial trees that can be found in `schnauzer.partials` and would look like:\n\n```js\n{\n  another: [{…}, {…}],\n  myInlinePartial: [{…}, {…}],\n  self: [{…}, {…}, {…}, {…}] // main partial\n}\n```\nYou could now use `JSON.stringify()` to convert this to a perfectly compressable text file. When received by the browser as a regular JSON again it then can be registered back like `new Schnauzer({ partials: partials })` in one go for all 3 partials.\nThis explains also why `.registerPartial(name, template)` can receive an array as 2nd argument. You can do: `.registerPartial('another', another)` and pass the array containing the tree of the `another` partial.\n\n\n## How Schnauzer templates works\n\nAll basic features of Schnauzer are explained in the [Handlebars documentation](https://handlebarsjs.com/guide/).\n\n\n### New in 3.x.x\n\nThe new version 3.x.x is completely re-programmed (minified ~3KB smaller), has a new parser that is 2.6x faster than in version 2.x.x, renders faster than ever and uses less memory. It is now also possible to pre-compile. Includes now the build in helpers `lookup` and `log`.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpitpik%2Fschnauzer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpitpik%2Fschnauzer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpitpik%2Fschnauzer/lists"}