{"id":23302241,"url":"https://github.com/noxum/compiledhandlebars","last_synced_at":"2025-08-22T07:32:08.126Z","repository":{"id":267476392,"uuid":"44325279","full_name":"noxum/CompiledHandlebars","owner":"noxum","description":"Compiled Handlebars for C# - Compiling Handlebars-Templates into native C# code for performant and type-safe serverside HTML rendering.","archived":false,"fork":false,"pushed_at":"2023-04-13T11:17:22.000Z","size":10081,"stargazers_count":9,"open_issues_count":2,"forks_count":3,"subscribers_count":11,"default_branch":"master","last_synced_at":"2024-12-10T15:33:33.265Z","etag":null,"topics":["asp-net","aspnet","aspnet-mvc","handlebars","handlebars-template","hbs","viewengine"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/noxum.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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}},"created_at":"2015-10-15T15:02:28.000Z","updated_at":"2024-08-25T05:04:36.000Z","dependencies_parsed_at":"2024-12-10T15:34:22.038Z","dependency_job_id":"007c354d-730e-4f2d-b53d-9e2302ee2efe","html_url":"https://github.com/noxum/CompiledHandlebars","commit_stats":null,"previous_names":["noxum/compiledhandlebars"],"tags_count":17,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/noxum%2FCompiledHandlebars","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/noxum%2FCompiledHandlebars/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/noxum%2FCompiledHandlebars/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/noxum%2FCompiledHandlebars/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/noxum","download_url":"https://codeload.github.com/noxum/CompiledHandlebars/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":230568920,"owners_count":18246432,"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":["asp-net","aspnet","aspnet-mvc","handlebars","handlebars-template","hbs","viewengine"],"created_at":"2024-12-20T10:19:31.380Z","updated_at":"2024-12-20T10:19:31.858Z","avatar_url":"https://github.com/noxum.png","language":"C#","readme":"Compiled Handlebars for C#\n==========================\n\nCompiling Handlebars-Templates into native C# code for performant and type-safe serverside HTML rendering.\n### About\nThis compiler is the result of Jakob Demler's bachelor thesis which covers the approach, design decisions, implementation details and its evaluation and can be found [here](ReadmeAssets/CompiledHandlebars_Jakob-Demler.pdf)\n\n### Project Status\nThis project is currently in a beta phase.\n\n### Features\n+ Get your type-errors at design-time\n+ Resolving partial and helper calls at design-time\n+ Trivial invocation: TemplateName.Render(viewModel);\n+ Minimal dependencies: resulting code just depends on System, System. Net and System.Text \n\n\n#### Performance\nA performance comparison was made against the microbenchmarks from the handlebars.js repository:\nhttps://github.com/wycats/handlebars.js/tree/master/bench\n\n| Microbenchmark | handlebars.js | CompiledHandlebars | Speedup |\n|----------------|---------------|--------------------|---------|\n|arrayeach|391 ops/ms|3039 ops/ms|7.77|\n|complex|120 ops/ms|1180 ops/ms|9.83|\n|data|295 ops/ms|1333 ops/ms|4.51|\n|depth1|228 ops/ms|3693 ops/ms|16.20|\n|depth2|63 ops/ms|1515 ops/ms|24.04|\n|partial-recursion|125 ops/ms|1895 ops/ms|15.16|\n|partial|211 ops/ms|905 ops/ms|4.29|\n|paths|2060 ops/ms|4646 ops/ms|2.25|\n|string|5563 ops/ms|13964 ops/ms|2.51|\n|variables|1991 ops/ms|4027 ops/ms|2.02|\n\n\n### Usage\n\n#### Visual Studio Integration\nJust install the vsix package from the CustomTool project and restart Visual Studio. Add a new Handlebars template to your solution (ending on .hbs) and then add \"HandlebarsCompiler\" to the file's CustomTool property. \nThe compiler will be invoked every time the Handlebar template is saved and will create a {templatename}.hbs.cs file containing the generated code.\n\n#### Basic Usage\nEvery Handlebars-Template needs a type which it renders. \nAs an example a class named \"PersonModel\" will serve:\n```CSharp\nnamespace ViewModels\n{\n  public class PersonModel\n  {\n    public string FirstName { get; set; }\n    public string LastName { get; set; }\n    public int Age { get; set; }\n    public List\u003cstring\u003e EMailAddresses { get; set; }\n  }\n}\n```\n\nNow, we must communicate the type to the HandlebarsCompiler. At the beginning of each Handlebars-Template there needs to be a socalled ModelToken:\n```Handlebars\n{{model NamespacePath.ClassName}}\n```\nFor our example that would be:\n```Handlebars\n{{model ViewModels.PersonModel}}\n```\nNote, that the type inside the ModelToken can also be a base class or interface of the actual ViewModel that is passed to the template.\n\n\nThe rest of the Handlebars-Templates follows standard Handlebars syntax and semantics.\nHere is the full example:\n```Handlebars\n{{model ViewModels.PersonModel}}\n\u003ch1\u003eHello {{FirstName}} {{LastName}}\u003c/h1\u003e\n\u003cp\u003eYou are {{Age}} years old and you have\n{{#if EMailAddresses}}\n  following email addresses:\n  \u003cul\u003e\n  {{#each EMailAddresses}}\n    \u003cli\u003e{{this}}\u003c/li\u003e\n  {{/each}}\n  \u003c/ul\u003e\n{{else}}\n  no email addresses.\n{{/if}}\u003c/p\u003e\n```\n\n#### Partials\nPartials do not need to be registered. Just be sure to compile the partial before the Handlebars-Template that uses that partial. For everything else standard handlebars.js logic applies.\n\n#### Helper Functions\nCompiledHandlebars allow the usage of helper functions. These must be static, return a string and be annotated by an attribute. Parameters are checked if they match at compile-time so overloading is possible. Other than that, they have no restrictions an can be placed anywhere in your codebase.\n\n```CSharp\n[CompiledHandlebarsHelperMethod]\npulic static string FullName(PersonModel model)\n{\n  return string.Concat(model.FirstName, \" \", model.LastName);\n}\n```\n\n#### Layout Functionality\nCompiledHandlebars offers differing functionality regarding layouts:\nAny HandlabarsTemplate can be rendered inside a HandlebarsLayout. HandlebarsLayouts differ from normal HandlebarsTemplates due to a special {{body}} token:\n```Handlebars\n{{model ViewModels.IPageModel}}\n\u003c!DOCTYPE html\u003e\n\u003chead\u003e\n  \u003ctitle\u003e{{Title}}\u003c/title\u003e\n  {{#if Keywords}}\u003cmeta name=\"keywords\" content=\"{{Keywords}}\"\u003e{{/if}}\n\u003c/head\u003e\n\u003cbody\u003e\n  {{body}}\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\nTo render a Handlebars-Template in that layout, use the {{layout}} Token right after the {{model}} token:\n```Handlebars\n{{model ViewModels.TitlePageModel}}\n{{layout MainLayout}}\n\u003ch1\u003e{{Headline}}\u003c/h1\u003e\n\u003cp\u003e{{Content}}\u003c/p\u003e\n```\n\nThe result of that template is equal to the following template:\n```Handlebars\n{{model ViewModels.TitlePageModel}}\n\u003c!DOCTYPE html\u003e\n\u003chead\u003e\n\u003ctitle\u003e{{Title}}\u003c/title\u003e\n  {{#if Keywords}}\u003cmeta name=\"keywords\" content=\"{{Keywords}}\"\u003e{{/if}}\n\u003c/head\u003e\n\u003cbody\u003e\n  \u003ch1\u003e{{Headline}}\u003c/h1\u003e\n  \u003cp\u003e{{Content}}\u003c/p\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\n\n\n\n\n## Compatability to Handlebars.js\n### Special Syntax\nBecause of the different approach to the Handlebars.js version (e.g. statically typed Handlebars-Templates), the compiler needs to know for which type your Handlebars-Template is meant.\nThis information is communicated to the compiler by a special ModelToken. Its syntax is straightforward:\n```Handlebars\n{{model NamespacePath.ClassName}}\n```\nFor example:\n```Handlebars\n{{model HandlebarsTest.TestViewModel}}\n```\n\nThis token needs to be at the beginning of every Handlebars-Template.\n\n#### Implemented Subset\n+ Html Encoding/Escaping\n+ Builtin Block Helpers\n+ Partials\n+ Helper Functions\n+ Whitespace Control\n \n#### Not Implemented:\n+ Mustache Blocks\n+ Block Helpers\n+ Subexpressions\n\n## Building\nFollowing prerequisites are needed in order to be able to build the solution:\n+ Visual Studio 2015\n+ Visual Studio 2015 Extensibility Tools\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnoxum%2Fcompiledhandlebars","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnoxum%2Fcompiledhandlebars","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnoxum%2Fcompiledhandlebars/lists"}