{"id":13456240,"url":"https://github.com/nextapps-de/mikado","last_synced_at":"2025-04-08T10:14:19.488Z","repository":{"id":35101172,"uuid":"206418939","full_name":"nextapps-de/mikado","owner":"nextapps-de","description":"Mikado is the webs fastest template library for building user interfaces.","archived":false,"fork":false,"pushed_at":"2024-08-10T11:46:26.000Z","size":2869,"stargazers_count":780,"open_issues_count":5,"forks_count":34,"subscribers_count":21,"default_branch":"master","last_synced_at":"2024-10-29T17:29:27.712Z","etag":null,"topics":["express-middleware","handlebars","handlebars-template","high-performance","mustache","mustache-templates","observable","reactive","rendering-engine","server-side-rendering","template","template-engine","template-library","templates","templating","virtual-dom"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nextapps-de.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","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},"funding":{"github":["ts-thomas"],"open_collective":"mikado","liberapay":"ts-thomas","patreon":"user?u=96245532","custom":["https://www.paypal.com/donate/?hosted_button_id=GEVR88FC9BWRW","https://salt.bountysource.com/teams/ts-thomas"]}},"created_at":"2019-09-04T21:37:13.000Z","updated_at":"2024-10-22T08:05:51.000Z","dependencies_parsed_at":"2024-02-06T12:46:59.758Z","dependency_job_id":"d3432b62-ce25-4d5e-a905-ec71b641d136","html_url":"https://github.com/nextapps-de/mikado","commit_stats":{"total_commits":271,"total_committers":9,"mean_commits":30.11111111111111,"dds":0.07749077490774903,"last_synced_commit":"ab9460460816354dd5a04a6fa265ecc1071f2993"},"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nextapps-de%2Fmikado","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nextapps-de%2Fmikado/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nextapps-de%2Fmikado/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nextapps-de%2Fmikado/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nextapps-de","download_url":"https://codeload.github.com/nextapps-de/mikado/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246612884,"owners_count":20805441,"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":["express-middleware","handlebars","handlebars-template","high-performance","mustache","mustache-templates","observable","reactive","rendering-engine","server-side-rendering","template","template-engine","template-library","templates","templating","virtual-dom"],"created_at":"2024-07-31T08:01:18.394Z","updated_at":"2025-04-01T09:22:58.953Z","avatar_url":"https://github.com/nextapps-de.png","language":"JavaScript","readme":"\u003ch1\u003e\u003cimg src=\"https://cdn.jsdelivr.net/gh/nextapps-de/mikado@master/doc/mikado-animated.svg?v=3\" alt=\"Mikado - Webs fastest templating engine\" width=\"550px\"\u003e\u003cp\u003e\u003c/p\u003e\u003c/h1\u003e\n\u003ch3\u003eMikado is the webs fastest template engine for building user interfaces. Carefully crafted to get the most out of the browser. Also providing the fastest Express Render Engine of today. Super-lightweight, outstanding performance, no dependencies.\u003c/h3\u003e\n\n\u003ca target=\"_blank\" href=\"https://www.npmjs.com/package/mikado\"\u003e\u003cimg src=\"https://img.shields.io/npm/v/mikado.svg\"\u003e\u003c/a\u003e\n\u003cimg src=\"https://img.shields.io/badge/build-passing-brightgreen\"\u003e\n\u003cimg src=\"https://img.shields.io/badge/coverage-90%25-brightgreen\"\u003e\n\u003cimg src=\"https://img.shields.io/badge/typed-93%25-brightgreen\"\u003e\n\u003ca target=\"_blank\" href=\"https://github.com/nextapps-de/mikado/issues\"\u003e\u003cimg src=\"https://img.shields.io/github/issues/nextapps-de/mikado.svg\"\u003e\u003c/a\u003e\n\u003ca target=\"_blank\" href=\"https://github.com/nextapps-de/mikado/blob/master/LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/npm/l/mikado.svg\"\u003e\u003c/a\u003e\n\n\u003ca href=\"#get-started\"\u003eGetting Started\u003c/a\u003e \u0026ensp;\u0026bull;\u0026ensp;\n\u003ca href=\"#options\"\u003eOptions\u003c/a\u003e \u0026ensp;\u0026bull;\u0026ensp;\n\u003ca href=\"#api\"\u003eAPI\u003c/a\u003e \u0026ensp;\u0026bull;\u0026ensp;\n\u003ca href=\"#benchmark\"\u003eBenchmark\u003c/a\u003e \u0026ensp;\u0026bull;\u0026ensp;\n\u003ca href=\"#compiler\"\u003eTemplate Compiler\u003c/a\u003e \u0026ensp;\u0026bull;\u0026ensp;\n\u003ca href=\"#ssr\"\u003eServer-Side-Rendering\u003c/a\u003e \u0026ensp;\u0026bull;\u0026ensp;\n\u003ca href=\"#express\"\u003eExpress Render Engine\u003c/a\u003e \u0026ensp;\u0026bull;\u0026ensp;\n\u003ca href=\"#proxy\"\u003eReactive\u003c/a\u003e \u0026ensp;\u0026bull;\u0026ensp;\n\u003ca href=\"#hydration\"\u003eHydration\u003c/a\u003e \u0026ensp;\u0026bull;\u0026ensp;\n\u003ca href=\"#shadow\"\u003eWeb Components (Shadow DOM)\u003c/a\u003e \u0026ensp;\u0026bull;\u0026ensp;\n\u003ca href=\"CHANGELOG.md\"\u003eChangelog\u003c/a\u003e\n\nWhen you are coming from any previous version: \u003ca href=\"doc/migrate-0.8.md\"\u003eMigration Guide 0.8.x\u003c/a\u003e\n\n**Benchmark:**\n\n- \u003ca href=\"#benchmark\"\u003eStress Test Benchmark\u003c/a\u003e\n- https://krausest.github.io/js-framework-benchmark/current.html\n\n**Demo:**\n\n- TodoMVC App: \u003ca href=\"examples/todomvc/\"\u003eProject\u003c/a\u003e\u0026ensp;/\u0026ensp;\u003ca href=\"examples/todomvc/src/\"\u003eSource\u003c/a\u003e\u0026ensp;/\u0026ensp;\u003ca href=\"https://raw.githack.com/nextapps-de/mikado/master/examples/todomvc/dist/index.html\"\u003eDemo\u003c/a\u003e\n\n\u003c!--\n1. \u003ca href=\"demo/basic/basic.html\"\u003eBasic Example + Runtime Compiler (HTML5 Template)\u003c/a\u003e\n2. \u003ca href=\"demo/basic/compiler.html\"\u003eBasic Example + Runtime Compiler (String Template)\u003c/a\u003e\n3. \u003ca href=\"demo/basic/demo.html\"\u003eBasic Example + Events (ES5)\u003c/a\u003e\n4. \u003ca href=\"demo/basic/demo.es6.html\"\u003eBasic Example + Events (ES6 Modules)\u003c/a\u003e\n5. \u003ca href=\"demo/basic/demo.dev.html\"\u003eBasic Example + Events (Development Sources)\u003c/a\u003e\n6. TodoMVC App: \u003ca href=\"demo/todomvc/\"\u003eSource Code\u003c/a\u003e\u0026ensp;/\u0026ensp;\u003ca href=\"https://raw.githack.com/nextapps-de/mikado/master/demo/todomvc/index.html\"\u003eRun Demo\u003c/a\u003e\n7. js-framework-benchmark: \u003ca href=\"https://github.com/krausest/js-framework-benchmark/tree/master/frameworks/keyed/mikado\"\u003ekeyed\u003c/a\u003e\u0026ensp;/\u0026ensp;\u003ca href=\"https://github.com/krausest/js-framework-benchmark/tree/master/frameworks/non-keyed/mikado\"\u003enon-keyed\u003c/a\u003e\u0026ensp;/\u0026ensp;\u003ca href=\"https://github.com/krausest/js-framework-benchmark/tree/master/frameworks/keyed/mikado-proxy\"\u003ekeyed (proxy)\u003c/a\u003e\n--\u003e\n\n## Support this Project\n\nMikado was getting so much positive feedback and also feature requests. Help keeping Mikado active by a personal donation.\n\n\u003ca href=\"https://opencollective.com/mikado/donate\" target=\"_blank\" style=\"margin-right: 10px\"\u003e\u003cimg src=\"doc/opencollective.png\" height=\"32\" alt=\"Donate using Open Collective\"\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/sponsors/ts-thomas/\" target=\"_blank\" style=\"margin-right: 10px\"\u003e\u003cimg src=\"doc/github-sponsors.png\" height=\"32\" alt=\"Donate using Github Sponsors\"\u003e\u003c/a\u003e\n\u003ca href=\"https://liberapay.com/ts-thomas/donate\" target=\"_blank\" style=\"margin-right: 10px\"\u003e\u003cimg src=\"doc/liberapay.svg\" height=\"32\" alt=\"Donate using Liberapay\"\u003e\u003c/a\u003e\n\u003ca href=\"https://www.patreon.com/user?u=96245532\" target=\"_blank\" style=\"margin-right: 10px\"\u003e\u003cimg src=\"doc/patron.png\" height=\"32\" alt=\"Donate using Patreon\"\u003e\u003c/a\u003e\n\u003ca href=\"https://salt.bountysource.com/teams/ts-thomas\" target=\"_blank\" style=\"margin-right: 10px\"\u003e\u003cimg src=\"doc/bountysource.svg\" height=\"32\" alt=\"Donate using Bountysource\"\u003e\u003c/a\u003e\n\u003ca href=\"https://www.paypal.com/donate/?hosted_button_id=GEVR88FC9BWRW\" target=\"_blank\"\u003e\u003cimg src=\"doc/paypal.png\" height=\"32\" alt=\"Donate using PayPal\"\u003e\u003c/a\u003e\n\n## Table of contents\n\nRendering has great **impact** on application performance, especially **on mobile devices**. Mikado takes \u003ca href=\"#benchmark\"\u003etemplating performance\u003c/a\u003e to a new level and provides you **keyed**, **non-keyed** recycling and also **reactive paradigm** switchable out of the box.\nAdditionally, Mikado provides a **server-side-rendering** approach on a top-notch performance level along full support for **hydration** to inject templates progressively within the client's runtime.\nServer and client are sharing the same template definitions simply written in **HTML-like markup**.\nThe server side approach will also come with the **fastest middleware render engine for Express** you can get today.\nPacked with a smart routing feature for event delegation and full support for web components by using the Shadow DOM, Mikado gives you everything you'll need to build \u003ca href=\"#concept\"\u003erealtime applications\u003c/a\u003e on a cutting edge performance level.\n\n1. \u003ca href=\"#get-latest\"\u003eGet Latest\u003c/a\u003e\n2. \u003ca href=\"#feature-comparison\"\u003eFeature Comparison: Mikado Light\u003c/a\u003e\n3. \u003ca href=\"#benchmark\"\u003eBenchmark Ranking (Rendering Performance)\u003c/a\u003e\n4. \u003ca href=\"#api\"\u003eAPI Overview\u003c/a\u003e\n5. \u003ca href=\"#options\"\u003eMikado Options\u003c/a\u003e\n6. \u003ca href=\"#get-started\"\u003eGetting Started (Basic Example)\u003c/a\u003e\n7. \u003ca href=\"#conventions\"\u003eRules and Conventions\u003c/a\u003e\n8. \u003ca href=\"#advanced_example\"\u003eAdvanced Example\u003c/a\u003e\n9. \u003ca href=\"#compiler\"\u003eTemplate Compiler\u003c/a\u003e\n    - \u003ca href=\"#identifier\"\u003eReserved Keywords\u003c/a\u003e\n    - \u003ca href=\"#compiler-flags\"\u003eCompiler Flags\u003c/a\u003e\n    - \u003ca href=\"#auto-naming\"\u003eAuto Naming\u003c/a\u003e\n    - \u003ca href=\"#prebuilt-cache\"\u003ePrebuilt Cache\u003c/a\u003e\n    - \u003ca href=\"#watcher\"\u003eWatcher (Auto-Compile)\u003c/a\u003e\n    - \u003ca href=\"#runtime-compiler\"\u003eRuntime Compiler\u003c/a\u003e\n10. \u003ca href=\"#expressions\"\u003eTemplate Expressions\u003c/a\u003e\n    - \u003ca href=\"#insertion\"\u003eValue Insertion\u003c/a\u003e\n    - \u003ca href=\"#inline-js\"\u003eJS Inline Code\u003c/a\u003e\n    - \u003ca href=\"#truthy\"\u003eTruthy Values\u003c/a\u003e\n    - \u003ca href=\"#escape-ssr\"\u003eEscape Values (SSR)\u003c/a\u003e\n    - \u003ca href=\"#html\"\u003eHTML Contents\u003c/a\u003e\n    - \u003ca href=\"#sanitize\"\u003eSanitizer\u003c/a\u003e\n    - \u003ca href=\"#bindings\"\u003eReactive Bindings\u003c/a\u003e\n11. \u003ca href=\"#event\"\u003eRouting \u0026 Event Delegation\u003c/a\u003e\n    - \u003ca href=\"#bubbling\"\u003eEvent Bubbling\u003c/a\u003e\n    - \u003ca href=\"#event-cache\"\u003eEvent Cache\u003c/a\u003e\n    - \u003ca href=\"#view.listen\"\u003eExplicit Register Event Delegation\u003c/a\u003e\n    - \u003ca href=\"#event-control\"\u003eControl Native Events\u003c/a\u003e\n    - \u003ca href=\"#view.dispatch\"\u003eDispatch Routes\u003c/a\u003e\n12. Recycling Modes:\n    - \u003ca href=\"#non-keyed\"\u003eNon-Keyed Recycling\u003c/a\u003e\n    - \u003ca href=\"#keyed\"\u003eKeyed Recycling\u003c/a\u003e\n13. Views:\n    - \u003ca href=\"#mikado.new\"\u003eCreate Views\u003c/a\u003e\n    - \u003ca href=\"#view.mount\"\u003eMount Views\u003c/a\u003e\n    - \u003ca href=\"#view.destroy\"\u003eDestroy Views\u003c/a\u003e\n    - \u003ca href=\"#view.render\"\u003eRender Templates\u003c/a\u003e\n    - \u003ca href=\"#view.create\"\u003eCreate Components\u003c/a\u003e\n    - \u003ca href=\"#modify-views\"\u003eModify Views\u003c/a\u003e\n    - \u003ca href=\"#helpers\"\u003eCommon View Helpers\u003c/a\u003e\n    - \u003ca href=\"#manipulate\"\u003eManipulate Views\u003c/a\u003e\n14. \u003ca href=\"#cache\"\u003eDOM State Caching\u003c/a\u003e\n    - \u003ca href=\"#cache-concept\"\u003eState Caching Concept\u003c/a\u003e\n    - \u003ca href=\"#cache-helpers\"\u003eDOM Cache Helpers\u003c/a\u003e\n15. \u003ca href=\"#view.state\"\u003eView State\u003c/a\u003e\n16. \u003ca href=\"#callbacks\"\u003eCustom Callbacks\u003c/a\u003e\n17. \u003ca href=\"#static\"\u003eStatic Templates\u003c/a\u003e\n    - \u003ca href=\"#mikado.once\"\u003eOnce (One-time rendering)\u003c/a\u003e\n18. \u003ca href=\"#ssr\"\u003eServer-Side Rendering (SSR)\u003c/a\u003e\n    - \u003ca href=\"#ssr-exclusive\"\u003eSSR-exclusive Mode\u003c/a\u003e\n19. \u003ca href=\"#express\"\u003eExpress Render Engine\u003c/a\u003e\n    - \u003ca href=\"#express-options\"\u003eCustom Options\u003c/a\u003e\n    - \u003ca href=\"#express-render\"\u003eRender Views\u003c/a\u003e\n20. Template Features:\n    - \u003ca href=\"#expressions\"\u003eTemplate Expressions\u003c/a\u003e\n    - \u003ca href=\"#includes\"\u003eIncludes\u003c/a\u003e\n    - \u003ca href=\"#loop-partials\"\u003eLoop Partials\u003c/a\u003e\n    - \u003ca href=\"#inline-loops\"\u003eInline Loops\u003c/a\u003e\n    - \u003ca href=\"#conditional\"\u003eConditional Template Structures\u003c/a\u003e\n21. Reactive Features:\n    - \u003ca href=\"#proxy\"\u003eReactive Properties (Proxy)\u003c/a\u003e\n    - \u003ca href=\"#observable\"\u003eReactive Array (Virtual NodeList)\u003c/a\u003e\n    - \u003ca href=\"#limitations\"\u003eLimitations\u003c/a\u003e\n    - \u003ca href=\"#strict-proxy\"\u003eStrict-Proxy Mode\u003c/a\u003e\n    - \u003ca href=\"#array.transaction\"\u003eTransactions\u003c/a\u003e\n22. \u003ca href=\"#pools\"\u003eTemplate Pools\u003c/a\u003e\n23. \u003ca href=\"#hydration\"\u003eHydration\u003c/a\u003e\n24. \u003ca href=\"#shadow\"\u003eWeb Components (Shadow DOM)\u003c/a\u003e\n25. \u003ca href=\"#full-template\"\u003eFull Template Example\u003c/a\u003e\n26. \u003ca href=\"#best-practices\"\u003eBest Practices\u003c/a\u003e\n27. \u003ca href=\"#concept\"\u003eConcept of Shared Components\u003c/a\u003e\n28. \u003ca href=\"#builds\"\u003eCustom Builds\u003c/a\u003e\n    - \u003ca href=\"#build-flags\"\u003eSupported Build Flags\u003c/a\u003e\n\n\u003ca name=\"get-latest\"\u003e\u003c/a\u003e\n\n## Get Latest\n\n\u003e Do not use the \"src\" folder of this repo. It isn't meant to be used directly, instead it needs compilation. You can easily perform a \u003ca href=\"#builds\"\u003ecustom build\u003c/a\u003e, but don't use the source folder for production. You will need at least any kind of compiler which resolve the compiler flags within the code. The \"dist\" folder is containing every version which you probably need including unminified modules.\n\n\u003ctable\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eBuild\u003c/td\u003e\n        \u003ctd\u003eFile\u003c/td\u003e\n        \u003ctd\u003eCDN\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003emikado.bundle.debug.js\u003c/td\u003e\n        \u003ctd\u003e\u003ca href=\"https://github.com/nextapps-de/mikado/raw/0.8.4/dist/mikado.bundle.debug.js\" target=\"_blank\"\u003eDownload\u003c/a\u003e\u003c/td\u003e\n        \u003ctd\u003e\u003ca href=\"https://rawcdn.githack.com/nextapps-de/mikado/0.8.4/dist/mikado.bundle.debug.js\" target=\"_blank\"\u003ehttps://rawcdn.githack.com/nextapps-de/mikado/0.8.4/dist/mikado.bundle.debug.js\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003emikado.bundle.min.js\u003c/td\u003e\n        \u003ctd\u003e\u003ca href=\"https://github.com/nextapps-de/mikado/raw/0.8.4/dist/mikado.bundle.min.js\" target=\"_blank\"\u003eDownload\u003c/a\u003e\u003c/td\u003e\n        \u003ctd\u003e\u003ca href=\"https://rawcdn.githack.com/nextapps-de/mikado/0.8.4/dist/mikado.bundle.min.js\" target=\"_blank\"\u003ehttps://rawcdn.githack.com/nextapps-de/mikado/0.8.4/dist/mikado.bundle.min.js\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003emikado.bundle.module.debug.js\u003c/td\u003e\n        \u003ctd\u003e\u003ca href=\"https://github.com/nextapps-de/mikado/raw/0.8.4/dist/mikado.bundle.module.debug.js\" target=\"_blank\"\u003eDownload\u003c/a\u003e\u003c/td\u003e\n        \u003ctd\u003e\u003ca href=\"https://rawcdn.githack.com/nextapps-de/mikado/0.8.4/dist/mikado.bundle.module.debug.js\" target=\"_blank\"\u003ehttps://rawcdn.githack.com/nextapps-de/mikado/0.8.4/dist/mikado.bundle.module.debug.js\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003emikado.bundle.module.min.js\u003c/td\u003e\n        \u003ctd\u003e\u003ca href=\"https://github.com/nextapps-de/mikado/raw/0.8.4/dist/mikado.bundle.module.min.js\" target=\"_blank\"\u003eDownload\u003c/a\u003e\u003c/td\u003e\n        \u003ctd\u003e\u003ca href=\"https://rawcdn.githack.com/nextapps-de/mikado/0.8.4/dist/mikado.bundle.module.min.js\" target=\"_blank\"\u003ehttps://rawcdn.githack.com/nextapps-de/mikado/0.8.4/dist/mikado.bundle.module.min.js\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003emikado.es5.debug.js\u003c/td\u003e\n        \u003ctd\u003e\u003ca href=\"https://github.com/nextapps-de/mikado/raw/0.8.4/dist/mikado.es5.debug.js\" target=\"_blank\"\u003eDownload\u003c/a\u003e\u003c/td\u003e\n        \u003ctd\u003e\u003ca href=\"https://rawcdn.githack.com/nextapps-de/mikado/0.8.4/dist/mikado.es5.debug.js\" target=\"_blank\"\u003ehttps://rawcdn.githack.com/nextapps-de/mikado/0.8.4/dist/mikado.es5.debug.js\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003emikado.es5.min.js\u003c/td\u003e\n        \u003ctd\u003e\u003ca href=\"https://github.com/nextapps-de/mikado/raw/0.8.4/dist/mikado.es5.min.js\" target=\"_blank\"\u003eDownload\u003c/a\u003e\u003c/td\u003e\n        \u003ctd\u003e\u003ca href=\"https://rawcdn.githack.com/nextapps-de/mikado/0.8.4/dist/mikado.es5.min.js\" target=\"_blank\"\u003ehttps://rawcdn.githack.com/nextapps-de/mikado/0.8.4/dist/mikado.es5.min.js\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003emikado.light.debug.js\u003c/td\u003e\n        \u003ctd\u003e\u003ca href=\"https://github.com/nextapps-de/mikado/raw/0.8.4/dist/mikado.light.debug.js\" target=\"_blank\"\u003eDownload\u003c/a\u003e\u003c/td\u003e\n        \u003ctd\u003e\u003ca href=\"https://rawcdn.githack.com/nextapps-de/mikado/0.8.4/dist/mikado.light.debug.js\" target=\"_blank\"\u003ehttps://rawcdn.githack.com/nextapps-de/mikado/0.8.4/dist/mikado.light.debug.js\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003emikado.light.min.js\u003c/td\u003e\n        \u003ctd\u003e\u003ca href=\"https://github.com/nextapps-de/mikado/raw/0.8.4/dist/mikado.light.min.js\" target=\"_blank\"\u003eDownload\u003c/a\u003e\u003c/td\u003e\n        \u003ctd\u003e\u003ca href=\"https://rawcdn.githack.com/nextapps-de/mikado/0.8.4/dist/mikado.light.min.js\" target=\"_blank\"\u003ehttps://rawcdn.githack.com/nextapps-de/mikado/0.8.4/dist/mikado.light.min.js\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003emikado.light.module.debug.js\u003c/td\u003e\n        \u003ctd\u003e\u003ca href=\"https://github.com/nextapps-de/mikado/raw/0.8.4/dist/mikado.light.module.debug.js\" target=\"_blank\"\u003eDownload\u003c/a\u003e\u003c/td\u003e\n        \u003ctd\u003e\u003ca href=\"https://rawcdn.githack.com/nextapps-de/mikado/0.8.4/dist/mikado.light.module.debug.js\" target=\"_blank\"\u003ehttps://rawcdn.githack.com/nextapps-de/mikado/0.8.4/dist/mikado.light.module.debug.js\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003emikado.light.module.min.js\u003c/td\u003e\n        \u003ctd\u003e\u003ca href=\"https://github.com/nextapps-de/mikado/raw/0.8.4/dist/mikado.light.module.min.js\" target=\"_blank\"\u003eDownload\u003c/a\u003e\u003c/td\u003e\n        \u003ctd\u003e\u003ca href=\"https://rawcdn.githack.com/nextapps-de/mikado/0.8.4/dist/mikado.light.module.min.js\" target=\"_blank\"\u003ehttps://rawcdn.githack.com/nextapps-de/mikado/0.8.4/dist/mikado.light.module.min.js\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eJavascript Modules\u003c/td\u003e\n        \u003ctd\u003e\u003ca href=\"https://github.com/nextapps-de/mikado/raw/0.8.4/dist/module/\" target=\"_blank\"\u003eDownload\u003c/a\u003e\u003c/td\u003e\n        \u003ctd\u003e\u003ca href=\"https://github.com/nextapps-de/mikado/tree/0.8.4/dist/module\" target=\"_blank\"\u003ehttps://github.com/nextapps-de/mikado/tree/0.8.4/dist/module\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eJavascript Modules (Minified)\u003c/td\u003e\n        \u003ctd\u003e\u003ca href=\"https://github.com/nextapps-de/mikado/raw/0.8.4/dist/module-min/\" target=\"_blank\"\u003eDownload\u003c/a\u003e\u003c/td\u003e\n        \u003ctd\u003e\u003ca href=\"https://github.com/nextapps-de/mikado/tree/0.8.4/dist/module-min\" target=\"_blank\"\u003ehttps://github.com/nextapps-de/mikado/tree/0.8.4/dist/module-min\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eJavascript Modules (Debug)\u003c/td\u003e\n        \u003ctd\u003e\u003ca href=\"https://github.com/nextapps-de/mikado/raw/0.8.4/dist/module-debug/\" target=\"_blank\"\u003eDownload\u003c/a\u003e\u003c/td\u003e\n        \u003ctd\u003e\u003ca href=\"https://github.com/nextapps-de/mikado/tree/0.8.4/dist/module-debug\" target=\"_blank\"\u003ehttps://github.com/nextapps-de/mikado/tree/0.8.4/dist/module-debug\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003emikado.custom.js\u003c/td\u003e\n        \u003ctd colspan=\"2\"\u003e\u003ca href=\"#builds\"\u003eRead more about \"Custom Build\"\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n\u003c/table\u003e\n\n\u003e All debug versions are providing debug information through the console and gives you helpful advices on certain situations.\n\n### Bundles\n\n\u003e Bundles export all their features as static functions to the public class namespace \"Mikado\" e.g. `Mikado.register()`.\n\nThe abbreviations used at the end of the filenames indicates:\n\n- `bundle` All features included, Mikado is available on `window.Mikado`\n- `light` Only basic features are included, Mikado is available on `window.Mikado`\n- `es5` bundle has support for EcmaScript5, Mikado is available on `window.Mikado`\n- `module` bundle is a Javascript module, Mikado is available by `import Mikado from \"./mikado.bundle.module.min.js\"`\n- `min` bundle is minified\n- `debug` bundle has enabled debug mode (only for development purposes, do not use for production)\n\n### Module\n\nWhen using modules you can choose from 2 variants: `mikado.xxx.module.min.js` has all features bundled on the public class namespace e.g. `Mikado.register()`, whereas the folder `/dist/module/` export most of the features as functions which needs to be imported explicitly by `import { register } from \"./dist/module/mikado.js\"`.\n\nAlso, for each variant there exist:\n1. A debug version for the development\n2. A pre-compiled minified version for production\n\n### Browser\n\nLoad the bundle by a script tag:\n\n```html\n\u003cscript src=\"dist/mikado.bundle.min.js\"\u003e\u003c/script\u003e\n\u003cscript\u003e\n  // ... access Mikado\n\u003c/script\u003e\n```\n\n### NPM\n\nInstall Mikado via NPM:\n\n```npm\nnpm install mikado\n```\n\nThe **_dist_** folder are located in `node_modules/mikado/dist/`.\n\n### Javascript Modules\n \nUse the bundled version exported as a module:\n\n```html\n\u003cscript type=\"module\"\u003e\n    import Mikado from \"./dist/mikado.bundle.module.min.js\";\n    // bundled access by e.g. Mikado.register()\n\u003c/script\u003e\n```\n\nAlso, pre-compiled non-bundled production-ready modules are located in `dist/module-min/`.\n\n```html\n\u003cscript type=\"module\"\u003e\n    import Mikado, { register } from \"./dist/module-min/mikado.js\";\n    // bundled access by Mikado.register isn't available\n    // requires direct access by e.g. register()\n\u003c/script\u003e\n```\n\nYou can also load modules via CDN:\n\n```html\n\u003cscript type=\"module\"\u003e\n    import Mikado from \"https://unpkg.com/mikado@0.8.404/dist/module/mikado.js\";\n\u003c/script\u003e\n```\n\n\u003e Loading modules via CDN commonly expects to build/bundle your app properly before distribution. Do not load them via CDN in production.\n\n\u003ca name=\"feature-comparison\"\u003e\u003c/a\u003e\n\n### Feature Comparison \"Bundle vs. Light\"\n\n\u003ctable\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eFeature\u003c/td\u003e\n        \u003ctd\u003emikado.bundle.js\u003c/td\u003e\n        \u003ctd\u003emikado.light.js\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\n            Template Render Engine\n        \u003c/td\u003e\n        \u003ctd\u003e✓\u003c/td\u003e\n        \u003ctd\u003e✓\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\n            \u003ca href=\"#cache\"\u003eDOM State Caching\u003c/a\u003e\n        \u003c/td\u003e\n        \u003ctd\u003e✓\u003c/td\u003e\n        \u003ctd\u003e✓\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\n            \u003ca href=\"#pool\"\u003eShared Pools / Live Pools\u003c/a\u003e\n        \u003c/td\u003e\n        \u003ctd\u003e✓\u003c/td\u003e\n        \u003ctd\u003e✓\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\n            \u003ca href=\"#keyed\"\u003eKeyed Recycle\u003c/a\u003e\n        \u003c/td\u003e\n        \u003ctd\u003e✓\u003c/td\u003e\n        \u003ctd\u003e✓\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\n            \u003ca href=\"#recycle\"\u003eNon-keyed Recycle\u003c/a\u003e\n        \u003c/td\u003e\n        \u003ctd\u003e✓\u003c/td\u003e\n        \u003ctd\u003e✓\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\n            \u003ca href=\"#reconcile\"\u003eReconcile (Diffing)\u003c/a\u003e\n        \u003c/td\u003e\n        \u003ctd\u003e✓\u003c/td\u003e\n        \u003ctd\u003e✓\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\n            \u003ca href=\"#hydration\"\u003eHydration\u003c/a\u003e\n        \u003c/td\u003e\n        \u003ctd\u003e✓\u003c/td\u003e\n        \u003ctd\u003e✓\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\n            \u003ca href=\"#expression\"\u003eTemplate Expressions\u003c/a\u003e\n        \u003c/td\u003e\n        \u003ctd\u003e✓\u003c/td\u003e\n        \u003ctd\u003e✓\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\n            \u003ca href=\"#conditional\"\u003eConditional Template Structures\u003c/a\u003e\n        \u003c/td\u003e\n        \u003ctd\u003e✓\u003c/td\u003e\n        \u003ctd\u003e✓\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\n            \u003ca href=\"#include\"\u003eIncludes/Partials/Loops\u003c/a\u003e\n        \u003c/td\u003e\n        \u003ctd\u003e✓\u003c/td\u003e\n        \u003ctd\u003e✓\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\n            \u003ca href=\"#shadow\"\u003eShadow DOM\u003c/a\u003e\n        \u003c/td\u003e\n        \u003ctd\u003e✓\u003c/td\u003e\n        \u003ctd\u003e✓\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\n            \u003ca href=\"#shadow\"\u003eWeb Components\u003c/a\u003e\n        \u003c/td\u003e\n        \u003ctd\u003e✓\u003c/td\u003e\n        \u003ctd\u003e-\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\n            \u003ca href=\"#runtime-compiler\"\u003eRuntime Compiler\u003c/a\u003e\n        \u003c/td\u003e\n        \u003ctd\u003e✓\u003c/td\u003e\n        \u003ctd\u003e-\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\n            \u003ca href=\"#event\"\u003eEvent Delegation + Routes\u003c/a\u003e\n        \u003c/td\u003e\n        \u003ctd\u003e✓\u003c/td\u003e\n        \u003ctd\u003e-\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\n            \u003ca href=\"#proxy\"\u003eReactive (Proxy, Observer)\u003c/a\u003e\n        \u003c/td\u003e\n        \u003ctd\u003e✓\u003c/td\u003e\n        \u003ctd\u003e-\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\n            \u003ca href=\"#async\"\u003eAsynchronous Render\u003c/a\u003e\n        \u003c/td\u003e\n        \u003ctd\u003e✓\u003c/td\u003e\n        \u003ctd\u003e-\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\n            \u003ca href=\"#manipulate\"\u003eView Manipulation Helpers\u003c/a\u003e\n        \u003c/td\u003e\n        \u003ctd\u003e✓\u003c/td\u003e\n        \u003ctd\u003e-\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\n            \u003ca href=\"#helper\"\u003eDOM Cache Helpers\u003c/a\u003e\n        \u003c/td\u003e\n        \u003ctd\u003e✓\u003c/td\u003e\n        \u003ctd\u003e-\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eFile Size (gzip)\u003c/td\u003e\n        \u003ctd\u003e9.3 kb\u003c/td\u003e\n        \u003ctd\u003e3.7 kb\u003c/td\u003e\n    \u003c/tr\u003e\n\u003c/table\u003e\n\n\u003ca name=\"benchmark\"\u003e\u003c/a\u003e\n\n## Benchmark Ranking (Rendering Performance)\n\nRun the benchmark (non-keyed recycle):\u003cbr\u003e\n\u003ca href=\"https://raw.githack.com/nextapps-de/mikado/bench/\"\u003ehttps://raw.githack.com/nextapps-de/mikado/bench/\u003c/a\u003e\u003cbr\u003e\n\nRun the benchmark (keyed recycle):\u003cbr\u003e\n\u003ca href=\"https://raw.githack.com/nextapps-de/mikado/bench/#keyed\"\u003ehttps://raw.githack.com/nextapps-de/mikado/bench/#keyed\u003c/a\u003e\u003cbr\u003e\n\nRun the benchmark (internal/data-driven):\u003cbr\u003e\n\u003ca href=\"https://raw.githack.com/nextapps-de/mikado/bench/#internal\"\u003ehttps://raw.githack.com/nextapps-de/mikado/bench/#internal\u003c/a\u003e\u003cbr\u003e\n\nThe values represent operations per second, each benchmark task has to process a data array of 100 items. Higher values are better, except for memory (the sum of allocated memory during the whole test).\n\n#### Keyed Test Results\n\n\u003ctable\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003csub\u003eLibrary\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"center\"\u003e\u003csub\u003eRAM\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"center\"\u003e\u003csub\u003eCreate\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"center\"\u003e\u003csub\u003eReplace\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"center\"\u003e\u003csub\u003eUpdate\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"center\"\u003e\u003csub\u003eOrder\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"center\"\u003e\u003csub\u003eRepaint\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"center\"\u003e\u003csub\u003eAdd\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"center\"\u003e\u003csub\u003eRemove\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"center\"\u003e\u003csub\u003eToggle\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"center\"\u003e\u003csub\u003eClear\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"center\"\u003e\u003csub\u003eScore\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"center\"\u003e\u003csub\u003eIndex\u003c/sub\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003csub\u003emikado\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e55\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e3589\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e2780\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e199816\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e134262\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e536052\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e93062\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e93058\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e92151\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e51219\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003cb\u003e\u003csub\u003e3202\u003c/sub\u003e\u003c/b\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003cb\u003e\u003csub\u003e92\u003c/sub\u003e\u003c/b\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003csub\u003esolid\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e44\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e2438\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e2230\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e20362\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e13101\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e34436\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e4595\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e24891\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e7858\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e70825\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003cb\u003e\u003csub\u003e312\u003c/sub\u003e\u003c/b\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003cb\u003e\u003csub\u003e37\u003c/sub\u003e\u003c/b\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003csub\u003einferno\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e46\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e2551\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e2151\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e14722\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e13900\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e16796\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e4780\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e20727\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e7724\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e54176\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003cb\u003e\u003csub\u003e238\u003c/sub\u003e\u003c/b\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003cb\u003e\u003csub\u003e34\u003c/sub\u003e\u003c/b\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003csub\u003emithril\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e45\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e1672\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e1505\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e15406\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e13868\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e16638\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e3599\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e21109\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e5653\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e41525\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003cb\u003e\u003csub\u003e223\u003c/sub\u003e\u003c/b\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003cb\u003e\u003csub\u003e28\u003c/sub\u003e\u003c/b\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003csub\u003estage0\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e56\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e2030\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e2446\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e11213\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e9749\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e11033\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e4427\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e18083\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e7209\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e90434\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003cb\u003e\u003csub\u003e199\u003c/sub\u003e\u003c/b\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003cb\u003e\u003csub\u003e35\u003c/sub\u003e\u003c/b\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003csub\u003eredom\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e81\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e1517\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e1421\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e10242\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e9614\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e10870\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e2857\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e16062\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e4875\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e28075\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003cb\u003e\u003csub\u003e160\u003c/sub\u003e\u003c/b\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003cb\u003e\u003csub\u003e22\u003c/sub\u003e\u003c/b\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003csub\u003edomc\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e124\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e3600\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e3424\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e3437\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e3472\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e3512\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e3592\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e6670\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e4540\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e100302\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003cb\u003e\u003csub\u003e120\u003c/sub\u003e\u003c/b\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003cb\u003e\u003csub\u003e38\u003c/sub\u003e\u003c/b\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003csub\u003einnerhtml\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e67\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e2791\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e2676\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e2471\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e2823\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e2799\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e2943\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e5752\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e3901\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e103405\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003cb\u003e\u003csub\u003e105\u003c/sub\u003e\u003c/b\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003cb\u003e\u003csub\u003e35\u003c/sub\u003e\u003c/b\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003csub\u003esurplus\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e92\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e2969\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e2577\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e2281\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e2386\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e2379\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e2285\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e4197\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e3023\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e86916\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003cb\u003e\u003csub\u003e91\u003c/sub\u003e\u003c/b\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003cb\u003e\u003csub\u003e32\u003c/sub\u003e\u003c/b\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003csub\u003edoohtml\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e71\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e2397\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e2308\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e2208\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e2208\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e2229\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e2275\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e4285\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e2945\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e63162\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003cb\u003e\u003csub\u003e82\u003c/sub\u003e\u003c/b\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003cb\u003e\u003csub\u003e29\u003c/sub\u003e\u003c/b\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003csub\u003esinuous\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e151\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e2038\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e2112\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e2454\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e2459\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e2461\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e2506\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e4820\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e3276\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e59556\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003cb\u003e\u003csub\u003e81\u003c/sub\u003e\u003c/b\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003cb\u003e\u003csub\u003e25\u003c/sub\u003e\u003c/b\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003csub\u003ejquery\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e103\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e2195\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e1919\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e1893\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e2092\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e2093\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e2084\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e3903\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e2594\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e19220\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003cb\u003e\u003csub\u003e66\u003c/sub\u003e\u003c/b\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003cb\u003e\u003csub\u003e21\u003c/sub\u003e\u003c/b\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003csub\u003elit-html\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e199\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e1410\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e1329\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e1349\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e1351\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e1333\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e1393\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e2415\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e1764\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e20837\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003cb\u003e\u003csub\u003e46\u003c/sub\u003e\u003c/b\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003cb\u003e\u003csub\u003e15\u003c/sub\u003e\u003c/b\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003csub\u003eractive\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e1870\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e739\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e672\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e690\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e686\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e691\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e725\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e1247\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e917\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e7394\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003cb\u003e\u003csub\u003e22\u003c/sub\u003e\u003c/b\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003cb\u003e\u003csub\u003e7\u003c/sub\u003e\u003c/b\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003csub\u003eknockout\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e1081\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e399\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e289\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e291\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e291\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e280\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e355\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e524\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e429\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003csub\u003e3424\u003c/sub\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003cb\u003e\u003csub\u003e12\u003c/sub\u003e\u003c/b\u003e\u003c/td\u003e\n        \u003ctd align=\"right\"\u003e\u003cb\u003e\u003csub\u003e4\u003c/sub\u003e\u003c/b\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n\u003c/table\u003e\n\nThe **_index_** is a statistic rank having a maximum possible value of 100, this requires a library to be the best in each test category (regardless how much better).\nThe **_score_** value is based on median factorization, here a score of 100 represents the statistical midfield.\n\n\u003ca name=\"api\"\u003e\u003c/a\u003e\n\n## API Overview\n\n\u003e Most of these methods are optional, you can just use **_view.render(data)_** to apply all changes automatically.\n\nConstructor:\n\n- new \u003ca href=\"#mikado.new\"\u003e**Mikado**(template, \\\u003coptions\\\u003e)\u003c/a\u003e : \u003csmall\u003e_view_\u003c/small\u003e\n- new Mikado.\u003ca href=\"#observable\"\u003e**Array**(array)\u003c/a\u003e : \u003csmall\u003e_observable_\u003c/small\u003e\n\nInstance properties:\n\n- view.\u003ca href=\"#view.name\"\u003e**name**\u003c/a\u003e \u003csmall\u003e_readonly_\u003c/small\u003e\n- view.\u003ca href=\"#view.root\"\u003e**root**\u003c/a\u003e \u003csmall\u003e_readonly_\u003c/small\u003e\n- view.\u003ca href=\"#view.length\"\u003e**length**\u003c/a\u003e \u003csmall\u003e_readonly_\u003c/small\u003e\n- view.\u003ca href=\"#view.state\"\u003e**state**\u003c/a\u003e \u003csmall\u003e_readonly_\u003c/small\u003e\n\nStatic properties (not included in mikado.light.js):\n\n- Mikado.\u003ca href=\"#mikado.eventCache\"\u003e**eventCache**\u003c/a\u003e : \u003csmall\u003e_boolean_\u003c/small\u003e\n- Mikado.\u003ca href=\"#mikado.eventBubble\"\u003e**eventBubble**\u003c/a\u003e : \u003csmall\u003e_boolean_\u003c/small\u003e\n\nStatic methods:\n\n- Mikado.\u003ca href=\"#mikado.once\"\u003e**once**(root, template, \\\u003cdata\\\u003e, \\\u003cstate\\\u003e, \\\u003ccallback\\\u003e)\u003c/a\u003e\n- Mikado.\u003ca href=\"#mikado.register\"\u003e**register**(template, \\\u003coptions\\\u003e)\u003c/a\u003e\n- Mikado.\u003ca href=\"#mikado.unregister\"\u003e**unregister**(template)\u003c/a\u003e\n\nStatic methods (not included in mikado.light.js):\n\n\u003c!-- - \u003ca href=\"#mikado.compile\"\u003e**compile**(\\\u003ctemplate | string\\\u003e)\u003c/a\u003e --\u003e\n- Mikado.\u003ca href=\"#mikado.route\"\u003e**route**(name, function, \\\u003coptions\\\u003e)\u003c/a\u003e\n- Mikado.\u003ca href=\"#mikado.listen\"\u003e**listen**(event, \\\u003coptions\\\u003e)\u003c/a\u003e\n- Mikado.\u003ca href=\"#mikado.unlisten\"\u003e**unlisten**(event)\u003c/a\u003e\n- Mikado.\u003ca href=\"#mikado.dispatch\"\u003e**dispatch**(route, \\\u003ctarget\\\u003e, \\\u003cevent\\\u003e)\u003c/a\u003e\n- Mikado.\u003ca href=\"#mikado.escape\"\u003e**escape**(text)\u003c/a\u003e : \u003csmall\u003e_string_\u003c/small\u003e\n- Mikado.\u003ca href=\"#mikado.sanitize\"\u003e**sanitize**(text)\u003c/a\u003e : \u003csmall\u003e_string_\u003c/small\u003e\n\nInstance methods:\n\n- view.\u003ca href=\"#view.mount\"\u003e**mount**(root, \\\u003chydrate\\\u003e)\u003c/a\u003e\n- view.\u003ca href=\"#view.render\"\u003e**render**(\\\u003cdata\\\u003e, \\\u003cstate\\\u003e, \\\u003ccallback\\\u003e)\u003c/a\u003e\n- view.\u003ca href=\"#view.create\"\u003e**create**(data, \\\u003cstate\\\u003e, \\\u003cindex\\\u003e)\u003c/a\u003e : \u003csmall\u003e_node_\u003c/small\u003e\n- view.\u003ca href=\"#view.add\"\u003e**add**(data, \\\u003cstate\\\u003e, \u003cposition\\\u003e)\u003c/a\u003e\n- view.\u003ca href=\"#view.append\"\u003e**append**(data, \\\u003cstate\\\u003e, \u003cposition\\\u003e)\u003c/a\u003e\n- view.\u003ca href=\"#view.update\"\u003e**update**(node | index, data, \\\u003cstate\\\u003e)\u003c/a\u003e\n- view.\u003ca href=\"#view.replace\"\u003e**replace**(node | index, data, \\\u003cstate\\\u003e)\u003c/a\u003e\n- view.\u003ca href=\"#view.remove\"\u003e**remove**(node, \u003ccount\\\u003e)\u003c/a\u003e\n- view.\u003ca href=\"#view.clear\"\u003e**clear**()\u003c/a\u003e\n- view.\u003ca href=\"#view.node\"\u003e**node**(index)\u003c/a\u003e : \u003csmall\u003e_node_\u003c/small\u003e\n- view.\u003ca href=\"#view.index\"\u003e**index**(node)\u003c/a\u003e : \u003csmall\u003e_number_\u003c/small\u003e\n- view.\u003ca href=\"#view.flush\"\u003e**flush**()\u003c/a\u003e\n- view.\u003ca href=\"#view.destroy\"\u003e**destroy**()\u003c/a\u003e\n\nInstance methods (not included in mikado.light.js):\n\n- view.\u003ca href=\"#view.route\"\u003e**route**(name, function, \\\u003coptions\\\u003e)\u003c/a\u003e\n- view.\u003ca href=\"#view.listen\"\u003e**listen**(event, \\\u003coptions\\\u003e)\u003c/a\u003e\n- view.\u003ca href=\"#view.unlisten\"\u003e**unlisten**(event)\u003c/a\u003e\n- view.\u003ca href=\"#view.dispatch\"\u003e**dispatch**(name, \\\u003ctarget\\\u003e, \\\u003cevent\\\u003e)\u003c/a\u003e\n\nView manipulation helpers (optional, not included in mikado.light.js):\n\n- view.\u003ca href=\"#view.move\"\u003e**move**(node | index, position)\u003c/a\u003e\n- view.\u003ca href=\"#view.shift\"\u003e**shift**(node | index, offset)\u003c/a\u003e\n- view.\u003ca href=\"#view.up\"\u003e**up**(node | index)\u003c/a\u003e\n- view.\u003ca href=\"#view.down\"\u003e**down**(node | index)\u003c/a\u003e\n- view.\u003ca href=\"#view.first\"\u003e**first**(node | index)\u003c/a\u003e\n- view.\u003ca href=\"#view.last\"\u003e**last**(node | index)\u003c/a\u003e\n- view.\u003ca href=\"#view.before\"\u003e**before**(node | index, node | index)\u003c/a\u003e\n- view.\u003ca href=\"#view.after\"\u003e**after**(node | index, node | index)\u003c/a\u003e\n- view.\u003ca href=\"#view.swap\"\u003e**swap**(node | index, node | index)\u003c/a\u003e\n\nStatic DOM Cache helpers (optional, not included in mikado.light.js):\n\n- Mikado.\u003ca href=\"#Mikado.setText\"\u003e**setText**(node, text)\u003c/a\u003e\n- Mikado.\u003ca href=\"#Mikado.getText\"\u003e**getText**(node)\u003c/a\u003e : \u003csmall\u003e_string_\u003c/small\u003e\n- Mikado.\u003ca href=\"#Mikado.setHtml\"\u003e**setHtml**(node, html)\u003c/a\u003e\n- Mikado.\u003ca href=\"#Mikado.getHtml\"\u003e**getHtml**(node)\u003c/a\u003e : \u003csmall\u003e_string_\u003c/small\u003e\n\n\n- Mikado.\u003ca href=\"#Mikado.setClass\"\u003e**setClass**(node, [classnames])\u003c/a\u003e\n- Mikado.\u003ca href=\"#Mikado.getClass\"\u003e**getClass**(node)\u003c/a\u003e : \u003csmall\u003e_[string]_\u003c/small\u003e\n- Mikado.\u003ca href=\"#Mikado.addClass\"\u003e**addClass**(node, classname)\u003c/a\u003e\n- Mikado.\u003ca href=\"#Mikado.addClass\"\u003e**addClass**(node, [classnames])\u003c/a\u003e\n- Mikado.\u003ca href=\"#Mikado.hasClass\"\u003e**hasClass**(node, classname)\u003c/a\u003e : \u003csmall\u003e_boolean_\u003c/small\u003e\n- Mikado.\u003ca href=\"#Mikado.removeClass\"\u003e**removeClass**(node, classname)\u003c/a\u003e\n- Mikado.\u003ca href=\"#Mikado.removeClass\"\u003e**removeClasses**(node, [classnames])\u003c/a\u003e\n- Mikado.\u003ca href=\"#Mikado.toggleClass\"\u003e**toggleClass**(node, classname, \\\u003cstate\\\u003e)\u003c/a\u003e\n- Mikado.\u003ca href=\"#Mikado.toggleClass\"\u003e**toggleClasses**(node, [classnames], \\\u003cstate\\\u003e)\u003c/a\u003e\n- Mikado.\u003ca href=\"#Mikado.toggleClass\"\u003e**toggleClasses**(node, {classname: state})\u003c/a\u003e\n\n\n- Mikado.\u003ca href=\"#Mikado.setStyle\"\u003e**setStyle**(node, property, value)\u003c/a\u003e\n- Mikado.\u003ca href=\"#Mikado.setStyle\"\u003e**setStyles**(node, {property: value})\u003c/a\u003e\n- Mikado.\u003ca href=\"#Mikado.getStyle\"\u003e**getStyle**(node, property)\u003c/a\u003e : \u003csmall\u003e_string_\u003c/small\u003e\n- Mikado.\u003ca href=\"#Mikado.setCss\"\u003e**setCss**(node, css)\u003c/a\u003e\n- Mikado.\u003ca href=\"#Mikado.getCss\"\u003e**getCss**(node)\u003c/a\u003e : \u003csmall\u003e_string_\u003c/small\u003e\n\n\n- Mikado.\u003ca href=\"#Mikado.setAttribute\"\u003e**setAttribute**(node, attribute, value)\u003c/a\u003e\n- Mikado.\u003ca href=\"#Mikado.setAttribute\"\u003e**setAttribute**(node, {attribute: value})\u003c/a\u003e\n- Mikado.\u003ca href=\"#Mikado.getAttribute\"\u003e**getAttribute**(node, attribute)\u003c/a\u003e : \u003csmall\u003e_string | null_\u003c/small\u003e\n- Mikado.\u003ca href=\"#Mikado.hasAttribute\"\u003e**hasAttribute**(node, attribute)\u003c/a\u003e : \u003csmall\u003e_boolean_\u003c/small\u003e\n- Mikado.\u003ca href=\"#Mikado.removeAttribute\"\u003e**removeAttribute**(node, attribute)\u003c/a\u003e\n- Mikado.\u003ca href=\"#Mikado.removeAttribute\"\u003e**removeAttribute**(node, [attributes])\u003c/a\u003e\n\nObservable constructor (optional, not included in mikado.light.js):\n\n- new \u003ca href=\"#mikado.array\"\u003e**Mikado.Array**(\\\u003carray\\\u003e)\u003c/a\u003e : \u003csmall\u003e_observable_\u003c/small\u003e\n\nObservable array-like methods (optional, not included in mikado.light.js):\n\n- observable.\u003ca href=\"#array.length\"\u003e**length**\u003c/a\u003e : \u003csmall\u003e_number_\u003c/small\u003e\n- observable.\u003ca href=\"#array.mount\"\u003e**mount**(view)\u003c/a\u003e\n- observable.\u003ca href=\"#array.concat\"\u003e**concat**([object])\u003c/a\u003e\n- observable.\u003ca href=\"#array.push\"\u003e**push**(object)\u003c/a\u003e\n- observable.\u003ca href=\"#array.splice\"\u003e**splice**\u003c/a\u003e : \u003csmall\u003e_[Object]_\u003c/small\u003e\n- observable.\u003ca href=\"#array.pop\"\u003e**pop**\u003c/a\u003e : \u003csmall\u003e_Object_\u003c/small\u003e\n- observable.\u003ca href=\"#array.shift\"\u003e**shift**\u003c/a\u003e : \u003csmall\u003e_Object_\u003c/small\u003e\n- observable.\u003ca href=\"#array.unshift\"\u003e**unshift**(object)\u003c/a\u003e\n- observable.\u003ca href=\"#array.slice\"\u003e**slice**(\\\u003cindex\\\u003e, \\\u003ccount\\\u003e)\u003c/a\u003e\n- observable.\u003ca href=\"#array.set\"\u003e**set**([object])\u003c/a\u003e\n- observable.\u003ca href=\"#array.sort\"\u003e**sort**(fn)\u003c/a\u003e\n- observable.\u003ca href=\"#array.reverse\"\u003e**reverse**()\u003c/a\u003e\n- observable.\u003ca href=\"#array.swap\"\u003e**swap**(idx_a, idx_b)\u003c/a\u003e\n- observable.\u003ca href=\"#array.map\"\u003e**map**(fn)\u003c/a\u003e\n- observable.\u003ca href=\"#array.filter\"\u003e**filter**(fn)\u003c/a\u003e\n- observable.\u003ca href=\"#array.indexOf\"\u003e**indexOf**(object)\u003c/a\u003e : \u003csmall\u003e_number_\u003c/small\u003e\n- observable.\u003ca href=\"#array.lastIndexOf\"\u003e**lastIndexOf**(object)\u003c/a\u003e : \u003csmall\u003e_number_\u003c/small\u003e\n- observable.\u003ca href=\"#array.includes\"\u003e**includes**(object)\u003c/a\u003e : \u003csmall\u003e_boolean_\u003c/small\u003e\n- observable.\u003ca href=\"#array.forEach\"\u003e**forEach**(fn)\u003c/a\u003e\n- observable.\u003ca href=\"#array.transaction\"\u003e**transaction**(fn)\u003c/a\u003e\n\n\u003ca name=\"options\"\u003e\u003c/a\u003e\n\n## Mikado Options\n\n\u003e Each Mikado instance, also named includes/partials can have their own options. Except inline partials always inherits the same options from its parent. For this reason you should prefer named includes over inlining in certain situations.\n\n\u003ctable\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eOption\u003c/td\u003e\n        \u003ctd\u003eDescription\u003c/td\u003e\n        \u003ctd\u003eDefault\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003cb\u003eroot\u003c/b\u003e\u003cbr\u003e\u003cb\u003emount\u003c/b\u003e\u003c/td\u003e\n        \u003ctd\u003eThe destination root element on where the template should be rendered.\u003c/td\u003e\n        \u003ctd\u003enull\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003cb\u003etemplate\u003c/b\u003e\u003c/td\u003e\n        \u003ctd\u003eYou will need to assign a template to the Mikado instance (or the name of the template when already registered/loaded).\u003c/td\u003e\n        \u003ctd\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003cb\u003easync\u003c/b\u003e\u003c/td\u003e\n        \u003ctd\u003ePerform the \u003ccode\u003e.render(data)\u003c/code\u003e task asynchronously and return a Promise.\u003c/td\u003e\n        \u003ctd\u003efalse\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003cb\u003ecache\u003c/b\u003e\u003c/td\u003e\n        \u003ctd\u003eEnable/disable \u003ca href=\"#cache\"\u003eDOM state caching\u003c/a\u003e which can greatly increase performance by a factor up to 25. When enabled make sure to use the \u003ca href=\"#cache\"\u003eDOM Cache Helpers\u003c/a\u003e when manipulating the DOM directly on properties which are also covered by template expressions.\u003c/td\u003e\n        \u003ctd\u003efalse\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003cb\u003eobserve\u003c/b\u003e\u003c/td\u003e\n        \u003ctd\u003eWhen using \u003ccode\u003eMikado.Array()\u003c/code\u003e for reactive approach you will need to pass this array instance to this property.\u003c/td\u003e\n        \u003ctd\u003enull\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003cb\u003erecycle\u003c/b\u003e\u003c/td\u003e\n        \u003ctd\u003eWhen enabled all dom elements which are already rendered will be re-used (recycled) for the next render task. This performs better, but it may produce issues when manual dom manipulations was made which are not fully covered by the template. Alternatively use the \u003ccode\u003ekeyed\u003c/code\u003e strategy, which limits recycling of components by matching the same data key (e.g. ID).\u003c/td\u003e\n        \u003ctd\u003efalse\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003cb\u003estate\u003c/b\u003e\u003c/td\u003e\n        \u003ctd\u003ePass an extern object which should be referenced as the \u003ccode\u003estate\u003c/code\u003e used within template expressions.\u003c/td\u003e\n        \u003ctd\u003e{ }\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003cb\u003epool\u003c/b\u003e\u003c/td\u003e\n        \u003ctd\u003ePooling can greatly enhance both the keyed and non-keyed recycle strategy.\u003c/td\u003e\n        \u003ctd\u003efalse\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003cb\u003ehydrate\u003c/b\u003e\u003c/td\u003e\n        \u003ctd\u003eProgressively enables hydration of already existing DOM structures when mounted. Make sure the existing DOM structure is based on the same template. When something differs from the given template schema, the hydration will stop and silently falls back into the default build strategy.\u003c/td\u003e\n        \u003ctd\u003efalse\u003c/td\u003e\n    \u003c/tr\u003e\n\u003c/table\u003e\n\n\u003ca name=\"get-started\"\u003e\u003c/a\u003e\n\n## Getting Started (Basic Example)\n\nThe Mikado Compiler requires Node.js to be installed. This is probably the simplest step in this guide.\n\nInstall Mikado from NPM (this will also install the compiler):\n\n```npm\nnpm install mikado\n```\n\nAssume there is an array of data items to render (or just one item as an object):\n\n```js\nconst data = [{\n    username: \"User A\",\n    tweets: [\"foo\", \"bar\", \"foobar\"]\n},{\n    username: \"User B\",\n    tweets: [\"foo\", \"bar\", \"foobar\"]\n},{\n    username: \"User C\",\n    tweets: [\"foo\", \"bar\", \"foobar\"]\n}];\n```\n\nAccordingly, a template **_tpl/partial/user.html_** might look like:\n\n```html\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eUser:\u003c/td\u003e\n    \u003ctd\u003e{{ data.username }}\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eTweets:\u003c/td\u003e\n    \u003ctd\u003e{{ data.tweets.length }}\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n```\n\n### Compile the template:\n\nIn your console type this command line:\n\n```cmd\nnpx mikado-compile ./tpl/\n```\n\n### Load library and initialize template as ES6 modules:\n\n```html\n\u003cscript type=\"module\"\u003e\n    import Mikado from \"mikado.bundle.module.min.js\";\n    import template from \"tpl/partial/user.js\";\n    const view = new Mikado(template, {/* options */});\n\u003c/script\u003e\n```\n\n### Load library and initialize template as legacy ES5:\n\n```html\n\u003cscript src=\"mikado.bundle.min.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"tpl/partial/user.es5.js\"\u003e\u003c/script\u003e\n\u003cscript\u003e\n    var view = new Mikado(\"user/list\", {/* options */});\n\u003c/script\u003e\n```\n\n\u003e The name of a template inherits from its corresponding filename starting by the folder you've passed through the `--src` flag when calling the compiler.\n\nAfter creation, you need mount the Mikado view instance to an HTML element as a destination for your render tasks:\n\n```js\nview.mount(HTMLelement);\nview.render(data);\n```\n\nYou can also chain methods:\n\n```js\nMikado(template).mount(HTMLelement).render(data);\n```\n\n\u003ca name=\"conventions\"\u003e\u003c/a\u003e\n\n## Rules and Conventions\n\nThere is just a single convention you always need to keep in mind:\n\n\u003e **Every template has to provide one single root element as the outer boundary.**\n\nInstead of doing this in a template:\n\n```html\n\u003cheader\u003e\n  \u003cnav\u003e\u003c/nav\u003e\n\u003c/header\u003e\n\u003csection\u003e\n  \u003cp\u003e\u003c/p\u003e\n\u003c/section\u003e\n\u003cfooter\u003e\n  \u003cnav\u003e\u003c/nav\u003e\n\u003c/footer\u003e\n```\n\nWrapping everything into a single outer root element by doing this:\n\n```html\n\u003cmain\u003e\n  \u003cheader\u003e\n    \u003cnav\u003e\u003c/nav\u003e\n  \u003c/header\u003e\n  \u003csection\u003e\n    \u003cp\u003e\u003c/p\u003e\n  \u003c/section\u003e\n  \u003cfooter\u003e\n    \u003cnav\u003e\u003c/nav\u003e\n  \u003c/footer\u003e\n\u003c/main\u003e\n```\n\nYou can also use a `\u003cdiv\u003e` or any other element as a template root (also custom elements). The root element can also hold two special attributes `key` and `cache`. We will come later to it.\n\n\u003ca name=\"advanced_example\"\u003e\u003c/a\u003e\n\n## Advanced Example\n\nA bit more complex template:\n\n```html\n\u003csection id=\"{{ data.id }}\" class=\"{{ this.state.theme }}\" data-index=\"{{ index }}\"\u003e\n  {{@ var is_today = data.date === state.today }}\n  \u003cdiv class=\"{{ data.class }} {{ is_today ? 'on' : 'off' }}\"\u003e\n    \u003cdiv class=\"title\" style=\"font-size: 2em\"\u003e{{ data.title.toUpperCase() }}\u003c/div\u003e\n    \u003cdiv class=\"content {{ index % 2 ? 'odd' : 'even' }}\"\u003e{{# data.content }}\u003c/div\u003e\n    \u003cdiv class=\"footer\"\u003e{{ state.parseFooter(data) }}\u003c/div\u003e\n  \u003c/div\u003e\n\u003c/section\u003e\n```\n\nYou can use \u003cu\u003eany\u003c/u\u003e Javascript within the {{ ... }} curly bracket notation. The scope is limited by the template, so variables from one template can't be accessed within another template (use `state` for this purpose).\n\n\u003e To pass HTML markup as a string, the curly brackets needs to be followed by **#** e.g. `{{# ... }}`. For better performance, relevant tasks avoid passing HTML contents as a string.\n\n\u003e To use Javascript outside an element's context you need to prevent concatenation of the returned value. For this purpose, the curly brackets need to be followed by **@** e.g. `{{@ ... }}`.\n\n\u003ca name=\"identifier\"\u003e\u003c/a\u003e\n\nWithin a template there are several **reserved keywords** you can use as an identifier:\n\n\u003ctable\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eIdentifier\u003c/td\u003e\n        \u003ctd\u003eDescription\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003cb\u003edata\u003c/b\u003e\u003c/td\u003e\n        \u003ctd\u003eA full reference to the passed data item. Within loops the keyword data points to each of the looped data items.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003cb\u003estate\u003c/b\u003e\u003c/td\u003e\n        \u003ctd\u003eAn optional payload used to manually pass in custom specific values or helper functions. The state will be delegated through all nested templates.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003cb\u003eindex\u003c/b\u003e\u003c/td\u003e\n        \u003ctd\u003eRepresents the index of the currently rendered data item (starting by 0 for the first item).\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003c!--\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003cb\u003eself\u003c/b\u003e\u003c/td\u003e\n        \u003ctd\u003ePoints to the current rendered element itself. Using \"js\" node property or by using the {{@ marker grants you to have \"self\" available.\u003c/td\u003e\n    \u003c/tr\u003e\n    --\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003cb\u003ethis\u003c/b\u003e\u003c/td\u003e\n        \u003ctd\u003eProvides you access to the Mikado view instance (e.g. this.state).\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003cb\u003ewindow\u003c/b\u003e\u003c/td\u003e\n        \u003ctd\u003eGives access to the global namespace.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e_p\u003cbr\u003e_v\u003cbr\u003e_x\u003cbr\u003e_o\u003cbr\u003e_f\u003cbr\u003e_inc\u003c/td\u003e\n        \u003ctd\u003eprivate identifiers, used by internal processing\u003c/td\u003e\n    \u003c/tr\u003e\n\u003c/table\u003e\n\nYou cannot change the names of those preserved keywords, also make sure you didn't override them.\n\nIt is recommended to pass custom functions via the _state_ object (see example above `state.parseFooter = function(str){ return str; }`). Alternatively you can also nest more complex computations inline as an IIFE and return the result.\n\n```html\n\u003cdiv class=\"date\"\u003e{{ \n    (function(){ \n        var date = new Date();\n        // perform some code ...\n        return date.toLocaleString();\n    }())\n}}\u003c/div\u003e\n```\n\nTo finish the example from above you need one single data object or an array of **_data_** items:\n\n```js\nvar data = [{\n    \"id\": \"230BA161-675A-2288-3B15-C343DB3A1DFC\",\n    \"date\": \"2019-01-11\",\n    \"class\": \"yellow, green\",\n    \"title\": \"Sed congue, egestas lacinia.\",\n    \"content\": \"\u003cp\u003eVivamus non lorem \u003cb\u003evitae\u003c/b\u003e odio sagittis amet ante.\u003c/p\u003e\",\n    \"footer\": \"Pellentesque tincidunt tempus vehicula.\"\n}];\n```\n\nProvide the optional **_state_** payload which includes specific values and helper methods used within template expressions:\n\n```js\nconst state = {\n  today: \"2019-01-11\",\n  theme: \"custom\",\n  parseFooter: function(data) {\n    return data.footer;\n  }\n};\n```\n\nMount the view to a target element as a destination for all the render tasks:\n\n```js\nview.mount(HTMLelement);\n```\n\nRender a mounted template:\n\n```js\nview.render(data, state);\n```\n\nRender asynchronously automatically by just providing a callback function:\n\n```js\nview.render(data, state, function() {\n  console.log(\"finished.\");\n});\n```\n\nTo render asynchronously by using promises you need to set the callback value to `true`:\n\n```js\n// callback \"true\" will use Promises\nview.render(data, state, true).then(function() {\n    console.log(\"finished.\");\n});\n\n// same, but uses async/await:\nawait view.render(data, state, true);\nconsole.log(\"finished.\");\n```\n\nWhen async should be the default strategy for all render tasks then you can also set the **_async_** option flag:\n\n```js\nconst view = new Mikado(template, { async: true });\nawait view.render(data, state);\nconsole.log(\"finished.\");\n```\n\n\u003ca name=\"compiler\"\u003e\u003c/a\u003e\n\n## Compile Templates\n\n\u003ca name=\"compiler\"\u003e\u003c/a\u003e\n\nDefine an HTML-like template and use double curly brackets to markup dynamic expressions which should be calculated and replaced during runtime:\n\n```html\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eUser:\u003c/td\u003e\n    \u003ctd\u003e{{ data.username }}\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eTweets:\u003c/td\u003e\n    \u003ctd\u003e{{ data.tweets.length }}\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n```\n\nSave this template e.g. to _tpl/partial/user.html_\n\n\u003e The preserved keyword **_data_** is a reference to the passed data item. You can access the whole nested object.\n\nMikado comes with a builtin template compiler you can simply access by typing `npx mikado-compile` into your console. The compiler uses a very simple command-line interface (CLI) running on Node.js to perform compilation tasks. The template compiles into a native javascript file which needs to be passed during creation of a Mikado instance. The same markup is also used for the server-side rendering part, so you can share the same template sources for client and server rendering.\n\nShow help to list all available commands:\n\n```cmd\nnpx mikado-compile --help\n```\n\nCompile the template through the command line by:\n\n```cmd\nnpx mikado-compile tpl/partial/user.html\n```\n\n**Basic Notation:**\n\u003e npx mikado-compile _source \\\u003cdestination\\\u003e_\n\n\u003c!--\nInstead of `npx mikado compile` you can also use `npx mikado-compile` alternatively. When a destination was not set, the input folder will be used instead.\n--\u003e\n\nWhen no destination folder was set, the compiled files will be saved to the source folder. After compilation, you will have 3 different files:\n\n1. **list.js** the template compiled as a ES6 module (which needs to be imported)\n2. **list.es5.js** the template compiled as ES5 compatible Javascript (which automatically register when loaded by script tag)\n3. **list.html** the source template you have implemented (do not delete it)\n\n**Extended Notation:**\n\u003e npx mikado-compile --src _{ source }_ --dest _{ destination }_ --extension html --type module  --compact\n\n\u003ca name=\"compiler-flags\"\u003e\u003c/a\u003e\nCompiler Flags:\n\n- `--type module`, `-t module` export as javascript modules (recommended)\n- `--type es5`, `-t es5` export as ES5-compatible package\n- `--extension html`, `--ext html`, `-e html` the file extension which should be compiled\n- `--inline`, `-i` or `--compact`, `-c` switch the build strategy to optimize either the performance (inline) or size (compact)\n- `--force`, `-f` force overwriting existing files\n- `--pretty`, `-p` do not minify the compiled result\n- `--watch`, `-w` start the watcher for automatically compile when files has changed (just for development purposes)\n\nSupported flags as attributes on the template root:\n\n```html\n\u003c!-- switch the build strategy to prebuilt enabled cache --\u003e\n\u003ctable cache=\"true\"\u003e\u003c/table\u003e\n```\n```html\n\u003c!-- switch the build strategy to prebuilt disabled cache --\u003e\n\u003ctable cache=\"false\"\u003e\u003c/table\u003e\n```\n\nUsing the flag attributes are the most performant variants but also cost you some flexibility, because the cache strategy couldn't be changed in runtime, it needs to change in markup before compilation.\n\n\u003ca name=\"auto-naming\"\u003e\u003c/a\u003e\n\n### Auto Naming\n\nThere is a new naming system which will apply by default. The name of your html files will be used as unique identifiers of your templates.\nBecause several folders can include same filenames, the template name inherits from the full path you pass in as `--src`.\n\nAssuming the following file structure:\n```\ntpl/view/start.html\ntpl/view/user.html\ntpl/view/cart.html\ntpl/partial/start.html\ntpl/partial/user.html\ntpl/partial/cart.html\n```\n\nThe command should define the path `/tpl/` as the source root because it is the most inner folder which covers all files:\n```cmd\nnpx mikado-compile ./tpl/\n```\n\nThe template names then becomes `view/start`, `view/user`, `view/cart` and `partial/start`, `partial/user`, `partial/cart` for the partials. So when including just use this name in your expression `\u003ctable include=\"partial/user\"\u003e`\n\nThe wrong way is to compile the folder /view/ and /partial/ separately, because their template names will be same.\n```cmd\nnpx mikado-compile ./tpl/view/\nnpx mikado-compile ./tpl/partial/\n```\nThis might also work, but it is better not to do.\n\n\u003ca name=\"prebuilt-cache\"\u003e\u003c/a\u003e\n\n### Prebuilt Cache Strategy\n\nThe option `{ cache: true/false }` when creating a Mikado instance could be better declared withing templates on their root element, let the compiler produce more optimized code for this strategy.\n\n```html\n\u003ctable cache=\"true\"\u003e\n    \u003c!-- ... --\u003e\n\u003c/table\u003e\n```\n\nAlso use this approach when set `cache=\"false\"`:\n\n```html\n\u003ctable cache=\"false\"\u003e\n    \u003c!-- ... --\u003e\n\u003c/table\u003e\n```\n\n\u003ca name=\"watcher\"\u003e\u003c/a\u003e\n\n### Watcher (Auto-Compile)\n\nA perfect fit for your local development environment is spawning a watcher to automatically compile files when they get changed. Just use the same command line you would also use for a full compilation and append the flag `--watch` or `-w` to it:\n\n```cmd\nnpx mikado-compile ./tpl/ --watch\n```\n\nDon't close the console, otherwise the watcher will stop. You can stop the watcher explicitly by pressing `CTRL + C`.\n\n\u003ca name=\"expressions\"\u003e\u003c/a\u003e\n\n## Template Expressions\n\n\u003e The template notation expects double curly brackets `{{ ... }}` for any kind of dynamic expressions.\n\n\u003e Except when using {{@ ... }} for inline code notation, the returned value of every dynamic expression will be replaced to its position.\n\n\u003ca name=\"insertion\"\u003e\u003c/a\u003e\n\n### Value Insertion `{{ ... }}`\n\n```html\n\u003cdiv\u003e{{ data.value }}\u003c/div\u003e\n```\n\n```js\nview.render({ value: \"test\" });\n```\n\nYou can also combine multiple expressions with non-expression contents:\n\n```html\n\u003cdiv\u003eThe title \"{{ data.title }}\" has the value: {{ data.value }}\u003c/div\u003e\n```\n\n```js\nview.render({ title: \"title\", value: \"test\" });\n```\n\nYou can also mix text nodes with elements on the same root element:\n\n```html\n\u003cdiv\u003eTitle: \u003cb\u003e{{ data.title }}\u003c/b\u003e\u003cbr\u003eValue: {{ data.value }}\u003c/div\u003e\n```\n\n```js\nview.render({ title: \"title\", value: \"test\" });\n```\n\nAlso, you can use expressions within every attribute:\n\n```html\n\u003cdiv data-id=\"{{ data.title }}\" class=\"{{ data.class }}\"\u003e{{ data.value }}\u003c/div\u003e\n```\n```js\nview.render({ id: 1, value: \"test\", class: \"test\" });\n```\n\nEvery Javascript syntax is allowed withing expression:\n\n```html\n\u003cdiv style=\"color: {{ data.active ? 'green' : 'black' }}; {{ data.value ? '' : 'display: none;' }}\"\u003e\u003c/div\u003e\n```\n```js\nview.render({ active: true, value: \"not empty\" });\n```\n\nSince expressions just need to return a value you can also use IIFE:\n\n```html\n\u003cdiv\u003e{{ \n    (function(){ \n        var date = new Date();\n        // perform some code ...\n        return date.toLocaleString();\n    }())\n}}\u003c/div\u003e\n```\n```js\nview.render();\n```\n\n\u003ca name=\"inline-js\"\u003e\u003c/a\u003e\n\n### JS Inline Code `{{@ ... }}`\n\nThe inline code expression is the only one which doesn't return a value to be rendered in place, it just executes.\n\n```html\n\u003cdiv\u003e\n    {{@ const value = data.title.toUpperCase(); }}\n    \u003ch1\u003e{{ value }}\u003c/h1\u003e\n\u003c/div\u003e\n```\n```js\nview.render({ title: \"title\" });\n```\n\nThe scope is limited to the template scope, but you can assign to `state` alternatively to share values across nested instances:\n\n```html\n\u003cdiv\u003e\n    {{@ state.value = data.title.toUpperCase(); }}\n    \u003cdiv include=\"header\"\u003e\n        \u003c!-- contents of header.html:\n        \u003ch1\u003e{{ state.value }}\u003c/h1\u003e\n        --\u003e\n    \u003c/div\u003e\n\u003c/div\u003e\n```\n```js\nview.render({ title: \"title\" });\n```\n\n\u003ca name=\"truthy\"\u003e\u003c/a\u003e\n\n### Truthy Values `{{? ... }}`\n\nThis will just output the result when it is not `null`, `undefined`, `NaN` or `false`.\n\n```html\n\u003cdiv\u003e{{? data.value }}\u003c/div\u003e\n```\n```js\nview.render([{\n    value: null\n},{\n    value: NaN\n},{\n    value: undefined\n},{\n    value: false\n}]);\n```\n\n\u003ca name=\"escape-ssr\"\u003e\u003c/a\u003e\n\n### Escape Values `{{! ... }}` (SSR only)\n\nThis will escape the value before return. This is just important for the server-side-rendering part, the client automatically escape contents by default (except when using the HTML-expression).\n\n```html\n\u003cdiv\u003e{{! data.value }}\u003c/div\u003e\n```\n```js\nview.render({ value: \"\u003cb\u003ehtml is not allowed\u003c/b\u003e\" });\n```\n\n\u003ca name=\"html\"\u003e\u003c/a\u003e\n\n### HTML Contents `{{# ... }}`\n\nThis will allow for inserting HTML returned string.\n\n\u003e Be aware of this can potentially lead into security issues like XSS. Use carefully!\n\n```html\n\u003cdiv\u003e{{# data.value }}\u003c/div\u003e\n```\n```js\nview.render({ value: \"\u003cb\u003ehtml is allowed\u003c/b\u003e\" });\n```\n\n\u003ca name=\"mikado.escape\"\u003e\u003c/a\u003e\u003ca name=\"mikado.sanitize\"\u003e\u003c/a\u003e\n\n#### Sanitizer\n\nMikado provides you high performant helper function you can use in this context to escape contents or to sanitize.\n\n```js\nview.render({ \n    value: \"\u003cb\u003ehtml allowed\u003c/b\u003e\u003cbr\u003e\" + Mikado.escape(\"\u003cb\u003enot allowed\u003c/b\u003e\")\n});\n```\n\n```js\nview.render({ \n    value: \"\u003cb\u003ehtml allowed\u003c/b\u003e\u003cbr\u003e\" + Mikado.sanitize(\"\u003cb\u003enot allowed\u003c/b\u003e\")\n});\n```\n\nUsing the sanitizer will remove the tags completely, whereas when escaping the content aren't removed but just escaped.\n\n\u003ca name=\"bindings\"\u003e\u003c/a\u003e\n\n### Reactive Bindings `{{= ... }}`\n\nDefine properties by using pure data object notation without any javascript inside:\n\n```html\n\u003cdiv class=\"{{= data.class }}\"\u003e{{= data.value }}\u003c/div\u003e\n```\n```js\n// store must be an array of elements:\nconst store = [{ class: \"active\", value: \"foo\" }];\n// it needs a initial render if store isn't empty:\nview.render(store);\n// the store array now was proxified!\n```\n\nNow you can change the properties of `store` and the corresponding DOM elements will change automatically:\n\n```js\nstore[0].class = \"inactive\";\nstore[0].value = \"bar\";\n```\n\n\u003ca name=\"runtime-compiler\"\u003e\u003c/a\u003e\n\n## Runtime Compiler\n\nAlternatively of using the `npx mikado-compile` you can also compile templates during runtime.\n\n\u003e If a page has set a `Content-Security-Policy` (CSP) header field, using the runtime compiler has disadvantage when not configure `script-src 'unsafe-eval'`. It is recommended to use the Mikado native compiler, which is CSP-friendly and also can optimize your templates more powerful.\n\nThe runtime compiler uses the performance optimized `inline` strategy for every task, you can't switch it. The compiler property flag `cache=\"true\"` or `cache=\"false\"` on a template root is not supported, therefore you can't use 2 of the most performant strategies. But they are just slightly faster, so this shouldn't be an issue.\n\nThose features aren't supported by the runtime compiler:\n\n- `cache=\"true\"` or `cache=\"false\"` on a template root\n- using any other compiler strategy than `inline`\n- detect and replace repeating inline includes\n- detect and solve/unroll non-dynamic expressions, e.g. ``\u003ch1\u003e{{ \"foor\" + \"bar \" }}\u003c/h1\u003e`` will transform to a static content `\u003ch1\u003efoobar\u003c/h1\u003e` and removes the expression completely\n- runtime-ready templates aren't available on page load (they need to compile)\n- the runtime compiler does not pass the \u003ca href=\"https://github.com/nextapps-de/mikado/blob/master/test/tpl/crazy.html\"\u003e\"crazy template\"\u003c/a\u003e test\n\n#### Examples\n\nDefine some HTML template structure:\n\n```html\n\u003ctemplate id=\"user-list\"\u003e\n  \u003c!-- just a single outer root element allowed: --\u003e \n  \u003ctable\u003e\n    \u003ctr\u003e\n      \u003ctd\u003eUser:\u003c/td\u003e\n      \u003ctd\u003e{{ data.user }}\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd\u003eTweets:\u003c/td\u003e\n      \u003ctd\u003e{{ data.tweets.length }}\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/table\u003e\n\u003c/template\u003e\n```\n\n\u003e Template definitions used by the runtime compiler needs manual naming when used as named includes.\n\nThe template name will derive from `\u003ctemplate id=\"user-list\"\u003e` or `\u003ctemplate name=\"user-list\"\u003e` and becomes `user-list`. \nWhen using named includes you will need to use this name for referencing, e.g. `\u003cdiv include=\"user-list\"\u003e\"`.\n\nCompile the template and use it for creating a Mikado view instance:\n\n```js\nconst template = document.getElementById(\"user-list\");\nconst tpl = Mikado.compile(template);\nconst view = new Mikado(tpl, { /* options */ });\n\nview.render(data);\n```\n\nWhen the template was get through element ID you can use a shortcut:\n\n```js\nconst tpl = Mikado.compile(\"user-list\");\n```\n\nAlso, you can compile the template and use it for registration as a named include referenced by another template e.g. `\u003cdiv include=\"user-list\"\u003e\"`:\n\n```js\nMikado.register(Mikado.compile(\"user-list\"));\n```\n\nYou can use non-template elements for defining templates also:\n\n```css\n#user-list{ display: none }\n```\n\n```html\n\u003c!-- just a single outer root element allowed: --\u003e \n\u003ctable id=\"user-list\"\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eUser:\u003c/td\u003e\n    \u003ctd\u003e{{ data.user }}\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eTweets:\u003c/td\u003e\n    \u003ctd\u003e{{ data.tweets.length }}\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n```\n\nLast but not least you can pass the template markup as a string:\n\n```js\nconst tpl_str = `\n\u003ctable name=\"user-list\"\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eUser:\u003c/td\u003e\n    \u003ctd\u003e{{ data.user }}\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eTweets:\u003c/td\u003e\n    \u003ctd\u003e{{ data.tweets.length }}\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e`;\n\nconst tpl = Mikado.compile(tpl_str);\nconst view = new Mikado(tpl, { /* options */ });\n\nview.render(data);\n```\n\n### Using Inline Code\n\nThe runtime compiler does not support all places of inserting inline code expressions. In some situations it might produce issues like here:\n\n```html\n\u003ctable id=\"user-list\"\u003e\n  \u003ctbody foreach=\"data.entries\"\u003e\n  {{@\n    /* the browser will move this before \u003ctable\u003e! */ \n    const value = \"test\";\n  }}\n  \u003ctr\u003e\n    \u003ctd\u003eValue: {{ value }}\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n```\n\nThe runtime compiler didn't parse the template by string, instead the compiler creates a dom structure when passing a template as string.\nOn the example above the `{{@ ... }}` expression is treated as a text node by the browser.\nSince the position isn't allowed to place text nodes (after `\u003ctable\u003e`, `\u003ctbody\u003e`, `\u003ctr\u003e`) the browser moves this text node up to the outer scope of the table. But the inline code is now executed within the first outer template function, instead the inline loop template function needs the value and is running in its own scope.\n\nIn this situation you can store values on `state` to pass through inline looped partials.\nOr you can use the `\u003cscript\u003e` tag in combination with the js-expression. The latter will keep the hierarchy, because those tags won't move outside by the browser:\n\n```html\n\u003ctable id=\"user-list\"\u003e\n  \u003ctbody foreach=\"data.entries\"\u003e\n    \u003cscript\u003e{{@ const value = \"test\"; }}\u003c/script\u003e\n    \u003ctr\u003e\n      \u003ctd\u003eValue: {{ value }}\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n```\n\n\u003e Don't forget to use the expression notation, otherwise it will be inserted as a normal code element.\n\n\u003e When the `\u003cscript\u003e` just including js-inline code expression it won't be added to the template as a script element.\n\n\u003ca name=\"event\"\u003e\u003c/a\u003e\n\n## Routing \u0026 Event Delegation\n\n\u003e All the special attributes used to assign event routing within templates are inherited from the native inline listener name but without the prefix `on`, e.g. to bind routing for an \"onclick\" just use `click`.\n\nLet's take this example:\n\n```html\n\u003ctable foreach=\"data\" data-user=\"{{ data.user }}\"\u003e\n  \u003ctr data-id=\"{{ data.id }}\" entry\u003e\n    \u003ctd\u003eItem:\u003c/td\u003e\n    \u003ctd click=\"item-show\"\u003e{{ data.name }}\u003c/td\u003e\n    \u003ctd\u003e\u003ca click=\"item-edit:entry\"\u003eEdit\u003c/a\u003e\u003c/td\u003e\n    \u003ctd\u003e\u003ca click=\"item-delete:entry\"\u003eDelete\u003c/a\u003e\u003c/td\u003e\n    \u003ctd\u003e\u003ca click=\"item-sort:root\"\u003eSort\u003c/a\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n```\n\nThere are 4 click listeners. The attribute value represents the name of the route.\nSome of the listener has a route separated by colon \":\", this will delegate the event from the route e.g. \"item-delete\" to the closest element which contains the attribute \"entry\".\nYou can freely choose attribute names, but it shouldn't collide with native attributes.\nThe last listener contains the keyword `root` which is a shortcut to automatically forward the components root (the \u0026lt;table\u003e in this example) as `target` to the assigned route.\n\n\u003e Forwarding events to a parent element by using the colon notation is also helpful when you have corresponding data-attributes assigned to an outer context and each of the nested listener needs to access those values.\n\nDefine routes:\n\n```js\nview.route(\"show-user\", function(target, event) {\n    alert(target.textContent);\n});\n\nview.route(\"delete-user\", function(target, event) {\n    // target was delegated to \"root\" by using the colon expression\n    alert(target.dataset.id); \n    // when target is delegated you can still get the\n    // original element where the event was fired:\n    const anchor = event.target;\n});\n```\n\nRoutes are stored globally, so they share through all Mikado instances.\n\n\u003cb\u003eList of all supported events:\u003c/b\u003e\n\n- tap (synthetic touch-enabled \"click\" listener, see below)\n- change, input, select, toggle\n- click, dblclick\n- keydown, keyup, keypress\n- mousedown, mouseenter, mouseleave, mousemove, mouseout, mouseover, mouseup, mousewheel\n- touchstart, touchmove, touchend\n- submit, reset\n- focus, blur\n- load, error\n- resize\n- scroll\n\n\u003cb\u003eSynthetic events:\u003c/b\u003e\n\n\u003ctable\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eEvent\u003c/td\u003e\n        \u003ctd\u003eDescription\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003cb\u003etap\u003c/b\u003e\u003c/td\u003e\n        \u003ctd\u003eThe tap event is a synthetic click event for touch-enabled devices. It also fully prevents the 300ms click delay. The tap event automatically falls back to a native click listener when running on non-touchable device.\u003c/td\u003e\n    \u003c/tr\u003e\n\u003c/table\u003e\n\n\u003ca name=\"bubbling\"\u003e\u003c/a\u003e\n\n### Event Bubbling\n\nWhen multiple listeners of the same type are nested, the event will bubble up to the HTML root element when enabling the global flag `Mikado.eventBubble = true`, otherwise bubbling will stop on the most inner definition which gets matched.\n\n```html\n\u003ctable\u003e\n    \u003ctr click=\"route-tr\"\u003e\n        \u003ctd click=\"route-td\"\u003e\u003c/td\u003e\n        \u003ctd\u003e\u003c/td\u003e\n        \u003ctd\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n\u003c/table\u003e\n```\n\n```js\nMikado.route(\"route-td\", function(target, event){\n    console.log(\"clicked td\");\n});\n\nMikado.route(\"route-tr\", function(target, event){\n    console.log(\"clicked tr\");\n});\n```\n\nBy default, the above example will just execute the route named \"route-td\" when clicked on the TD element. When `Mikado.eventBubble = true` was enabled the bubble continues after calling the most inner matched handler and both routes will be executed when clicking on TD element.\n\nTo control Mikados internal event bubbling mechanism you can pass in options as the 3rd parameter when defining routes:\n\n```js\nMikado.route(\"route-td\", function(){ /*...*/ }, { stop: true });\n```\n\nSupported Options (mixable):\n\n- `stop: boolean` stop capturing/bubbling the event up to the root element (stops Mikado event + native event)\n- `prevent: boolean` prevents the default behavior for this native event\n- `cancel: boolean` just stop bubbling the Mikado event, but the native event bubbling will still continue\n- `once: boolean` just catch the event once and remove the route then\n\n\u003ca name=\"event-cache\"\u003e\u003c/a\u003e\n\n#### Event Cache\n\nYou can cache more complex event delegations by setting the global flag `Mikado.eventCache = true`.\nA candidate for a complex delegation is forwarding a different target to the handler by using the \":\" colon notation or when using `Mikado.eventBubble = true`.\n\n\u003e When using Event Cache the scope of forwarding custom target elements to the handler and also nested routes of the same event type should be defined in the same template scope. Thinks may break when components are shared through multiple instances.\n\nThis is okay, because all partials are inline:\n\n```html\n\u003ctable foreach=\"data.result\"\u003e\n    \u003c!-- a new template scope --\u003e\n    \u003ctr foreach=\"data.user\" click=\"route-tr:root\"\u003e\n        \u003c!-- a new template scope --\u003e\n        \u003ctd click=\"route-td:root\"\u003e{{ data.username }}\u003c/td\u003e\n    \u003c/tr\u003e\n\u003c/table\u003e\n```\n\nWhen using extern includes it might produce unexpected behavior:\n\ntpl.html:\n```html\n\u003ctable foreach=\"data.result\" entry\u003e\n    \u003c!-- a new template scope --\u003e\n    \u003ctr foreach=\"data.user\" include=\"tpl-td\"\u003e\n        \u003c!-- a new template scope --\u003e\n    \u003c/tr\u003e\n\u003c/table\u003e\n```\n\ntpl-td.html:\n```html\n\u003ctd click=\"route-td:entry\"\u003e{{ data.username }}\u003c/td\u003e\n```\n\nThis will have no side effects when the partial \"tpl-td.html\" is just use for the template \"tpl.html\".\nBut imagine you have another template which includes \"tpl-td.html\" and **also** one of the recycle strategies (keyed, non-keyed) was enabled on both.\nIn this specific situation the cache might point to a false element `\u003ctable entry\u003e` used to forward to the handler.\nThen you need to choose between: 1. limiting the scope of used event notation to the template scope, 2. do not enable `Mikado.eventCache = true`. \n\n\u003ca name=\"view.listen\"\u003e\u003c/a\u003e\u003ca name=\"view.unlisten\"\u003e\u003c/a\u003e\n\n#### Explicit Register/Unregister Event Delegation\n\nYou can use Mikado routing and event delegation feature everywhere, also outside a template. Just apply the event attribute as you would do in a template.\n\n```html\n\u003cbody\u003e\n  \u003cdiv click=\"handler\"\u003eClick Me\u003c/div\u003e\n\u003c/body\u003e\n```\n\n```js\nMikado.route(\"handler\", function(target, event) {\n  console.log(\"Clicked\");\n});\n```\n\nThen you have to explicit register the global \"click\" listener once:\n\n```js\nMikado.listen(\"click\");\n```\n\nBecause events automatically register when creating the template factory under the hood. When no template was created which includes the same type of event, a global listener does not exist. For that reason, you have to explicitly register the listener once.\n\n\u003ca name=\"event-control\"\u003e\u003c/a\u003e\n\n#### Control the Native Event Flow\n\nThe default \"EventListenerOptions\" are set to `true` by default and is using the capturing phase, this is preferred since the event is required on a global listener.\n\nWhen you need to configure event capturing and passive listener globally just register the specific listener manually before creating any Mikado instance which is including references to this specific event type:\n\n```js\nMikado.listen(\"touchmove\", {\n    passive: true,\n    capture: true \n});\n```\n\nUnregister listener:\n\n```js\nMikado.unlisten(\"click\");\n```\n\n\u003e Mikado will store the original `EventListenerOptions` when calling `.listen(event)` under the hood, to make sure the listener will be removed properly.\n\n\u003ca name=\"view.dispatch\"\u003e\u003c/a\u003e\n\n#### Dispatch Routes\n\nManually dispatch a route:\n\n```js\nview.dispatch(\"route-name\");\n```\n\nManually dispatch a route and pass parameters for the assigned handler:\n\n```js\nview.dispatch(\"handler\", target, event);\n```\n\n\u003ca name=\"recycle\"\u003e\u003c/a\u003e\n\n## Keyed \u0026 Non-Keyed Recycling\n\n\u003e Each template instance can run in its own mode independently.\n\n\u003c!--\nCompare benchmark of all supported modes here:\u003cbr\u003e\nhttps://raw.githack.com/nextapps-de/mikado/bench/#modes\n--\u003e\n\n\u003ca name=\"non-keyed\"\u003e\u003c/a\u003e\n\n#### 1. Non-Keyed Recycle\n\nA non-keyed recycle strategy will re-use all existing components without any limitations and is faster than keyed but also has some side effects when not used properly. That's why limitation by keyed data is a more common strategy for recycling. But when an unlimited recycle strategy was used carefully you won't get any disadvantages.\n\nJust provide a template as usual:\n\n```html\n\u003cdiv\u003e\n  \u003cdiv\u003eUser:\u003c/div\u003e\n  \u003cdiv\u003e{{data.name}}\u003c/div\u003e\n\u003c/div\u003e\n```\n\nalong with these options:\n\n```js\nvar view = new Mikado(template, { recycle: true });\n```\n\nThis will switch Mikado into a recycle strategy to enable re-use of already rendered components.\n\n\u003ca name=\"keyed\"\u003e\u003c/a\u003e\n\n#### 2. Keyed Recycle\n\nA keyed strategy limits the recycle strategy on components matching the given data key. It just requires a **unique identifier** on each rendered item (e.g. the ID).\n\nJust add the attribute **_key_** to the **_root element_** of a template (or the root of an inline partial) and assign the scope to the unique identifier will automatically switch Mikado into keyed-recycle mode:\n\n```html\n\u003cdiv key=\"data.id\"\u003e\n  \u003cdiv\u003eUser:\u003c/div\u003e\n  \u003cdiv\u003e{{ data.name }}\u003c/div\u003e\n\u003c/div\u003e\n```\n\n\u003e A given key in template does not need the `recycle: true` option to be passed.\n\n```js\nvar view = Mikado(template);\n```\n\nThis will switch Mikado into a recycle strategy which is limited by its corresponding data keys.\n\n\u003ca name=\"usage\"\u003e\u003c/a\u003e\n\n## Create, Mount, Destroy Views\n\n\u003ca name=\"mikado.new\"\u003e\u003c/a\u003e\nCreate a view by passing a template and customized options:\n\n```js\nvar view = Mikado(template, options);\n```\n\nCreate a view and also mount it to a target element right away (you can also do this before render):\n\n```js\nvar view = Mikado(template, { \n    mount: HTMLElement\n});\n```\n\n\u003e Whenever `.mount()` is called for the first time, the template factory will be created once. Also, within this routine the hydration will apply when enabled. You can \"prebuild\" views by mounting early. Bigger sized applications does not hold all views in memory, so here it is recommended to mount the view right before render `view.mount(node).render(data)`.\n\n\u003ca name=\"view.mount\"\u003e\u003c/a\u003e\n\nMount or re-mount a view to an HTML element:\n\n```js\nview.mount(element);\n```\n\n\u003ca name=\"view.destroy\"\u003e\u003c/a\u003e\n\nDestroy a view:\n\n```js\nview.destroy();\n```\n\n\u003ca name=\"view.render\"\u003e\u003c/a\u003e\n\n## Render Templates\n\nRender just a single data object:\n\n```js\nview.render({/* object */});\n```\n\nRender a template repeated incrementally through a set of data items:\n\n```js\nview.render([/* array of objects */]);\n```\n\nRender a template and also pass a custom state:\n\n```js\nview.render(data, state);\n```\n\n\u003e When passing a custom state you can still access the original view state by using `this.state` within template expressions.\n\nSchedule an asynchronous render task without any callback:\n\n```js\nview.render(data, state, true);\n```\n\n\u003e All asynchronous render tasks will be scheduled to the next animation frame.\n\nSchedule an asynchronous render task by using a callback:\n\n```js\nview.render(data, state, function() {\n  // finished\n});\n```\n\nSchedule a render task by using promises (requires the option **_async_** to be enabled during initialization):\n\n```js\nview.render(data, state).then(function() {\n  // finished\n});\n```\n\nOr as async/await (requires the option **_async_** to be enabled during initialization):\n\n```js\nawait view.render(data, payload);\n// finished\n```\n\nRender a static template (didn't include any dynamic contents):\n\n```js\nview.render();\n```\n\n\u003ca name=\"view.create\"\u003e\u003c/a\u003e\n\n#### Create Components\n\nJust create a component from a template without adding/assigning/rendering them to the root (\"orphan\"):\n\n```js\nvar partial = view.create(data);\n```\n\nOrphans are not a part of the internal render tree of a view. The construction of orphan components is also really fast.\n\n\u003ca name=\"modify-views\"\u003e\u003c/a\u003e\n\n## Modify Views\n\n\u003ca name=\"view.add\"\u003e\u003c/a\u003e\n\nAdd one data item to the end:\n\n```js\nview.add(data);\n```\n\nAdd one data item to a specific index position (did not replace):\n\n```js\n// add to beginning:\nview.add(data, 0);\n```\n\nAdd one data item to a reversed index position (did not replace):\n\n```js\n// add before the last element:\nview.add(data, -1);\n```\n\n\u003ca name=\"view.append\"\u003e\u003c/a\u003e\n\nAppend multiple data items to the end:\n\n```js\nview.append(data);\n```\n\nAppend multiple data before an index:\n\n```js\n// append to beginning\nview.append(data, 0);\n```\n\nAppend multiple data before a reversed index position:\n\n```js\n// append before the last element:\nview.append(data, -1);\n```\n\n\u003ca name=\"view.remove\"\u003e\u003c/a\u003e\n\nRemove a specific template node:\n\n\u003e Parameter: `remove(position, \u003ccount\u003e)`\n\n```js\nview.remove(node);\n```\n\nRemove a specific template node by its index:\n\n```js\nview.remove(20);\n```\n\nRemove a specific template node by its reversed index:\n\n```js\n// remove the last:\nview.remove(-1);\n```\n\nRemove a range of nodes starting from a specific node or index (included in removal):\n\n```js\nview.remove(20, 10);\n```\n\n```js\nview.remove(node, 20);\n```\n\nRemove last 20 node items by using reversed index:\n\n```js\nview.remove(-20, 20);\n```\n\nRemove previous 20 node items starting of a given node/index (included in removal):\n\n```js\nview.remove(node, -20);\n```\n\n\u003ca name=\"view.clear\"\u003e\u003c/a\u003e\n\nRemove all:\n\n```js\nview.clear();\n```\n\n\u003ca name=\"view.replace\"\u003e\u003c/a\u003e\n\nReplace a data item/node:\n\n```js\nview.replace(node, data);\n```\n\n```js\nview.replace(index, data);\n```\n\n\u003ca name=\"view.update\"\u003e\u003c/a\u003e\n\nUpdate a single data item/node:\n\n```js\nview.update(node, data);\n```\n\n```js\nview.update(index, data);\n```\n\n\u003ca name=\"helpers\"\u003e\u003c/a\u003e\n\n#### Common View Helpers\n\n\u003ca name=\"view.node\"\u003e\u003c/a\u003e\n\nGet a components root element by a specific index:\n\n```js\nvar node = view.node(index);\n```\n\n\u003ca name=\"view.index\"\u003e\u003c/a\u003e\n\nGet the index from a specific components root element:\n\n```js\nvar index = view.index(node);\n```\n\n\u003ca name=\"view.length\"\u003e\u003c/a\u003e\n\nGet the length of all components currently rendered:\n\n```js\nvar length = view.length;\n```\n\n\u003ca name=\"view.name\"\u003e\u003c/a\u003e\n\nGet the current template name which is assigned to a Mikado instance:\n\n```js\nvar name = view.name;\n```\n\u003ca name=\"view.root\"\u003e\u003c/a\u003e\n\nGet the mounted root element on which the template is assigned to:\n\n```js\nvar element = view.root;\n```\n\n\u003ca name=\"manipulate\"\u003e\u003c/a\u003e\n\n## Manipulate Views\n\nMikado provides you several optional helper functions to manipulate the DOM and also keep them in sync with the internal view state. Using the helper functions also will gain performance.\n\n\u003e All helpers support passed parameter by index or by node.\n\nHelpers let you apply simple transformations without running through the whole render loop of the template. Reconciliation isn't the holy grail, it is just for your laziness. In certain situations it is just more efficient to apply a known transformation directly instead of altering the data and request a whole render task.\n\n\u003ca name=\"view.move\"\u003e\u003c/a\u003e\n\nMove a data item/node to a specific index position:\n\n```js\nview.move(node, 15); // 15 from start\nview.move(node, -15); // 15 from end\n```\n\n\u003ca name=\"view.first\"\u003e\u003c/a\u003e\u003ca name=\"view.last\"\u003e\u003c/a\u003e\n\nMove a data item/node to the top or bottom:\n\n```js\nview.first(node);\nview.last(node);\n```\n\n\u003ca name=\"view.up\"\u003e\u003c/a\u003e\u003ca name=\"view.down\"\u003e\u003c/a\u003e\n\nMove a data item/node by 1 index up or down:\n\n```js\nview.up(node);\nview.down(node);\n```\n\nMove a data item/node by a specific offset (pretty much the same as **_shift_**):\n\n```js\nview.up(node, 3);\nview.down(node, 3);\n```\n\n\u003ca name=\"view.shift\"\u003e\u003c/a\u003e\n\nShift a data item/node relatively by a specific offset (both directions):\n\n```js\nview.shift(node, 3);\nview.shift(node, -3);\n```\n\n\u003ca name=\"view.before\"\u003e\u003c/a\u003e\u003ca name=\"view.after\"\u003e\u003c/a\u003e\n\nMove a data item/node before or after another data item/node:\n\n```js\nview.before(node_a, node_b);\nview.after(node_a, node_b);\n```\n\n\u003ca name=\"view.swap\"\u003e\u003c/a\u003e\n\nSwap two data items/nodes:\n\n```js\nview.swap(node_a, node_b);\n```\n\n\u003ca name=\"cache\"\u003e\u003c/a\u003e\n\n## DOM State Caching\n\nCaching of DOM properties can greatly increase performance (up to 20x). There are just a few situations where caching will not improve performance, it fully depends on your application.\n\n\u003e **Recommendation:** enable caching when some of your data will stay unchanged from one to another render task. Disable caching when changes on data almost requires a fully re-render.\n\n\u003e The state cache will just apply when `recycle` was enabled or the `keyed` strategy was used. Otherwise, the cache is never used.\n\nCaching is disabled by default, you will need to explicitly set this flag when initializing:\n\n```js\nconst view = new Mikado(template, { \n    recycle:true,\n    cache: true \n});\n```\n\nIt is very recommended reading the next section to understand how caching is working.\n\n\u003ca name=\"cache-concept\"\u003e\u003c/a\u003e\n\n#### State Caching Concept\n\nLet's take a simple template as an example:\n\n```html\n\u003croot\u003e\n  \u003cdiv class=\"active\"\u003e{{ data.title }}\u003c/div\u003e\n\u003c/root\u003e\n```\n\nThe template above has just one dynamic expression. It could be rendered as follows:\n\n```js\nview.render({ title: \"foobar\" });\n```\n\nAssume you get new data and wants to update the view, but the new data has still the same value for the _title_:\n\n```js\nview.render({ title: \"foobar\" });\n```\n\nThis time, when cache was enabled no changes are applied to the text node, since the new value matches the previous cached value.\nThat specific part now executes more than 10,000 times faster. Make a maximum use of this strategy will speed up things amazingly.\n\nNow let's come to the most important part when using caching properly. Assume you have rendered the template above with caching enabled. Now you **manually** change parts of the DOM **which is covered by a dynamic template expression**:\n\n```js\nvar node = document.querySelector(\".active\");\nnode.textContent = \"manual change\";\n```\n\nThe changes will apply to the DOM as expected. Now you re-render the template with the \"old\" state from the previous render:\n\n```js\nview.render({ title: \"foobar\" });\n```\n\nThis time the change will not apply! Because the internal cache assumes that the current value is still \"foobar\" and skips the change.\n\nYou have 2 options in this situation:\n\n1. Do not manually change dom entries which are part of a dynamic template expression and update specific parts through rendering templates only.\n2. Using the \u003ca href=\"#cache-helpers\"\u003eDOM Cache Helpers\u003c/a\u003e Mikado provides you exactly for this situation.\n\n\u003ca name=\"cache-helpers\"\u003e\u003c/a\u003e\n\n#### DOM Cache Helpers (optional)\n\n\u003e Caching helpers let you apply manual changes to the DOM easily without going out of sync with the corresponding view instance.\n\n\u003e It is recommended also using these helpers to any DOM changes regardless if it is part of the template or not. Generally, these helpers will greatly improve your application performance.\n\nA well implemented application can still save between 20 and 40% of unnecessary DOM access just by using those helpers everywhere. On regular implementations it is almost between 50% and 70%.\n\n\u003ca name=\"view.setAttribute\"\u003e\u003c/a\u003e\n\nSet an attribute of a node (will not replace old attributes):\n\n```js\nMikado.setAttribute(node, \"href\", \"/foo\");\n```\n\nSet multiple attributes of a node (will not replace old attributes):\n\n```js\nMikado.setAttribute(node, {\n  id: \"foo\",\n  href: \"/foo\"\n});\n```\n\n\u003ca name=\"Mikado.getAttribute\"\u003e\u003c/a\u003e\n\nGet an attribute value of a node:\n\n```js\nvar attr = Mikado.getAttribute(node, \"href\");\n```\n\n\u003ca name=\"Mikado.removeAttribute\"\u003e\u003c/a\u003e\n\nRemove an attribute of a node:\n\n```js\nvar attr = Mikado.removeAttribute(node, \"href\");\n```\n\nRemove multiple attributes of a node:\n\n```js\nvar attr = Mikado.removeAttribute(node, [\"href\", \"target\"]);\n```\n\n\u003ca name=\"Mikado.hasAttribute\"\u003e\u003c/a\u003e\n\nCheck existence of a nodes attribute:\n\n```js\nvar href = Mikado.hasAttribute(node, \"href\");\n```\n\n\u003ca name=\"Mikado.setClass\"\u003e\u003c/a\u003e\n\nSet class name of a node (fully replaces old classes):\n\n```js\nMikado.setClass(node, \"class_a class_b\");\n```~~\n~~\n```js\nMikado.setClass(node, [\"class_a\", \"class_b\"]);\n```\n\n\u003ca name=\"Mikado.addClass\"\u003e\u003c/a\u003e\n\nAdd a classname to a node:\n\n```js\nMikado.addClass(node, \"class_a\");\n```\n\nAdd multiple classnames to a node:\n\n```js\nMikado.addClass(node, [\"class_a\", \"class_b\"]);\n```\n\n\u003ca name=\"Mikado.getClass\"\u003e\u003c/a\u003e\n\nGet all classnames of a node (returns an array):\n\n```js\nvar classList = Mikado.getClass(node);\n```\n\n\u003ca name=\"Mikado.toggleClass\"\u003e\u003c/a\u003e\n\nToggle classnames of a node:\n\n```js\nvar classList = Mikado.toggleClass(node, \"class_a\");\n```\n\nToggle classnames of a node to a specific state (a short variant of conditional \"add\" and \"remove\"):\n\n```js\nvar classList = Mikado.toggleClass(node, \"class_a\", true);\n```\n\nToggle multiple classnames of a node:\n\n```js\nvar classList = Mikado.toggleClass(node, [\"class_a\", \"class_b\"]);\n```\n\nToggle multiple classnames of a node each of them to a specific state:\n\n```js\nvar classList = Mikado.toggleClass(node, {\n    \"class_a\": true,\n    \"class_b\": false\n});\n```\n\n\u003ca name=\"Mikado.hasClass\"\u003e\u003c/a\u003e\n\nCheck existence of a nodes classnames:\n\n```js\nvar class_a = Mikado.hasClass(node, \"class_a\");\n```\n\n\u003ca name=\"Mikado.removeClass\"\u003e\u003c/a\u003e\n\nRemoves a classnames of a node:\n\n```js\nMikado.removeClass(node, \"class_a\");\n```\n\nRemoves multiple classnames of a node:\n\n```js\nMikado.removeClass(node, [\"class_a\", \"class_b\"]);\n```\n\n\u003ca name=\"Mikado.setCss\"\u003e\u003c/a\u003e\n\nSet the whole elements inline style tag `style=\"...\"` (fully replaces old styles):\n\n```js\nMikado.setCss(node, \"top: 0; padding-right: 10px\");\n```\n\n```js\nMikado.setCss(node, [\"top: 0\", \"padding-right: 10px\"]);\n```\n\n\u003ca name=\"Mikado.getCss\"\u003e\u003c/a\u003e\n\nGet all inline styles of a nodes style tag:\n\n```js\nvar css = Mikado.getCss(node);\n```\n\n\u003ca name=\"Mikado.setStyle\"\u003e\u003c/a\u003e\n\nSet a specific inline style of a node (will not replace old styles):\n\n```js\nMikado.setStyle(node, \"padding-right\", \"10px\");\n```\n\nSet multiple specific inline styles of a node (will not replace old styles):\n\n```js\nMikado.setStyle(node, { \"top\": 0, \"padding-right\": \"10px\" });\n```\n\n\u003ca name=\"Mikado.getStyle\"\u003e\u003c/a\u003e\n\nGet a specific inline style value of a node:\n\n```js\nvar padding = Mikado.getStyle(node, \"padding-right\");\n```\n\n\u003ca name=\"Mikado.setText\"\u003e\u003c/a\u003e\n\nSet text of an element or text node:\n\n```js\nMikado.setText(node, \"This is a title.\");\n```\n\n\u003ca name=\"Mikado.getText\"\u003e\u003c/a\u003e\n\nGet text of an element or text node:\n\n```js\nvar text = Mikado.getText(node);\n```\n\n\u003ca name=\"Mikado.setHtml\"\u003e\u003c/a\u003e\n\nSet inner HTML of an element:\n\n```js\nMikado.setHtml(node, \"\u003cb\u003eThis is a title.\u003c/b\u003e\");\n```\n\n\u003ca name=\"Mikado.getHtml\"\u003e\u003c/a\u003e\n\nGet inner HTML of an element:\n\n```js\nvar html = Mikado.getHtml(node);\n```\n\n\u003ca name=\"view.state\"\u003e\u003c/a\u003e\n\n## View State\n\nEvery Mikado instance has by default a state object you can access by `view.state`.\n\nState is a payload keeping values and functions during runtime you can use within template expressions additionally to the data.\nThe state also will be delegated through the whole render loop (including partials).\nYou can bind one global state to every Mikado instances, you can also assign a dedicated state for each view.\nAdditionally, a custom state could be passed on all render tasks.\n\n```js\nconst view = Mikado(template, options);\nconsole.log(view.state); // {}\n```\n\nWhen creating an instance you can optionally pass an extern state via options to share the same state object through multiple views:\n\n```js\nconst state = { foo: 1 };\nconst view_a = Mikado(template_a, { state });\nconst view_b = Mikado(template_b, { state });\nconsole.log(view_a.state); // { foo: 1 }\nconsole.log(view_b.state); // { foo: 1 }\n```\n\nYou can access the state within templates by the builtin keyword \"state\" or also by using \"this\" which points to the current Mikado instance.\n\n```html\n\u003cdiv\u003e\n    \u003cp\u003e{{ state.foo }}\u003c/p\u003e      \u003c!-- output: 1 --\u003e\n    \u003cp\u003e{{ this.state.foo }}\u003c/p\u003e \u003c!-- output: 1 --\u003e\n\u003c/div\u003e\n```\n\nWhen using `.render()` you can optionally pass a state as 2nd parameter which will temporarily override the views default keyword \"state\" for this specific render task:\n\n```js\nconst state = { foo: 1 };\nconst view = Mikado(template, { state });\nview.render(data, { foo: 2 });\n```\n\n```html\n\u003cdiv\u003e\n    \u003cp\u003e{{ state.foo }}\u003c/p\u003e      \u003c!-- output: 2 --\u003e\n    \u003cp\u003e{{ this.state.foo }}\u003c/p\u003e \u003c!-- output: 1 --\u003e\n\u003c/div\u003e\n```\n\nAs you can see you can still access the original state by using `this.state`.\n\nWhen using `foreach` the keyword `data` within nested template expressions refers to the most inner element.\n\n```html\n\u003c!-- data points to root --\u003e\n\u003ctable foreach=\"data.rows\"\u003e\n    \u003c!-- data points to root.rows[] --\u003e\n    \u003ctr foreach=\"data.columns\"\u003e\n        \u003c!-- data points to root.rows[].columns[] --\u003e\n        \u003ctd\u003e{{ data.value }}\u003c/td\u003e\n    \u003c/tr\u003e\n\u003c/table\u003e\n```\n\nIf you need the root data element within nested templates then just assign the data to the `state` or pass a temporary state object as 2nd parameter by simply using `.render(data, data)`. Now you can access the root data element via `state` through all the template scopes.\n\n\u003ca name=\"callbacks\"\u003e\u003c/a\u003e\n\n## Custom Callbacks\n\n\u003e The 2nd parameter `view` of custom callbacks points to the Mikado view instance.\n\nDefine custom callbacks during initialization:\n\n```js\nvar view = new Mikado(template, {\n  on: {\n    create: function(node, view) {\n      console.log(\"created:\", node);\n    },\n    recycle: function(node, view) {\n      console.log(\"recycled:\", node);\n    },\n    insert: function(node, view) {\n      console.log(\"inserted:\", node);\n    },\n    update: function(node, view) {\n      console.log(\"updated:\", node);\n    },\n    replace: function(node, view) {\n      console.log(\"replaced:\", node);\n    },\n    remove: function(node, view) {\n      console.log(\"removed:\", node);\n    },\n    mount: function(root, view) {\n      console.log(\"mounted:\", root);\n    },\n    unmount: function(root, view) {\n      console.log(\"unmounted:\", root);\n    }\n  }\n});\n```\n\n\u003ctable\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eCallback\u003c/td\u003e\n        \u003ctd\u003eDescription\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003ecreate\u003c/td\u003e\n        \u003ctd\u003eCalled when a new template node was created (not recycled).\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003erecycle\u003c/td\u003e\n        \u003ctd\u003eCalled when a template node was recycled instead of created.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003einsert\u003c/td\u003e\n        \u003ctd\u003eCalled when a template node was inserted into DOM.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eupdate\u003c/td\u003e\n        \u003ctd\u003eCalled when a template node was updated.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003ereplace\u003c/td\u003e\n        \u003ctd\u003eCalled when a template node was replaced ny another template node.\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eremove\u003c/td\u003e\n        \u003ctd\u003eCalled when a template node was removed.\u003c/td\u003e\n    \u003c/tr\u003e\n\u003c/table\u003e\n\n\u003ca name=\"static\"\u003e\u003c/a\u003e\n\n## Static Templates\n\nWhen a template has no dynamic expressions (within curly brackets) which needs to be evaluated during runtime Mikado will handle those templates as _static_ and skips the dynamic render part. You can render static views without passing data.\n\n\u003ca name=\"mikado.once\"\u003e\u003c/a\u003e\n\n#### Once (One-time rendering)\n\nWhen a template just needs to be rendered once you can theoretically create, mount, render and destroy as follows:\n\n```js\nMikado(template)\n  .mount(root)\n  .render()\n  .destroy();\n```\n\nYou can also simply use a shorthand function:\n\n```js\n// static views doesn't require data\nMikado.once(root, template);\n```\n\n```js\n// if the view has dynamic contents just pass data\nMikado.once(root, template, data);\n// full example by also using async callback\nMikado.once(root, template, data, state, callback);\n```\n\nThere is one important advantage when using `once` over `render`. It will always append to the root without mounting:\n\n```js\nMikado.once(document.body, template);\n```\n\nWhen using `render` instead you probably can't do that, because it needs mounting and `document.body` isn't a root which just includes elements from the same template.\nSo using `Mikado.once` is great when initializing your app and building the shape of the DOM layout.\n\nIf a view was destroyed you will need to create the Mikado instance again when re-using.\n\n\u003ca name=\"ssr\"\u003e\u003c/a\u003e\n\n## Server-Side Rendering (SSR)\n\nJust use the same template syntax (or same source files also served for the client).\n\n```js\nconst mikado = require(\"mikado/ssr\");\nconst view = await mikado.compile(\"view/start.html\", {\n    compression: true,\n    debug: false,\n    cache: 200\n});\n\n// render the html markup\nconst html = view.render([{ /* data */ }]);\n\n// send the html to the client, e.g.:\nres.send(html);\n```\n\nSupported Options (mixable):\n\n- `compression` minify the html markup (true/false)\n- `debug` when enabled it compiles the template on every render, good for development environments (true/false)\n- `cache` sets the size of the encoder-cache (true/false/number)\n- `csr` when set to \"false\" it fully unlocks template restrictions applied by the support of client-side-rendering\n\n\u003ca name=\"ssr-exclusive\"\u003e\u003c/a\u003e\n\n### SSR-exclusive Mode\n\nBy explicitly setting the option `csr` to \"false\" you can switch into SSR-exclusive mode where the limitation of having one outer element as the template root is unlocked, also there is an `extract` directive to place logical placeholder elements, which will be self-extracted when rendered.\n\n```js\nconst mikado = require(\"mikado/ssr\");\nconst view = await mikado.compile(\"view/start.html\", {\n    csr: false\n});\n```\n\n```html\n\u003cdiv if=\"data.length\" extract\u003e\n    \u003ctable foreach=\"data\"\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e1\u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e2\u003c/td\u003e\n        \u003c/tr\u003e\n        \u003ctr\u003e\n            \u003ctd\u003e3\u003c/td\u003e\n        \u003c/tr\u003e\n    \u003c/table\u003e\n\u003c/div\u003e\n```\n\n\u003e Those templates aren't supported by the client render engine, also you can't hydrate them.\n\n\u003ca name=\"express\"\u003e\u003c/a\u003e\n\n## Express Render Engine\n\n```js\nconst mikado = require(\"mikado/express\");\nconst express = require(\"express\");\nconst app = express();\n\n// set path to your static views\napp.set(\"views\", [\n    __dirname + \"/view\"\n    // ...\n]);\n\n// set path to your partial views (optional)\napp.set(\"partials\", [\n    __dirname + \"/partial\"\n    // ...\n]);\n\n// register engine to filetype .html\napp.engine(\"html\", mikado);\n// enable engine for filetype .html\napp.set(\"view engine\", \"html\");\n```\n\n\u003ca name=\"express-options\"\u003e\u003c/a\u003e\n\n#### Custom Options\n\nYou can set options by Express `app.set`:\n\n```js\n// enable compression (optional)\napp.set(\"view compression\", true);\n// enable cache and set pool size (optional)\napp.set(\"view cache\", 200);\n// set debug to false to enable compiler cache\napp.set(\"view debug\", false);\n```\n\nOr you can specify options by `mikado.options` alternatively:\n\n```js\nmikado.options = {\n    compression: true,\n    cache: 200,\n    debug: false\n};\n```\n\n\u003ca name=\"express-render\"\u003e\u003c/a\u003e\n\n#### Render Views\n\nRegister a route and render the file `./view/start.html`:\n\n```js\napp.get(\"/\", function(req, res){\n\n    res.render(\"view/start\", [{ /* data */ }]);\n});\n```\n\n\u003ca name=\"includes\"\u003e\u003c/a\u003e\n\n## Includes\n\nPartials gets its own instance under the hood. This performance gain also makes a template factory re-usable when the same partials are shared across different views.\n\n\u003e Be aware of circular includes. A partial cannot include itself or somewhere later in its own chain.\n\nAssume you've created one or more partial templates. Make sure each of the partial templates is providing one single root as the outer bound.\n\nThe file structure might look like:\n\n- _tpl/header.html_\n- _tpl/article.html_\n- _tpl/footer.html_\n\nYou will need to compile the templates:\n\n```bash\nnpx mikado-compile ./tpl/\n```\n\nYou have to register all partial templates once **before** you initialize the templates which will including them:\n\n```js\nimport tpl_header from \"./tpl/header.es6.js\";\nimport tpl_article from \"./tpl/article.es6.js\";\nimport tpl_footer from \"./tpl/footer.es6.js\";\n\nMikado.register(tpl_header);\nMikado.register(tpl_article);\nMikado.register(tpl_footer);\n```\n\nWhen using templates in ES5 compatible format, they are automatically registered by default when loaded.\n\u003c!--You can also use the runtime compiler and pass the returned template to the register method.--\u003e\n\nInclude partial templates in another template __tpl/section.html__:\n\n```html\n\u003csection\u003e\n  \u003cheader include=\"header\"\u003e\u003c/header\u003e\n  \u003carticle include=\"article\"\u003e\u003c/article\u003e\n  \u003cfooter include=\"footer\"\u003e\u003c/footer\u003e\n\u003c/section\u003e\n```\n\nThe \"section\" from above could be also included by another one (and so on):\n\n```html\n\u003chtml\u003e\n\u003cbody\u003e\n    \u003cmain foreach=\"data.sections\" include=\"section\"\u003e\u003c/main\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\n\u003ca name=\"loop-partials\"\u003e\u003c/a\u003e\n\n## Loop Partials\n\nAssume the template example from above is a tweet (title, article, footer).\n\n```html\n\u003csection\u003e\n  \u003ctitle\u003e{{ data.title }}\u003c/title\u003e\n  \u003ctweets foreach=\"data.tweets\" include=\"tweet\"\u003e\n    \u003c!-- tweet --\u003e\n    \u003c!-- tweet --\u003e\n    \u003c!-- tweet --\u003e\n  \u003c/tweets\u003e\n\u003c/section\u003e\n```\n\nThis expression will render the template \"tweet\" through an array of data items/tweets. The template \"tweet\" is getting the array value **_data.tweets_** as **_data_**.\n\nThe **_limit_** and **_offset_** attributes could be used optionally to specify a custom portion of the partial loop:\n\n```html\n\u003ctweets foreach=\"data.tweets\" include=\"tweet\" limit=\"5\" offset=\"5\"\u003e\u003c/tweets\u003e\n```\n\nThe **_offset_** attribute could also be negative to reverse the boundary direction, e.g. loop through the last 5 items:\n\n```html\n\u003ctweets foreach=\"data.tweets\" include=\"tweet\" limit=\"5\" offset=\"-5\"\u003e\u003c/tweets\u003e\n```\n\n\u003ca name=\"inline-loops\"\u003e\u003c/a\u003e\n\n### Inline Loops\n\nYou can also loop through an inline partial. Mikado will extract and referencing this partial to its own instance under the hood.\n\n```html\n\u003cmain\u003e\n  \u003ctitle\u003e{{ data.title }}\u003c/title\u003e\n  \u003ctweets foreach=\"data.tweets\"\u003e\n    \u003csection\u003e\n      \u003cheader include=\"header\"\u003e\u003c/header\u003e\n      \u003carticle include=\"article\"\u003e\u003c/article\u003e\n      \u003cfooter include=\"footer\"\u003e\u003c/footer\u003e\n    \u003c/section\u003e\n  \u003c/tweets\u003e\n\u003c/main\u003e\n```\n\nYou can also nest loops:\n\n```html\n\u003c!-- root view --\u003e\n\u003ctweets foreach=\"data.tweets\"\u003e\n  \u003c!-- new partial template --\u003e\n  \u003ctweet\u003e\n    \u003ch1\u003e{{ data.title }}\u003c/h1\u003e\n    \u003ctitle\u003eComments:\u003c/title\u003e\n    \u003cdiv foreach=\"data.comments\"\u003e\n      \u003c!-- new partial template --\u003e\n      \u003ccomment\u003e\n        \u003cp\u003e{{ data.content }}\u003c/p\u003e\n        \u003ctitle\u003eReplies:\u003c/title\u003e\n        \u003cdiv foreach=\"data.replies\"\u003e\n          \u003c!-- new partial template --\u003e\n          \u003cp\u003e{{ data.content }}\u003c/p\u003e\n        \u003c/div\u003e\n      \u003c/comment\u003e\n    \u003c/div\u003e\n  \u003c/tweet\u003e\n\u003c/tweets\u003e\n```\n\n\u003e Every looped partial has to provide **one single element root** as the outer bound.\n\nIn this example every foreach-expression is wrong (you will find the right example above):\n\n```html\n\u003ctweets foreach=\"data.tweets\"\u003e\n  \u003c!-- no outer bound! --\u003e\n  \u003ch1\u003e{{ data.title }}\u003c/h1\u003e\n  \u003ctitle\u003eComments:\u003c/title\u003e\n  \u003cdiv foreach=\"data.comments\"\u003e\n    \u003c!-- no outer bound! --\u003e\n    \u003cp\u003e{{ data.content }}\u003c/p\u003e\n    \u003ctitle\u003eReplies:\u003c/title\u003e\n    \u003cdiv foreach=\"data.replies\"\u003e\n      \u003c!-- no outer bound! --\u003e\n      {{ data.content }}\n    \u003c/div\u003e\n  \u003c/div\u003e\n\u003c/tweets\u003e\n```\n\n\u003ca name=\"conditional\" id=\"conditional\"\u003e\u003c/a\u003e\n\n## Conditional Template Structures\n\n```html\n\u003cmain\u003e\n  \u003ctitle if=\"data.tweet.length\"\u003eTweets: {{ data.tweet.length }}\u003c/title\u003e\n  \u003ctitle if=\"!data.tweet.length\"\u003eNo tweets found.\u003c/title\u003e\n\u003c/main\u003e\n```\n\n```html\n\u003cmain\u003e\n  \u003ctitle\u003e{{ data.title }}\u003c/title\u003e\n  \u003ctweets if=\"data.tweets.length\" foreach=\"data.tweets\"\u003e\n    \u003csection\u003e{{ data.content }}\u003c/section\u003e\n  \u003c/tweets\u003e\n\u003c/main\u003e\n```\n\n```html\n\u003cmain\u003e\n  \u003ctitle\u003e{{ data.title }}\u003c/title\u003e\n  \u003ctweets foreach=\"data.tweets\"\u003e\n    \u003csection if=\"data.content\"\u003e{{ data.content }}\u003c/section\u003e\n  \u003c/tweets\u003e\n\u003c/main\u003e\n```\n\nThink in real code branches, instead of doing this:\n\n```html\n\u003cmain\u003e\n  {{@ var result = (function(){ return \"some big computation\"; }()) }}\n  \u003csection if=\"data.content\"\u003e{{ result }}\u003c/section\u003e\n\u003c/main\u003e\n```\n\nDoing this:\n\n```html\n\u003cmain\u003e\n  \u003csection if=\"data.content\"\u003e\n    {{ (function(){ return \"some big computation\"; }()) }}\n  \u003c/section\u003e\n\u003c/main\u003e\n```\n\n\u003e Conditional branches will skip their expressions inside when not taken.\n\nAlso, try to assign computations outside a loop by using the state to delegate values to the scope of the partial loop:\n\n```html\n\u003cmain\u003e\n  {{@ state.result = (function(){ return \"some big computation\"; }()) }}\n  \u003ctweets foreach=\"data.tweets\"\u003e\n    \u003csection\u003e{{ state.result }}\u003c/section\u003e\n  \u003c/tweets\u003e\n\u003c/main\u003e\n```\n\n\u003ca name=\"proxy\" id=\"proxy\"\u003e\u003c/a\u003e\n\n## Reactive Properties (Proxy)\n\nMikado provides you a reactive approach to listen for changes to the data and apply them accordingly to the DOM.\nIt is based on native Proxy feature which has great performance, a small memory footprint and fully falls back to a legacy observer when Proxy is not available.\nUsing a reactive strategy can additionally boost performance beyond a factor of 100 when updating specific data instead of leverage a full render task.\nIt depends on your application or current view, this feature has an advantage when updating data **partially** has to process more often than full data updates.\n\n**Template markup**:\n\n```html\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eName:\u003c/td\u003e\n    \u003ctd\u003e{{= data.name }}\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eEmail:\u003c/td\u003e\n    \u003ctd\u003e{{= data.email }}\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n```\n\n\u003e The expression for an observable property uses this syntax: `{{=`. You can combine with other expressions, but should be defined at least, e.g. `{{#=` or `{{!=` or `{{?=`.\n\n\u003e You can't use any Javascript code inside reactive expressions, just the full data scope of the value is allowed to specify within those expressions.\n\nWhen using reactive properties you'll need to manage a store (could be a simple Array) which gets proxified under the hood.\n\n```js\n// store must be an array of elements:\nconst store = [/* Array of objects */];\n\n// create, mount and initial render the store by using\n// a template which has reactive properties included\nMikado(template).mount(root).render(store);\n\n// the store now has proxified item properties!\n// do not throw it away, instead apply updates on it\nstore[0].name = \"John Doe\";\nstore[0].email = \"john@doe.com\";\n\n// when data changes, the corresponding DOM elements\n// will automatically change also\n```\n\n\u003e The data store must be an Array of elements, also when just having one item. Because the array index reference gets proxified, that's why you can't pass a single object.\n\nIf you just have a single data item, and you don't like the array index access you can also define a reference, but you need to do this after initially calling `render`:\n\n```js\nconst store = [{ class: \"active\", value: \"foo\" }];\n// the store isn't proxified\nconst test = store[0];\n// initial render\nview.render(store);\n// the store array now was proxified!\nconst item = store[0];\n\n// these objects aren't the same anymore\nconsole.log(test === item); // false\n\n// nothing will change on screen:\ntest.value = \"bar\";\n// this works properly\nitem.value = \"bar\";\n```\n\nOn the upper example nothing on the DOM will change when you set the values `test.value = \"bar\"`, because this reference holds the un-proxified original version.\nSet `item.value = \"bar\"` will work properly.\n\n\u003ca name=\"limitations\"\u003e\u003c/a\u003e\n\n### Limitations\n\nActually there are some limitations on template expressions.\n\n1.\u0026nbsp;Fields from deeply nested data objects are not reactive:\n\n```js\nvar data = {\n  id: \"foobar\", // \u003c-- observable\n  content: {    // \u003c-- observable\n    title: \"title\",  // \u003c-- NOT\n    body: \"body\",    // \u003c-- NOT\n    footer: \"footer\" // \u003c-- NOT\n  }\n};\n```\n\n2.\u0026nbsp;Template expressions including any kind of Javascript syntax are not supported:\n\n```html\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eName:\u003c/td\u003e\n    \u003c!-- Supported: --\u003e\n    \u003ctd\u003e{{= data.name }}\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd\u003eTweets:\u003c/td\u003e\n    \u003c!-- Not Supported: --\u003e\n    \u003ctd\u003e{{= data.tweets ? data.tweets.length : 0 }}\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n```\n\nJust use plain property notation within the curly brackets.\n\n\u003ca name=\"strict-proxy\"\u003e\u003c/a\u003e\n\n### Strict-Proxy Mode\n\nWhenever **all** your template expressions are just using proxy notation it enables a special \"strict-proxy\" mode under the hood, which further boosts performance from every update to a maximum. This mode has no advantage when every render loop has to apply almost new items.\n\nThis enables \"strict-proxy\" mode:\n\n```html\n\u003citem\u003e\n  \u003ccaption\u003e\n    Name:\n  \u003c/caption\u003e\n  \u003cp\u003e{{= data.name }}\u003c/p\u003e\n  \u003ccaption\u003e\n    Email:\n  \u003c/caption\u003e\n  \u003cp\u003e{{= data.mail }}\u003c/p\u003e\n\u003c/item\u003e\n```\n\nThis won't enable it:\n\n```html\n\u003citem\u003e\n  \u003ccaption\u003e\n    Name:\n  \u003c/caption\u003e\n  \u003cp\u003e{{= data.name }}\u003c/p\u003e\n  \u003ccaption\u003e\n    Email:\n  \u003c/caption\u003e\n  \u003cp\u003e{{ data.mail }}\u003c/p\u003e\n\u003c/item\u003e\n```\n\nAlso using conditionals, includes, loops and inline Javascript will prevent switching to the \"strict-proxy\" mode. You can't switch this mode by yourself. It just activates when conditions are met.\n\n\u003ca name=\"observable\"\u003e\u003c/a\u003e\n\n### Observable Array (Virtual NodeList)\n\nIn addition to react on changes of property values you can additionally also listen to changes made to the Array index of the store.\nMikado provides you an observable Array that acts like a native Array and apply all changes to a synchronized NodeList under the hood.\nIt also uses native Proxy which fully falls back to a legacy observer, when not available.\n\n\u003e Semantically the observable array you will get from `Mikado.Array()` is equal to an array-like Javascript Array.\n\n\u003ca name=\"mikado.array\"\u003e\u003c/a\u003e\n\nCreate an observable array:\n\n```js\nvar store = new Mikado.Array();\n```\n\nCreate an observable array with initial data:\n\n```js\nvar items = [ ... ];\nvar store = new Mikado.Array(items);\n```\n\nEvery observable array requires binding to a **mounted** Mikado instance, because it needs to apply render tasks somewhere:\n\n```js\nvar view = Mikado(template, { observe: store, mount: root });\n```\n\n\u003ca name=\"array.mount\"\u003e\u003c/a\u003e\n\nYou can also mount an observable array to a Mikado instance (and also switch mounting):\n\n```js\nconst store = new Mikado.Array();\nconst view = Mikado(template, { mount: root });\n\nstore.mount(view);\n```\n\nNow the observable array is linked with your instance. Whenever you change the array all changes will apply automatically to the corresponding DOM components.\n\nYou can use all common array built-ins, e.g.:\n\n\u003ca name=\"array.push\"\u003e\u003c/a\u003e\n\n```js\nstore.push({ ... });\n```\n\n\u003ca name=\"array.pop\"\u003e\u003c/a\u003e\n\n```js\nvar last = store.pop();\n```\n\n\u003ca name=\"array.unshift\"\u003e\u003c/a\u003e\n\n```js\nstore.unshift({ ... });\n```\n\n\u003ca name=\"array.shift\"\u003e\u003c/a\u003e\n\n```js\nvar first = store.shift();\n```\n\n\u003ca name=\"array.slice\"\u003e\u003c/a\u003e\n\n```js\nstore.slice(3, 1);\n```\n\n\u003ca name=\"array.splice\"\u003e\u003c/a\u003e\n\n```js\nstore.splice(0, 1, { ... });\n```\n\nYou can **get and set via array index access**. This feature also has a non-proxy fallback included.\n\n```js\nstore[0] = { ... };\n```\n\n```js\nstore[store.length] = { ... };\n```\n\n```js\nvar first = store[0];\n```\n\n\u003ca name=\"array.set\"\u003e\u003c/a\u003e\n\nYou can replace the array contents by:\n\n```js\nvar items = [ ... ];\nstore.set(items);\n```\n\nThis is recommended instead of pushing each item one by one, `store.set` will also handle keyed reconciliation.\n\n\u003ca name=\"array.concat\"\u003e\u003c/a\u003e\n\u003ca name=\"array.indexOf\"\u003e\u003c/a\u003e\n\u003ca name=\"array.lastIndexOf\"\u003e\u003c/a\u003e\n\u003ca name=\"array.includes\"\u003e\u003c/a\u003e\n\u003ca name=\"array.filter\"\u003e\u003c/a\u003e\n\u003ca name=\"array.map\"\u003e\u003c/a\u003e\n\u003ca name=\"array.reverse\"\u003e\u003c/a\u003e\n\u003ca name=\"array.sort\"\u003e\u003c/a\u003e\n\u003ca name=\"array.swap\"\u003e\u003c/a\u003e\n\u003ca name=\"array.forEach\"\u003e\u003c/a\u003e\n\nA list of all supported array prototypes:\n\n- length\n- push(obj)\n- pop()\n- shift(obj)\n- unshift(obj)\n- slice(index, count)\n- splice(index, count, insert)\n- concat(arr)\n- indexOf(obj)\n- lastIndexOf(obj)\n- includes(obj)\n- filter(fn)\n- map(fn)\n- reverse()\n- sort(fn)\n- swap(a, b)\n- forEach(fn)\n- set(arr) (used to replace the array contents)\n\nThese methods are implemented without some extensions like parameter chaining, e.g. `array.push(a, b, c)` is not available, instead, you have to call push for each item one by one.\n\nThere are some methods which slightly differs from the original implementation of native Arrays. The following methods will apply changes **_in place_** and returning the original reference instead of making a copy:\n\n- concat\n- filter\n- map\n\nWhenever you need the original native Array behavior including all extensions and variants you can simply do that by:\n\n```js\nconst new_array = [ ... ];\nconst copy = Array.prototype.concat.call(store, new_array);\n```\n\n```js\nconst copy = Array.prototype.map.call(store, obj =\u003e obj);\n```\n\nIn a situation when falling back to the non-proxy polyfill because of missing support for native Proxy, there is a limitation.\nYou cannot fill sparse arrays or access indexes which are greater than the current `array.length`.\nThere is just one undefined index that could always access (by read/write) that is the last \"undefined\" index on an array when you call `array[array.length]`.\nThis index is a special marker that increases the \"virtual\" array size.\nWhenever you assign a value to this special index the size of the observable index growth automatically and the next \"undefined\" index in the queue becomes this marker.\nThis limitation is not existing when the ES6 proxy is available.\n\nAlso, there are some divergent characteristics when using reflection:\n\n```js\nvar store = Mikado.Array();\nconsole.log(store.constructor === Array); // -\u003e false\nconsole.log(store.prototype === Array.prototype); // -\u003e false\nconsole.log(store instanceof Array); // -\u003e false\nconsole.log(Array.isArray(store)); // -\u003e false\nconsole.log(store instanceof Mikado.Array); // -\u003e true\n```\n\nThe proxy feature theoretically allows all those checks but could not be used to keep the polyfill working in addition to sharing most of the same codebase. Alternatively you can use an `instanceof` check for identification.\n\n\u003ca name=\"array.transaction\"\u003e\u003c/a\u003e\n\n### Transactions\n\nSince the array observer apply all changes on the array index instantly to the DOM, reconciliation has no chance to run.\nFor this purpose you can use the `store.transaction()` feature, which let you apply all changes within a function and commit them by taking reconciling into account.\n\n```js\nstore.transaction(function(){\n    // collect changes:\n    store[0].title = \"John\";\n    store[12].class = \"active\";\n    store[10] = store.pop();\n    store[11] = store.shift();\n});\n// changes applied\n```\n\nA transaction is used when editing an **existing** state in a bulk. Whenever you want to initialize a new state, e.g. when data was coming from a server, you should use `store.set(data)` instead.\n\n\u003ca name=\"pools\"\u003e\u003c/a\u003e\n\n## Component Pools\n\nUsing pools greatly enhance the strategy of keyed and non-keyed recycling. Mikado detects automatically if it needs to use keyed or non-keyed pooling and will apply different strategies optimized for each of them.\n\n\u003e Pools just enables when a keyed or non-keyed recycle strategy was used in combination.\n\nEnable pool (keyed or non-keyed):\n\n```js\nconst view = new Mikado(tpl, {\n    recycle: true,\n    pool: true\n});\n```\n\nMikado will auto-balance pools automatically.\n\n\u003ca name=\"mikado.flush\"\u003e\u003c/a\u003e\n\n#### Flush Pools\n\nYou can delete pool contents at any time by:\n\n```js\nview.flush();\n```\n\n\u003ca name=\"hydration\"\u003e\u003c/a\u003e\n\n## Hydration\n\nHydration is a concept where the server is sending some basic HTML structure (or the whole App/Page) and the client consumes those contents into its own rendering system. This will improve several performance aspects of page loading (e.g. the Lighthouse test) but also it enables you to have server-side-rendered content by also providing a full PWA (aka \"Single-Page-Application\") experience at the same time.\n\nMikado uses hydration strategy, where components are hydrated progressively right before a render task will be performed.\n\nAssume the server was sending this HTML structure as initial:\n\n```html\n\u003chtml\u003e\n\u003cbody\u003e\n  \u003cmain\u003e\n    \u003csection\u003e\n      \u003ctitle\u003eTitle\u003c/title\u003e\n      \u003ctweets\u003e\n        \u003ctweet\u003e\u003c!-- ... --\u003e\u003c/tweet\u003e\n        \u003ctweet\u003e\u003c!-- ... --\u003e\u003c/tweet\u003e\n        \u003ctweet\u003e\u003c!-- ... --\u003e\u003c/tweet\u003e\n      \u003c/tweets\u003e\n    \u003c/section\u003e\n  \u003c/main\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\nYour template looks like:\n\n```html\n\u003csection\u003e\n  \u003ctitle\u003e{{ data.title }}\u003c/title\u003e\n  \u003ctweets foreach=\"data.tweets\"\u003e\n    \u003ctweet\u003e\n      \u003ch1\u003e{{ data.title }}\u003c/h1\u003e\n      \u003ctitle\u003eComments:\u003c/title\u003e\n      \u003cdiv foreach=\"data.comments\"\u003e\n        \u003ccomment\u003e\u003c!-- ... --\u003e\u003c/comment\u003e\n      \u003c/div\u003e\n   \u003c/tweet\u003e\n  \u003c/tweets\u003e\n\u003c/section\u003e\n```\n\n\u003e When a mounted template matches the same DOM structure like the component which should be hydrated, the initialization of the template will boot up faster because the factory is derived instead of created. You can use Mikados SSR feature to provide client-compatible structures on the server-side.\n\n\u003e When `DEBUG` is enabled (or by using one of the debug builds) you'll get a message in the console when hydration falls back into factory construction because of an incompatible DOM structure.\n\nYou can hydrate the existing structure when creating instance (prefetch):\n\n```js\nconst root = document.querySelector(\"main\");\nconst view = new Mikado(tpl, { mount: root, hydrate: true });\n```\n\nYou can also do this just right before mounting by passing the 2nd parameter:\n\n```js\nconst view = new Mikado(tpl);\n// ... somewhat later in the runtime\nview.mount(document.querySelector(\"main\"), /* hydrate? */ true);\n```\n\n\u003e When a hydration breaks because it isn't compatible for some reason, it fully skips this process silently (logs a message when DEBUG was enabled) and falls back to a construction of a factory instead.\n\n\u003ca name=\"shadow\"\u003e\u003c/a\u003e\n\n## Web Components (Shadow DOM)\n\nWhen using shadow DOM to build web components the compiler needs to apply a different strategy.\nTherefore, you will need 2 additional template tags:\n\n1. `\u003ccomponent/\u003e` as the outer root will enable rendering on a shadow root\n2. `\u003ctemplate/\u003e` will identify your template from the rest of markup\n\n```html\n\u003ccomponent\u003e\n  \u003c!-- optional styles/scripts/etc. --\u003e\n  \u003clink href=\"css/component.css\" rel=\"stylesheet\"\u003e\n  \u003cscript src=\"js/component.js\"\u003e\u003c/script\u003e\n  \u003cstyle\u003e#user-list{ width: 100%; }\u003c/style\u003e\n  \u003cscript\u003ewindow.username = \"John\";\u003c/script\u003e\n  \u003c!-- you can include anything here ... --\u003e\n  \u003c!-- components requires the template tag --\u003e\n  \u003ctemplate\u003e\n    \u003c!-- templates has single outer root element: --\u003e\n    \u003ctable id=\"user-list\"\u003e\n      \u003ctr\u003e\n        \u003ctd\u003eUser:\u003c/td\u003e\n        \u003ctd\u003e{{ window.username }}\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n        \u003ctd\u003eTweets:\u003c/td\u003e\n        \u003ctd\u003e{{ data.tweets.length }}\u003c/td\u003e\n      \u003c/tr\u003e\n    \u003c/table\u003e\n  \u003c/template\u003e\n\u003c/component\u003e\n```\n\n\u003e You can't use any template expressions outside `\u003ctemplate/\u003e`.\n\nYou can also render any normal template (non-components) to a plain dedicated shadow root by using the `shadow: true` option (also supported by the light bundle):\n\n```js\nconst view = new Mikado(tpl, { shadow: true });\n```\n\nTheoretically you can put the `\u003clink/\u003e`, `\u003cstyle/\u003e` and `\u003cscript/\u003e` inside a normal non-component template by also using the `shadow: true` option.\nBut there is one important difference. Within a normal template those tags could be re-rendered and this might end in re-initializing of all those assets.\nWithin a web component there is a top level scope, which is created once and will stay for all your further template tasks.\nThe template will render on a new \"hidden\" element `\u003croot/\u003e` which is part of the top level scope.\nThat is because the view needs to be mounted to an element, and the top level scope of shadow root couldn't be mounted because of mixed content.\nDon't rely on the existence of `\u003croot/\u003e`, when using static templates or `view.once()` it might not exist.\n\nAssume when mounted a web component template to an element `\u003cmain\u003e`, the DOM structure looks like:\n\n```\n\u003cmain\u003e\n  #shadow-root\n    \u003clink/\u003e\n    \u003cstyle/\u003e\n    \u003cscript/\u003e\n    \u003croot\u003e\n      #template\n      #template\n      #template\n      ...\n    \u003c/root\u003e\n```\n\n\u003ca name=\"full-template\"\u003e\u003c/a\u003e\n\n## Full Template Example\n\nUse this almost complete template example to check if you know everything about the template mechanism:\n\n```html\n\u003cmain cache=\"true\" id=\"{{ data.view }}\"\u003e\n  \u003ctable\u003e\n      \u003cthead\u003e\n        \u003ctr\u003e\n          \u003cth\u003eIndex\u003c/th\u003e\n          \u003cth\u003eTitle\u003c/th\u003e\n          \u003cth\u003eMedia\u003c/th\u003e\n          \u003cth\u003eCategory\u003c/th\u003e\n          \u003cth\u003eComment\u003c/th\u003e\n          \u003cth\u003eDate\u003c/th\u003e\n          \u003cth include=\"pager\"\u003e\u003c/th\u003e\n        \u003c/tr\u003e\n      \u003c/thead\u003e\n      \u003ctbody foreach=\"data.entries\"\u003e\n        \u003cscript\u003e{{@ const datestr = new Date(data.date).toLocaleString() }}\u003c/script\u003e\n        \u003ctr key=\"data.id\" data-id=\"{{ data.id }}\"\u003e\n          \u003ctd\u003e{{ index + 1 }}\u003c/td\u003e\n          \u003ctd\u003e{{= data.title }}\u003c/td\u003e\n          \u003ctd\u003e{{# data.media }}\u003c/td\u003e\n          \u003ctd\u003e{{? data.category }}\u003c/td\u003e\n          \u003ctd\u003e{{! data.comment }}\u003c/td\u003e\n          \u003ctd\u003e{{ datestr }}\u003c/td\u003e\n          \u003ctd style=\"opacity: {{ state.selected === data.id ? '1' : '0.5' }}\"\u003e\n            \u003cselect change=\"select-active:root\"\u003e\n              \u003coption value=\"on\" selected=\"{{ data.mode === 'on' }}\"\u003eEnabled\u003c/option\u003e\n              \u003coption value=\"off\" selected=\"{{ data.mode === 'off' }}\"\u003eDisabled\u003c/option\u003e\n            \u003c/select\u003e\n          \u003c/td\u003e\n        \u003c/tr\u003e\n      \u003c/tbody\u003e\n      \u003ctfoot if=\"!data.entries.length\"\u003e\n        \u003ctr\u003e\n          \u003ctd colspan=\"7\"\u003eNo entries found.\u003c/td\u003e\n        \u003c/tr\u003e\n      \u003c/tfoot\u003e\n  \u003c/table\u003e\n\u003c/main\u003e\n```\n\nA proper definition and call for this template could look like this:\n\n```js\n// the named include \"pager\" needs to be registered before use\nMikado.register(tpl_pager);\n\n// define route \"select-active\"\nview.route(\"select-active\", function(target, event){\n    const id = Number(target.dataset.id);\n    view.state.selected = id;\n});\n\nview.render({\n  view: \"video\",\n  entries: [{\n    id: 1,\n    date: \"2023-12-01T14:00:00\",\n    title: \"A simple title 1\",\n    media: \"\u003cimg src='img1.jpg'\u003e\",\n    category: null,\n    comment: \"Some \u003cscript\u003euntrusted\u003c/script\u003e content\",\n    mode: \"off\"\n  },{\n    id: 2,\n    date: \"2023-12-02T15:00:00\",\n    title: \"A simple title 2\",\n    media: \"\u003cvideo src='mov2.mp4'\u003e\",\n    category: null,\n    comment: \"Some \u003cscript\u003euntrusted\u003c/script\u003e content\",\n    mode: \"on\"\n  },{\n    id: 3,\n    date: \"2023-12-03T16:00:00\",\n    title: \"A simple title 3\",\n    media: \"\u003cimg src='img3.jpg'\u003e\",\n    category: null,\n    comment: \"Some \u003cscript\u003euntrusted\u003c/script\u003e content\",\n    mode: \"off\"\n  }]\n});\n```\n\nEach template part explained:\n\n- `cache=\"true\"` let the compiler prebuilt the cache strategy, you can't switch it to off when creating an instance\n- `id=\"{{ data.view }}\"` simple expression for inserting dynamic content\n- `if=\"!data.entries.length\"` the if-directive checks the condition and will render everything nested as a new template (inline definition or extern by using \"include\"), the nested template needs to have one outer element as the root\n- `foreach=\"data.entries\"` the foreach-directive loops the rendering of array items by everything nested as a new template (inline definition or extern by using \"include\"), the nested template needs to have one outer element as the root\n- `{{@ ... }}` an expression to include pure javascript syntax (access limited by the scope of the template), wrapped into a `\u003cscript/\u003e` tag just for runtime compiler support.\n- `key=\"data.id\"` extract the key value from the data, a given key is limiting the recycling of already rendered components by a keyed strategy\n- `data-id=\"{{ data.id }}\" root` exports \"data.id\" as an attribute, also define \"root\" as the event target for the listener \"select-active\", pretty useful when multiple routes on different elements needs the same data attributes\n- `{{ index + 1 }}` uses the builtin keyword \"index\" which refers to the current index of looped data\n- `{{= data.title }}` uses reactive approach by binding the html node to the data field, so when changing the data `data.title =\"another title\"` the node contents will also change accordingly\n- `{{# data.media }}` allows to include html syntax (this is unsafe, don't pass user inputs, you will need to prevent XSS by yourself)\n- `{{? data.category }}` only prints a \"truthy\" value including 0 (skips undefined, null, NaN, false)\n- `{{! data.comment }}` escape the value before print out (SSR only)\n- `{{ datestr }}` access the variable which was created by inline syntax before\n- `style=\"opacity: {{ state.selected === data.id '1' ? '0.5' }}\"` example of dynamic attribute value\n- `change=\"select-active:root\"` assign the route named \"select-active\" and forward the event to the element which has the given attribute name assigned to it or in this case \"root\" points to the components root \u003ctr\u003e (so the target inside the root function becomes the forwarded element)\n- `selected=\"data.active === 'yes'\"` when dynamic attribute values results to boolean \"false\" (not string) it will be removed from the element, because some attributes enables just by their existence (consider an option element having selected=\"false\" will end up also as a truthy selection state)\n\n\u003c!--\n\u003ca name=\"best-practices\"\u003e\u003c/a\u003e\n\n## Best Practices\n\nWhen you are focus on performance you should take those settings as a goal:\n\n1. For keyed recycling use: `{ pool: true }` by adding `cache=\"true\"` on the template root element in addition to a key like `key=\"data.id\"` accordingly to your data.\n2. For non-keyed recycling use: `{ recycle: true, pool: true }` by adding `cache=\"true\"` on the template root element.\n3. Also enable `Mikado.eventCache = true`.\n\n\u003e Please don't just use them blindly, you will need to understand at least a minimum about what those options are doing. Also, in certain situations they might not the best pick. You will also get a great performance when not using this options.\n\n- Remember, looped inline partials can also have a property `key` on their inline root element to switch them also in keyed recycling mode.\n- Prefer named includes when structures will be reused by multiple views, also when assigning custom options gives you any advantage.\n- In larger applications, it might be better to destroy views when they are closed by the user to free memory instead of saving too much on the options.\n--\u003e\n\n\u003c!--\n### Personal Recommendation\n\nKeyed recycling isn't the best pick, it just gives you (or other libs) the freedom to apply things to the DOM directly.\nPersonally I prefer cache-enabled non-keyed recycling for all looped templates e.g. a table view and for \"create\" and \"edit\" views I also use non-keyed but without recycling enabled (\"create\" and \"edit\" views are the same template).\nI don't get any conflicts or side effects, since I apply every change by Mikado (also by using the library helpers).\nLong story short, keyed rendering is just for your laziness or when you can't control everything for some reason.\n--\u003e\n\n\u003ca name=\"concept\"\u003e\u003c/a\u003e\n\n## Concept of Shared Components\n\nMikado heavily makes use of runtime optimization. Since it is not possible to predict the recycle state of the next render task, Mikado uses a technique called `progressive enhancement` on which optimizations will apply iteratively. Recycle enhancements growth as needed.\n\nThe most benchmarks you will find ends at the point where Mikado starts to shine. Rendering a simple table isn't really a complex task. Real applications have bigger structures including partials, includes, conditionals, etc. The concept of shared components was the basic idea of this library. It is the \"ultimate\" upgrade of the recycle paradigm and when properly used, it is one of the biggest optimization improvement you can unlock.\n\n\u003cbr\u003e\u003cimg src=\"https://cdn.jsdelivr.net/gh/nextapps-de/mikado@master/doc/concept.svg\" alt=\"Mikado Shared Components (Concept)\"\u003e\u003cbr\u003e\u003cbr\u003e\n\nMikado will take away every complexity you might expect of such a system. You just need to structure your HTML templates and use `.render(data)`, that's it!\n\n\u003ca name=\"builds\" id=\"builds\"\u003e\u003c/a\u003e\n\n## Custom Builds\n\nThe `src` folder of this repository requires some compilation to resolve the build flags. Those are your options:\n\n- Closure Compiler (Simple or Advanced, used by this library, \u003ca href=\"https://github.com/krausest/js-framework-benchmark/blob/master/frameworks/keyed/mikado/task/build.js\"\u003eexample\u003c/a\u003e)\n- Babel + Plugin `babel-plugin-conditional-compile` (used by this library \u003ca href=\"task/babel.min.json\"\u003ehere\u003c/a\u003e)\n\nAs far as I know you can't resolve build flags with:\n\n- Webpack\n- esbuild\n- rollup\n- Terser\n\nPlease let me know when you have some additions. As long as you will see flags like `if(DEBUG)` (could be minified) in your build you shouldn't use that.\n\nThese are some of the basic builds located in the `dist` folder:\n\n```bash\nnpm run build:bundle\nnpm run build:light\nnpm run build:module\nnpm run build:es5\n```\n\nPerform a custom build (UMD bundle) by passing build flags:\n\n```bash\nnpm run build:custom SUPPORT_CACHE=true SUPPORT_POOLS=true LANGUAGE_OUT=ECMASCRIPT5 POLYFILL=true\n```\n\nPerform a custom build in ESM module format:\n\n```bash\nnpm run build:custom RELEASE=custom.module SUPPORT_CACHE=true SUPPORT_POOLS=true \n```\n\nPerform a debug build:\n\n```bash\nnpm run build:custom DEBUG=true SUPPORT_CACHE=true SUPPORT_POOLS=true \n```\n\n\u003e On custom builds each build flag will be set to _**false**_ by default when not passed.\n\nThe custom build will be saved to `dist/mikado.custom.xxxx.min.js` or when format is module to `dist/mikado.custom.module.xxxx.min.js` (the \"xxxx\" is a hash based on the used build flags).\n\n\u003ca name=\"build-flags\" id=\"builds\"\u003e\u003c/a\u003e\n\n##### Supported Build Flags\n\n\u003ctable\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eFlag\u003c/td\u003e\n        \u003ctd\u003eValues\u003c/td\u003e\n        \u003ctd\u003eInfo\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eDEBUG\u003c/td\u003e\n        \u003ctd\u003etrue, \u003cb\u003efalse\u003c/b\u003e\u003c/td\u003e\n        \u003ctd\u003eOutput debug information to the console (default: false)\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eSUPPORT_CACHE\u003c/td\u003e\n        \u003ctd\u003etrue, false\u003c/td\u003e\n        \u003ctd\u003eDOM State Cache\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eSUPPORT_EVENTS\u003c/td\u003e\n        \u003ctd\u003etrue, false\u003c/td\u003e\n        \u003ctd\u003eRouting \u0026 Event Delegation (template event bindings)\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eSUPPORT_KEYED\u003c/td\u003e\n        \u003ctd\u003etrue, false\u003c/td\u003e\n        \u003ctd\u003eSupport for keyed recycling (reconciliation)\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eSUPPORT_WEB_COMPONENTS\u003c/td\u003e\n        \u003ctd\u003etrue, false\u003c/td\u003e\n        \u003ctd\u003eSupport for web components (Shadow DOM)\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eSUPPORT_DOM_HELPERS\u003c/td\u003e\n        \u003ctd\u003etrue, false\u003c/td\u003e\n        \u003ctd\u003eDOM Manipulation Helpers\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eSUPPORT_CACHE_HELPERS\u003c/td\u003e\n        \u003ctd\u003etrue, false\u003c/td\u003e\n        \u003ctd\u003eDOM Cache Helpers\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eSUPPORT_ASYNC\u003c/td\u003e\n        \u003ctd\u003etrue, false\u003c/td\u003e\n        \u003ctd\u003eAsynchronous Rendering (support Promises)\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eSUPPORT_POOLS\u003c/td\u003e\n        \u003ctd\u003etrue, false\u003c/td\u003e\n        \u003ctd\u003eSupport component pools for keyed and non-keyed recycle strategies\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eSUPPORT_REACTIVE\u003c/td\u003e\n        \u003ctd\u003etrue, false\u003c/td\u003e\n        \u003ctd\u003eUse reactive data binding\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eREACTIVE_ONLY\u003c/td\u003e\n        \u003ctd\u003etrue, \u003cb\u003efalse\u003c/b\u003e\u003c/td\u003e\n        \u003ctd\u003eUse a full reactive approach for all views, exclude \u003ccode\u003e.render()\u003c/code\u003e and dependencies from build (default: false)\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eSUPPORT_CALLBACKS\u003c/td\u003e\n        \u003ctd\u003etrue, false\u003c/td\u003e\n        \u003ctd\u003eUse callbacks for specific render tasks\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eSUPPORT_COMPACT_TEMPLATE\u003c/td\u003e\n        \u003ctd\u003etrue, false\u003c/td\u003e\n        \u003ctd\u003eTurn on when templates are compiled with the \u003ccode\u003ecompact\u003c/code\u003e or \u003ccode\u003edefault\u003c/code\u003e strategy\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eSUPPORT_COMPILE\u003c/td\u003e\n        \u003ctd\u003etrue, false\u003c/td\u003e\n        \u003ctd\u003eUse the runtime compiler\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd colspan=\"3\"\u003e\u003cbr\u003e\u003cb\u003eCompiler Flags\u003c/b\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eRELEASE\u003cbr\u003e\u003cbr\u003e\u003cbr\u003e\u003cbr\u003e\u003cbr\u003e\u003c/td\u003e\n        \u003ctd\u003e\u003cb\u003ecustom\u003c/b\u003e\u003cbr\u003ecustom.module\u003cbr\u003ebundle\u003cbr\u003ebundle.module\u003cbr\u003ees5\u003cbr\u003elight\u003c/td\u003e\n        \u003ctd\u003eOutput debug information to the console (default: false)\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003ePOLYFILL\u003c/td\u003e\n        \u003ctd\u003etrue, \u003cb\u003efalse\u003c/b\u003e\u003c/td\u003e\n        \u003ctd\u003eInclude Polyfills (based on LANGUAGE_OUT)\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003ePROFILER\u003c/td\u003e\n        \u003ctd\u003etrue, \u003cb\u003efalse\u003c/b\u003e\u003c/td\u003e\n        \u003ctd\u003eJust used for automatic performance tests\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eLANGUAGE_OUT\u003cbr\u003e\u003cbr\u003e\u003cbr\u003e\u003cbr\u003e\u003cbr\u003e\u003cbr\u003e\u003cbr\u003e\u003cbr\u003e\u003cbr\u003e\u003cbr\u003e\u003cbr\u003e\u003c/td\u003e\n        \u003ctd\u003eECMASCRIPT3\u003cbr\u003eECMASCRIPT5\u003cbr\u003eECMASCRIPT_2015\u003cbr\u003eECMASCRIPT_2016\u003cbr\u003eECMASCRIPT_2017\u003cbr\u003eECMASCRIPT_2018\u003cbr\u003eECMASCRIPT_2019\u003cbr\u003eECMASCRIPT_2020\u003cbr\u003eECMASCRIPT_2021\u003cbr\u003eECMASCRIPT_2022\u003cbr\u003eECMASCRIPT_NEXT\u003cbr\u003eSTABLE\u003c/td\u003e\n        \u003ctd\u003eTarget language\u003c/td\u003e\n    \u003c/tr\u003e\n\u003c/table\u003e\n\n---\n\nCopyright 2019-2024 Nextapps GmbH\u003cbr\u003e\nReleased under the \u003ca href=\"http://www.apache.org/licenses/LICENSE-2.0.html\" target=\"_blank\"\u003eApache 2.0 License\u003c/a\u003e\u003cbr\u003e\n","funding_links":["https://github.com/sponsors/ts-thomas","https://opencollective.com/mikado","https://liberapay.com/ts-thomas","https://patreon.com/user?u=96245532","https://www.paypal.com/donate/?hosted_button_id=GEVR88FC9BWRW","https://salt.bountysource.com/teams/ts-thomas","https://opencollective.com/mikado/donate","https://github.com/sponsors/ts-thomas/","https://liberapay.com/ts-thomas/donate","https://www.patreon.com/user?u=96245532"],"categories":["JavaScript","others"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnextapps-de%2Fmikado","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnextapps-de%2Fmikado","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnextapps-de%2Fmikado/lists"}