https://github.com/astromechza/spiro
A simple binary to do project templating
https://github.com/astromechza/spiro
cli golang stencil template
Last synced: 11 months ago
JSON representation
A simple binary to do project templating
- Host: GitHub
- URL: https://github.com/astromechza/spiro
- Owner: astromechza
- License: mit
- Created: 2017-02-10T20:22:17.000Z (over 9 years ago)
- Default Branch: master
- Last Pushed: 2019-07-31T13:05:38.000Z (almost 7 years ago)
- Last Synced: 2025-03-09T03:41:24.708Z (over 1 year ago)
- Topics: cli, golang, stencil, template
- Language: Go
- Size: 1.24 MB
- Stars: 5
- Watchers: 2
- Forks: 1
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# `spiro` - a project template generator

Spiro is an template structure generator that uses Golangs text/template library. It accepts both single files as well as directory trees as input and will interpret any template calls found inside the files and the file/directory names.
#### Quick Example
**{{ .name }}.txt.templated:**
```
{{ if .enabled }}x = {{ .x }}
y = {{ .y }}
{{ end }}
Footer content. Generated at {{ now.Format "2006-01-02" }}
```
**spec.yaml**:
```yaml
name: example
enabled: true
x: 10
y: hello world
```
Then you can execute `spiro '{{ .name }}.txt.templated' spec.yaml .` in order to generate a file called `example.txt` that contains:
```
x = 10
y = hello world
Footer content. Generated at 2018-03-18
```
---
The rule-set is probably a bit complex to display here, but the following links are useful:
- https://golang.org/pkg/text/template
- https://gohugo.io/templates/go-templates/
The only additional rule is the rule that controls whether a file or directory is processed or not. If a file name is templated like `{{ if .blah }}filename.txt{{ end }}` then that file will only be processed _if_ the name evaluates to a non-empty string.
The contents of a file will only be treated as templated if the file name has a `.templated` suffix. If it does, the contents will be evaluated and the `.templated` suffix will be removed.
Templating _inside_ the file is evaluated after any template in the file name. So if you want an optional file that has templated content you'll need to use a name like `{{ if .blah }}filename.txt.templated{{ end }}`. If the `.templated` declaration is outside the condition the behaviour should be similar but is probably not the convention.
Some additional template functions are supplied:
- `title`: capitalise string `(string) -> (string)`
- `upper`: convert string to upper case `(string) -> (string)`
- `lower`: convert string to lower case `(string) -> (string)`
- `now`: return current time object `() -> (time.Time)`
- `json`: output a structure as json `(object) -> (string)`
- `jsonindent`: output a structure as indented json `(object) -> (string)`
- `unescape`: unescape escaped html characters `(string) -> (string)`
- `stringreplace`: basic string replace `(subject, old, new) -> (string)`
- `regexreplace`: regular expression based string replace `(subject, pattern, repl) -> (string)`
- `add`: Calculate the sum of two numbers `(int, int) -> (int)`
The spec file should be in JSON or Yaml form and will be passed to each template invocation. The specfile can be "-" to indicate that YAML should be read from stdin.
Permission bits for any files, including `.templated` ones, **will** be copied to the destination files.
### Basic example of features:
You have a file on disk called `{{ lower .projectname }}.md.templated` with the following content:
```
# Heading for {{ .projectname }}
This project was started on {{ now.Format "2006-01-02" }} by {{ .author }}.
```
And if you feed it the following spec JSON:
```json
{
"projectname": "HelloWorld",
"author": "Joe Soap"
}
```
You'll end up with a file called `helloworld.md` containing:
```
# Heading for HelloWorld
This project was started on 2017-02-11 by Joe Soap.
```
### Overriding the template characters
By default the normal Golang template characters `{{` are used but sometimes the files you're working with containing and you have to laboriously escape them.
You can provide the special key `_spiro_delimiters_` in your spec file in order to override them:
```yaml
_spiro_delimiters_:
- "<<<"
- ">>>"
```
### Enforcing a `spiro` version
Sometimes new features are added to Spiro which are not supported by earlier versions. Sometimes templates rely on these features. By specifying a `_spiro_min_version_` in your spec file, an error will be thrown if an earlier version of `spiro` is used to build the template.
```yaml
_sprio_min_version_: 1.5
```
The version rules work as follows:
- 3 numbers are allowed (`major.minor.patch`)
- `X.Y` == `X.Y.0` and `X` == `X.0.0`
- `X.Z` >= `X.0`
### What should you use this project for:
- Does your team have a template project that gets copied and modified by hand? Use `spiro`!
## Demo
Some demos exist in the `/demo` directory. Run them as follows:
```
$ rm -rfv demo/output/project
$ ./spiro demo/example1 demo/example1.yml demo/output
Processing 'demo/example1/' -> 'demo/output/example1/'
Processing 'demo/example1/demo-{{upper .animal}}.templated' -> 'demo/output/example1/demo-BEAR'
Processing 'demo/example1/{{ if .x }}dontskip.txt{{ end }}' -> 'demo/output/example1/dontskip.txt'
Skipping 'demo/example1/{{ if not .x }}skipthis.txt{{ end }}' since the name evaluated to ''
Processing 'demo/example1/{{.subdir}}-thing/' -> 'demo/output/example1/Elephant-thing/'
Processing 'demo/example1/{{.subdir}}-thing/noop' -> 'demo/output/example1/Elephant-thing/noop'
Processing 'demo/example1/{{.subdir}}-thing/{{.subfile.name}}.{{.subfile.type}}' -> 'demo/output/example1/Elephant-thing/snake.xml'
$ find demo/output
demo/output
demo/output/example1
demo/output/example1/demo-BEAR
demo/output/example1/dontskip.txt
demo/output/example1/Elephant-thing
demo/output/example1/Elephant-thing/noop
demo/output/example1/Elephant-thing/snake.xml
```
## Download & Installation
The best option is to download the latest binaries from the [releases page](https://github.com/astromechza/spiro/releases). Extract the one for your platform and put it in any directory where you have access.
Alternatively, use the install script which will do this for you:
```
$ curl https://raw.githubusercontent.com/astromechza/spiro/master/install.sh | sh
```
If a binary is not available for your platform, you'll need to build one yourself.
## Changelog
**v1.8**
- Added `-edit` option to the CLI
**v1.7**
- Allow spec to be read from stdin when `-` is given ([#5](https://github.com/astromechza/spiro/issues/5))
**v1.6.0**
- ...
## Future features
- More useful template functions (need feedback from users)
- Syntax to split a single file into multiple