{"id":13644883,"url":"https://github.com/ukautz/tmpl","last_synced_at":"2025-09-02T18:37:19.257Z","repository":{"id":54195851,"uuid":"105679500","full_name":"ukautz/tmpl","owner":"ukautz","description":"tmpl is a lightweight, shell focused, swiss army knife for document template processing","archived":false,"fork":false,"pushed_at":"2021-03-03T20:51:17.000Z","size":43,"stargazers_count":40,"open_issues_count":0,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-07-31T22:50:17.648Z","etag":null,"topics":["automation","ci-cd","cli","go","golang","shell","template","tool"],"latest_commit_sha":null,"homepage":"","language":"Go","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/ukautz.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}},"created_at":"2017-10-03T17:10:30.000Z","updated_at":"2025-04-17T02:18:32.000Z","dependencies_parsed_at":"2022-08-13T09:00:15.396Z","dependency_job_id":null,"html_url":"https://github.com/ukautz/tmpl","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/ukautz/tmpl","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ukautz%2Ftmpl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ukautz%2Ftmpl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ukautz%2Ftmpl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ukautz%2Ftmpl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ukautz","download_url":"https://codeload.github.com/ukautz/tmpl/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ukautz%2Ftmpl/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273332437,"owners_count":25086958,"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-09-02T02:00:09.530Z","response_time":77,"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":["automation","ci-cd","cli","go","golang","shell","template","tool"],"created_at":"2024-08-02T01:02:18.084Z","updated_at":"2025-09-02T18:37:19.205Z","avatar_url":"https://github.com/ukautz.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"# tmpl \n\ntmpl is a lightweight, shell script friendly document renderer. Something like `envsubst` just different.\n\ntmpl is inspired by recent extensions of the shell toolset like [jq](https://github.com/stedolan/jq), which allows to\nwork with complex, structured (JSON) data from the shell. This tool provides a solution for a special case in that\nparticular niche: automated generation of complex documents out of structured data using smart templates.\n\n## Examples\n\n```shell\n# hello world\n$ tmpl -d 'env:' -t 'envsubst:hello ${USER}, how are you?'\n\n# print out all env vars as JSON\n$ tmpl -d 'env:' -t 'template:{{ json .data }}'\n\n# use source from remote location to render local template and store the result\n# in a local file\n$ tmpl --data-location https://config.acme.tld/node/$(uname -n).json \\\n    --template-location /etc/apache/templates/homepage.tmpl \\\n    --output /var/www/home/index.html\n\n# get data from output of execution, then pull template from remote # location\n# and pipe output to script that sends alarm\n$ tmpl --data-location \"shell://elasticdump ... args ...\" \\\n    --decoder json \\\n    --template-location \"https://wiki.acme.tld/templates/report.tmpl?auth=$(tokengen.sh)\" | \\\n    send-alarm.sh ...\n```\n\nThere are many possible applications or integrations. Here are a few:\n\n* **Reporting**, eg generate HTML reports or summaries based on \"native JSON sources\" like ElasticSearch or MongoDB\n* **Build pipeline**, eg\n  * transform generic YAML/JSON into domain specific configuration files (think YAML -\u003e NGINX config)\n  * render templates from environment variables\n* **Monitoring / alerting**, eg generate system alert emails with complex information rendered in a human readable way\n* **Transactional messaging**, eg create rich documents from raw JSON (eg JSON -\u003e DocX)\n* you can think of something ..\n\n\n\n## Data Locations\n\nA data location contains input data (structures). Some locations indicate a data format, and thereby a Decoder. support guessing of the decoder, e.g. an URL like `http://acme.tld/foo.json` implies JSON format.\n\n**Supported locations** are:\n\n* `env:` or `env:SOME_PREFIX_` converting all (prefix) matching env vars into a flat data map; for example `env:FOO_` converts `FOO_PARAM=x` and `FOO_Other=yy` into `{\"PARAM\":\"x\", \"Other\": \"yy\"}`; uses JSON internally\n* `http://` or `https://`: arbitrary, GETable HTTP(S) URLs; decoder guessed from file ending like `.json` or `.yaml` ending of file in URL path (`https://acme.tld/my/file.json`)\n* `file:///path/to/file` or `/path/to/file`: arbitrary local files; decoder guessed from file ending like `.json` or `.yaml`\n* `shell://`: arbitrary, atomic shell command lines, eg `shell://date +%F`, which would execute `echo '{\"foo\":\"bar\"}'` or anything that would return JSON/YAML on STDOUT. Don't use pipes or somesuch..\n* `-`: STDIN, requires decoder specification\n\n\n### Data Decoder\n\nSupported decoders are JSON and YAML. Per default, tmpl tries to guess the format from the URL. The decoder can be set explicitly with `--decoder \u003cjson|yaml\u003e` (or `-d \u003cjson|yaml\u003e`).\n## Template Locations\n\ntmpl supports multiple template render engines:\n- [**template**, from the go standard libraries](https://golang.org/pkg/text/template/)\n- [**pongo2** (go implementation)](https://github.com/flosch/pongo2) which implements\n[Python Django's templating engine](https://docs.djangoproject.com/en/dev/topics/templates/)\n- [**envsubst** (go implementation)](github.com/drone/envsubst), which supports a syntax close to the [envsubst](https://linux.die.net/man/1/envsubst) command line tool\n\nThe same as with data sources: specify the renderer explicitly with `--renderer | -r \u003cname\u003e` or let tmpl try to guess\nit from the template location:\n\n* Template URLs with `.envsubst` file name endings default to `envsubst` engine. Examples:\n  * `http://acme.tld/templates/vhost.envsubst?t=123456`\n  * `file:///etc/apache/vhost.envsubst`\n* Template URLs with `.tmpl` or `.template` file names default to `template` engine. Examples:\n  * `http://acme.tld/templates/vhost.tmpl?foo=bar`\n  * `file:///etc/apache/vhost.template`\n* Template URLs with `.pongo2` or `.pongo` files name endings default to `pongo2` engine. Examples:\n  * `http://acme.tld/templates/vhost.pongo2?t=123456`\n  * `file:///etc/apache/vhost.pongo`\n\nFor template and pongo2 see the examples below, assume the following data structure \u0026 content:\n\n```json\n{\n  \"name\": \"www.acme.tld\",\n  \"aliases\": [\"acme.tld\", \"blog.acme.tld\"],\n  \"directory\": \"/var/www/homepage\",\n  \"directories\": [\n    {\"path\": \"/foo\", \"users\": [\"bar\"]},\n    {\"path\": \"/lorem\"}\n  ]\n}\n```\n\nand the following expected result (+/- a few empty lines, see [optimized templates here](https://github.com/ukautz/tmpl/tree/master/example)):\n\n```$xslt\n\u003cVirtualHost www.acme.tld:80\u003e\n    ServerName www.acme.tld\n    ServerAlias acme.tld blog.acme.tld\n    DocumentRoot \"/var/www/homepage\"\n\n    \u003cDirectory \"/var/www/homepage/foo\"\u003e\n        Require user foo bar\n    \u003c/Directory\u003e\n    \u003cDirectory \"/var/www/homepage/lorem\"\u003e\n        Require valid-user\n    \u003c/Directory\u003e\n\u003c/VirtualHost\u003e\n```\n\n### `template` engine\n\n```\n\u003cVirtualHost {{.data.name}}:80\u003e\n    ServerName {{.data.name}}\n    ServerAlias{{range .data.aliases}} {{.}}{{end}}\n    DocumentRoot \"{{.data.directory}}\"\n    {{range $idx, $directory := .data.directories}}\n    \u003cDirectory \"{{$.data.directory}}{{$directory.path}}\"\u003e\n        {{if $directory.users}}\n        Require user{{range $directory.users}} {{.}}{{end}}\n        {{else}}\n        Require valid-user\n        {{end}}\n    \u003c/Directory\u003e\n    {{end}}\n\u003c/VirtualHost\u003e\n```\n\nFind more examples for [including additional templates, working with macro like blocks, ..](https://golang.org/pkg/text/template/#hdr-Actions)\n\n### `pongo2` engine\n\nExample template:\n\n```\n\u003cVirtualHost {{ data.name }}:80\u003e\n    ServerName {{ data.name }}\n    ServerAlias {{ data.aliases | join:\" \" }}\n    DocumentRoot \"{{ data.directory }}\"\n    {% for directory in data.directories %}\n    \u003cDirectory \"{{ data.directory }}{{ directory.path }}\"\u003e\n        {% if directory.users %}\n        Require user {{ directory.users | join:\" \" }}\n        {% else %}\n        Require valid-user\n        {% endif %}\n    \u003c/Directory\u003e\n    {% endfor %}\n\u003c/VirtualHost\u003e\n```\n\nFind more examples for including additional templates, macros, functions, .. [here](https://github.com/flosch/pongo2#pongo2)\nand [here](https://docs.djangoproject.com/en/dev/topics/templates/)\n\n### `envsubst` engine\n\nThis engine only supports flat data structures and is intended to use with the `env:` data location.\n\nAssuming the following env vars are set:\n\n```shell\nUSER=myself\nHOME=/home/myself\nAPP_NAME=the-app\nAPP_DOMAIN=the-domain.tld\n```\n\n#### Using all env variables\n\nWith the following template\n\n```\nHello ${USER}, here is your home: ${HOME}. Your application is named ${APP_NAME}.\n```\n\nexecuted with `tmpl -d 'env:' -t 'file:///path/to/template'` would render:\n\n```text\nHello myself, here is your home: /home/myself. Your application is named the-app.\n```\n\n#### Using prefixed env variables\n\nWith the following template\n\n```\nApp name ${NAME} has domain ${DOMAIN}\n```\n\nexecuted with `tmpl -d 'env:APP_' -t 'file:///path/to/template'` would render:\n\n```text\nApp name the-app has domain the-domain.tld\n```\n\n\n## Use as library\n\ntmpl is (mostly) structured in the [Standard Go Project Layout](https://github.com/golang-standards/project-layout) and follows ('ish) the [Standard Package Layout, as defined by Ben Johnson](https://medium.com/@benbjohnson/standard-package-layout-7cdbc8391fc1).\n\n- **Note**: Parts of the library in [`pkg/`](pkg/) is using singletons, intended to be used in a program.\n- **Note**: Check out the [example folder](https://github.com/ukautz/tmpl/tree/master/example), the `BuildTmpl` facade function in [tmpl.go](pkg/tmpl.go) and the integration tests in [imports_test.go](pkg/imports/imports_test.go) to get an understanding on how to use.\n\nTo use guessers and builders, you can import the whole bundle:\n\n```go\npackage mypackage\n\nimport (\n\t\"fmt\"\n\t\"...\"\n\t_ \"github.com/ukautz/tmpl/pkg/imports\"\n)\n\n// --- %\u003c ---\n\nrenderer, err := tmpl.GuessRenderer(\"http://some/url.tmpl\")  // or \"file:///etc/file.pongo\" or ..\nsource, err := tmpl.GuessSource(\"http://some/url\") // or \"file:///path\" or ..\ndecoder, err := tmpl.GuessDecoder(\"http://some/url.json\") // or \"/srv/path/file.yaml\" or ..\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fukautz%2Ftmpl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fukautz%2Ftmpl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fukautz%2Ftmpl/lists"}