{"id":24083343,"url":"https://github.com/mitranim/gax","last_synced_at":"2025-04-30T18:23:18.975Z","repository":{"id":57619352,"uuid":"389304927","full_name":"mitranim/gax","owner":"mitranim","description":"Simple system for writing HTML as Go code. Use normal Go conditionals, loops and functions. Benefit from typing and code analysis. Better performance than templating. Tiny and dependency-free.","archived":false,"fork":false,"pushed_at":"2023-06-19T17:21:09.000Z","size":80,"stargazers_count":20,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-26T06:56:56.290Z","etag":null,"topics":["golang","html","rendering","templating"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mitranim.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":"2021-07-25T09:03:21.000Z","updated_at":"2024-12-23T13:56:00.000Z","dependencies_parsed_at":"2024-06-21T14:24:35.611Z","dependency_job_id":null,"html_url":"https://github.com/mitranim/gax","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mitranim%2Fgax","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mitranim%2Fgax/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mitranim%2Fgax/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mitranim%2Fgax/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mitranim","download_url":"https://codeload.github.com/mitranim/gax/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251758744,"owners_count":21639100,"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":["golang","html","rendering","templating"],"created_at":"2025-01-09T23:56:26.133Z","updated_at":"2025-04-30T18:23:18.943Z","avatar_url":"https://github.com/mitranim.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Overview\n\nSimple system for writing HTML/XML as Go code. Better-performing replacement for `html/template` and `text/template`. Vaguely inspired by JS library https://github.com/mitranim/prax.\n\nAdvantages over string-based templating:\n\n  * No weird special language to learn.\n  * Normal Go code.\n  * Normal Go conditionals.\n  * Normal Go loops.\n  * Normal Go functions.\n  * Normal Go static typing.\n  * Normal Go code analysis.\n  * Much better performance.\n\nOther features / benefits:\n\n  * Tiny and dependency-free (only stdlib).\n\n## TOC\n\n* [Usage](#usage)\n* [Performance](#performance)\n* [Changelog](#changelog)\n* [License](#license)\n* [Misc](#misc)\n\n## Usage\n\nAPI docs: https://pkg.go.dev/github.com/mitranim/gax.\n\n```golang\npackage main\n\nimport (\n  \"fmt\"\n\n  gax \"github.com/mitranim/gax\"\n)\n\nvar (\n  E  = gax.E\n  AP = gax.AP\n)\n\nfunc main() {\n  fmt.Println(Page(mockDat))\n  // \u003c!doctype html\u003e\u003chtml lang=\"en\"\u003e\u003chead\u003e\u003cmeta charset=\"utf-8\"\u003e\u003clink rel=\"icon\" href=\"data:;base64,=\"\u003e\u003ctitle\u003ePosts\u003c/title\u003e\u003c/head\u003e\u003cbody\u003e\u003ch1 class=\"title\"\u003ePosts\u003c/h1\u003e\u003ch2\u003ePost0\u003c/h2\u003e\u003ch2\u003ePost1\u003c/h2\u003e\u003c/body\u003e\u003c/html\u003e\n}\n\nfunc Page(dat Dat) gax.Bui {\n  return gax.F(\n    gax.Str(gax.Doctype),\n    E(`html`, AP(`lang`, `en`),\n      E(`head`, nil,\n        E(`meta`, AP(`charset`, `utf-8`)),\n        E(`link`, AP(`rel`, `icon`, `href`, `data:;base64,=`)),\n\n        // Use normal Go conditionals.\n        func(bui *gax.Bui) {\n          if dat.Title != `` {\n            bui.E(`title`, nil, dat.Title)\n          } else {\n            bui.E(`title`, nil, `test markup`)\n          }\n        },\n      ),\n\n      E(`body`, nil,\n        E(`h1`, AP(`class`, `title`), `Posts`),\n\n        // Use normal Go loops.\n        func(bui *gax.Bui) {\n          for _, post := range dat.Posts {\n            bui.E(`h2`, nil, post)\n          }\n        },\n      ),\n    ),\n  )\n}\n\nvar mockDat = Dat{\n  Title: `Posts`,\n  Posts: []string{`Post0`, `Post1`},\n}\n\ntype Dat struct {\n  Title string\n  Posts []string\n}\n```\n\n## Performance\n\nGax easily beats `text/template` and `html/template`. The more complex a template is, the better it gets.\n\nThe static benchmark is \"unfair\" because the Gax version renders just once into a global variable. This is recommended for all completely static markup. Prerendering is also possible with `text/template` and `html/template`, but syntactically inconvenient and usually avoided. With Gax it's syntactically convenient and easily done, and the benchmark reflects that.\n\nThe dynamic benchmark is intentionally naive, avoiding some Gax optimizations such as static prerender, to mimic simple user code.\n\n```sh\ngo test -bench . -benchmem\n```\n\n```\ncpu: Intel(R) Core(TM) i9-8950HK CPU @ 2.90GHz\nBenchmark_template_static-12   17002192    67.31 ns/op     48 B/op     1 allocs/op\nBenchmark_gax_static-12        640101200   1.845 ns/op      0 B/op     0 allocs/op\nBenchmark_template_dynamic-12      9205   130812 ns/op  51811 B/op  1370 allocs/op\nBenchmark_gax_dynamic-12          70465    17090 ns/op  10376 B/op   169 allocs/op\n```\n\n## Changelog\n\n### `v0.3.1`\n\nAdded various attribute-manipulating methods to `Attr`, `Attrs`, `Elem`.\n\n### `v0.3.0`\n\n* Renamed `.Append` to `.AppendTo` for consistency with other libraries.\n* `Elem` with empty `.Tag` no longer renders anything. As a result, zero value of `Elem` is the same as nil. This can be convenient for functions that return `Elem`.\n* Added `LinkBlank`.\n* Require Go 1.20.\n\n### `v0.2.1`\n\nChild rendering now supports walking `[]Ren` and `[]T where T is Ren`.\n\n### `v0.2.0`\n\nAPI revision. Now supports both the append-only style via `Bui.E` and the expression style via free `E`. Mix and match for simpler code.\n\n### `v0.1.4`\n\n`Bui.Child` also supports `func(E)`.\n\n### `v0.1.3`\n\nAdded `Bui.With` and `Ebui`.\n\n### `v0.1.2`\n\nMinor syntactic bugfix.\n\n### `v0.1.1`\n\nConverted methods `.WriteTo(*[]byte)` methods to `.Append([]byte) []byte` for better compliance with established interfaces.\n\n### `v0.1.0`\n\nInit.\n\n## License\n\nhttps://unlicense.org\n\n## Misc\n\nI'm receptive to suggestions. If this library _almost_ satisfies you but needs changes, open an issue or chat me up. Contacts: https://mitranim.com/#contacts\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmitranim%2Fgax","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmitranim%2Fgax","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmitranim%2Fgax/lists"}