{"id":24668858,"url":"https://github.com/linuxerwang/goats-html","last_synced_at":"2025-10-26T00:38:53.071Z","repository":{"id":10902508,"uuid":"13197828","full_name":"linuxerwang/goats-html","owner":"linuxerwang","description":"goats-html is an atribute-based template system specialized for HTML.","archived":false,"fork":false,"pushed_at":"2022-04-09T18:47:32.000Z","size":2140,"stargazers_count":8,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-02T00:35:04.447Z","etag":null,"topics":["golang","html","template"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/linuxerwang.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}},"created_at":"2013-09-29T18:52:51.000Z","updated_at":"2020-02-11T17:21:17.000Z","dependencies_parsed_at":"2022-08-29T20:30:34.261Z","dependency_job_id":null,"html_url":"https://github.com/linuxerwang/goats-html","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/linuxerwang/goats-html","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/linuxerwang%2Fgoats-html","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/linuxerwang%2Fgoats-html/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/linuxerwang%2Fgoats-html/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/linuxerwang%2Fgoats-html/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/linuxerwang","download_url":"https://codeload.github.com/linuxerwang/goats-html/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/linuxerwang%2Fgoats-html/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278892184,"owners_count":26063945,"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","status":"online","status_checked_at":"2025-10-08T02:00:06.501Z","response_time":56,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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","template"],"created_at":"2025-01-26T09:17:47.485Z","updated_at":"2025-10-08T05:31:53.819Z","avatar_url":"https://github.com/linuxerwang.png","language":"Go","readme":"goats-html: Go Attribute-based Template System for HTML.\n\nWhat's New in version 0.3?\n==========================\n\ngoats-html version 0.3 introduces the capability to generate JavaScript\nfrom the HTML template. At present, it generates JavaScript code with [Google\nClosure Library](https://developers.google.com/closure/library/).\n\nTogether with this capability, version 0.3 also introduces officially the\nsupport for [Protocol Buffers](https://developers.google.com/protocol-buffers/).\nAnd this change breaks the compatibility with version 0.2!!! From version 0.3\na protocol buffer argument or variable must be followed with a \"[pb]\",\notherwise goats-html will simply treat it as a normal name and output it\nverbatim.\n\nThe specifier \"[pb]\" should also be added in the go:import and followed by\nthe protocol buffer package name, like the following snippet:\n\n```html\n\u003chtml go:import=\"proto: mycompany.client.proto [pb] frontend.client.proto\"\u003e\n\t\u003cdiv go:template=\"ProductCard\"\n\t\tgo:arg=\"product[pb]: proto.Product\"\n\t\tgo:var=\"resellers[pb]: product.resellers\"\u003e\n\t\t\u003cdiv\u003eName:\u003c/div\u003e\n\t\t\u003cdiv go:content=\"product.name\"\u003e\u003c/div\u003e\n\t\t\u003cdiv\u003ePrice:\u003c/div\u003e\n\t\t\u003cdiv go:content=\"product.price\"\u003e\u003c/div\u003e\n\t\u003c/div\u003e\n\u003c/html\u003e\n```\n\nNote that the protocol buffer field names have to remain the same as\nwhat are defined in the proto file. To support protocol buffer enum values,\na special rule was introduced in which if an identifier within a protocol\nbuffer reference experssion ends with a captialized first letter, then the\nwhole experssion will not be translated. Thus the following expression can\nbe correctly handled:\n\n```html\n\u003cdiv go:if=\"product.category == proto.Product.Category_Clothes\"\u003e\n...\n\u003c/div\u003e\n```\n\nAlso note that the generated Closure Library code uses JSON based wrapper\nfor protocol buffers. At present, a plugin for proto compiler named\n[jspb](https://github.com/linuxerwang/jspb) is able to generate such wrapper\nclasses.\n\nThe design of the generated JavaScript ensures that when it was compiled\n(together with the wrappers generated by jspb) with\n[Google Closure Compiler](https://developers.google.com/closure/compiler),\nthe end library can be obfuscated meanwhile exposes enough APIs for any\nJavaScript code to call (for instance, jQuery etc.). The following snippet\nshows such an example in jQuery:\n\n```javascript\n$( document ).ready(function() {\n\tvar jsonData = {\n\t\t\"product\": {\n\t\t\t\"name\": \"Kid shoes size 7\",\n\t\t\t\"price\": 14.99,\n\t\t\t\"resellers\": []\n\t\t}\n\t};\n\t// The name ProductListTemplate is exposed when obfuscated.\n\tvar tmpl = new frontend.client.ProductListTemplate();\n\t// The name render is also exposed.\n\t// Always pass in a container element, and the raw JSON data.\n\ttmpl.render($('products-container'), jsonData);\n});\n```\n\nWhat is goats-html?\n==================\n\ngoats-html is an atribute-based template system specialized for HTML. It borrows\nconcepts from Template Attribute Language (TAL) (https://en.wikipedia.org/wiki/\nTemplate_Attribute_Language) and implements its own set of attributes. A well-\nknown TAL system is used in Plone (and Chameleon as a standalone implementation:\nhttp://chameleon.readthedocs.org/en/latest/). Goats-html is largely inspired by\nChameleon.\n\nDiffernt from most of other template system, goats-html does not maintain a run-\ntime rendering engine (AST). Instead, templates are preprocessed and translated\ninto Go language! For each template there will be a set of Go structs generated.\nYour Go program should import and call these templates types hence the template\nlogic is statically linked into your binary.\n\nCompared to classic template systems like velocity, etc., templates written in\ngoats-html is more readable and maintainable because of the ATL syntax. However,\ndue to its not having a runtime rendering engine (AST), it's hard to write\ntemplates in goats-html in dev environment. Even changing one character of the\ntemplate forces you to rebuild your server and restart it. For this reason I\nintroduced a specially designed developer server which enable you to modify your\ntemplate without rebuilding/restarting your server. Hence there are dual execution\nmodes in goats-html: production mode and development mode:\n\n![Dual Modes](images/DualModes.png)\n\nFor each template, the command goats generates a Go interface, a template\nimplementation, and a template proxy, both implements the same interface. When\nyou compile your server without the flag \"--tags gots_devmod\" the built binary\ncontains the template implementation. When it's compiled with the flag, the\nstub will convert the template call into a HTTP request to the development\nserver. So in dev mode you don't need to rebuild/restart your server if you\nmodified the template (as long as the template interface was not changed).\n\nBoth the template generator and the dev server is provided the command goats.\n\n\nGo-Get and Install\n==================\n\nSince version 0.2.0, goats-html switched to the normal go-get instead of debian\npackage. This is to make the installation easier because now most gophers are\nmore comfortable to work with go-get.\n\nInstall dependent packages\n--------------------------\n\n    $ go get golang.org/x/net/html\n    $ go get github.com/howeyc/fsnotify\n\nInstall goats-html\n------------------\nTo install goats-html, simply run these commands:\n\n    $ go get -u github.com/linuxerwang/goats-html\n    $ go install github.com/linuxerwang/goats-html/goats\n\nSuppose you've added $GOPATH/bin to $PATH, you can build template with:\n\n    $ goats gen --template_dir goats-html/example\n\nThe output directory is by default the same as the template directory, but\nyou can specify differently:\n\n    $ goats gen --template_dir goats-html/example --output_dir goats-html/mypkg\n\n\nRun the Example Program\n=======================\n\nUnder your GOPATH folder (on my machine it's ~/go), run the following commands:\n\n    $ cd $GOPATH\n    $ go run goats-html/examples/main.go --benchmark --large\n\nBenchmark example template:\n\n    $ go run goats-html/examples/main.go --benchmark --small\n    $ go run goats-html/examples/main.go --benchmark --large\n\n\nRun the Example Server in Dev Mode\n==================================\n\nUnder your GOPATH folder (on my machine it's ~/go), run the following commands:\n\n    $ cd $GOPATH\n    $ go run --tags goats_devmod goats-html/examples/server/main.go\n\nvisit the template: http://localhost:8000.\n\n\nTags and Attributes\n===================\n\nAll goats-html attributes start with \"go:\". There are many such attributes and an\nHTML tag can be attached by multiple attributes. However, not all attributes can\nbe attached to all HTML tags. If a tag was attached by multiple attributes,\nthere's an inherent execution order of them, regardless of their attaching order\non the tag. The following section lists all tags and corresponding attributes\nwith specific execution order.\n\nANY TAG:\n\n  * go:template\n  * go:arg (multiple)\n  * go:var (multiple)\n  * go:attr (multiple)\n\n\u0026lt;HTML\u0026gt;:\n\n  * go:import\n\nOther TAGs:\n\n  * go:if\n  * go:for\n  * go:content\n  * go:replace\n  * go:replaceable\n  * go:switch\n  * go:case\n  * go:default\n  * go:call\n  * go:omit-tag\n\n\nTemplate Built-in Functions:\n============================\n\nIn goats-html templates, the following built-in functions can be used in\nexpressions such as go:var, go:arg, go:content:\n\n* center\n* cut\n* debug\n* floatformat\n* join\n* len\n* ljust\n* rjust\n* title\n* quote\n\nWe intented to implement filters like in Django template (using | as the filter\noperator), and finished a primitive implementation which pass the expression\nto go package \"ast/parser\" and parse the binary operator |. Unfortunately | is\nthe \"bitwise or\" in Go lang and it has lower precedence so such expressions\ncan't be correctly interpreted:\n\n    go:if=\"price \u003e= 10 \u0026\u0026 title|length \u003e 20\"\n\nbecause \u0026\u0026 has higher precedence than |, the express is interpreted as:\n\n    (price \u003e= 10 \u0026\u0026 title)|(length \u003e 20)\n\ninstead of:\n\n    price \u003e= 10 \u0026\u0026 (title|length) \u003e 20\n\nWe don't want to force template authors to use parenthesis, so at present only\nbuilt-in function calls are accepted.\n\n\nExamples\n========\n\nTemplate examples:\n\n    \u003chtml\u003e\n      \u003cdiv go:template=\"ProductCard\"\n           go:arg=\"product: proto.Product\"\u003e\n         \u003cdiv\u003eName:\u003c/div\u003e\n         \u003cdiv go:content=\"product.Name\"\u003e\u003c/div\u003e\n         \u003cdiv\u003ePrice:\u003c/div\u003e\n         \u003cdiv go:content=\"product.Price\"\u003e\u003c/div\u003e\n      \u003c/div\u003e\n    \u003c/html\u003e\n\n    \u003chtml go:template=\"HomePage\"\n          go:import=\"products/templets.html as product\"\n          go:arg=\"pageData: proto.PageData\"\u003e\n    \u003cbody\u003e\n      \u003cp\u003eMy card:\n        \u003cdiv go:template=\"UserCard\"\n             go:arg=\"user: proto.User = pageData.loginUser\"\n             go:if=\"user.IsActive\"\n             go:var=\"age: time.Now().Year - user.Birthday.Year\"\u003e\n          \u003cspan go:content=\"title(user.Name)\"\u003e\u003c/span\u003e\n          \u003cdiv go:for=\"@idx, skill: user.skills\"\u003e\n            \u003cspan go:content=\"idx.Counter\"\u003e\u003cspan go:content=\"skill\"\u003e\n          \u003c/div\u003e\n          \u003cspan\u003eAge:\u003cspan\u003e \u003cspan go:content=\"age\"\u003e\u003c/span\u003e\n        \u003c/div\u003e\n        Items I sell:\n        \u003cdiv go:for=\"product: pageData.products\"\n             go:call=\"product#ProductCard\"\u003e\n        \u003c/div\u003e\n      \u003c/p\u003e\n\n      Your Friends:\u003chr\u003e\n      \u003cp go:for=\"friend: pageData.Friends\"\u003e\n        \u003cspan go:content=\"friend.Name\"\u003e\u003c/span\u003e\n        \u003cdiv go:call=\"#UserCard\"\n             go:var=\"user: friend\"\u003e\u003c/div\u003e\n      \u003c/p\u003e\n\n      \u003cul\u003e\n        \u003cli go:for=\"product: pageData.products\" go:content=\"product.Name\"\u003e\u003c/li\u003e\n      \u003c/ul\u003e\n\n      \u003cdiv go:for=\"product: pageData.products\"\u003e\n        \u003cspan go:content=\"product.Name\"\u003e\u003c/span\u003e\n        \u003cspan go:content=\"product.Price\"\u003e\u003c/span\u003e\n      \u003c/div\u003e\n    \u003c/body\u003e\n    \u003c/html\u003e\n\n\nCredits\n=======\n\n* linuxerwang (linuxerwang@gmail.com): Created the original system.\n* nwlearning (nwlearning@gmail.com): Implemented most of the built-in template functions.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flinuxerwang%2Fgoats-html","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flinuxerwang%2Fgoats-html","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flinuxerwang%2Fgoats-html/lists"}