diff --git a/internal/format/asciidoc_document.go b/internal/format/asciidoc_document.go
index f003b3a..7625283 100644
--- a/internal/format/asciidoc_document.go
+++ b/internal/format/asciidoc_document.go
@@ -15,8 +15,8 @@ import (
gotemplate "text/template"
"github.com/terraform-docs/terraform-docs/internal/print"
- "github.com/terraform-docs/terraform-docs/internal/template"
"github.com/terraform-docs/terraform-docs/internal/terraform"
+ "github.com/terraform-docs/terraform-docs/template"
)
//go:embed templates/asciidoc_document*.tmpl
diff --git a/internal/format/asciidoc_table.go b/internal/format/asciidoc_table.go
index 8678a4b..26d1dec 100644
--- a/internal/format/asciidoc_table.go
+++ b/internal/format/asciidoc_table.go
@@ -15,8 +15,8 @@ import (
gotemplate "text/template"
"github.com/terraform-docs/terraform-docs/internal/print"
- "github.com/terraform-docs/terraform-docs/internal/template"
"github.com/terraform-docs/terraform-docs/internal/terraform"
+ "github.com/terraform-docs/terraform-docs/template"
)
//go:embed templates/asciidoc_table*.tmpl
diff --git a/internal/format/markdown_document.go b/internal/format/markdown_document.go
index 9c32443..4f49a75 100644
--- a/internal/format/markdown_document.go
+++ b/internal/format/markdown_document.go
@@ -15,8 +15,8 @@ import (
gotemplate "text/template"
"github.com/terraform-docs/terraform-docs/internal/print"
- "github.com/terraform-docs/terraform-docs/internal/template"
"github.com/terraform-docs/terraform-docs/internal/terraform"
+ "github.com/terraform-docs/terraform-docs/template"
)
//go:embed templates/markdown_document*.tmpl
diff --git a/internal/format/markdown_table.go b/internal/format/markdown_table.go
index 3758389..0baca66 100644
--- a/internal/format/markdown_table.go
+++ b/internal/format/markdown_table.go
@@ -15,8 +15,8 @@ import (
gotemplate "text/template"
"github.com/terraform-docs/terraform-docs/internal/print"
- "github.com/terraform-docs/terraform-docs/internal/template"
"github.com/terraform-docs/terraform-docs/internal/terraform"
+ "github.com/terraform-docs/terraform-docs/template"
)
//go:embed templates/markdown_table*.tmpl
diff --git a/internal/format/pretty.go b/internal/format/pretty.go
index e36b0c6..b6dc634 100644
--- a/internal/format/pretty.go
+++ b/internal/format/pretty.go
@@ -17,8 +17,8 @@ import (
gotemplate "text/template"
"github.com/terraform-docs/terraform-docs/internal/print"
- "github.com/terraform-docs/terraform-docs/internal/template"
"github.com/terraform-docs/terraform-docs/internal/terraform"
+ "github.com/terraform-docs/terraform-docs/template"
)
//go:embed templates/pretty.tmpl
diff --git a/internal/format/tfvars_hcl.go b/internal/format/tfvars_hcl.go
index 52b7445..da73c82 100644
--- a/internal/format/tfvars_hcl.go
+++ b/internal/format/tfvars_hcl.go
@@ -17,9 +17,9 @@ import (
gotemplate "text/template"
"github.com/terraform-docs/terraform-docs/internal/print"
- "github.com/terraform-docs/terraform-docs/internal/template"
"github.com/terraform-docs/terraform-docs/internal/terraform"
"github.com/terraform-docs/terraform-docs/internal/types"
+ "github.com/terraform-docs/terraform-docs/template"
)
//go:embed templates/tfvars_hcl.tmpl
diff --git a/internal/format/util.go b/internal/format/util.go
index 991e880..9bcd7fc 100644
--- a/internal/format/util.go
+++ b/internal/format/util.go
@@ -17,7 +17,7 @@ import (
"regexp"
"strings"
- "github.com/terraform-docs/terraform-docs/internal/template"
+ "github.com/terraform-docs/terraform-docs/template"
)
// sanitize cleans a Markdown document to soothe linters.
diff --git a/internal/template/doc.go b/internal/template/doc.go
deleted file mode 100644
index d8230c6..0000000
--- a/internal/template/doc.go
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
-Copyright 2021 The terraform-docs Authors.
-
-Licensed under the MIT license (the "License"); you may not
-use this file except in compliance with the License.
-
-You may obtain a copy of the License at the LICENSE file in
-the root directory of this source tree.
-*/
-
-// Package template provides templating functionality
-package template
diff --git a/internal/template/template.go b/internal/template/template.go
deleted file mode 100644
index 17b9beb..0000000
--- a/internal/template/template.go
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
-Copyright 2021 The terraform-docs Authors.
-
-Licensed under the MIT license (the "License"); you may not
-use this file except in compliance with the License.
-
-You may obtain a copy of the License at the LICENSE file in
-the root directory of this source tree.
-*/
-
-package template
-
-import (
- gotemplate "text/template"
-
- templatesdk "github.com/terraform-docs/plugin-sdk/template"
- "github.com/terraform-docs/terraform-docs/internal/print"
- "github.com/terraform-docs/terraform-docs/internal/terraform"
- "github.com/terraform-docs/terraform-docs/internal/types"
-)
-
-// Item represents a named templated which can reference
-// other named templated too.
-type Item struct {
- Name string
- Text string
-}
-
-// Template represents a new Template with given name and content
-// to be rendered with provided settings with use of built-in and
-// custom functions.
-type Template struct {
- engine *templatesdk.Template
- settings *print.Settings
-}
-
-// New returns new instance of Template.
-func New(settings *print.Settings, items ...*Item) *Template {
- ii := []*templatesdk.Item{}
- for _, v := range items {
- ii = append(ii, &templatesdk.Item{Name: v.Name, Text: v.Text})
- }
-
- engine := templatesdk.New(settings.Convert(), ii...)
- engine.CustomFunc(gotemplate.FuncMap{
- "tostring": func(s types.String) string {
- return string(s)
- },
- "sanitizeSection": func(s string) string {
- return sanitizeSection(s, settings)
- },
- "sanitizeDoc": func(s string) string {
- return sanitizeDocument(s, settings)
- },
- "sanitizeMarkdownTbl": func(s string) string {
- return sanitizeMarkdownTable(s, settings)
- },
- "sanitizeAsciidocTbl": func(s string) string {
- return sanitizeAsciidocTable(s, settings)
- },
- "anchorNameMarkdown": func(s string, t string) string {
- return createAnchorMarkdown(s, t, settings)
- },
- "anchorNameAsciidoc": func(s string, t string) string {
- return createAnchorAsciidoc(s, t, settings)
- },
- })
-
- return &Template{
- engine: engine,
- settings: settings,
- }
-}
-
-// Funcs return available template out of the box and custom functions.
-func (t Template) Funcs() gotemplate.FuncMap {
- return t.engine.Funcs()
-}
-
-// CustomFunc adds new custom functions to the template
-// if functions with the same names didn't exist.
-func (t Template) CustomFunc(funcs gotemplate.FuncMap) {
- t.engine.CustomFunc(funcs)
-}
-
-// Render template with given Module struct.
-func (t Template) Render(name string, module *terraform.Module) (string, error) {
- return t.engine.Render(name, module)
-}
diff --git a/internal/template/anchor.go b/template/anchor.go
similarity index 65%
rename from internal/template/anchor.go
rename to template/anchor.go
index e07e11a..74163c6 100644
--- a/internal/template/anchor.go
+++ b/template/anchor.go
@@ -16,13 +16,13 @@ import (
"github.com/terraform-docs/terraform-docs/internal/print"
)
-// createAnchorMarkdown
-func createAnchorMarkdown(t string, s string, settings *print.Settings) string {
- sanitizedName := sanitizeName(s, settings)
+// CreateAnchorMarkdown creates HTML anchor for Markdown format.
+func CreateAnchorMarkdown(t string, s string, settings *print.Settings) string {
+ sanitizedName := SanitizeName(s, settings)
if settings.ShowAnchor {
anchorName := fmt.Sprintf("%s_%s", t, s)
- sanitizedAnchorName := sanitizeName(anchorName, settings)
+ sanitizedAnchorName := SanitizeName(anchorName, settings)
// the link is purposely not sanitized as this breaks markdown formatting
return fmt.Sprintf(" [%s](#%s)", anchorName, sanitizedName, sanitizedAnchorName)
}
@@ -30,13 +30,13 @@ func createAnchorMarkdown(t string, s string, settings *print.Settings) string {
return sanitizedName
}
-// createAnchorAsciidoc
-func createAnchorAsciidoc(t string, s string, settings *print.Settings) string {
- sanitizedName := sanitizeName(s, settings)
+// CreateAnchorAsciidoc creates HTML anchor for AsciiDoc format.
+func CreateAnchorAsciidoc(t string, s string, settings *print.Settings) string {
+ sanitizedName := SanitizeName(s, settings)
if settings.ShowAnchor {
anchorName := fmt.Sprintf("%s_%s", t, s)
- sanitizedAnchorName := sanitizeName(anchorName, settings)
+ sanitizedAnchorName := SanitizeName(anchorName, settings)
return fmt.Sprintf("[[%s]] <<%s,%s>>", sanitizedAnchorName, sanitizedAnchorName, sanitizedName)
}
diff --git a/internal/template/anchor_test.go b/template/anchor_test.go
similarity index 95%
rename from internal/template/anchor_test.go
rename to template/anchor_test.go
index fbfb7ab..418d5c8 100644
--- a/internal/template/anchor_test.go
+++ b/template/anchor_test.go
@@ -62,7 +62,7 @@ func TestAnchorMarkdown(t *testing.T) {
ShowAnchor: tt.anchor,
EscapeCharacters: tt.escape,
}
- actual := createAnchorMarkdown(tt.typeSection, tt.name, settings)
+ actual := CreateAnchorMarkdown(tt.typeSection, tt.name, settings)
assert.Equal(tt.expected, actual)
})
@@ -113,7 +113,7 @@ func TestAnchorAsciidoc(t *testing.T) {
ShowAnchor: tt.anchor,
EscapeCharacters: tt.escape,
}
- actual := createAnchorAsciidoc(tt.typeSection, tt.name, settings)
+ actual := CreateAnchorAsciidoc(tt.typeSection, tt.name, settings)
assert.Equal(tt.expected, actual)
})
diff --git a/template/doc.go b/template/doc.go
new file mode 100644
index 0000000..a39f8bf
--- /dev/null
+++ b/template/doc.go
@@ -0,0 +1,53 @@
+/*
+Copyright 2021 The terraform-docs Authors.
+
+Licensed under the MIT license (the "License"); you may not
+use this file except in compliance with the License.
+
+You may obtain a copy of the License at the LICENSE file in
+the root directory of this source tree.
+*/
+
+// Package template provides templating functionality.
+//
+// Usage
+//
+// import (
+// "fmt"
+// gotemplate "text/template"
+//
+// "github.com/terraform-docs/terraform-docs/internal/print"
+// "github.com/terraform-docs/terraform-docs/internal/terraform"
+// "github.com/terraform-docs/terraform-docs/template"
+// )
+//
+// const mainTpl =`
+// {{- if .Settings.ShowHeader -}}
+// {{- with .Module.Header -}}
+// {{ colorize "\033[90m" . }}
+// {{ end -}}
+// {{- printf "\n\n" -}}
+// {{ end -}}`
+//
+// func render(settings *print.Settings, module *terraform.Module) (string, error) {
+// tt := template.New(settings, &template.Item{
+// Name: "main",
+// Text: mainTpl,
+// })
+//
+// tt := template.New(settings, items...)
+// tt.CustomFunc(gotemplate.FuncMap{
+// "colorize": func(c string, s string) string {
+// r := "\033[0m"
+// if !settings.ShowColor {
+// c = ""
+// r = ""
+// }
+// return fmt.Sprintf("%s%s%s", c, s, r)
+// },
+// })
+//
+// return tt.Render("main", module)
+// }
+//
+package template
diff --git a/internal/template/sanitizer.go b/template/sanitizer.go
similarity index 80%
rename from internal/template/sanitizer.go
rename to template/sanitizer.go
index 7bbbdb1..9ab836f 100644
--- a/internal/template/sanitizer.go
+++ b/template/sanitizer.go
@@ -22,8 +22,8 @@ import (
"github.com/terraform-docs/terraform-docs/internal/print"
)
-// sanitizeName escapes underscore character which have special meaning in Markdown.
-func sanitizeName(name string, settings *print.Settings) string {
+// SanitizeName escapes underscore character which have special meaning in Markdown.
+func SanitizeName(name string, settings *print.Settings) string {
if settings.EscapeCharacters {
// Escape underscore
name = strings.ReplaceAll(name, "_", "\\_")
@@ -31,13 +31,13 @@ func sanitizeName(name string, settings *print.Settings) string {
return name
}
-// sanitizeSection converts passed 'string' to suitable Markdown or AsciiDoc
+// SanitizeSection converts passed 'string' to suitable Markdown or AsciiDoc
// representation for a document. (including line-break, illegal characters,
// code blocks etc). This is in particular being used for header and footer.
//
-// IMPORTANT: sanitizeSection will never change the line-endings and preserve
+// IMPORTANT: SanitizeSection will never change the line-endings and preserve
// them as they are provided by the users.
-func sanitizeSection(s string, settings *print.Settings) string {
+func SanitizeSection(s string, settings *print.Settings) string {
if s == "" {
return "n/a"
}
@@ -45,9 +45,9 @@ func sanitizeSection(s string, settings *print.Settings) string {
s,
"```",
func(segment string, first bool, last bool) string {
- segment = escapeIllegalCharacters(segment, settings, false)
- segment = convertMultiLineText(segment, false, true, settings.ShowHTML)
- segment = normalizeURLs(segment, settings)
+ segment = EscapeCharacters(segment, settings, false)
+ segment = ConvertMultiLineText(segment, false, true, settings.ShowHTML)
+ segment = NormalizeURLs(segment, settings)
return segment
},
func(segment string, first bool, last bool) string {
@@ -71,10 +71,10 @@ func sanitizeSection(s string, settings *print.Settings) string {
return result
}
-// sanitizeDocument converts passed 'string' to suitable Markdown or AsciiDoc
+// SanitizeDocument converts passed 'string' to suitable Markdown or AsciiDoc
// representation for a document. (including line-break, illegal characters,
// code blocks etc)
-func sanitizeDocument(s string, settings *print.Settings) string {
+func SanitizeDocument(s string, settings *print.Settings) string {
if s == "" {
return "n/a"
}
@@ -82,9 +82,9 @@ func sanitizeDocument(s string, settings *print.Settings) string {
s,
"```",
func(segment string, first bool, last bool) string {
- segment = escapeIllegalCharacters(segment, settings, false)
- segment = convertMultiLineText(segment, false, false, settings.ShowHTML)
- segment = normalizeURLs(segment, settings)
+ segment = EscapeCharacters(segment, settings, false)
+ segment = ConvertMultiLineText(segment, false, false, settings.ShowHTML)
+ segment = NormalizeURLs(segment, settings)
return segment
},
func(segment string, first bool, last bool) string {
@@ -99,9 +99,9 @@ func sanitizeDocument(s string, settings *print.Settings) string {
return result
}
-// sanitizeMarkdownTable converts passed 'string' to suitable Markdown representation
+// SanitizeMarkdownTable converts passed 'string' to suitable Markdown representation
// for a table. (including line-break, illegal characters, code blocks etc)
-func sanitizeMarkdownTable(s string, settings *print.Settings) string {
+func SanitizeMarkdownTable(s string, settings *print.Settings) string {
if s == "" {
return "n/a"
}
@@ -109,9 +109,9 @@ func sanitizeMarkdownTable(s string, settings *print.Settings) string {
s,
"```",
func(segment string, first bool, last bool) string {
- segment = escapeIllegalCharacters(segment, settings, true)
- segment = convertMultiLineText(segment, true, false, settings.ShowHTML)
- segment = normalizeURLs(segment, settings)
+ segment = EscapeCharacters(segment, settings, true)
+ segment = ConvertMultiLineText(segment, true, false, settings.ShowHTML)
+ segment = NormalizeURLs(segment, settings)
return segment
},
func(segment string, first bool, last bool) string {
@@ -133,7 +133,7 @@ func sanitizeMarkdownTable(s string, settings *print.Settings) string {
codeend = codeend[:3]
}
- segment = convertOneLineCodeBlock(segment)
+ segment = ConvertOneLineCodeBlock(segment)
}
segment = strings.ReplaceAll(segment, "\n", linebreak)
@@ -145,9 +145,9 @@ func sanitizeMarkdownTable(s string, settings *print.Settings) string {
return result
}
-// sanitizeAsciidocTable converts passed 'string' to suitable AsciiDoc representation
+// SanitizeAsciidocTable converts passed 'string' to suitable AsciiDoc representation
// for a table. (including line-break, illegal characters, code blocks etc)
-func sanitizeAsciidocTable(s string, settings *print.Settings) string {
+func SanitizeAsciidocTable(s string, settings *print.Settings) string {
if s == "" {
return "n/a"
}
@@ -155,8 +155,8 @@ func sanitizeAsciidocTable(s string, settings *print.Settings) string {
s,
"```",
func(segment string, first bool, last bool) string {
- segment = escapeIllegalCharacters(segment, settings, true)
- segment = normalizeURLs(segment, settings)
+ segment = EscapeCharacters(segment, settings, true)
+ segment = NormalizeURLs(segment, settings)
return segment
},
func(segment string, first bool, last bool) string {
@@ -168,8 +168,8 @@ func sanitizeAsciidocTable(s string, settings *print.Settings) string {
return result
}
-// convertMultiLineText converts a multi-line text into a suitable Markdown representation.
-func convertMultiLineText(s string, isTable bool, isHeader bool, showHTML bool) string {
+// ConvertMultiLineText converts a multi-line text into a suitable Markdown representation.
+func ConvertMultiLineText(s string, isTable bool, isHeader bool, showHTML bool) string {
if isTable {
s = strings.TrimSpace(s)
}
@@ -204,9 +204,9 @@ func convertMultiLineText(s string, isTable bool, isHeader bool, showHTML bool)
return strings.ReplaceAll(s, "\n", linebreak)
}
-// convertOneLineCodeBlock converts a multi-line code block into a one-liner.
+// ConvertOneLineCodeBlock converts a multi-line code block into a one-liner.
// Line breaks are replaced with single space.
-func convertOneLineCodeBlock(s string) string {
+func ConvertOneLineCodeBlock(s string) string {
splitted := strings.Split(s, "\n")
result := []string{}
for _, segment := range splitted {
@@ -220,8 +220,8 @@ func convertOneLineCodeBlock(s string) string {
return strings.Join(result, " ")
}
-// escapeIllegalCharacters escapes characters which have special meaning in Markdown into their corresponding literal.
-func escapeIllegalCharacters(s string, settings *print.Settings, escapePipe bool) string {
+// EscapeCharacters escapes characters which have special meaning in Markdown into their corresponding literal.
+func EscapeCharacters(s string, settings *print.Settings, escapePipe bool) string {
// Escape pipe (only for 'markdown table' or 'asciidoc table')
if escapePipe {
s = processSegments(
@@ -285,10 +285,10 @@ func escapeIllegalCharacters(s string, settings *print.Settings, escapePipe bool
return s
}
-// normalizeURLs runs after escape function and normalizes URL back
+// NormalizeURLs runs after escape function and normalizes URL back
// to the original state. For example any underscore in the URL which
// got escaped by 'EscapeIllegalCharacters' will be reverted back.
-func normalizeURLs(s string, settings *print.Settings) string {
+func NormalizeURLs(s string, settings *print.Settings) string {
if settings.EscapeCharacters {
if urls := xurls.Strict().FindAllString(s, -1); len(urls) > 0 {
for _, url := range urls {
diff --git a/internal/template/sanitizer_test.go b/template/sanitizer_test.go
similarity index 97%
rename from internal/template/sanitizer_test.go
rename to template/sanitizer_test.go
index bbd1b04..8ca9749 100644
--- a/internal/template/sanitizer_test.go
+++ b/template/sanitizer_test.go
@@ -100,7 +100,7 @@ func TestSanitizeName(t *testing.T) {
settings := &print.Settings{
EscapeCharacters: tt.escape,
}
- actual := sanitizeName(tt.input, settings)
+ actual := SanitizeName(tt.input, settings)
assert.Equal(tt.expected, actual)
})
@@ -139,7 +139,7 @@ func TestSanitizeSection(t *testing.T) {
bytes, err := ioutil.ReadFile(filepath.Join("testdata", "section", tt.filename+".golden"))
assert.Nil(err)
- actual := sanitizeSection(string(bytes), settings)
+ actual := SanitizeSection(string(bytes), settings)
expected, err := ioutil.ReadFile(filepath.Join("testdata", "section", tt.filename+".expected"))
assert.Nil(err)
@@ -181,7 +181,7 @@ func TestSanitizeDocument(t *testing.T) {
bytes, err := ioutil.ReadFile(filepath.Join("testdata", "document", tt.filename+".golden"))
assert.Nil(err)
- actual := sanitizeDocument(string(bytes), settings)
+ actual := SanitizeDocument(string(bytes), settings)
expected, err := ioutil.ReadFile(filepath.Join("testdata", "document", tt.filename+".expected"))
assert.Nil(err)
@@ -246,7 +246,7 @@ func TestSanitizeMarkdownTable(t *testing.T) {
bytes, err := ioutil.ReadFile(filepath.Join("testdata", "table", tt.filename+".golden"))
assert.Nil(err)
- actual := sanitizeMarkdownTable(string(bytes), settings)
+ actual := SanitizeMarkdownTable(string(bytes), settings)
expected, err := ioutil.ReadFile(filepath.Join("testdata", "table", tt.expected+".markdown.expected"))
assert.Nil(err)
@@ -288,7 +288,7 @@ func TestSanitizeAsciidocTable(t *testing.T) {
bytes, err := ioutil.ReadFile(filepath.Join("testdata", "table", tt.filename+".golden"))
assert.Nil(err)
- actual := sanitizeAsciidocTable(string(bytes), settings)
+ actual := SanitizeAsciidocTable(string(bytes), settings)
expected, err := ioutil.ReadFile(filepath.Join("testdata", "table", tt.filename+".asciidoc.expected"))
assert.Nil(err)
@@ -420,7 +420,7 @@ func TestConvertMultiLineText(t *testing.T) {
bytes, err := ioutil.ReadFile(path)
assert.Nil(err)
- actual := convertMultiLineText(string(bytes), tt.isTable, false, tt.showHTML)
+ actual := ConvertMultiLineText(string(bytes), tt.isTable, false, tt.showHTML)
assert.Equal(tt.expected, actual)
})
}
@@ -581,7 +581,7 @@ func TestEscapeIllegalCharacters(t *testing.T) {
settings := &print.Settings{
EscapeCharacters: tt.escapeChars,
}
- actual := escapeIllegalCharacters(tt.input, settings, tt.escapePipe)
+ actual := EscapeCharacters(tt.input, settings, tt.escapePipe)
assert.Equal(tt.expected, actual)
})
@@ -638,7 +638,7 @@ func TestNormalizeURLs(t *testing.T) {
settings := &print.Settings{
EscapeCharacters: tt.escape,
}
- actual := normalizeURLs(tt.input, settings)
+ actual := NormalizeURLs(tt.input, settings)
assert.Equal(tt.expected, actual)
})
diff --git a/template/template.go b/template/template.go
new file mode 100644
index 0000000..00b4bfb
--- /dev/null
+++ b/template/template.go
@@ -0,0 +1,244 @@
+/*
+Copyright 2021 The terraform-docs Authors.
+
+Licensed under the MIT license (the "License"); you may not
+use this file except in compliance with the License.
+
+You may obtain a copy of the License at the LICENSE file in
+the root directory of this source tree.
+*/
+
+package template
+
+import (
+ "bytes"
+ "fmt"
+ "strings"
+ gotemplate "text/template"
+
+ "github.com/terraform-docs/terraform-docs/internal/print"
+ "github.com/terraform-docs/terraform-docs/internal/terraform"
+ "github.com/terraform-docs/terraform-docs/internal/types"
+)
+
+// Item represents a named templated which can reference other named templated too.
+type Item struct {
+ Name string
+ Text string
+}
+
+// Template represents a new Template with given name and content to be rendered
+// with provided settings with use of built-in and custom functions.
+type Template struct {
+ items []*Item
+ settings *print.Settings
+
+ funcMap gotemplate.FuncMap
+ customFunc gotemplate.FuncMap
+}
+
+// New returns new instance of Template.
+func New(settings *print.Settings, items ...*Item) *Template {
+ return &Template{
+ items: items,
+ settings: settings,
+ funcMap: builtinFuncs(settings),
+ customFunc: make(gotemplate.FuncMap),
+ }
+}
+
+// Funcs return available template out of the box and custom functions.
+func (t Template) Funcs() gotemplate.FuncMap {
+ return t.funcMap
+}
+
+// CustomFunc adds new custom functions to the template if functions with the same
+// names didn't exist.
+func (t *Template) CustomFunc(funcs gotemplate.FuncMap) {
+ for name, fn := range funcs {
+ if _, found := t.customFunc[name]; !found {
+ t.customFunc[name] = fn
+ }
+ }
+ t.applyCustomFunc()
+}
+
+// applyCustomFunc is re-adding the custom functions to list of available functions.
+func (t *Template) applyCustomFunc() {
+ for name, fn := range t.customFunc {
+ if _, found := t.funcMap[name]; !found {
+ t.funcMap[name] = fn
+ }
+ }
+}
+
+// Render template with given Module struct.
+func (t *Template) Render(name string, module *terraform.Module) (string, error) {
+ if len(t.items) < 1 {
+ return "", fmt.Errorf("base template not found")
+ }
+
+ item := t.findByName(name)
+ if item == nil {
+ return "", fmt.Errorf("%s template not found", name)
+ }
+
+ var buffer bytes.Buffer
+
+ tmpl := gotemplate.New(item.Name)
+ tmpl.Funcs(t.funcMap)
+ gotemplate.Must(tmpl.Parse(normalize(item.Text)))
+
+ for _, ii := range t.items {
+ tt := tmpl.New(ii.Name)
+ tt.Funcs(t.funcMap)
+ gotemplate.Must(tt.Parse(normalize(ii.Text)))
+ }
+
+ if err := tmpl.ExecuteTemplate(&buffer, item.Name, struct {
+ Module *terraform.Module
+ Settings *print.Settings
+ }{
+ Module: module,
+ Settings: t.settings,
+ }); err != nil {
+ return "", err
+ }
+
+ return buffer.String(), nil
+}
+
+func (t *Template) findByName(name string) *Item {
+ if name == "" {
+ if len(t.items) > 0 {
+ return t.items[0]
+ }
+ return nil
+ }
+ for _, i := range t.items {
+ if i.Name == name {
+ return i
+ }
+ }
+ return nil
+}
+
+func builtinFuncs(settings *print.Settings) gotemplate.FuncMap { // nolint:gocyclo
+ return gotemplate.FuncMap{
+ "default": func(d string, s string) string {
+ if s != "" {
+ return s
+ }
+ return d
+ },
+ "indent": func(l int, char string) string {
+ return GenerateIndentation(l, char, settings)
+ },
+ "name": func(n string) string {
+ return SanitizeName(n, settings)
+ },
+ "ternary": func(condition interface{}, trueValue string, falseValue string) string {
+ var c bool
+ switch x := fmt.Sprintf("%T", condition); x {
+ case "string":
+ c = condition.(string) != ""
+ case "int":
+ c = condition.(int) != 0
+ case "bool":
+ c = condition.(bool)
+ }
+ if c {
+ return trueValue
+ }
+ return falseValue
+ },
+ "tostring": func(s types.String) string {
+ return string(s)
+ },
+
+ // trim
+ "trim": func(cut string, s string) string {
+ if s != "" {
+ return strings.Trim(s, cut)
+ }
+ return s
+ },
+ "trimLeft": func(cut string, s string) string {
+ if s != "" {
+ return strings.TrimLeft(s, cut)
+ }
+ return s
+ },
+ "trimRight": func(cut string, s string) string {
+ if s != "" {
+ return strings.TrimRight(s, cut)
+ }
+ return s
+ },
+ "trimPrefix": func(prefix string, s string) string {
+ if s != "" {
+ return strings.TrimPrefix(s, prefix)
+ }
+ return s
+ },
+ "trimSuffix": func(suffix string, s string) string {
+ if s != "" {
+ return strings.TrimSuffix(s, suffix)
+ }
+ return s
+ },
+
+ // sanitize
+ "sanitizeSection": func(s string) string {
+ return SanitizeSection(s, settings)
+ },
+ "sanitizeDoc": func(s string) string {
+ return SanitizeDocument(s, settings)
+ },
+ "sanitizeMarkdownTbl": func(s string) string {
+ return SanitizeMarkdownTable(s, settings)
+ },
+ "sanitizeAsciidocTbl": func(s string) string {
+ return SanitizeAsciidocTable(s, settings)
+ },
+
+ // anchors
+ "anchorNameMarkdown": func(s string, t string) string {
+ return CreateAnchorMarkdown(s, t, settings)
+ },
+ "anchorNameAsciidoc": func(s string, t string) string {
+ return CreateAnchorAsciidoc(s, t, settings)
+ },
+ }
+}
+
+// normalize the template and remove any space from all the lines. This makes
+// it possible to have a indented, human-readable template which doesn't affect
+// the rendering of them.
+func normalize(s string) string {
+ segments := strings.Split(s, "\n")
+ buffer := bytes.NewBufferString("")
+ for _, segment := range segments {
+ buffer.WriteString(strings.TrimSpace(segment)) // nolint:gosec
+ buffer.WriteString("\n") // nolint:gosec
+ }
+ return buffer.String()
+}
+
+// GenerateIndentation generates indentation of Markdown and AsciiDoc headers
+// with base level of provided 'settings.IndentLevel' plus any extra level needed
+// for subsection (e.g. 'Required Inputs' which is a subsection of 'Inputs' section)
+func GenerateIndentation(extra int, char string, settings *print.Settings) string {
+ if char == "" {
+ return ""
+ }
+ var base = settings.IndentLevel
+ if base < 1 || base > 5 {
+ base = 2
+ }
+ var indent string
+ for i := 0; i < base+extra; i++ {
+ indent += char
+ }
+ return indent
+}
diff --git a/internal/template/template_test.go b/template/template_test.go
similarity index 92%
rename from internal/template/template_test.go
rename to template/template_test.go
index 64c3eef..147d8ff 100644
--- a/internal/template/template_test.go
+++ b/template/template_test.go
@@ -420,8 +420,7 @@ func TestBuiltinFunc(t *testing.T) {
assert := assert.New(t)
settings := print.DefaultSettings()
settings.EscapeCharacters = tt.escape
- tmpl := New(settings)
- funcs := tmpl.Funcs()
+ funcs := builtinFuncs(settings)
fn, ok := funcs[tt.funcName]
assert.Truef(ok, "function %s is not defined", tt.funcName)
@@ -462,3 +461,51 @@ func TestBuiltinFunc(t *testing.T) {
})
}
}
+
+func TestGenerateIndentation(t *testing.T) {
+ tests := []struct {
+ name string
+ base int
+ extra int
+ expected string
+ }{
+ {
+ name: "generate indentation",
+ base: 2,
+ extra: 1,
+ expected: "###",
+ },
+ {
+ name: "generate indentation",
+ extra: 2,
+ expected: "####",
+ },
+ {
+ name: "generate indentation",
+ base: 4,
+ extra: 3,
+ expected: "#######",
+ },
+ {
+ name: "generate indentation",
+ base: 0,
+ extra: 0,
+ expected: "##",
+ },
+ {
+ name: "generate indentation",
+ base: 6,
+ extra: 1,
+ expected: "###",
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ assert := assert.New(t)
+ settings := &print.Settings{IndentLevel: tt.base}
+ actual := GenerateIndentation(tt.extra, "#", settings)
+
+ assert.Equal(tt.expected, actual)
+ })
+ }
+}
diff --git a/internal/template/testdata/document/codeblock.expected b/template/testdata/document/codeblock.expected
similarity index 100%
rename from internal/template/testdata/document/codeblock.expected
rename to template/testdata/document/codeblock.expected
diff --git a/internal/template/testdata/document/codeblock.golden b/template/testdata/document/codeblock.golden
similarity index 100%
rename from internal/template/testdata/document/codeblock.golden
rename to template/testdata/document/codeblock.golden
diff --git a/internal/template/testdata/document/complex.expected b/template/testdata/document/complex.expected
similarity index 100%
rename from internal/template/testdata/document/complex.expected
rename to template/testdata/document/complex.expected
diff --git a/internal/template/testdata/document/complex.golden b/template/testdata/document/complex.golden
similarity index 100%
rename from internal/template/testdata/document/complex.golden
rename to template/testdata/document/complex.golden
diff --git a/internal/template/testdata/document/empty.expected b/template/testdata/document/empty.expected
similarity index 100%
rename from internal/template/testdata/document/empty.expected
rename to template/testdata/document/empty.expected
diff --git a/internal/template/testdata/document/empty.golden b/template/testdata/document/empty.golden
similarity index 100%
rename from internal/template/testdata/document/empty.golden
rename to template/testdata/document/empty.golden
diff --git a/internal/template/testdata/multiline/indentations.golden b/template/testdata/multiline/indentations.golden
similarity index 100%
rename from internal/template/testdata/multiline/indentations.golden
rename to template/testdata/multiline/indentations.golden
diff --git a/internal/template/testdata/multiline/list.golden b/template/testdata/multiline/list.golden
similarity index 100%
rename from internal/template/testdata/multiline/list.golden
rename to template/testdata/multiline/list.golden
diff --git a/internal/template/testdata/multiline/newline-double.golden b/template/testdata/multiline/newline-double.golden
similarity index 100%
rename from internal/template/testdata/multiline/newline-double.golden
rename to template/testdata/multiline/newline-double.golden
diff --git a/internal/template/testdata/multiline/newline-single.golden b/template/testdata/multiline/newline-single.golden
similarity index 100%
rename from internal/template/testdata/multiline/newline-single.golden
rename to template/testdata/multiline/newline-single.golden
diff --git a/internal/template/testdata/multiline/paragraph.golden b/template/testdata/multiline/paragraph.golden
similarity index 100%
rename from internal/template/testdata/multiline/paragraph.golden
rename to template/testdata/multiline/paragraph.golden
diff --git a/internal/template/testdata/section/codeblock.expected b/template/testdata/section/codeblock.expected
similarity index 100%
rename from internal/template/testdata/section/codeblock.expected
rename to template/testdata/section/codeblock.expected
diff --git a/internal/template/testdata/section/codeblock.golden b/template/testdata/section/codeblock.golden
similarity index 100%
rename from internal/template/testdata/section/codeblock.golden
rename to template/testdata/section/codeblock.golden
diff --git a/internal/template/testdata/section/complex.expected b/template/testdata/section/complex.expected
similarity index 100%
rename from internal/template/testdata/section/complex.expected
rename to template/testdata/section/complex.expected
diff --git a/internal/template/testdata/section/complex.golden b/template/testdata/section/complex.golden
similarity index 100%
rename from internal/template/testdata/section/complex.golden
rename to template/testdata/section/complex.golden
diff --git a/internal/template/testdata/section/empty.expected b/template/testdata/section/empty.expected
similarity index 100%
rename from internal/template/testdata/section/empty.expected
rename to template/testdata/section/empty.expected
diff --git a/internal/template/testdata/section/empty.golden b/template/testdata/section/empty.golden
similarity index 100%
rename from internal/template/testdata/section/empty.golden
rename to template/testdata/section/empty.golden
diff --git a/internal/template/testdata/table/codeblock-html.markdown.expected b/template/testdata/table/codeblock-html.markdown.expected
similarity index 100%
rename from internal/template/testdata/table/codeblock-html.markdown.expected
rename to template/testdata/table/codeblock-html.markdown.expected
diff --git a/internal/template/testdata/table/codeblock-nohtml.markdown.expected b/template/testdata/table/codeblock-nohtml.markdown.expected
similarity index 100%
rename from internal/template/testdata/table/codeblock-nohtml.markdown.expected
rename to template/testdata/table/codeblock-nohtml.markdown.expected
diff --git a/internal/template/testdata/table/codeblock.asciidoc.expected b/template/testdata/table/codeblock.asciidoc.expected
similarity index 100%
rename from internal/template/testdata/table/codeblock.asciidoc.expected
rename to template/testdata/table/codeblock.asciidoc.expected
diff --git a/internal/template/testdata/table/codeblock.golden b/template/testdata/table/codeblock.golden
similarity index 100%
rename from internal/template/testdata/table/codeblock.golden
rename to template/testdata/table/codeblock.golden
diff --git a/internal/template/testdata/table/complex-html.markdown.expected b/template/testdata/table/complex-html.markdown.expected
similarity index 100%
rename from internal/template/testdata/table/complex-html.markdown.expected
rename to template/testdata/table/complex-html.markdown.expected
diff --git a/internal/template/testdata/table/complex-nohtml.markdown.expected b/template/testdata/table/complex-nohtml.markdown.expected
similarity index 100%
rename from internal/template/testdata/table/complex-nohtml.markdown.expected
rename to template/testdata/table/complex-nohtml.markdown.expected
diff --git a/internal/template/testdata/table/complex.asciidoc.expected b/template/testdata/table/complex.asciidoc.expected
similarity index 100%
rename from internal/template/testdata/table/complex.asciidoc.expected
rename to template/testdata/table/complex.asciidoc.expected
diff --git a/internal/template/testdata/table/complex.golden b/template/testdata/table/complex.golden
similarity index 100%
rename from internal/template/testdata/table/complex.golden
rename to template/testdata/table/complex.golden
diff --git a/internal/template/testdata/table/empty.asciidoc.expected b/template/testdata/table/empty.asciidoc.expected
similarity index 100%
rename from internal/template/testdata/table/empty.asciidoc.expected
rename to template/testdata/table/empty.asciidoc.expected
diff --git a/internal/template/testdata/table/empty.golden b/template/testdata/table/empty.golden
similarity index 100%
rename from internal/template/testdata/table/empty.golden
rename to template/testdata/table/empty.golden
diff --git a/internal/template/testdata/table/empty.markdown.expected b/template/testdata/table/empty.markdown.expected
similarity index 100%
rename from internal/template/testdata/table/empty.markdown.expected
rename to template/testdata/table/empty.markdown.expected