{"id":13502976,"url":"https://github.com/maciejhirsz/ramhorns","last_synced_at":"2025-05-14T22:09:12.439Z","repository":{"id":40346191,"uuid":"172568075","full_name":"maciejhirsz/ramhorns","owner":"maciejhirsz","description":"Fast Mustache template engine implementation in pure Rust.","archived":false,"fork":false,"pushed_at":"2025-02-13T11:42:24.000Z","size":314,"stargazers_count":326,"open_issues_count":17,"forks_count":31,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-05-14T04:29:01.386Z","etag":null,"topics":["handlebars","mustache","mustache-templates","rust","templates","templating-engine"],"latest_commit_sha":null,"homepage":"https://crates.io/crates/ramhorns","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/maciejhirsz.png","metadata":{"files":{"readme":"README.md","changelog":null,"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,"zenodo":null},"funding":{"github":["maciejhirsz"]}},"created_at":"2019-02-25T19:12:20.000Z","updated_at":"2025-05-11T18:45:20.000Z","dependencies_parsed_at":"2024-01-14T07:04:11.652Z","dependency_job_id":"8ab369e1-9080-4e95-bf1d-4ea9676dc097","html_url":"https://github.com/maciejhirsz/ramhorns","commit_stats":{"total_commits":79,"total_committers":8,"mean_commits":9.875,"dds":0.6835443037974683,"last_synced_commit":"a6d020e9df3c4690301ac67b0b59360b0aeb2681"},"previous_names":[],"tags_count":25,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maciejhirsz%2Framhorns","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maciejhirsz%2Framhorns/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maciejhirsz%2Framhorns/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maciejhirsz%2Framhorns/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/maciejhirsz","download_url":"https://codeload.github.com/maciejhirsz/ramhorns/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254110287,"owners_count":22016387,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["handlebars","mustache","mustache-templates","rust","templates","templating-engine"],"created_at":"2024-07-31T22:02:32.321Z","updated_at":"2025-05-14T22:09:07.414Z","avatar_url":"https://github.com/maciejhirsz.png","language":"Rust","funding_links":["https://github.com/sponsors/maciejhirsz"],"categories":["Rust","rust"],"sub_categories":[],"readme":"\u003cimg src=\"https://raw.githubusercontent.com/maciejhirsz/ramhorns/master/ramhorns.svg?sanitize=true\" alt=\"Ramhorns logo\" width=\"250\" align=\"right\"\u003e\n\n# Ramhorns\n\n[![Tests badge](https://github.com/maciejhirsz/ramhorns/workflows/tests/badge.svg?branch=master)](https://github.com/maciejhirsz/ramhorns/actions?query=workflow%3Atests)\n[![Crates.io version badge](https://img.shields.io/crates/v/ramhorns.svg)](https://crates.io/crates/ramhorns)\n[![Docs](https://docs.rs/ramhorns/badge.svg)](https://docs.rs/ramhorns)\n[![Crates.io license badge](https://img.shields.io/crates/l/ramhorns.svg)](https://crates.io/crates/ramhorns)\n\nFast [**Mustache**](https://mustache.github.io/) template engine implementation\nin pure Rust.\n\n**Ramhorns** loads and processes templates **at runtime**. It comes with a derive macro\nwhich allows for templates to be rendered from native Rust data structures without doing\ntemporary allocations, intermediate `HashMap`s or what have you.\n\nWith a touch of magic 🎩, the power of friendship 🥂, and a sparkle of\n[FNV hashing](https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function)\n✨, render times easily compete with static template engines like\n[**Askama**](https://github.com/djc/askama).\n\n### Cargo.toml\n\n```toml\n[dependencies]\nramhorns = \"0.5\"\n```\n\n### Example\n\n```rust\nuse ramhorns::{Template, Content};\n\n#[derive(Content)]\nstruct Post\u003c'a\u003e {\n    title: \u0026'a str,\n    teaser: \u0026'a str,\n}\n\n#[derive(Content)]\nstruct Blog\u003c'a\u003e {\n    title: String,        // Strings are cool\n    posts: Vec\u003cPost\u003c'a\u003e\u003e, // \u0026'a [Post\u003c'a\u003e] would work too\n}\n\n// Standard Mustache action here\nlet source = \"\u003ch1\u003e{{title}}\u003c/h1\u003e\\\n              {{#posts}}\u003carticle\u003e\u003ch2\u003e{{title}}\u003c/h2\u003e\u003cp\u003e{{teaser}}\u003c/p\u003e\u003c/article\u003e{{/posts}}\\\n              {{^posts}}\u003cp\u003eNo posts yet :(\u003c/p\u003e{{/posts}}\";\n\nlet tpl = Template::new(source).unwrap();\n\nlet rendered = tpl.render(\u0026Blog {\n    title: \"My Awesome Blog!\".to_string(),\n    posts: vec![\n        Post {\n            title: \"How I tried Ramhorns and found love 💖\",\n            teaser: \"This can happen to you too\",\n        },\n        Post {\n            title: \"Rust is kinda awesome\",\n            teaser: \"Yes, even the borrow checker! 🦀\",\n        },\n    ]\n});\n\nassert_eq!(rendered, \"\u003ch1\u003eMy Awesome Blog!\u003c/h1\u003e\\\n                      \u003carticle\u003e\\\n                          \u003ch2\u003eHow I tried Ramhorns and found love 💖\u003c/h2\u003e\\\n                          \u003cp\u003eThis can happen to you too\u003c/p\u003e\\\n                      \u003c/article\u003e\\\n                      \u003carticle\u003e\\\n                          \u003ch2\u003eRust is kinda awesome\u003c/h2\u003e\\\n                          \u003cp\u003eYes, even the borrow checker! 🦀\u003c/p\u003e\\\n                      \u003c/article\u003e\");\n```\n\n### Features\n\n+ Rendering common types, such as `\u0026str`, `String`, `bool`s, and numbers into `{{variables}}`.\n+ Unescaped printing with `{{{tripple-brace}}}` or `{{\u0026ampersant}}`.\n+ Rendering sections `{{#foo}} ... {{/foo}}`.\n+ Rendering inverse sections `{{^foo}} ... {{/foo}}`.\n+ Rendering partials `{{\u003efile.html}}`.\n+ Zero-copy [CommonMark](https://commonmark.org/) rendering from fields marked with `#[md]`.\n\n### Benches\n\nRendering a tiny template:\n```\ntest a_simple_ramhorns            ... bench:          82 ns/iter (+/- 4) = 1182 MB/s\ntest b_simple_askama              ... bench:         178 ns/iter (+/- 8) = 544 MB/s\ntest c_simple_tera                ... bench:         416 ns/iter (+/- 98) = 233 MB/s\ntest c_simple_tera_from_serialize ... bench:         616 ns/iter (+/- 33) = 157 MB/s\ntest d_simple_mustache            ... bench:         613 ns/iter (+/- 34) = 158 MB/s\ntest e_simple_handlebars          ... bench:         847 ns/iter (+/- 40) = 114 MB/s\n```\n\nRendering a tiny template with partials:\n```\ntest pa_partials_ramhorns         ... bench:          85 ns/iter (+/- 7) = 1141 MB/s\ntest pb_partials_askama           ... bench:         210 ns/iter (+/- 9) = 461 MB/s\ntest pc_partials_mustache         ... bench:         827 ns/iter (+/- 39) = 117 MB/s\ntest pd_partials_handlebars       ... bench:         846 ns/iter (+/- 29) = 114 MB/s\n```\n\nCompiling a template from a string:\n```\ntest xa_parse_ramhorns            ... bench:         190 ns/iter (+/- 10) = 821 MB/s\ntest xb_parse_mustache            ... bench:       3,229 ns/iter (+/- 159) = 48 MB/s\ntest xe_parse_handlebars          ... bench:       6,883 ns/iter (+/- 383) = 22 MB/s\n```\n\nWorth noting here is that [**Askama**](https://github.com/djc/askama) is processing\ntemplates at compile time and generates static rust code for rendering. This is great\nfor performance, but it also means you can't swap out templates without recompiling\nyour Rust binaries. In some cases, like for a static site generator, this is\nunfortunately a deal breaker.\n\nParsing the templates on runtime is never going to be free, however **Ramhorns** has\na really fast parser built on top of [**Logos**](https://github.com/maciejhirsz/logos),\nthat makes even that part of the process snappy.\n\nThe [**Mustache** crate](https://github.com/nickel-org/rust-mustache) is the closest\nthing to **Ramhorns** in design and feature set.\n\n### License\n\nRamhorns is free software, and is released under the terms of the [Mozilla Public License](https://www.mozilla.org/en-US/MPL/) version 2.0. See [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaciejhirsz%2Framhorns","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmaciejhirsz%2Framhorns","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaciejhirsz%2Framhorns/lists"}