{"id":13367051,"url":"https://github.com/sipin/Gorazor","last_synced_at":"2025-03-12T18:31:47.607Z","repository":{"id":16582745,"uuid":"19336908","full_name":"sipin/gorazor","owner":"sipin","description":"Razor view engine for go","archived":false,"fork":false,"pushed_at":"2024-07-22T14:36:14.000Z","size":519,"stargazers_count":859,"open_issues_count":2,"forks_count":91,"subscribers_count":57,"default_branch":"main","last_synced_at":"2024-10-25T05:24:54.128Z","etag":null,"topics":["fast","go","template-engine"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sipin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"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}},"created_at":"2014-05-01T05:30:31.000Z","updated_at":"2024-10-20T13:14:19.000Z","dependencies_parsed_at":"2024-06-18T14:04:40.310Z","dependency_job_id":"9bba106f-4904-4536-b10b-4cf6c7b3eea4","html_url":"https://github.com/sipin/gorazor","commit_stats":{"total_commits":376,"total_committers":10,"mean_commits":37.6,"dds":0.3936170212765957,"last_synced_commit":"67f855c09c0a93f51aa2bdd4d56c47aa9d747ecb"},"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sipin%2Fgorazor","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sipin%2Fgorazor/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sipin%2Fgorazor/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sipin%2Fgorazor/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sipin","download_url":"https://codeload.github.com/sipin/gorazor/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243271381,"owners_count":20264449,"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":["fast","go","template-engine"],"created_at":"2024-07-30T00:01:37.383Z","updated_at":"2025-03-12T18:31:47.600Z","avatar_url":"https://github.com/sipin.png","language":"Go","readme":"# gorazor\n\n[![Go Report Card](https://goreportcard.com/badge/github.com/sipin/gorazor?v=1)](https://goreportcard.com/report/github.com/sipin/gorazor)\n\u003ca href='https://github.com/jpoles1/gopherbadger' target='_blank'\u003e![gopherbadger-tag-do-not-edit](https://img.shields.io/badge/Go%20Coverage-90%25-brightgreen.svg?longCache=true\u0026style=flat)\u003c/a\u003e\n[![996.icu](https://img.shields.io/badge/link-996.icu-red.svg)](https://996.icu)\n[![LICENSE](https://img.shields.io/badge/license-Anti%20996-blue.svg)](https://github.com/996icu/996.ICU/blob/master/LICENSE)\n\n`gorazor` is the Go port of the razor view engine originated from [asp.net in 2011](http://weblogs.asp.net/scottgu/archive/2010/07/02/introducing-razor.aspx). In summary, `gorazor` is:\n\n* Extremely Fast. Templates are converted into Go code and then compiled with optimizations.\n* Concise syntax, no delimiter like `\u003c?`, `\u003c%`, or `{{`.\n  * Original [Razor Syntax](http://www.asp.net/web-pages/tutorials/basics/2-introduction-to-asp-net-web-programming-using-the-razor-syntax) \u0026 [quick reference](http://haacked.com/archive/2011/01/06/razor-syntax-quick-reference.aspx/) for asp.net.\n* Able to mix go code in view template\n  * Insert code block to import \u0026 call arbitrary go modules \u0026 functions\n  * Flow controls are just Go, no need to learn another mini-language\n* Code generation approach\n  * No reflection overhead\n  * Go compiler validation for free\n* Strong type view model\n* Embedding templates support\n* Layout/Section support\n\n# Extremely Fast\n\n`gorazor` is about **20X** times faster than [html/template](https://golang.org/pkg/html/template/) when using standard `strings.Builder` for template writing.\n\nWhen using `quicktemplate`'s `ByteBuffer` and `unsafeStrToBytes` method to for template writing, `gorazor`'s performance is comparable to [quicktemplate](https://github.com/valyala/quicktemplate), if not faster.\n\nBenchmark results:\n```bash\n$ go test -bench='Benchmark(Razor|RazorQuick|Quick|HTML)Template' -benchmem github.com/valyala/quicktemplate/tests github.com/sipin/gorazor/tests\ngoos: windows\ngoarch: amd64\npkg: github.com/valyala/quicktemplate/tests\nBenchmarkQuickTemplate1-8       50000000                35.6 ns/op             0 B/op          0 allocs/op\nBenchmarkQuickTemplate10-8      10000000               152 ns/op               0 B/op          0 allocs/op\nBenchmarkQuickTemplate100-8      1000000              1460 ns/op               0 B/op          0 allocs/op\nBenchmarkHTMLTemplate1-8         2000000               712 ns/op             608 B/op         21 allocs/op\nBenchmarkHTMLTemplate10-8         500000              3586 ns/op            2834 B/op        111 allocs/op\nBenchmarkHTMLTemplate100-8         50000             35180 ns/op           28055 B/op       1146 allocs/op\nPASS\nok      github.com/valyala/quicktemplate/tests  11.360s\ngoos: windows\ngoarch: amd64\npkg: github.com/sipin/gorazor/tests\nBenchmarkRazorTemplate1-8                       30000000                49.8 ns/op           224 B/op          3 allocs/op\nBenchmarkRazorTemplate10-8                      10000000               122 ns/op             480 B/op          4 allocs/op\nBenchmarkRazorTemplate100-8                      2000000               931 ns/op            4064 B/op          7 allocs/op\nBenchmarkRazorQuickTemplate1-8                  100000000               19.9 ns/op             0 B/op          0 allocs/op\nBenchmarkRazorQuickTemplate10-8                 20000000                82.5 ns/op             0 B/op          0 allocs/op\nBenchmarkRazorQuickTemplate100-8                 2000000               767 ns/op               0 B/op          0 allocs/op\nBenchmarkRazorQuickTemplateOriginal1-8          100000000               17.4 ns/op             0 B/op          0 allocs/op\nBenchmarkRazorQuickTemplateOriginal10-8         20000000                68.8 ns/op             0 B/op          0 allocs/op\nBenchmarkRazorQuickTemplateOriginal100-8         2000000               656 ns/op               0 B/op          0 allocs/op\nPASS\nok      github.com/sipin/gorazor/tests  19.921s\n```\n\n* `BenchmarkRazorQuickTemplate`'s manually modified ensure **exact output** as quicktemplate for comparism.\n* `BenchmarkRazorQuickTemplateOriginal` are `gorazor`'s default code-gen, which produce less white-space, thus faster.\n\n# Usage\n\n`gorazor` supports `go 1.10` and above, for go version **below 1.10**, you may use [gorazor classic version](https://github.com/sipin/gorazor/releases/tag/v1.0).\n\n`go 1.12` are recommended for better **compiler optimization**.\n\n## Install\n\n```sh\ngo get github.com/sipin/gorazor\n```\n\n## Usage\n\n* Process folder: `gorazor template_folder output_folder`\n* Process file: `gorazor template_file output_file`\n\n## Examples\n\n[Examples] gives examples using layout / helper etc.\n\nWhen using layout, you may need to set `-prefix` parameter, like:\n\n```bash\ngit clone https://github.com/sipin/gorazor/\ncd gorazor\ngo build\n\n# -prefix parameter here tells gorazor the current folder is the base path for github.com/sipin/gorazor\n# So that, when importing \"github.com/sipin/gorazor/examples/tpl/layout\" in example/tpl/home.gohtml\n# gorazor will know how to find the layout/helper files\n./gorazor -prefix github.com/sipin/gorazor ./examples/tpl ./examples/tpl\ngo run example/main.go\n```\n\n# Syntax\n\n## Variable\n\n* `@variable` to insert **string** variable into html template\n  * variable could be wrapped by arbitrary go functions\n  * variable inserted will be automatically [escaped](http://golang.org/pkg/html/template/#HTMLEscapeString)\n\n```html\n\u003cdiv\u003eHello @user.Name\u003c/div\u003e\n```\n\n```html\n\u003cdiv\u003eHello @strings.ToUpper(req.CurrentUser.Name)\u003c/div\u003e\n```\n\nUse `raw` to skip escaping:\n\n```html\n\u003cdiv\u003e@raw(user.Name)\u003c/div\u003e\n```\n\nOnly use `raw` when you are 100% sure what you are doing, please always be aware of [XSS attack](http://en.wikipedia.org/wiki/Cross-site_scripting).\n\n## Flow Control\n\n```php\n@if .... {\n\t....\n}\n\n@if .... {\n\t....\n} else {\n\t....\n}\n\n@for .... {\n\n}\n\n@{\n\tswitch .... {\n\tcase ....:\n\t      \u003cp\u003e...\u003c/p\u003e\n\tcase 2:\n\t      \u003cp\u003e...\u003c/p\u003e\n\tdefault:\n\t      \u003cp\u003e...\u003c/p\u003e\n\t}\n}\n```\n\nPlease use [example](https://github.com/sipin/gorazor/blob/master/examples/tpl/home.gohtml) for reference.\n\n## Code block\n\nArbitrary go code could be used in templates, like creating a new variable.\n\n```html\n@{\n\tusername := u.Name\n\tif u.Email != \"\" {\n\t\tusername += \"(\" + u.Email + \")\"\n\t}\n}\n\u003cdiv class=\"welcome\"\u003e\n\u003ch4\u003eHello @username\u003c/h4\u003e\n\u003c/div\u003e\n```\n\nIt's recommended to keep clean separation of code \u0026 view. **Please consider** move logic into your code before creating a code block in a template.\n\n## Declaration\n\nThe **first code block** in template is strictly for declaration:\n\n* imports\n* model type\n* layout\n\nlike:\n\n```go\n@{\n\timport  (\n\t\t\"kp/models\"   //import `\"kp/models\"` package\n\t\t\"tpl/layout\"  //import tpl/layout namespace\n\t)\n\n\tlayout := layout.Base //Use layout package's **Base func** for layout\n\tvar user *models.User //1st template param\n\tvar blog *models.Blog //2nd template param\n}\n...\n```\n\n**first code block** must be at the beginning of the template, i.e. before any html.\n\nAny other codes inside the first code block will **be ignored**.\n\nimport must be wrapped in `()`, `import \"package_name\"` is not yet supported.\n\nThe variables declared in **first code block** will be the models of the template, i.e. the parameters of generated function.\n\nIf your template doesn't need any model input, then just leave it blank.\n\n## Helper / Include other template\n\nAs `gorazor` compiles templates to go function, embedding another template is just calling the generated function, like any other go function.\n\nHowever, if the templates are designed to be embedded, they must be under `helper` namespace, i.e. put them in `helper` sub-folder.\n\nSo, using a helper template is similar to:\n\n```html\n\n@if msg != \"\" {\n\t\u003cdiv\u003e@helper.ShowMsg(msg)\u003c/div\u003e\n}\n\n```\n\n`gorazor` won't HTML escape the output of `helper.XXX`.\n\nPlease use [example](https://github.com/sipin/gorazor/blob/master/examples/tpl/home.gohtml) for reference.\n\n## Layout \u0026 Section\n\nThe syntax for declaring layout is a bit tricky, in the example mentioned above:\n\n```go\n@{\n\timport  (\n\t\t\"tpl/layout\"\n\t)\n\n\tlayout := layout.Base //Use layout package's **base func** for layout\n}\n```\n\n`\"tpl/layout\"` **is** the layout package namespace, and the `layout` variable refers to `\"layout.Base\"` func, which should be generated by `tpl/layout/base.gohtml`.\n\n\u003e Must use `layout` as the variable name\n\n### Package / Variable convention\n\n* The namespace/folder name for layout templates **must be** `layout`\n  * `gorazor` relies on this to determine if a template is for layout\n* The template `variable name` also **must be** `layout`\n\nA layout file `tpl/layout/base.gohtml` may look like:\n\n```html\n@{\n\tvar body string\n\tvar sidebar string\n\tvar footer string\n\tvar title string\n\tvar css string\n\tvar js string\n}\n\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n\u003chead\u003e\n\t\u003cmeta charset=\"utf-8\" /\u003e\n\t\u003ctitle\u003e@title\u003c/title\u003e\n\u003c/head\u003e\n\u003cbody\u003e\n    \u003cdiv class=\"container\"\u003e@body\u003c/div\u003e\n    \u003cdiv class=\"sidebar\"\u003e@sidebar\u003c/div\u003e\n    \u003cdiv class=\"footer\"\u003e@footer\u003c/div\u003e\n\t@js\n  \u003c/body\u003e\n\u003c/html\u003e\n```\n\nIt's just a usual `gorazor` template, but:\n\n* First param must be `var body string` (As it's always required, maybe we could remove it in future?)\n* All params **must be** string, each param is considered as a **section**, the variable name is the **section name**.\n* Under `layout` package, i.e. within \"layout\" folder.\n  * Optionally, use `isLayout := true` to declare a template as layout\n\nA template using such layout `tpl/index.gohtml` may look like:\n\n```html\n@{\n\timport (\n\t\t\"tpl/layout\"\n\t)\n\n\tlayout := layout.Base\n}\n\n@section footer {\n\t\u003cdiv\u003eCopyright 2014\u003c/div\u003e\n}\n\n\u003ch2\u003eWelcome to homepage\u003c/h2\u003e\n```\n\nIt's also possible to use import alias:\n\n```html\n@{\n\timport (\n\t\tshare \"tpl/layout\"\n\t)\n\n\tlayout := share.Base\n}\n```\n\nWith the page, the page content will be treated as the `body` section in the layout.\n\nThe other section content need to be wrapped with\n```\n@section SectionName {\n\t....\n}\n```\n\nThe template doesn't need to specify all sections defined in the layout. If a section is not specified, it will be considered as `\"\"`.\n\nThus, it's possible for the layout to define default section content in such manner:\n\n```html\n@{\n\tvar body string\n\tvar sidebar string\n}\n\n\u003cbody\u003e\n    \u003cdiv class=\"container\"\u003e@body\u003c/div\u003e\n    @if sidebar == \"\" {\n    \u003cdiv class=\"sidebar\"\u003eI'm the default side bar\u003c/div\u003e\n\t} else {\n    \u003cdiv class=\"sidebar\"\u003e@sidebar\u003c/div\u003e\n\t}\n\u003c/body\u003e\n```\n\n* A layout should be able to use another layout, it's just function call.\n\n# Conventions\n\n* Template **folder name** will be used as **package name** in generated code\n* Template file name must has the extension name `.gohtml`\n* Template strip of `.gohtml` extension name will be used as the **function name** in generated code, with **first letter Capitalized**.\n  * So that the function will be accessible to other modules. (I hate GO about this.)\n* Helper templates **must** has the package name **helper**, i.e. in `helper` folder.\n* Layout templates **must** has the package name **layout**, i.e. in `layout` folder.\n\n# Example\n\nHere is a simple example of [gorazor templates](https://github.com/sipin/gorazor/tree/master/examples/tpl) and the corresponding [generated codes](https://github.com/sipin/gorazor/tree/master/examples/gen).\n\n# FAQ\n\n## IDE / Editor support?\n\n### Sublime Text 2/3\n\n* **Syntax highlight** Search \u0026 install `gorazor` via Package Control.\n* **Context aware auto-completion**, you may need to [manually modify](https://github.com/sipin/GoSublime/commit/fd0b979e7cc1d8f2438bb314399c2456d16f3ffb) GoSublime package, basically replace `gscomplete.py` in with [this](https://raw.githubusercontent.com/sipin/GoSublime/gorazor/gscomplete.py) and `gslint.py` with [this](https://raw.githubusercontent.com/sipin/GoSublime/gorazor/gslint.py)\n\n### Emacs\n[web-mode](http://web-mode.org/) supports Razor template engine, so add this into your Emacs config file:\n\n```lisp\n(require 'web-mode)\n(add-hook 'web-mode-hook  'my-web-mode-hook)\n(add-to-list 'auto-mode-alist '(\"\\\\.html?\\\\'\" . web-mode))\n(add-to-list 'auto-mode-alist '(\"\\\\.gohtml\\\\'\" . web-mode))\n(add-to-list 'auto-mode-alist '(\"\\\\.js\\\\'\" . web-mode))\n(setq web-mode-engines-alist '((\"razor\" . \"\\\\.gohtml\\\\'\")))\n```\n\n# Credits\n\nThe very [first version](https://github.com/sipin/gorazor/releases/tag/vash) of `gorazor` is a hack of razor's port in javascript: [vash](https://github.com/kirbysayshi/vash), thus requires node's to run.\n\n`gorazor` has been though several rounds of refactoring, and it has completely rewritten in pure Go. Nonetheless, THANK YOU [@kirbysayshi](https://github.com/kirbysayshi) for Vash! Without Vash, `gorazor` may never start.\n\n# LICENSE\n\n[LICENSE](LICENSE)? Well, [WTFPL](http://www.wtfpl.net/about/) and [996.icu](LICENSE).\n\n# Project Status\n\nFeature completed.\n\nArchived [todo](https://github.com/sipin/gorazor/blob/master/todo.md)\n","funding_links":[],"categories":["模板引擎"],"sub_categories":["高级控制台界面","高級控制台界面"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsipin%2FGorazor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsipin%2FGorazor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsipin%2FGorazor/lists"}