Skip to content

Commit ea34bce

Browse files
committed
Include relative files into generated content
Local relative files can be included automatically in the generated content with `{{ include "..." }} function. This can be very useful for: - inject arbitrary markdown files in between sections - automatically include example usage ````yaml content: |- include any relative files {{ include "relative/path/to/file" }} or examples ```hcl {{ include "examples/foo/main.tf" }} ``` ```` Signed-off-by: Khosrow Moossavi <khos2ow@gmail.com>
1 parent 6777364 commit ea34bce

File tree

7 files changed

+97
-4
lines changed

7 files changed

+97
-4
lines changed

docs/user-guide/configuration.md

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -160,14 +160,14 @@ used for `FORMATTER_NAME`:
160160
use the plugin. For example, if plugin binary file is called `tfdocs-format-foo`,
161161
formatter name must be set to `foo`.
162162

163-
## header-from
163+
## Header From
164164

165165
Since `v0.10.0`
166166

167167
Relative path to a file to extract header for the generated output from. Supported
168168
file formats are `.adoc`, `.md`, `.tf`, and `.txt`. Default value is `main.tf`.
169169

170-
## footer-from
170+
## Footer From
171171

172172
Since `v0.12.0`
173173

@@ -211,7 +211,11 @@ Go template with following additional variables:
211211
- `{{ .Requirements }}`
212212
- `{{ .Resources }}`
213213

214-
```yaml
214+
and
215+
216+
- `{{ include "relative/path/to/file" }}`
217+
218+
````yaml
215219
content: |-
216220
Any arbitrary text can be placed anywhere in the content
217221
@@ -226,7 +230,17 @@ content: |-
226230
{{ .Outputs }}
227231
228232
{{ .Inputs }}
229-
```
233+
234+
and include any relative files
235+
236+
{{ include "relative/path/to/file" }}
237+
238+
or examples
239+
240+
```hcl
241+
{{ include "examples/foo/main.tf" }}
242+
```
243+
````
230244

231245
These variables are the generated output of individual sections in the selected
232246
formatter. For example `{{ .Inputs }}` is Markdown Table representation of _inputs_

docs/user-guide/how-to.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,46 @@ default file to attempt extraction from, you need to explicitly specify desired
150150
to extract content from with `--footer-from FILE` or corresponding `footer-from` in
151151
configuration file.
152152

153+
## Include Examples
154+
155+
Since `v0.14.0`
156+
157+
Example can be automatically included into README by using `content` in configuration
158+
file. There are [multiple variables and function] available in `content`. As an example:
159+
160+
````bash
161+
$ tree
162+
.
163+
├── examples
164+
│   ├── example-1
165+
│   │   ├── main.tf
166+
│ └── example-2
167+
│ └── main.tf
168+
├── ...
169+
├── main.tf
170+
├── variables.tf
171+
├── ...
172+
└── .terraform-docs.yml
173+
````
174+
175+
and
176+
177+
````yaml
178+
# .terraform-docs.yml
179+
content: |-
180+
{{ .Header }}
181+
182+
## Example
183+
184+
```hcl
185+
{{ file "example-1/main.tf" }}
186+
```
187+
188+
{{ .Inputs }}
189+
190+
{{ .Outputs }}
191+
````
192+
153193
## Insert Output To File
154194

155195
Since `v0.12.0`

examples/.terraform-docs.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ sections:
2424
#
2525
# and even in between sections
2626
#
27+
# ## Examples
28+
#
29+
# ```hcl
30+
# {{ include "relative/path/to/main.tf" }}
31+
# ```
32+
#
2733
# {{ .Providers }}
2834
#
2935
# and they don't even need to be in the default order

internal/cli/run.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ func RunEFunc(config *Config) func(*cobra.Command, []string) error {
149149
if err != nil {
150150
return err
151151
}
152+
generator.Path(config.moduleRoot)
152153

153154
content, err := generator.ExecuteTemplate(config.Content)
154155
if err != nil {

internal/print/generator.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ package print
1212

1313
import (
1414
"bytes"
15+
"os"
16+
"path/filepath"
1517
"text/template"
1618
)
1719

@@ -106,6 +108,7 @@ type Generator struct {
106108
Requirements string
107109
Resources string
108110

111+
path string // module's path
109112
content string // all the content combined
110113
formatter string // name of the formatter
111114
}
@@ -125,6 +128,11 @@ func NewGenerator(name string, fns ...GenerateFunc) *Generator {
125128
return g
126129
}
127130

131+
// Path of module's directory.
132+
func (g *Generator) Path(root string) {
133+
g.path = root
134+
}
135+
128136
// ExecuteTemplate applies the template with Generator known items. If template
129137
// is empty Generator.content is returned as is. If template is not empty this
130138
// still returns Generator.content for incompatible formatters.
@@ -140,6 +148,15 @@ func (g *Generator) ExecuteTemplate(contentTmpl string) (string, error) {
140148
var buf bytes.Buffer
141149

142150
tmpl := template.New("content")
151+
tmpl.Funcs(template.FuncMap{
152+
"include": func(s string) string {
153+
content, err := os.ReadFile(filepath.Join(g.path, s))
154+
if err != nil {
155+
panic(err)
156+
}
157+
return string(content)
158+
},
159+
})
143160
template.Must(tmpl.Parse(contentTmpl))
144161

145162
if err := tmpl.ExecuteTemplate(&buf, "content", g); err != nil {

internal/print/generator_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,20 @@ func TestExecuteTemplate(t *testing.T) {
107107
expected: "",
108108
wantErr: true,
109109
},
110+
"Compatible with template include file": {
111+
name: "markdown table",
112+
content: "this is the header\nthis is the footer",
113+
template: "{{ include \"testdata/sample-file.txt\" }}",
114+
expected: "Sample file to be included.\n",
115+
wantErr: false,
116+
},
117+
"Compatible with template include unknown file": {
118+
name: "markdown table",
119+
content: "this is the header\nthis is the footer",
120+
template: "{{ include \"file-not-found\" }}",
121+
expected: "",
122+
wantErr: true,
123+
},
110124
"Incompatible without template": {
111125
name: "yaml",
112126
content: "header: \"this is the header\"\nfooter: \"this is the footer\"",
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Sample file to be included.

0 commit comments

Comments
 (0)