From d2fe2b1b2994a6ab847fc268465fa8d416176378 Mon Sep 17 00:00:00 2001 From: Khosrow Moossavi Date: Tue, 28 Sep 2021 14:45:36 -0400 Subject: [PATCH] Move print package from internal to public Signed-off-by: Khosrow Moossavi --- README.md | 42 ++++ cmd/asciidoc/asciidoc.go | 3 +- cmd/asciidoc/document/document.go | 3 +- cmd/asciidoc/table/table.go | 3 +- cmd/json/json.go | 3 +- cmd/markdown/document/document.go | 3 +- cmd/markdown/markdown.go | 3 +- cmd/markdown/table/table.go | 3 +- cmd/pretty/pretty.go | 3 +- cmd/root.go | 13 +- cmd/tfvars/hcl/hcl.go | 3 +- cmd/tfvars/json/json.go | 3 +- cmd/tfvars/tfvars.go | 3 +- cmd/toml/toml.go | 3 +- cmd/xml/xml.go | 3 +- cmd/yaml/yaml.go | 3 +- docs/reference/asciidoc-document.md | 4 - docs/reference/asciidoc-table.md | 4 - docs/reference/json.md | 2 +- docs/reference/markdown-document.md | 4 - docs/reference/markdown-table.md | 4 - docs/reference/pretty.md | 4 - docs/reference/toml.md | 2 +- docs/reference/xml.md | 2 +- docs/reference/yaml.md | 5 +- format/asciidoc_document.go | 40 ++-- format/asciidoc_document_test.go | 8 +- format/asciidoc_table.go | 40 ++-- format/asciidoc_table_test.go | 8 +- format/common_test.go | 4 +- format/doc.go | 21 +- format/factory.go | 45 ---- format/factory_test.go | 211 ----------------- format/json.go | 51 ++--- format/json_test.go | 8 +- format/markdown_document.go | 40 ++-- format/markdown_document_test.go | 8 +- format/markdown_table.go | 40 ++-- format/markdown_table_test.go | 8 +- format/pretty.go | 33 +-- format/pretty_test.go | 8 +- format/tfvars_hcl.go | 33 +-- format/tfvars_hcl_test.go | 8 +- format/tfvars_json.go | 38 ++-- format/tfvars_json_test.go | 8 +- format/toml.go | 51 ++--- format/toml_test.go | 8 +- format/type.go | 66 ++++++ format/type_test.go | 212 ++++++++++++++++++ format/util.go | 57 +++++ format/xml.go | 47 ++-- format/xml_test.go | 8 +- format/yaml.go | 53 ++--- format/yaml_test.go | 8 +- internal/cli/mappings.go | 45 ++++ internal/cli/run.go | 49 ++-- internal/cli/writer.go | 6 +- internal/cli/writer_test.go | 73 +++--- internal/print/doc.go | 12 - internal/print/engine.go | 20 -- internal/testutil/settings.go | 2 +- {internal/cli => print}/config.go | 210 ++++++++--------- {internal/cli => print}/config_test.go | 38 ++-- print/doc.go | 51 +++++ {internal/print => print}/generator.go | 112 ++++++--- {internal/print => print}/generator_test.go | 54 +++-- {internal/print => print}/settings.go | 80 +++---- .../print => print}/testdata/sample-file.txt | 0 {internal/cli => print}/util.go | 2 +- {internal/cli => print}/util_test.go | 2 +- scripts/docs/generate.go | 25 +-- template/anchor.go | 2 +- template/anchor_test.go | 2 +- template/doc.go | 2 +- template/sanitizer.go | 2 +- template/sanitizer_test.go | 2 +- template/template.go | 2 +- template/template_test.go | 2 +- 78 files changed, 1143 insertions(+), 950 deletions(-) delete mode 100644 format/factory.go delete mode 100644 format/factory_test.go create mode 100644 format/type.go create mode 100644 format/type_test.go create mode 100644 internal/cli/mappings.go delete mode 100644 internal/print/doc.go delete mode 100644 internal/print/engine.go rename {internal/cli => print}/config.go (70%) rename {internal/cli => print}/config_test.go (92%) create mode 100644 print/doc.go rename {internal/print => print}/generator.go (58%) rename {internal/print => print}/generator_test.go (78%) rename {internal/print => print}/settings.go (75%) rename {internal/print => print}/testdata/sample-file.txt (100%) rename {internal/cli => print}/util.go (98%) rename {internal/cli => print}/util_test.go (99%) diff --git a/README.md b/README.md index ad4428b..933eec6 100644 --- a/README.md +++ b/README.md @@ -276,6 +276,48 @@ content: |- ``` ```` +## Build on top of terraform-docs + +terraform-docs primary use-case is to be utilized as a standalone binary, but +some parts of it is also available publicly and can be imported in your project +as a library. + +```go +import ( + "github.com/terraform-docs/terraform-docs/format" + "github.com/terraform-docs/terraform-docs/print" + "github.com/terraform-docs/terraform-docs/terraform" +) + +// buildTerraformDocs for module root `path` and provided content `tmpl`. +func buildTerraformDocs(path string, tmpl string) (string, error) { + config := print.DefaultConfig() + config.ModuleRoot = path // module root path (can be relative or absolute) + + _, options := config.Extract() + + module, err := terraform.LoadWithOptions(options) + if err != nil { + return "", err + } + + // Generate in Markdown Table format + formatter := format.NewMarkdownTable(config) + + if err := formatter.Generate(module); err != nil { + return "", err + } + + // // Note: if you don't intend to provide additional template for the generated + // // content, or the target format doesn't provide templating (e.g. json, yaml, + // // xml, or toml) you can use `Content()` function instead of `ExecuteTemplate()`. + // // `Content()` returns all the sections combined with predefined order. + // return formatter.Content(), nil + + return formatter.ExecuteTemplate(tmpl) +} +``` + ## Documentation - **Users** diff --git a/cmd/asciidoc/asciidoc.go b/cmd/asciidoc/asciidoc.go index 264d6b4..ba54444 100644 --- a/cmd/asciidoc/asciidoc.go +++ b/cmd/asciidoc/asciidoc.go @@ -16,10 +16,11 @@ import ( "github.com/terraform-docs/terraform-docs/cmd/asciidoc/document" "github.com/terraform-docs/terraform-docs/cmd/asciidoc/table" "github.com/terraform-docs/terraform-docs/internal/cli" + "github.com/terraform-docs/terraform-docs/print" ) // NewCommand returns a new cobra.Command for 'asciidoc' formatter -func NewCommand(runtime *cli.Runtime, config *cli.Config) *cobra.Command { +func NewCommand(runtime *cli.Runtime, config *print.Config) *cobra.Command { cmd := &cobra.Command{ Args: cobra.ExactArgs(1), Use: "asciidoc [PATH]", diff --git a/cmd/asciidoc/document/document.go b/cmd/asciidoc/document/document.go index 64a8fed..0b2a42c 100644 --- a/cmd/asciidoc/document/document.go +++ b/cmd/asciidoc/document/document.go @@ -14,10 +14,11 @@ import ( "github.com/spf13/cobra" "github.com/terraform-docs/terraform-docs/internal/cli" + "github.com/terraform-docs/terraform-docs/print" ) // NewCommand returns a new cobra.Command for 'asciidoc document' formatter -func NewCommand(runtime *cli.Runtime, config *cli.Config) *cobra.Command { +func NewCommand(runtime *cli.Runtime, config *print.Config) *cobra.Command { cmd := &cobra.Command{ Args: cobra.ExactArgs(1), Use: "document [PATH]", diff --git a/cmd/asciidoc/table/table.go b/cmd/asciidoc/table/table.go index 00121eb..cf6e83c 100644 --- a/cmd/asciidoc/table/table.go +++ b/cmd/asciidoc/table/table.go @@ -14,10 +14,11 @@ import ( "github.com/spf13/cobra" "github.com/terraform-docs/terraform-docs/internal/cli" + "github.com/terraform-docs/terraform-docs/print" ) // NewCommand returns a new cobra.Command for 'asciidoc table' formatter -func NewCommand(runtime *cli.Runtime, config *cli.Config) *cobra.Command { +func NewCommand(runtime *cli.Runtime, config *print.Config) *cobra.Command { cmd := &cobra.Command{ Args: cobra.ExactArgs(1), Use: "table [PATH]", diff --git a/cmd/json/json.go b/cmd/json/json.go index dfc42d2..8e61e3d 100644 --- a/cmd/json/json.go +++ b/cmd/json/json.go @@ -14,10 +14,11 @@ import ( "github.com/spf13/cobra" "github.com/terraform-docs/terraform-docs/internal/cli" + "github.com/terraform-docs/terraform-docs/print" ) // NewCommand returns a new cobra.Command for 'json' formatter -func NewCommand(runtime *cli.Runtime, config *cli.Config) *cobra.Command { +func NewCommand(runtime *cli.Runtime, config *print.Config) *cobra.Command { cmd := &cobra.Command{ Args: cobra.ExactArgs(1), Use: "json [PATH]", diff --git a/cmd/markdown/document/document.go b/cmd/markdown/document/document.go index d434739..a989f95 100644 --- a/cmd/markdown/document/document.go +++ b/cmd/markdown/document/document.go @@ -14,10 +14,11 @@ import ( "github.com/spf13/cobra" "github.com/terraform-docs/terraform-docs/internal/cli" + "github.com/terraform-docs/terraform-docs/print" ) // NewCommand returns a new cobra.Command for 'markdown document' formatter -func NewCommand(runtime *cli.Runtime, config *cli.Config) *cobra.Command { +func NewCommand(runtime *cli.Runtime, config *print.Config) *cobra.Command { cmd := &cobra.Command{ Args: cobra.ExactArgs(1), Use: "document [PATH]", diff --git a/cmd/markdown/markdown.go b/cmd/markdown/markdown.go index f073321..b2b1a2b 100644 --- a/cmd/markdown/markdown.go +++ b/cmd/markdown/markdown.go @@ -16,10 +16,11 @@ import ( "github.com/terraform-docs/terraform-docs/cmd/markdown/document" "github.com/terraform-docs/terraform-docs/cmd/markdown/table" "github.com/terraform-docs/terraform-docs/internal/cli" + "github.com/terraform-docs/terraform-docs/print" ) // NewCommand returns a new cobra.Command for 'markdown' formatter -func NewCommand(runtime *cli.Runtime, config *cli.Config) *cobra.Command { +func NewCommand(runtime *cli.Runtime, config *print.Config) *cobra.Command { cmd := &cobra.Command{ Args: cobra.ExactArgs(1), Use: "markdown [PATH]", diff --git a/cmd/markdown/table/table.go b/cmd/markdown/table/table.go index 0fa0670..adbfa1c 100644 --- a/cmd/markdown/table/table.go +++ b/cmd/markdown/table/table.go @@ -14,10 +14,11 @@ import ( "github.com/spf13/cobra" "github.com/terraform-docs/terraform-docs/internal/cli" + "github.com/terraform-docs/terraform-docs/print" ) // NewCommand returns a new cobra.Command for 'markdown table' formatter -func NewCommand(runtime *cli.Runtime, config *cli.Config) *cobra.Command { +func NewCommand(runtime *cli.Runtime, config *print.Config) *cobra.Command { cmd := &cobra.Command{ Args: cobra.ExactArgs(1), Use: "table [PATH]", diff --git a/cmd/pretty/pretty.go b/cmd/pretty/pretty.go index d4b86a9..d53906b 100644 --- a/cmd/pretty/pretty.go +++ b/cmd/pretty/pretty.go @@ -14,10 +14,11 @@ import ( "github.com/spf13/cobra" "github.com/terraform-docs/terraform-docs/internal/cli" + "github.com/terraform-docs/terraform-docs/print" ) // NewCommand returns a new cobra.Command for pretty formatter -func NewCommand(runtime *cli.Runtime, config *cli.Config) *cobra.Command { +func NewCommand(runtime *cli.Runtime, config *print.Config) *cobra.Command { cmd := &cobra.Command{ Args: cobra.ExactArgs(1), Use: "pretty [PATH]", diff --git a/cmd/root.go b/cmd/root.go index ec771fc..abbbb83 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -28,6 +28,7 @@ import ( "github.com/terraform-docs/terraform-docs/cmd/yaml" "github.com/terraform-docs/terraform-docs/internal/cli" "github.com/terraform-docs/terraform-docs/internal/version" + "github.com/terraform-docs/terraform-docs/print" ) // Execute adds all child commands to the root command and sets flags appropriately. @@ -42,7 +43,7 @@ func Execute() error { // NewCommand returns a new cobra.Command for 'root' command func NewCommand() *cobra.Command { - config := cli.DefaultConfig() + config := print.DefaultConfig() runtime := cli.NewRuntime(config) cmd := &cobra.Command{ Args: cobra.MaximumNArgs(1), @@ -62,16 +63,16 @@ func NewCommand() *cobra.Command { cmd.PersistentFlags().BoolVar(&config.Recursive, "recursive", false, "update submodules recursively (default false)") cmd.PersistentFlags().StringVar(&config.RecursivePath, "recursive-path", "modules", "submodules path to recursively update") - cmd.PersistentFlags().StringSliceVar(&config.Sections.Show, "show", []string{}, "show section ["+cli.AllSections+"]") - cmd.PersistentFlags().StringSliceVar(&config.Sections.Hide, "hide", []string{}, "hide section ["+cli.AllSections+"]") + cmd.PersistentFlags().StringSliceVar(&config.Sections.Show, "show", []string{}, "show section ["+print.AllSections+"]") + cmd.PersistentFlags().StringSliceVar(&config.Sections.Hide, "hide", []string{}, "hide section ["+print.AllSections+"]") cmd.PersistentFlags().StringVar(&config.Output.File, "output-file", "", "file path to insert output into (default \"\")") - cmd.PersistentFlags().StringVar(&config.Output.Mode, "output-mode", "inject", "output to file method ["+cli.OutputModes+"]") - cmd.PersistentFlags().StringVar(&config.Output.Template, "output-template", cli.OutputTemplate, "output template") + cmd.PersistentFlags().StringVar(&config.Output.Mode, "output-mode", "inject", "output to file method ["+print.OutputModes+"]") + cmd.PersistentFlags().StringVar(&config.Output.Template, "output-template", print.OutputTemplate, "output template") cmd.PersistentFlags().BoolVar(&config.Output.Check, "output-check", false, "check if content of output file is up to date (default false)") cmd.PersistentFlags().BoolVar(&config.Sort.Enabled, "sort", true, "sort items") - cmd.PersistentFlags().StringVar(&config.Sort.By, "sort-by", "name", "sort items by criteria ["+cli.SortTypes+"]") + cmd.PersistentFlags().StringVar(&config.Sort.By, "sort-by", "name", "sort items by criteria ["+print.SortTypes+"]") cmd.PersistentFlags().StringVar(&config.HeaderFrom, "header-from", "main.tf", "relative path of a file to read header from") cmd.PersistentFlags().StringVar(&config.FooterFrom, "footer-from", "", "relative path of a file to read footer from (default \"\")") diff --git a/cmd/tfvars/hcl/hcl.go b/cmd/tfvars/hcl/hcl.go index b28d9d1..5239ec3 100644 --- a/cmd/tfvars/hcl/hcl.go +++ b/cmd/tfvars/hcl/hcl.go @@ -14,10 +14,11 @@ import ( "github.com/spf13/cobra" "github.com/terraform-docs/terraform-docs/internal/cli" + "github.com/terraform-docs/terraform-docs/print" ) // NewCommand returns a new cobra.Command for 'tfvars hcl' formatter -func NewCommand(runtime *cli.Runtime, config *cli.Config) *cobra.Command { +func NewCommand(runtime *cli.Runtime, config *print.Config) *cobra.Command { cmd := &cobra.Command{ Args: cobra.ExactArgs(1), Use: "hcl [PATH]", diff --git a/cmd/tfvars/json/json.go b/cmd/tfvars/json/json.go index afdcf29..6e1bf4c 100644 --- a/cmd/tfvars/json/json.go +++ b/cmd/tfvars/json/json.go @@ -14,10 +14,11 @@ import ( "github.com/spf13/cobra" "github.com/terraform-docs/terraform-docs/internal/cli" + "github.com/terraform-docs/terraform-docs/print" ) // NewCommand returns a new cobra.Command for 'tfvars json' formatter -func NewCommand(runtime *cli.Runtime, config *cli.Config) *cobra.Command { +func NewCommand(runtime *cli.Runtime, config *print.Config) *cobra.Command { cmd := &cobra.Command{ Args: cobra.ExactArgs(1), Use: "json [PATH]", diff --git a/cmd/tfvars/tfvars.go b/cmd/tfvars/tfvars.go index d72eb33..c2838ee 100644 --- a/cmd/tfvars/tfvars.go +++ b/cmd/tfvars/tfvars.go @@ -16,10 +16,11 @@ import ( "github.com/terraform-docs/terraform-docs/cmd/tfvars/hcl" "github.com/terraform-docs/terraform-docs/cmd/tfvars/json" "github.com/terraform-docs/terraform-docs/internal/cli" + "github.com/terraform-docs/terraform-docs/print" ) // NewCommand returns a new cobra.Command for 'tfvars' formatter -func NewCommand(runtime *cli.Runtime, config *cli.Config) *cobra.Command { +func NewCommand(runtime *cli.Runtime, config *print.Config) *cobra.Command { cmd := &cobra.Command{ Args: cobra.ExactArgs(1), Use: "tfvars [PATH]", diff --git a/cmd/toml/toml.go b/cmd/toml/toml.go index d4431e4..f75f903 100644 --- a/cmd/toml/toml.go +++ b/cmd/toml/toml.go @@ -14,10 +14,11 @@ import ( "github.com/spf13/cobra" "github.com/terraform-docs/terraform-docs/internal/cli" + "github.com/terraform-docs/terraform-docs/print" ) // NewCommand returns a new cobra.Command for 'toml' formatter -func NewCommand(runtime *cli.Runtime, config *cli.Config) *cobra.Command { +func NewCommand(runtime *cli.Runtime, config *print.Config) *cobra.Command { cmd := &cobra.Command{ Args: cobra.ExactArgs(1), Use: "toml [PATH]", diff --git a/cmd/xml/xml.go b/cmd/xml/xml.go index 07e079d..6e9bdf8 100644 --- a/cmd/xml/xml.go +++ b/cmd/xml/xml.go @@ -14,10 +14,11 @@ import ( "github.com/spf13/cobra" "github.com/terraform-docs/terraform-docs/internal/cli" + "github.com/terraform-docs/terraform-docs/print" ) // NewCommand returns a new cobra.Command for 'xml' formatter -func NewCommand(runtime *cli.Runtime, config *cli.Config) *cobra.Command { +func NewCommand(runtime *cli.Runtime, config *print.Config) *cobra.Command { cmd := &cobra.Command{ Args: cobra.ExactArgs(1), Use: "xml [PATH]", diff --git a/cmd/yaml/yaml.go b/cmd/yaml/yaml.go index 2aa647e..49c9815 100644 --- a/cmd/yaml/yaml.go +++ b/cmd/yaml/yaml.go @@ -14,10 +14,11 @@ import ( "github.com/spf13/cobra" "github.com/terraform-docs/terraform-docs/internal/cli" + "github.com/terraform-docs/terraform-docs/print" ) // NewCommand returns a new cobra.Command for 'yaml' formatter -func NewCommand(runtime *cli.Runtime, config *cli.Config) *cobra.Command { +func NewCommand(runtime *cli.Runtime, config *print.Config) *cobra.Command { cmd := &cobra.Command{ Args: cobra.ExactArgs(1), Use: "yaml [PATH]", diff --git a/docs/reference/asciidoc-document.md b/docs/reference/asciidoc-document.md index 0d26d6d..e547d3c 100644 --- a/docs/reference/asciidoc-document.md +++ b/docs/reference/asciidoc-document.md @@ -484,8 +484,4 @@ generates the following output: Description: It's unquoted output. - ## This is an example of a footer - - It looks exactly like a header, but is placed at the end of the document - [examples]: https://github.com/terraform-docs/terraform-docs/tree/master/examples diff --git a/docs/reference/asciidoc-table.md b/docs/reference/asciidoc-table.md index b343f96..21b0c00 100644 --- a/docs/reference/asciidoc-table.md +++ b/docs/reference/asciidoc-table.md @@ -421,8 +421,4 @@ generates the following output: |[[output_unquoted]] <> |It's unquoted output. |=== - ## This is an example of a footer - - It looks exactly like a header, but is placed at the end of the document - [examples]: https://github.com/terraform-docs/terraform-docs/tree/master/examples diff --git a/docs/reference/json.md b/docs/reference/json.md index 6659c84..a7eebdf 100644 --- a/docs/reference/json.md +++ b/docs/reference/json.md @@ -57,7 +57,7 @@ generates the following output: { "header": "Usage:\n\nExample of 'foo_bar' module in `foo_bar.tf`.\n\n- list item 1\n- list item 2\n\nEven inline **formatting** in _here_ is possible.\nand some [link](https://domain.com/)\n\n* list item 3\n* list item 4\n\n```hcl\nmodule \"foo_bar\" {\n source = \"github.com/foo/bar\"\n\n id = \"1234567890\"\n name = \"baz\"\n\n zones = [\"us-east-1\", \"us-west-1\"]\n\n tags = {\n Name = \"baz\"\n Created-By = \"first.last@email.com\"\n Date-Created = \"20180101\"\n }\n}\n```\n\nHere is some trailing text after code block,\nfollowed by another line of text.\n\n| Name | Description |\n|------|-----------------|\n| Foo | Foo description |\n| Bar | Bar description |", - "footer": "## This is an example of a footer\n\nIt looks exactly like a header, but is placed at the end of the document", + "footer": "", "inputs": [ { "name": "bool-1", diff --git a/docs/reference/markdown-document.md b/docs/reference/markdown-document.md index b614611..0a9c38e 100644 --- a/docs/reference/markdown-document.md +++ b/docs/reference/markdown-document.md @@ -486,8 +486,4 @@ generates the following output: Description: It's unquoted output. - ## This is an example of a footer - - It looks exactly like a header, but is placed at the end of the document - [examples]: https://github.com/terraform-docs/terraform-docs/tree/master/examples diff --git a/docs/reference/markdown-table.md b/docs/reference/markdown-table.md index f3775a8..e022355 100644 --- a/docs/reference/markdown-table.md +++ b/docs/reference/markdown-table.md @@ -184,8 +184,4 @@ generates the following output: | [output-2](#output\_output-2) | It's output number two. | | [unquoted](#output\_unquoted) | It's unquoted output. | - ## This is an example of a footer - - It looks exactly like a header, but is placed at the end of the document - [examples]: https://github.com/terraform-docs/terraform-docs/tree/master/examples diff --git a/docs/reference/pretty.md b/docs/reference/pretty.md index d3e798d..db52246 100644 --- a/docs/reference/pretty.md +++ b/docs/reference/pretty.md @@ -259,8 +259,4 @@ generates the following output: output.unquoted It's unquoted output. - ## This is an example of a footer - - It looks exactly like a header, but is placed at the end of the document - [examples]: https://github.com/terraform-docs/terraform-docs/tree/master/examples diff --git a/docs/reference/toml.md b/docs/reference/toml.md index 75c3eb6..30a4770 100644 --- a/docs/reference/toml.md +++ b/docs/reference/toml.md @@ -55,7 +55,7 @@ terraform-docs toml --footer-from footer.md ./examples/ generates the following output: header = "Usage:\n\nExample of 'foo_bar' module in `foo_bar.tf`.\n\n- list item 1\n- list item 2\n\nEven inline **formatting** in _here_ is possible.\nand some [link](https://domain.com/)\n\n* list item 3\n* list item 4\n\n```hcl\nmodule \"foo_bar\" {\n source = \"github.com/foo/bar\"\n\n id = \"1234567890\"\n name = \"baz\"\n\n zones = [\"us-east-1\", \"us-west-1\"]\n\n tags = {\n Name = \"baz\"\n Created-By = \"first.last@email.com\"\n Date-Created = \"20180101\"\n }\n}\n```\n\nHere is some trailing text after code block,\nfollowed by another line of text.\n\n| Name | Description |\n|------|-----------------|\n| Foo | Foo description |\n| Bar | Bar description |" - footer = "## This is an example of a footer\n\nIt looks exactly like a header, but is placed at the end of the document" + footer = "" [[inputs]] name = "bool-1" diff --git a/docs/reference/xml.md b/docs/reference/xml.md index 9788b53..23e6cc4 100644 --- a/docs/reference/xml.md +++ b/docs/reference/xml.md @@ -56,7 +56,7 @@ generates the following output:
Usage: Example of 'foo_bar' module in `foo_bar.tf`. - list item 1 - list item 2 Even inline **formatting** in _here_ is possible. and some [link](https://domain.com/) * list item 3 * list item 4 ```hcl module "foo_bar" { source = "github.com/foo/bar" id = "1234567890" name = "baz" zones = ["us-east-1", "us-west-1"] tags = { Name = "baz" Created-By = "first.last@email.com" Date-Created = "20180101" } } ``` Here is some trailing text after code block, followed by another line of text. | Name | Description | |------|-----------------| | Foo | Foo description | | Bar | Bar description |
-
## This is an example of a footer It looks exactly like a header, but is placed at the end of the document
+
bool-1 diff --git a/docs/reference/yaml.md b/docs/reference/yaml.md index 79a1667..8780a89 100644 --- a/docs/reference/yaml.md +++ b/docs/reference/yaml.md @@ -92,10 +92,7 @@ generates the following output: |------|-----------------| | Foo | Foo description | | Bar | Bar description | - footer: |- - ## This is an example of a footer - - It looks exactly like a header, but is placed at the end of the document + footer: "" inputs: - name: bool-1 type: bool diff --git a/format/asciidoc_document.go b/format/asciidoc_document.go index 528b473..150a255 100644 --- a/format/asciidoc_document.go +++ b/format/asciidoc_document.go @@ -14,7 +14,7 @@ import ( "embed" gotemplate "text/template" - "github.com/terraform-docs/terraform-docs/internal/print" + "github.com/terraform-docs/terraform-docs/print" "github.com/terraform-docs/terraform-docs/template" "github.com/terraform-docs/terraform-docs/terraform" ) @@ -22,14 +22,18 @@ import ( //go:embed templates/asciidoc_document*.tmpl var asciidocsDocumentFS embed.FS -// AsciidocDocument represents AsciiDoc Document format. -type AsciidocDocument struct { +// asciidocDocument represents AsciiDoc Document format. +type asciidocDocument struct { + *print.Generator + + config *print.Config template *template.Template settings *print.Settings } -// NewAsciidocDocument returns new instance of AsciidocDocument. -func NewAsciidocDocument(settings *print.Settings) print.Engine { +// NewAsciidocDocument returns new instance of Asciidoc Document. +func NewAsciidocDocument(config *print.Config) Type { + settings, _ := config.Extract() items := readTemplateItems(asciidocsDocumentFS, "asciidoc_document") settings.EscapeCharacters = false @@ -57,30 +61,26 @@ func NewAsciidocDocument(settings *print.Settings) print.Engine { return settings.ShowRequired }, }) - return &AsciidocDocument{ - template: tt, - settings: settings, + + return &asciidocDocument{ + Generator: print.NewGenerator("json", config.ModuleRoot), + config: config, + template: tt, + settings: settings, } } // Generate a Terraform module as AsciiDoc document. -func (d *AsciidocDocument) Generate(module *terraform.Module) (*print.Generator, error) { - funcs := []print.GenerateFunc{} - - err := print.ForEach(func(name string, fn print.GeneratorCallback) error { +func (d *asciidocDocument) Generate(module *terraform.Module) error { + err := d.Generator.ForEach(func(name string) (string, error) { rendered, err := d.template.Render(name, module) if err != nil { - return err + return "", err } - - funcs = append(funcs, fn(sanitize(rendered))) - return nil + return sanitize(rendered), nil }) - if err != nil { - return nil, err - } - return print.NewGenerator("asciidoc document", funcs...), nil + return err } func init() { diff --git a/format/asciidoc_document_test.go b/format/asciidoc_document_test.go index 27aff7d..460dce0 100644 --- a/format/asciidoc_document_test.go +++ b/format/asciidoc_document_test.go @@ -15,8 +15,8 @@ import ( "github.com/stretchr/testify/assert" - "github.com/terraform-docs/terraform-docs/internal/print" "github.com/terraform-docs/terraform-docs/internal/testutil" + "github.com/terraform-docs/terraform-docs/print" "github.com/terraform-docs/terraform-docs/terraform" ) @@ -184,12 +184,12 @@ func TestAsciidocDocument(t *testing.T) { module, err := testutil.GetModule(options) assert.Nil(err) - formatter := NewAsciidocDocument(&tt.settings) + formatter := NewAsciidocDocument(tt.settings.ToConfig()) - generator, err := formatter.Generate(module) + err = formatter.Generate(module) assert.Nil(err) - actual, err := generator.ExecuteTemplate("") + actual, err := formatter.ExecuteTemplate("") assert.Nil(err) assert.Equal(expected, actual) diff --git a/format/asciidoc_table.go b/format/asciidoc_table.go index 460a8b1..28871cc 100644 --- a/format/asciidoc_table.go +++ b/format/asciidoc_table.go @@ -14,7 +14,7 @@ import ( "embed" gotemplate "text/template" - "github.com/terraform-docs/terraform-docs/internal/print" + "github.com/terraform-docs/terraform-docs/print" "github.com/terraform-docs/terraform-docs/template" "github.com/terraform-docs/terraform-docs/terraform" ) @@ -22,14 +22,18 @@ import ( //go:embed templates/asciidoc_table*.tmpl var asciidocTableFS embed.FS -// AsciidocTable represents AsciiDoc Table format. -type AsciidocTable struct { +// asciidocTable represents AsciiDoc Table format. +type asciidocTable struct { + *print.Generator + + config *print.Config template *template.Template settings *print.Settings } -// NewAsciidocTable returns new instance of AsciidocTable. -func NewAsciidocTable(settings *print.Settings) print.Engine { +// NewAsciidocTable returns new instance of Asciidoc Table. +func NewAsciidocTable(config *print.Config) Type { + settings, _ := config.Extract() items := readTemplateItems(asciidocTableFS, "asciidoc_table") settings.EscapeCharacters = false @@ -48,30 +52,26 @@ func NewAsciidocTable(settings *print.Settings) print.Engine { return result }, }) - return &AsciidocTable{ - template: tt, - settings: settings, + + return &asciidocTable{ + Generator: print.NewGenerator("json", config.ModuleRoot), + config: config, + template: tt, + settings: settings, } } // Generate a Terraform module as AsciiDoc tables. -func (t *AsciidocTable) Generate(module *terraform.Module) (*print.Generator, error) { - funcs := []print.GenerateFunc{} - - err := print.ForEach(func(name string, fn print.GeneratorCallback) error { +func (t *asciidocTable) Generate(module *terraform.Module) error { + err := t.Generator.ForEach(func(name string) (string, error) { rendered, err := t.template.Render(name, module) if err != nil { - return err + return "", err } - - funcs = append(funcs, fn(sanitize(rendered))) - return nil + return sanitize(rendered), nil }) - if err != nil { - return nil, err - } - return print.NewGenerator("asciidoc table", funcs...), nil + return err } func init() { diff --git a/format/asciidoc_table_test.go b/format/asciidoc_table_test.go index fff9458..31626da 100644 --- a/format/asciidoc_table_test.go +++ b/format/asciidoc_table_test.go @@ -15,8 +15,8 @@ import ( "github.com/stretchr/testify/assert" - "github.com/terraform-docs/terraform-docs/internal/print" "github.com/terraform-docs/terraform-docs/internal/testutil" + "github.com/terraform-docs/terraform-docs/print" "github.com/terraform-docs/terraform-docs/terraform" ) @@ -184,12 +184,12 @@ func TestAsciidocTable(t *testing.T) { module, err := testutil.GetModule(options) assert.Nil(err) - formatter := NewAsciidocTable(&tt.settings) + formatter := NewAsciidocTable(tt.settings.ToConfig()) - generator, err := formatter.Generate(module) + err = formatter.Generate(module) assert.Nil(err) - actual, err := generator.ExecuteTemplate("") + actual, err := formatter.ExecuteTemplate("") assert.Nil(err) assert.Equal(expected, actual) diff --git a/format/common_test.go b/format/common_test.go index f9f102c..cad58e7 100644 --- a/format/common_test.go +++ b/format/common_test.go @@ -11,7 +11,7 @@ the root directory of this source tree. package format import ( - "encoding/json" + jsonsdk "encoding/json" "testing" "github.com/stretchr/testify/assert" @@ -73,7 +73,7 @@ func TestCommonSort(t *testing.T) { var expected Expected - err = json.Unmarshal([]byte(golden), &expected) + err = jsonsdk.Unmarshal([]byte(golden), &expected) assert.Nil(err) for ii, i := range module.Inputs { diff --git a/format/doc.go b/format/doc.go index 7de0419..a7beda3 100644 --- a/format/doc.go +++ b/format/doc.go @@ -8,28 +8,39 @@ You may obtain a copy of the License at the LICENSE file in the root directory of this source tree. */ -// Package format provides different, out of the box supported, output formats. +// Package format provides different, out of the box supported, output format types. // // Usage // -// A specific format can be instantiated either for `format.Factory()` function or +// A specific format can be instantiated either for `format.New()` function or // directly calling its function (e.g. `NewMarkdownTable`, etc) // -// formatter, err := format.Factory("markdown table", settings) +// config := print.DefaultConfig() +// config.Formatter = "markdown table" +// +// formatter, err := format.New(config) // if err != nil { // return err // } // -// generator, err := formatter.Generate(tfmodule) +// err := formatter.Generate(tfmodule) // if err != nil { // return err // } // -// output, err := generator.ExecuteTemplate("") +// +// output, err := formatter.ExecuteTemplate("") // if err != nil { // return err // } // +// Note: if you don't intend to provide additional template for the generated +// content, or the target format doesn't provide templating (e.g. json, yaml, +// xml, or toml) you can use `Content()` function instead of `ExecuteTemplate()`. +// `Content()` returns all the sections combined with predefined order. +// +// output := formatter.Content() +// // Supported formats are: // // • `NewAsciidocDocument` diff --git a/format/factory.go b/format/factory.go deleted file mode 100644 index 4d1513b..0000000 --- a/format/factory.go +++ /dev/null @@ -1,45 +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 format - -import ( - "fmt" - - "github.com/terraform-docs/terraform-docs/internal/print" -) - -// initializerFn returns a concrete implementation of an Engine. -type initializerFn func(*print.Settings) print.Engine - -// initializers list of all registered engine initializer functions. -var initializers = make(map[string]initializerFn) - -// register a formatter engine initializer function. -func register(e map[string]initializerFn) { - if e == nil { - return - } - for k, v := range e { - initializers[k] = v - } -} - -// Factory initializes and returns the concrete implementation of -// format.Engine based on the provided 'name', for example for name -// of 'json' it will return '*format.JSON' through 'format.NewJSON' -// function. -func Factory(name string, settings *print.Settings) (print.Engine, error) { - fn, ok := initializers[name] - if !ok { - return nil, fmt.Errorf("formatter '%s' not found", name) - } - return fn(settings), nil -} diff --git a/format/factory_test.go b/format/factory_test.go deleted file mode 100644 index 60049d2..0000000 --- a/format/factory_test.go +++ /dev/null @@ -1,211 +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 format - -import ( - "reflect" - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/terraform-docs/terraform-docs/internal/print" -) - -func TestFormatFactory(t *testing.T) { - tests := []struct { - name string - format string - expected string - wantErr bool - }{ - { - name: "format factory from name", - format: "asciidoc", - expected: "*format.AsciidocTable", - wantErr: false, - }, - { - name: "format factory from name", - format: "adoc", - expected: "*format.AsciidocTable", - wantErr: false, - }, - { - name: "format factory from name", - format: "asciidoc document", - expected: "*format.AsciidocDocument", - wantErr: false, - }, - { - name: "format factory from name", - format: "asciidoc doc", - expected: "*format.AsciidocDocument", - wantErr: false, - }, - { - name: "format factory from name", - format: "adoc document", - expected: "*format.AsciidocDocument", - wantErr: false, - }, - { - name: "format factory from name", - format: "adoc doc", - expected: "*format.AsciidocDocument", - wantErr: false, - }, - { - name: "format factory from name", - format: "asciidoc table", - expected: "*format.AsciidocTable", - wantErr: false, - }, - { - name: "format factory from name", - format: "asciidoc tbl", - expected: "*format.AsciidocTable", - wantErr: false, - }, - { - name: "format factory from name", - format: "adoc table", - expected: "*format.AsciidocTable", - wantErr: false, - }, - { - name: "format factory from name", - format: "adoc tbl", - expected: "*format.AsciidocTable", - wantErr: false, - }, - { - name: "format factory from name", - format: "json", - expected: "*format.JSON", - wantErr: false, - }, - { - name: "format factory from name", - format: "markdown", - expected: "*format.MarkdownTable", - wantErr: false, - }, - { - name: "format factory from name", - format: "md", - expected: "*format.MarkdownTable", - wantErr: false, - }, - { - name: "format factory from name", - format: "markdown document", - expected: "*format.MarkdownDocument", - wantErr: false, - }, - { - name: "format factory from name", - format: "markdown doc", - expected: "*format.MarkdownDocument", - wantErr: false, - }, - { - name: "format factory from name", - format: "md document", - expected: "*format.MarkdownDocument", - wantErr: false, - }, - { - name: "format factory from name", - format: "md doc", - expected: "*format.MarkdownDocument", - wantErr: false, - }, - { - name: "format factory from name", - format: "markdown table", - expected: "*format.MarkdownTable", - wantErr: false, - }, - { - name: "format factory from name", - format: "markdown tbl", - expected: "*format.MarkdownTable", - wantErr: false, - }, - { - name: "format factory from name", - format: "md table", - expected: "*format.MarkdownTable", - wantErr: false, - }, - { - name: "format factory from name", - format: "md tbl", - expected: "*format.MarkdownTable", - wantErr: false, - }, - { - name: "format factory from name", - format: "pretty", - expected: "*format.Pretty", - wantErr: false, - }, - { - name: "format factory from name", - format: "tfvars hcl", - expected: "*format.TfvarsHCL", - wantErr: false, - }, - { - name: "format factory from name", - format: "tfvars json", - expected: "*format.TfvarsJSON", - wantErr: false, - }, - { - name: "format factory from name", - format: "toml", - expected: "*format.TOML", - wantErr: false, - }, - { - name: "format factory from name", - format: "xml", - expected: "*format.XML", - wantErr: false, - }, - { - name: "format factory from name", - format: "yaml", - expected: "*format.YAML", - wantErr: false, - }, - { - name: "format factory from name", - format: "unknown", - expected: "", - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert := assert.New(t) - settings := &print.Settings{} - actual, err := Factory(tt.format, settings) - if tt.wantErr { - assert.NotNil(err) - } else { - assert.Nil(err) - assert.Equal(tt.expected, reflect.TypeOf(actual).String()) - } - }) - } -} diff --git a/format/json.go b/format/json.go index 02b6613..c56c2d3 100644 --- a/format/json.go +++ b/format/json.go @@ -12,55 +12,48 @@ package format import ( "bytes" - "encoding/json" + jsonsdk "encoding/json" "strings" - "github.com/terraform-docs/terraform-docs/internal/print" + "github.com/terraform-docs/terraform-docs/print" "github.com/terraform-docs/terraform-docs/terraform" ) -// JSON represents JSON format. -type JSON struct { +// json represents JSON format. +type json struct { + *print.Generator + + config *print.Config settings *print.Settings } // NewJSON returns new instance of JSON. -func NewJSON(settings *print.Settings) print.Engine { - return &JSON{ - settings: settings, +func NewJSON(config *print.Config) Type { + settings, _ := config.Extract() + + return &json{ + Generator: print.NewGenerator("json", config.ModuleRoot), + config: config, + settings: settings, } } // Generate a Terraform module as json. -func (j *JSON) Generate(module *terraform.Module) (*print.Generator, error) { - copy := &terraform.Module{ - Header: "", - Footer: "", - Inputs: make([]*terraform.Input, 0), - ModuleCalls: make([]*terraform.ModuleCall, 0), - Outputs: make([]*terraform.Output, 0), - Providers: make([]*terraform.Provider, 0), - Requirements: make([]*terraform.Requirement, 0), - Resources: make([]*terraform.Resource, 0), - } - - print.CopySections(j.settings, module, copy) +func (j *json) Generate(module *terraform.Module) error { + copy := copySections(j.settings, module) buffer := new(bytes.Buffer) - - encoder := json.NewEncoder(buffer) + encoder := jsonsdk.NewEncoder(buffer) encoder.SetIndent("", " ") encoder.SetEscapeHTML(j.settings.EscapeCharacters) - err := encoder.Encode(copy) - if err != nil { - return nil, err + if err := encoder.Encode(copy); err != nil { + return err } - return print.NewGenerator( - "json", - print.WithContent(strings.TrimSuffix(buffer.String(), "\n")), - ), nil + j.Generator.Funcs(print.WithContent(strings.TrimSuffix(buffer.String(), "\n"))) + + return nil } func init() { diff --git a/format/json_test.go b/format/json_test.go index e50d114..3f0de03 100644 --- a/format/json_test.go +++ b/format/json_test.go @@ -15,8 +15,8 @@ import ( "github.com/stretchr/testify/assert" - "github.com/terraform-docs/terraform-docs/internal/print" "github.com/terraform-docs/terraform-docs/internal/testutil" + "github.com/terraform-docs/terraform-docs/print" "github.com/terraform-docs/terraform-docs/terraform" ) @@ -125,12 +125,12 @@ func TestJson(t *testing.T) { module, err := testutil.GetModule(options) assert.Nil(err) - formatter := NewJSON(&tt.settings) + formatter := NewJSON(tt.settings.ToConfig()) - generator, err := formatter.Generate(module) + err = formatter.Generate(module) assert.Nil(err) - actual, err := generator.ExecuteTemplate("") + actual, err := formatter.ExecuteTemplate("") assert.Nil(err) assert.Equal(expected, actual) diff --git a/format/markdown_document.go b/format/markdown_document.go index 985d935..9e201bf 100644 --- a/format/markdown_document.go +++ b/format/markdown_document.go @@ -14,7 +14,7 @@ import ( "embed" gotemplate "text/template" - "github.com/terraform-docs/terraform-docs/internal/print" + "github.com/terraform-docs/terraform-docs/print" "github.com/terraform-docs/terraform-docs/template" "github.com/terraform-docs/terraform-docs/terraform" ) @@ -22,14 +22,18 @@ import ( //go:embed templates/markdown_document*.tmpl var markdownDocumentFS embed.FS -// MarkdownDocument represents Markdown Document format. -type MarkdownDocument struct { +// markdownDocument represents Markdown Document format. +type markdownDocument struct { + *print.Generator + + config *print.Config template *template.Template settings *print.Settings } -// NewMarkdownDocument returns new instance of Document. -func NewMarkdownDocument(settings *print.Settings) print.Engine { +// NewMarkdownDocument returns new instance of Markdown Document. +func NewMarkdownDocument(config *print.Config) Type { + settings, _ := config.Extract() items := readTemplateItems(markdownDocumentFS, "markdown_document") tt := template.New(settings, items...) @@ -55,30 +59,26 @@ func NewMarkdownDocument(settings *print.Settings) print.Engine { return settings.ShowRequired }, }) - return &MarkdownDocument{ - template: tt, - settings: settings, + + return &markdownDocument{ + Generator: print.NewGenerator("json", config.ModuleRoot), + config: config, + template: tt, + settings: settings, } } // Generate a Terraform module as Markdown document. -func (d *MarkdownDocument) Generate(module *terraform.Module) (*print.Generator, error) { - funcs := []print.GenerateFunc{} - - err := print.ForEach(func(name string, fn print.GeneratorCallback) error { +func (d *markdownDocument) Generate(module *terraform.Module) error { + err := d.Generator.ForEach(func(name string) (string, error) { rendered, err := d.template.Render(name, module) if err != nil { - return err + return "", err } - - funcs = append(funcs, fn(sanitize(rendered))) - return nil + return sanitize(rendered), nil }) - if err != nil { - return nil, err - } - return print.NewGenerator("markdown document", funcs...), nil + return err } func init() { diff --git a/format/markdown_document_test.go b/format/markdown_document_test.go index 3b88081..fb8c5ec 100644 --- a/format/markdown_document_test.go +++ b/format/markdown_document_test.go @@ -15,8 +15,8 @@ import ( "github.com/stretchr/testify/assert" - "github.com/terraform-docs/terraform-docs/internal/print" "github.com/terraform-docs/terraform-docs/internal/testutil" + "github.com/terraform-docs/terraform-docs/print" "github.com/terraform-docs/terraform-docs/terraform" ) @@ -232,12 +232,12 @@ func TestMarkdownDocument(t *testing.T) { module, err := testutil.GetModule(options) assert.Nil(err) - formatter := NewMarkdownDocument(&tt.settings) + formatter := NewMarkdownDocument(tt.settings.ToConfig()) - generator, err := formatter.Generate(module) + err = formatter.Generate(module) assert.Nil(err) - actual, err := generator.ExecuteTemplate("") + actual, err := formatter.ExecuteTemplate("") assert.Nil(err) assert.Equal(expected, actual) diff --git a/format/markdown_table.go b/format/markdown_table.go index 8b596d9..17e1379 100644 --- a/format/markdown_table.go +++ b/format/markdown_table.go @@ -14,7 +14,7 @@ import ( "embed" gotemplate "text/template" - "github.com/terraform-docs/terraform-docs/internal/print" + "github.com/terraform-docs/terraform-docs/print" "github.com/terraform-docs/terraform-docs/template" "github.com/terraform-docs/terraform-docs/terraform" ) @@ -22,14 +22,18 @@ import ( //go:embed templates/markdown_table*.tmpl var markdownTableFS embed.FS -// MarkdownTable represents Markdown Table format. -type MarkdownTable struct { +// markdownTable represents Markdown Table format. +type markdownTable struct { + *print.Generator + + config *print.Config template *template.Template settings *print.Settings } -// NewMarkdownTable returns new instance of Table. -func NewMarkdownTable(settings *print.Settings) print.Engine { +// NewMarkdownTable returns new instance of Markdown Table. +func NewMarkdownTable(config *print.Config) Type { + settings, _ := config.Extract() items := readTemplateItems(markdownTableFS, "markdown_table") tt := template.New(settings, items...) @@ -46,30 +50,26 @@ func NewMarkdownTable(settings *print.Settings) print.Engine { return result }, }) - return &MarkdownTable{ - template: tt, - settings: settings, + + return &markdownTable{ + Generator: print.NewGenerator("markdown table", config.ModuleRoot), + config: config, + template: tt, + settings: settings, } } // Generate a Terraform module as Markdown tables. -func (t *MarkdownTable) Generate(module *terraform.Module) (*print.Generator, error) { - funcs := []print.GenerateFunc{} - - err := print.ForEach(func(name string, fn print.GeneratorCallback) error { +func (t *markdownTable) Generate(module *terraform.Module) error { + err := t.Generator.ForEach(func(name string) (string, error) { rendered, err := t.template.Render(name, module) if err != nil { - return err + return "", err } - - funcs = append(funcs, fn(sanitize(rendered))) - return nil + return sanitize(rendered), nil }) - if err != nil { - return nil, err - } - return print.NewGenerator("markdown table", funcs...), nil + return err } func init() { diff --git a/format/markdown_table_test.go b/format/markdown_table_test.go index 76c9f89..42bbe05 100644 --- a/format/markdown_table_test.go +++ b/format/markdown_table_test.go @@ -15,8 +15,8 @@ import ( "github.com/stretchr/testify/assert" - "github.com/terraform-docs/terraform-docs/internal/print" "github.com/terraform-docs/terraform-docs/internal/testutil" + "github.com/terraform-docs/terraform-docs/print" "github.com/terraform-docs/terraform-docs/terraform" ) @@ -232,12 +232,12 @@ func TestMarkdownTable(t *testing.T) { module, err := testutil.GetModule(options) assert.Nil(err) - formatter := NewMarkdownTable(&tt.settings) + formatter := NewMarkdownTable(tt.settings.ToConfig()) - generator, err := formatter.Generate(module) + err = formatter.Generate(module) assert.Nil(err) - actual, err := generator.ExecuteTemplate("") + actual, err := formatter.ExecuteTemplate("") assert.Nil(err) assert.Equal(expected, actual) diff --git a/format/pretty.go b/format/pretty.go index d4634d4..fb44e5a 100644 --- a/format/pretty.go +++ b/format/pretty.go @@ -16,7 +16,7 @@ import ( "regexp" gotemplate "text/template" - "github.com/terraform-docs/terraform-docs/internal/print" + "github.com/terraform-docs/terraform-docs/print" "github.com/terraform-docs/terraform-docs/template" "github.com/terraform-docs/terraform-docs/terraform" ) @@ -24,14 +24,19 @@ import ( //go:embed templates/pretty.tmpl var prettyTpl []byte -// Pretty represents colorized pretty format. -type Pretty struct { +// pretty represents colorized pretty format. +type pretty struct { + *print.Generator + + config *print.Config template *template.Template settings *print.Settings } // NewPretty returns new instance of Pretty. -func NewPretty(settings *print.Settings) print.Engine { +func NewPretty(config *print.Config) Type { + settings, _ := config.Extract() + tt := template.New(settings, &template.Item{ Name: "pretty", Text: string(prettyTpl), @@ -46,23 +51,25 @@ func NewPretty(settings *print.Settings) print.Engine { return fmt.Sprintf("%s%s%s", c, s, r) }, }) - return &Pretty{ - template: tt, - settings: settings, + + return &pretty{ + Generator: print.NewGenerator("pretty", config.ModuleRoot), + config: config, + template: tt, + settings: settings, } } // Generate a Terraform module document. -func (p *Pretty) Generate(module *terraform.Module) (*print.Generator, error) { +func (p *pretty) Generate(module *terraform.Module) error { rendered, err := p.template.Render("pretty", module) if err != nil { - return nil, err + return err } - return print.NewGenerator( - "pretty", - print.WithContent(regexp.MustCompile(`(\r?\n)*$`).ReplaceAllString(rendered, "")), - ), nil + p.Generator.Funcs(print.WithContent(regexp.MustCompile(`(\r?\n)*$`).ReplaceAllString(rendered, ""))) + + return nil } func init() { diff --git a/format/pretty_test.go b/format/pretty_test.go index 9b1f4a7..4c05506 100644 --- a/format/pretty_test.go +++ b/format/pretty_test.go @@ -15,8 +15,8 @@ import ( "github.com/stretchr/testify/assert" - "github.com/terraform-docs/terraform-docs/internal/print" "github.com/terraform-docs/terraform-docs/internal/testutil" + "github.com/terraform-docs/terraform-docs/print" "github.com/terraform-docs/terraform-docs/terraform" ) @@ -125,12 +125,12 @@ func TestPretty(t *testing.T) { module, err := testutil.GetModule(options) assert.Nil(err) - formatter := NewPretty(&tt.settings) + formatter := NewPretty(tt.settings.ToConfig()) - generator, err := formatter.Generate(module) + err = formatter.Generate(module) assert.Nil(err) - actual, err := generator.ExecuteTemplate("") + actual, err := formatter.ExecuteTemplate("") assert.Nil(err) assert.Equal(expected, actual) diff --git a/format/tfvars_hcl.go b/format/tfvars_hcl.go index 5e31ef4..29728be 100644 --- a/format/tfvars_hcl.go +++ b/format/tfvars_hcl.go @@ -16,8 +16,8 @@ import ( "strings" gotemplate "text/template" - "github.com/terraform-docs/terraform-docs/internal/print" "github.com/terraform-docs/terraform-docs/internal/types" + "github.com/terraform-docs/terraform-docs/print" "github.com/terraform-docs/terraform-docs/template" "github.com/terraform-docs/terraform-docs/terraform" ) @@ -25,8 +25,11 @@ import ( //go:embed templates/tfvars_hcl.tmpl var tfvarsHCLTpl []byte -// TfvarsHCL represents Terraform tfvars HCL format. -type TfvarsHCL struct { +// tfvarsHCL represents Terraform tfvars HCL format. +type tfvarsHCL struct { + *print.Generator + + config *print.Config template *template.Template settings *print.Settings } @@ -34,7 +37,9 @@ type TfvarsHCL struct { var padding []int // NewTfvarsHCL returns new instance of TfvarsHCL. -func NewTfvarsHCL(settings *print.Settings) print.Engine { +func NewTfvarsHCL(config *print.Config) Type { + settings, _ := config.Extract() + tt := template.New(settings, &template.Item{ Name: "tfvars", Text: string(tfvarsHCLTpl), @@ -56,25 +61,27 @@ func NewTfvarsHCL(settings *print.Settings) print.Engine { return settings.ShowDescription }, }) - return &TfvarsHCL{ - template: tt, - settings: settings, + + return &tfvarsHCL{ + Generator: print.NewGenerator("tfvars hcl", config.ModuleRoot), + config: config, + template: tt, + settings: settings, } } // Generate a Terraform module as Terraform tfvars HCL. -func (h *TfvarsHCL) Generate(module *terraform.Module) (*print.Generator, error) { +func (h *tfvarsHCL) Generate(module *terraform.Module) error { alignments(module.Inputs, h.settings) rendered, err := h.template.Render("tfvars", module) if err != nil { - return nil, err + return err } - return print.NewGenerator( - "tfvars hcl", - print.WithContent(strings.TrimSuffix(sanitize(rendered), "\n")), - ), nil + h.Generator.Funcs(print.WithContent(strings.TrimSuffix(sanitize(rendered), "\n"))) + + return nil } func isMultilineFormat(input *terraform.Input) bool { diff --git a/format/tfvars_hcl_test.go b/format/tfvars_hcl_test.go index dc32f4b..be9b17e 100644 --- a/format/tfvars_hcl_test.go +++ b/format/tfvars_hcl_test.go @@ -15,8 +15,8 @@ import ( "github.com/stretchr/testify/assert" - "github.com/terraform-docs/terraform-docs/internal/print" "github.com/terraform-docs/terraform-docs/internal/testutil" + "github.com/terraform-docs/terraform-docs/print" "github.com/terraform-docs/terraform-docs/terraform" ) @@ -104,12 +104,12 @@ func TestTfvarsHcl(t *testing.T) { module, err := testutil.GetModule(options) assert.Nil(err) - formatter := NewTfvarsHCL(&tt.settings) + formatter := NewTfvarsHCL(tt.settings.ToConfig()) - generator, err := formatter.Generate(module) + err = formatter.Generate(module) assert.Nil(err) - actual, err := generator.ExecuteTemplate("") + actual, err := formatter.ExecuteTemplate("") assert.Nil(err) assert.Equal(expected, actual) diff --git a/format/tfvars_json.go b/format/tfvars_json.go index 31ab08d..f90ecff 100644 --- a/format/tfvars_json.go +++ b/format/tfvars_json.go @@ -12,29 +12,36 @@ package format import ( "bytes" - "encoding/json" + jsonsdk "encoding/json" "strings" "github.com/iancoleman/orderedmap" - "github.com/terraform-docs/terraform-docs/internal/print" + "github.com/terraform-docs/terraform-docs/print" "github.com/terraform-docs/terraform-docs/terraform" ) -// TfvarsJSON represents Terraform tfvars JSON format. -type TfvarsJSON struct { +// tfvarsJSON represents Terraform tfvars JSON format. +type tfvarsJSON struct { + *print.Generator + + config *print.Config settings *print.Settings } // NewTfvarsJSON returns new instance of TfvarsJSON. -func NewTfvarsJSON(settings *print.Settings) print.Engine { - return &TfvarsJSON{ - settings: settings, +func NewTfvarsJSON(config *print.Config) Type { + settings, _ := config.Extract() + + return &tfvarsJSON{ + Generator: print.NewGenerator("tfvars json", config.ModuleRoot), + config: config, + settings: settings, } } // Generate a Terraform module as Terraform tfvars JSON. -func (j *TfvarsJSON) Generate(module *terraform.Module) (*print.Generator, error) { +func (j *tfvarsJSON) Generate(module *terraform.Module) error { copy := orderedmap.New() copy.SetEscapeHTML(false) for _, i := range module.Inputs { @@ -42,20 +49,17 @@ func (j *TfvarsJSON) Generate(module *terraform.Module) (*print.Generator, error } buffer := new(bytes.Buffer) - - encoder := json.NewEncoder(buffer) + encoder := jsonsdk.NewEncoder(buffer) encoder.SetIndent("", " ") encoder.SetEscapeHTML(false) - err := encoder.Encode(copy) - if err != nil { - return nil, err + if err := encoder.Encode(copy); err != nil { + return err } - return print.NewGenerator( - "tfvars json", - print.WithContent(strings.TrimSuffix(buffer.String(), "\n")), - ), nil + j.Generator.Funcs(print.WithContent(strings.TrimSuffix(buffer.String(), "\n"))) + + return nil } diff --git a/format/tfvars_json_test.go b/format/tfvars_json_test.go index 4228435..ede0db1 100644 --- a/format/tfvars_json_test.go +++ b/format/tfvars_json_test.go @@ -13,8 +13,8 @@ import ( "github.com/stretchr/testify/assert" - "github.com/terraform-docs/terraform-docs/internal/print" "github.com/terraform-docs/terraform-docs/internal/testutil" + "github.com/terraform-docs/terraform-docs/print" "github.com/terraform-docs/terraform-docs/terraform" ) @@ -89,12 +89,12 @@ func TestTfvarsJson(t *testing.T) { module, err := testutil.GetModule(options) assert.Nil(err) - formatter := NewTfvarsJSON(&tt.settings) + formatter := NewTfvarsJSON(tt.settings.ToConfig()) - generator, err := formatter.Generate(module) + err = formatter.Generate(module) assert.Nil(err) - actual, err := generator.ExecuteTemplate("") + actual, err := formatter.ExecuteTemplate("") assert.Nil(err) assert.Equal(expected, actual) diff --git a/format/toml.go b/format/toml.go index 59e9e47..c01058b 100644 --- a/format/toml.go +++ b/format/toml.go @@ -14,50 +14,45 @@ import ( "bytes" "strings" - "github.com/BurntSushi/toml" + tomlsdk "github.com/BurntSushi/toml" - "github.com/terraform-docs/terraform-docs/internal/print" + "github.com/terraform-docs/terraform-docs/print" "github.com/terraform-docs/terraform-docs/terraform" ) -// TOML represents TOML format. -type TOML struct { +// toml represents TOML format. +type toml struct { + *print.Generator + + config *print.Config settings *print.Settings } // NewTOML returns new instance of TOML. -func NewTOML(settings *print.Settings) print.Engine { - return &TOML{ - settings: settings, +func NewTOML(config *print.Config) Type { + settings, _ := config.Extract() + + return &toml{ + Generator: print.NewGenerator("toml", config.ModuleRoot), + config: config, + settings: settings, } } // Generate a Terraform module as toml. -func (t *TOML) Generate(module *terraform.Module) (*print.Generator, error) { - copy := &terraform.Module{ - Header: "", - Footer: "", - Inputs: make([]*terraform.Input, 0), - ModuleCalls: make([]*terraform.ModuleCall, 0), - Outputs: make([]*terraform.Output, 0), - Providers: make([]*terraform.Provider, 0), - Requirements: make([]*terraform.Requirement, 0), - Resources: make([]*terraform.Resource, 0), - } - - print.CopySections(t.settings, module, copy) +func (t *toml) Generate(module *terraform.Module) error { + copy := copySections(t.settings, module) buffer := new(bytes.Buffer) - encoder := toml.NewEncoder(buffer) - err := encoder.Encode(copy) - if err != nil { - return nil, err + encoder := tomlsdk.NewEncoder(buffer) + + if err := encoder.Encode(copy); err != nil { + return err } - return print.NewGenerator( - "toml", - print.WithContent(strings.TrimSuffix(buffer.String(), "\n")), - ), nil + t.Generator.Funcs(print.WithContent(strings.TrimSuffix(buffer.String(), "\n"))) + + return nil } diff --git a/format/toml_test.go b/format/toml_test.go index a79edb9..845b9a0 100644 --- a/format/toml_test.go +++ b/format/toml_test.go @@ -15,8 +15,8 @@ import ( "github.com/stretchr/testify/assert" - "github.com/terraform-docs/terraform-docs/internal/print" "github.com/terraform-docs/terraform-docs/internal/testutil" + "github.com/terraform-docs/terraform-docs/print" "github.com/terraform-docs/terraform-docs/terraform" ) @@ -114,12 +114,12 @@ func TestToml(t *testing.T) { module, err := testutil.GetModule(options) assert.Nil(err) - formatter := NewTOML(&tt.settings) + formatter := NewTOML(tt.settings.ToConfig()) - generator, err := formatter.Generate(module) + err = formatter.Generate(module) assert.Nil(err) - actual, err := generator.ExecuteTemplate("") + actual, err := formatter.ExecuteTemplate("") assert.Nil(err) assert.Equal(expected, actual) diff --git a/format/type.go b/format/type.go new file mode 100644 index 0000000..121c58c --- /dev/null +++ b/format/type.go @@ -0,0 +1,66 @@ +/* +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 format + +import ( + "fmt" + + "github.com/terraform-docs/terraform-docs/print" + "github.com/terraform-docs/terraform-docs/terraform" +) + +// Type represents an output format type (e.g. json, markdown table, yaml, etc). +type Type interface { + Generate(*terraform.Module) error // generate the Terraform module + + Content() string // all the sections combined based on the underlying format + + Header() string // header section based on the underlying format + Footer() string // footer section based on the underlying format + Inputs() string // inputs section based on the underlying format + Modules() string // modules section based on the underlying format + Outputs() string // outputs section based on the underlying format + Providers() string // providers section based on the underlying format + Requirements() string // requirements section based on the underlying format + Resources() string // resources section based on the underlying format + + ExecuteTemplate(contentTmpl string) (string, error) +} + +// initializerFn returns a concrete implementation of an Engine. +type initializerFn func(*print.Config) Type + +// initializers list of all registered engine initializer functions. +var initializers = make(map[string]initializerFn) + +// register a formatter engine initializer function. +func register(e map[string]initializerFn) { + if e == nil { + return + } + for k, v := range e { + initializers[k] = v + } +} + +// New initializes and returns the concrete implementation of +// format.Engine based on the provided 'name', for example for name +// of 'json' it will return '*format.JSON' through 'format.NewJSON' +// function. +// func New(name string, settings *print.Settings) (Generator, error) { +func New(config *print.Config) (Type, error) { + name := config.Formatter + fn, ok := initializers[name] + if !ok { + return nil, fmt.Errorf("formatter '%s' not found", name) + } + return fn(config), nil +} diff --git a/format/type_test.go b/format/type_test.go new file mode 100644 index 0000000..5c55b3e --- /dev/null +++ b/format/type_test.go @@ -0,0 +1,212 @@ +// /* +// 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 format + +import ( + "reflect" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/terraform-docs/terraform-docs/print" +) + +func TestFormatType(t *testing.T) { + tests := []struct { + name string + format string + expected string + wantErr bool + }{ + { + name: "format type from name", + format: "asciidoc", + expected: "*format.asciidocTable", + wantErr: false, + }, + { + name: "format type from name", + format: "adoc", + expected: "*format.asciidocTable", + wantErr: false, + }, + { + name: "format type from name", + format: "asciidoc document", + expected: "*format.asciidocDocument", + wantErr: false, + }, + { + name: "format type from name", + format: "asciidoc doc", + expected: "*format.asciidocDocument", + wantErr: false, + }, + { + name: "format type from name", + format: "adoc document", + expected: "*format.asciidocDocument", + wantErr: false, + }, + { + name: "format type from name", + format: "adoc doc", + expected: "*format.asciidocDocument", + wantErr: false, + }, + { + name: "format type from name", + format: "asciidoc table", + expected: "*format.asciidocTable", + wantErr: false, + }, + { + name: "format type from name", + format: "asciidoc tbl", + expected: "*format.asciidocTable", + wantErr: false, + }, + { + name: "format type from name", + format: "adoc table", + expected: "*format.asciidocTable", + wantErr: false, + }, + { + name: "format type from name", + format: "adoc tbl", + expected: "*format.asciidocTable", + wantErr: false, + }, + { + name: "format type from name", + format: "json", + expected: "*format.json", + wantErr: false, + }, + { + name: "format type from name", + format: "markdown", + expected: "*format.markdownTable", + wantErr: false, + }, + { + name: "format type from name", + format: "md", + expected: "*format.markdownTable", + wantErr: false, + }, + { + name: "format type from name", + format: "markdown document", + expected: "*format.markdownDocument", + wantErr: false, + }, + { + name: "format type from name", + format: "markdown doc", + expected: "*format.markdownDocument", + wantErr: false, + }, + { + name: "format type from name", + format: "md document", + expected: "*format.markdownDocument", + wantErr: false, + }, + { + name: "format type from name", + format: "md doc", + expected: "*format.markdownDocument", + wantErr: false, + }, + { + name: "format type from name", + format: "markdown table", + expected: "*format.markdownTable", + wantErr: false, + }, + { + name: "format type from name", + format: "markdown tbl", + expected: "*format.markdownTable", + wantErr: false, + }, + { + name: "format type from name", + format: "md table", + expected: "*format.markdownTable", + wantErr: false, + }, + { + name: "format type from name", + format: "md tbl", + expected: "*format.markdownTable", + wantErr: false, + }, + { + name: "format type from name", + format: "pretty", + expected: "*format.pretty", + wantErr: false, + }, + { + name: "format type from name", + format: "tfvars hcl", + expected: "*format.tfvarsHCL", + wantErr: false, + }, + { + name: "format type from name", + format: "tfvars json", + expected: "*format.tfvarsJSON", + wantErr: false, + }, + { + name: "format type from name", + format: "toml", + expected: "*format.toml", + wantErr: false, + }, + { + name: "format type from name", + format: "xml", + expected: "*format.xml", + wantErr: false, + }, + { + name: "format type from name", + format: "yaml", + expected: "*format.yaml", + wantErr: false, + }, + { + name: "format type from name", + format: "unknown", + expected: "", + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert := assert.New(t) + config := print.DefaultConfig() + config.Formatter = tt.format + actual, err := New(config) + if tt.wantErr { + assert.NotNil(err) + } else { + assert.Nil(err) + assert.Equal(tt.expected, reflect.TypeOf(actual).String()) + } + }) + } +} diff --git a/format/util.go b/format/util.go index 8c0f25f..9be51f9 100644 --- a/format/util.go +++ b/format/util.go @@ -17,7 +17,9 @@ import ( "regexp" "strings" + "github.com/terraform-docs/terraform-docs/print" "github.com/terraform-docs/terraform-docs/template" + "github.com/terraform-docs/terraform-docs/terraform" ) // sanitize cleans a Markdown document to soothe linters. @@ -99,3 +101,58 @@ func readTemplateItems(efs embed.FS, prefix string) []*template.Item { } return items } + +// copySections sets the sections that'll be printed +func copySections(settings *print.Settings, src *terraform.Module) *terraform.Module { + dest := &terraform.Module{ + Header: "", + Footer: "", + Inputs: make([]*terraform.Input, 0), + ModuleCalls: make([]*terraform.ModuleCall, 0), + Outputs: make([]*terraform.Output, 0), + Providers: make([]*terraform.Provider, 0), + Requirements: make([]*terraform.Requirement, 0), + Resources: make([]*terraform.Resource, 0), + } + + if settings.ShowHeader { + dest.Header = src.Header + } + if settings.ShowFooter { + dest.Footer = src.Footer + } + if settings.ShowInputs { + dest.Inputs = src.Inputs + } + if settings.ShowModuleCalls { + dest.ModuleCalls = src.ModuleCalls + } + if settings.ShowOutputs { + dest.Outputs = src.Outputs + } + if settings.ShowProviders { + dest.Providers = src.Providers + } + if settings.ShowRequirements { + dest.Requirements = src.Requirements + } + if settings.ShowResources || settings.ShowDataSources { + dest.Resources = filterResourcesByMode(settings, src.Resources) + } + + return dest +} + +// filterResourcesByMode returns the managed or data resources defined by the show argument +func filterResourcesByMode(settings *print.Settings, module []*terraform.Resource) []*terraform.Resource { + resources := make([]*terraform.Resource, 0) + for _, r := range module { + if settings.ShowResources && r.Mode == "managed" { + resources = append(resources, r) + } + if settings.ShowDataSources && r.Mode == "data" { + resources = append(resources, r) + } + } + return resources +} diff --git a/format/xml.go b/format/xml.go index eb612a0..efe8323 100644 --- a/format/xml.go +++ b/format/xml.go @@ -11,49 +11,44 @@ the root directory of this source tree. package format import ( - "encoding/xml" + xmlsdk "encoding/xml" "strings" - "github.com/terraform-docs/terraform-docs/internal/print" + "github.com/terraform-docs/terraform-docs/print" "github.com/terraform-docs/terraform-docs/terraform" ) -// XML represents XML format. -type XML struct { +// xml represents XML format. +type xml struct { + *print.Generator + + config *print.Config settings *print.Settings } // NewXML returns new instance of XML. -func NewXML(settings *print.Settings) print.Engine { - return &XML{ - settings: settings, +func NewXML(config *print.Config) Type { + settings, _ := config.Extract() + + return &xml{ + Generator: print.NewGenerator("xml", config.ModuleRoot), + config: config, + settings: settings, } } // Generate a Terraform module as xml. -func (x *XML) Generate(module *terraform.Module) (*print.Generator, error) { - copy := &terraform.Module{ - Header: "", - Footer: "", - Inputs: make([]*terraform.Input, 0), - ModuleCalls: make([]*terraform.ModuleCall, 0), - Outputs: make([]*terraform.Output, 0), - Providers: make([]*terraform.Provider, 0), - Requirements: make([]*terraform.Requirement, 0), - Resources: make([]*terraform.Resource, 0), - } +func (x *xml) Generate(module *terraform.Module) error { + copy := copySections(x.settings, module) - print.CopySections(x.settings, module, copy) - - out, err := xml.MarshalIndent(copy, "", " ") + out, err := xmlsdk.MarshalIndent(copy, "", " ") if err != nil { - return nil, err + return err } - return print.NewGenerator( - "xml", - print.WithContent(strings.TrimSuffix(string(out), "\n")), - ), nil + x.Generator.Funcs(print.WithContent(strings.TrimSuffix(string(out), "\n"))) + + return nil } func init() { diff --git a/format/xml_test.go b/format/xml_test.go index a332a6d..2d51a9c 100644 --- a/format/xml_test.go +++ b/format/xml_test.go @@ -15,8 +15,8 @@ import ( "github.com/stretchr/testify/assert" - "github.com/terraform-docs/terraform-docs/internal/print" "github.com/terraform-docs/terraform-docs/internal/testutil" + "github.com/terraform-docs/terraform-docs/print" "github.com/terraform-docs/terraform-docs/terraform" ) @@ -114,12 +114,12 @@ func TestXml(t *testing.T) { module, err := testutil.GetModule(options) assert.Nil(err) - formatter := NewXML(&tt.settings) + formatter := NewXML(tt.settings.ToConfig()) - generator, err := formatter.Generate(module) + err = formatter.Generate(module) assert.Nil(err) - actual, err := generator.ExecuteTemplate("") + actual, err := formatter.ExecuteTemplate("") assert.Nil(err) assert.Equal(expected, actual) diff --git a/format/yaml.go b/format/yaml.go index 97fbb3f..c022e41 100644 --- a/format/yaml.go +++ b/format/yaml.go @@ -14,53 +14,46 @@ import ( "bytes" "strings" - "gopkg.in/yaml.v3" + yamlv3 "gopkg.in/yaml.v3" - "github.com/terraform-docs/terraform-docs/internal/print" + "github.com/terraform-docs/terraform-docs/print" "github.com/terraform-docs/terraform-docs/terraform" ) -// YAML represents YAML format. -type YAML struct { +// yaml represents YAML format. +type yaml struct { + *print.Generator + + config *print.Config settings *print.Settings } // NewYAML returns new instance of YAML. -func NewYAML(settings *print.Settings) print.Engine { - return &YAML{ - settings: settings, +func NewYAML(config *print.Config) Type { + settings, _ := config.Extract() + + return &yaml{ + Generator: print.NewGenerator("yaml", config.ModuleRoot), + config: config, + settings: settings, } } -// Generate a Terraform module as yaml. -func (y *YAML) Generate(module *terraform.Module) (*print.Generator, error) { - copy := &terraform.Module{ - Header: "", - Footer: "", - Inputs: make([]*terraform.Input, 0), - ModuleCalls: make([]*terraform.ModuleCall, 0), - Outputs: make([]*terraform.Output, 0), - Providers: make([]*terraform.Provider, 0), - Requirements: make([]*terraform.Requirement, 0), - Resources: make([]*terraform.Resource, 0), - } - - print.CopySections(y.settings, module, copy) +// Generate a Terraform module as YAML. +func (y *yaml) Generate(module *terraform.Module) error { + copy := copySections(y.settings, module) buffer := new(bytes.Buffer) - - encoder := yaml.NewEncoder(buffer) + encoder := yamlv3.NewEncoder(buffer) encoder.SetIndent(2) - err := encoder.Encode(copy) - if err != nil { - return nil, err + if err := encoder.Encode(copy); err != nil { + return err } - return print.NewGenerator( - "yaml", - print.WithContent(strings.TrimSuffix(buffer.String(), "\n")), - ), nil + y.Generator.Funcs(print.WithContent(strings.TrimSuffix(buffer.String(), "\n"))) + + return nil } func init() { diff --git a/format/yaml_test.go b/format/yaml_test.go index b065b05..02bc8da 100644 --- a/format/yaml_test.go +++ b/format/yaml_test.go @@ -15,8 +15,8 @@ import ( "github.com/stretchr/testify/assert" - "github.com/terraform-docs/terraform-docs/internal/print" "github.com/terraform-docs/terraform-docs/internal/testutil" + "github.com/terraform-docs/terraform-docs/print" "github.com/terraform-docs/terraform-docs/terraform" ) @@ -114,12 +114,12 @@ func TestYaml(t *testing.T) { module, err := testutil.GetModule(options) assert.Nil(err) - formatter := NewYAML(&tt.settings) + formatter := NewYAML(tt.settings.ToConfig()) - generator, err := formatter.Generate(module) + err = formatter.Generate(module) assert.Nil(err) - actual, err := generator.ExecuteTemplate("") + actual, err := formatter.ExecuteTemplate("") assert.Nil(err) assert.Equal(expected, actual) diff --git a/internal/cli/mappings.go b/internal/cli/mappings.go new file mode 100644 index 0000000..f4cab70 --- /dev/null +++ b/internal/cli/mappings.go @@ -0,0 +1,45 @@ +/* +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 cli + +// Mappings of CLI flags to Viper config +var flagMappings = map[string]string{ + "header-from": "header-from", + "footer-from": "footer-from", + + "hide-empty": "hide-empty", + + "show": "sections.show", + "hide": "sections.hide", + + "output-file": "output.file", + "output-mode": "output.mode", + "output-template": "output.template", + + "output-values": "output-values.enabled", + "output-values-from": "output-values.from", + + "sort": "sort.enabled", + "sort-by": "sort.by", + "sort-by-required": "required", + "sort-by-type": "type", + + "anchor": "settings.anchor", + "color": "settings.color", + "default": "settings.default", + "description": "settings.description", + "escape": "settings.escape", + "indent": "settings.indent", + "read-comments": "settings.read-comments", + "required": "settings.required", + "sensitive": "settings.sensitive", + "type": "settings.type", +} diff --git a/internal/cli/run.go b/internal/cli/run.go index 9c7d13c..4af099a 100644 --- a/internal/cli/run.go +++ b/internal/cli/run.go @@ -26,6 +26,7 @@ import ( "github.com/terraform-docs/terraform-docs/format" "github.com/terraform-docs/terraform-docs/internal/plugin" "github.com/terraform-docs/terraform-docs/internal/version" + "github.com/terraform-docs/terraform-docs/print" "github.com/terraform-docs/terraform-docs/terraform" ) @@ -34,16 +35,17 @@ type Runtime struct { rootDir string formatter string - config *Config + config *print.Config - cmd *cobra.Command + cmd *cobra.Command + isFlagChanged func(string) bool } // NewRuntime returns new instance of Runtime. If `config` is not provided // default config will be used. -func NewRuntime(config *Config) *Runtime { +func NewRuntime(config *print.Config) *Runtime { if config == nil { - config = DefaultConfig() + config = print.DefaultConfig() } return &Runtime{config: config} } @@ -60,7 +62,7 @@ func (r *Runtime) PreRunEFunc(cmd *cobra.Command, args []string) error { os.Exit(0) } - r.config.isFlagChanged = cmd.Flags().Changed + r.isFlagChanged = cmd.Flags().Changed r.rootDir = args[0] r.cmd = cmd @@ -79,7 +81,7 @@ func (r *Runtime) PreRunEFunc(cmd *cobra.Command, args []string) error { type module struct { rootDir string - config *Config + config *print.Config } // RunEFunc is the 'cobra.Command#RunE' function for 'formatter' commands. It attempts @@ -111,10 +113,10 @@ func (r *Runtime) RunEFunc(cmd *cobra.Command, args []string) error { } // set the module root directory - cfg.moduleRoot = module.rootDir + cfg.ModuleRoot = module.rootDir // process and validate configuration - if err := cfg.process(); err != nil { + if err := cfg.Validate(); err != nil { return err } @@ -133,10 +135,10 @@ func (r *Runtime) RunEFunc(cmd *cobra.Command, args []string) error { // readConfig attempts to read config file, either default `.terraform-docs.yml` // or provided file with `-c, --config` flag. It will then attempt to override // them with corresponding flags (if set). -func (r *Runtime) readConfig(config *Config, submoduleDir string) error { +func (r *Runtime) readConfig(config *print.Config, submoduleDir string) error { v := viper.New() - if config.isFlagChanged("config") { + if r.isFlagChanged("config") { v.SetConfigFile(config.File) } else { v.SetConfigName(".terraform-docs") @@ -186,6 +188,9 @@ func (r *Runtime) readConfig(config *Config, submoduleDir string) error { config.Formatter = r.formatter } + // TODO + config.Parse() + return nil } @@ -246,13 +251,13 @@ func (r *Runtime) findSubmodules() ([]module, error) { continue } - var cfg *Config + var cfg *print.Config path := filepath.Join(dir, file.Name()) cfgfile := filepath.Join(path, r.config.File) if _, err := os.Stat(cfgfile); !os.IsNotExist(err) { - cfg = DefaultConfig() + cfg = print.DefaultConfig() if err := r.readConfig(cfg, path); err != nil { return nil, err @@ -289,16 +294,15 @@ func checkConstraint(versionRange string, currentVersion string) error { // generateContent extracts print.Settings and terraform.Options from normalized // Config and generates the output content for the module (and submodules if available) // and write the result to the output (either stdout or a file). -func generateContent(config *Config) error { - settings, options := config.extract() - options.Path = config.moduleRoot +func generateContent(config *print.Config) error { + settings, options := config.Extract() module, err := terraform.LoadWithOptions(options) if err != nil { return err } - formatter, err := format.Factory(config.Formatter, settings) + formatter, err := format.New(config) // formatter is unknown, this might mean that the intended formatter is // coming from a plugin. We are going to attempt to find a plugin with @@ -325,13 +329,12 @@ func generateContent(config *Config) error { return writeContent(config, content) } - generator, err := formatter.Generate(module) + err = formatter.Generate(module) if err != nil { return err } - generator.Path(options.Path) - content, err := generator.ExecuteTemplate(config.Content) + content, err := formatter.ExecuteTemplate(config.Content) if err != nil { return err } @@ -341,22 +344,22 @@ func generateContent(config *Config) error { // writeContent to a Writer. This can either be os.Stdout or specific // file (e.g. README.md) if '--output-file' is provided. -func writeContent(config *Config, content string) error { +func writeContent(config *print.Config, content string) error { var w io.Writer // writing to a file (either inject or replace) if config.Output.File != "" { w = &fileWriter{ file: config.Output.File, - dir: config.moduleRoot, + dir: config.ModuleRoot, mode: config.Output.Mode, check: config.Output.Check, template: config.Output.Template, - begin: config.Output.beginComment, - end: config.Output.endComment, + begin: config.Output.BeginComment, + end: config.Output.EndComment, } } else { // writing to stdout diff --git a/internal/cli/writer.go b/internal/cli/writer.go index 5a68427..3a00e0c 100644 --- a/internal/cli/writer.go +++ b/internal/cli/writer.go @@ -19,6 +19,8 @@ import ( "path/filepath" "strings" "text/template" + + "github.com/terraform-docs/terraform-docs/print" ) // stdoutWriter writes content to os.Stdout. @@ -62,7 +64,7 @@ func (fw *fileWriter) Write(p []byte) (int, error) { if fw.template == "" { // template is optional for mode replace - if fw.mode == outputModeReplace { + if fw.mode == print.OutputModeReplace { return fw.write(filename, p) } return 0, errors.New("template is missing") @@ -76,7 +78,7 @@ func (fw *fileWriter) Write(p []byte) (int, error) { // Replace the content of 'filename' with generated output, // no further processing is required for mode 'replace'. - if fw.mode == outputModeReplace { + if fw.mode == print.OutputModeReplace { return fw.write(filename, buf.Bytes()) } diff --git a/internal/cli/writer_test.go b/internal/cli/writer_test.go index 6b6aae8..59a05ce 100644 --- a/internal/cli/writer_test.go +++ b/internal/cli/writer_test.go @@ -19,6 +19,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/terraform-docs/terraform-docs/internal/testutil" + "github.com/terraform-docs/terraform-docs/print" ) func TestFileWriterFullPath(t *testing.T) { @@ -73,9 +74,9 @@ func TestFileWriter(t *testing.T) { file: "mode-inject.md", mode: "inject", check: false, - template: OutputTemplate, - begin: outputBeginComment, - end: outputEndComment, + template: print.OutputTemplate, + begin: print.OutputBeginComment, + end: print.OutputEndComment, writer: &bytes.Buffer{}, expected: "mode-inject", @@ -86,9 +87,9 @@ func TestFileWriter(t *testing.T) { file: "empty-file.md", mode: "inject", check: false, - template: OutputTemplate, - begin: outputBeginComment, - end: outputEndComment, + template: print.OutputTemplate, + begin: print.OutputBeginComment, + end: print.OutputEndComment, writer: &bytes.Buffer{}, expected: "mode-inject-empty-file", @@ -99,9 +100,9 @@ func TestFileWriter(t *testing.T) { file: "mode-inject-no-comment.md", mode: "inject", check: false, - template: OutputTemplate, - begin: outputBeginComment, - end: outputEndComment, + template: print.OutputTemplate, + begin: print.OutputBeginComment, + end: print.OutputEndComment, writer: &bytes.Buffer{}, expected: "mode-inject-no-comment", @@ -112,9 +113,9 @@ func TestFileWriter(t *testing.T) { file: "file-missing.md", mode: "inject", check: false, - template: OutputTemplate, - begin: outputBeginComment, - end: outputEndComment, + template: print.OutputTemplate, + begin: print.OutputBeginComment, + end: print.OutputEndComment, writer: &bytes.Buffer{}, expected: "mode-inject-file-missing", @@ -125,9 +126,9 @@ func TestFileWriter(t *testing.T) { file: "mode-replace.md", mode: "replace", check: false, - template: OutputTemplate, - begin: outputBeginComment, - end: outputEndComment, + template: print.OutputTemplate, + begin: print.OutputBeginComment, + end: print.OutputEndComment, writer: &bytes.Buffer{}, expected: "mode-replace-with-comment", @@ -138,9 +139,9 @@ func TestFileWriter(t *testing.T) { file: "mode-replace.md", mode: "replace", check: false, - template: OutputTemplate, - begin: outputBeginComment, - end: outputEndComment, + template: print.OutputTemplate, + begin: print.OutputBeginComment, + end: print.OutputEndComment, writer: &bytes.Buffer{}, expected: "mode-replace-with-comment", @@ -151,9 +152,9 @@ func TestFileWriter(t *testing.T) { file: "file-missing.md", mode: "replace", check: false, - template: OutputTemplate, - begin: outputBeginComment, - end: outputEndComment, + template: print.OutputTemplate, + begin: print.OutputBeginComment, + end: print.OutputEndComment, writer: &bytes.Buffer{}, expected: "mode-replace-with-comment", @@ -164,7 +165,7 @@ func TestFileWriter(t *testing.T) { file: "mode-replace.md", mode: "replace", check: false, - template: outputContent, + template: print.OutputContent, begin: "", end: "", writer: &bytes.Buffer{}, @@ -193,8 +194,8 @@ func TestFileWriter(t *testing.T) { mode: "inject", check: false, template: "", - begin: outputBeginComment, - end: outputEndComment, + begin: print.OutputBeginComment, + end: print.OutputEndComment, writer: nil, expected: "", @@ -205,9 +206,9 @@ func TestFileWriter(t *testing.T) { file: "begin-comment-missing.md", mode: "inject", check: false, - template: OutputTemplate, - begin: outputBeginComment, - end: outputEndComment, + template: print.OutputTemplate, + begin: print.OutputBeginComment, + end: print.OutputEndComment, writer: nil, expected: "", @@ -218,9 +219,9 @@ func TestFileWriter(t *testing.T) { file: "end-comment-missing.md", mode: "inject", check: false, - template: OutputTemplate, - begin: outputBeginComment, - end: outputEndComment, + template: print.OutputTemplate, + begin: print.OutputBeginComment, + end: print.OutputEndComment, writer: nil, expected: "", @@ -231,9 +232,9 @@ func TestFileWriter(t *testing.T) { file: "end-comment-before-begin.md", mode: "inject", check: false, - template: OutputTemplate, - begin: outputBeginComment, - end: outputEndComment, + template: print.OutputTemplate, + begin: print.OutputBeginComment, + end: print.OutputEndComment, writer: nil, expected: "", @@ -244,9 +245,9 @@ func TestFileWriter(t *testing.T) { file: "mode-replace.md", mode: "replace", check: true, - template: OutputTemplate, - begin: outputBeginComment, - end: outputEndComment, + template: print.OutputTemplate, + begin: print.OutputBeginComment, + end: print.OutputEndComment, writer: nil, expected: "", diff --git a/internal/print/doc.go b/internal/print/doc.go deleted file mode 100644 index f47be4a..0000000 --- a/internal/print/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 print provides a specific definition of a printer Format -package print diff --git a/internal/print/engine.go b/internal/print/engine.go deleted file mode 100644 index 321e66c..0000000 --- a/internal/print/engine.go +++ /dev/null @@ -1,20 +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 print - -import ( - "github.com/terraform-docs/terraform-docs/terraform" -) - -// Engine represents a format engine (e.g. json, table, yaml, ...) -type Engine interface { - Generate(*terraform.Module) (*Generator, error) -} diff --git a/internal/testutil/settings.go b/internal/testutil/settings.go index 2e97c4a..71f95c9 100644 --- a/internal/testutil/settings.go +++ b/internal/testutil/settings.go @@ -13,7 +13,7 @@ package testutil import ( "github.com/imdario/mergo" - "github.com/terraform-docs/terraform-docs/internal/print" + "github.com/terraform-docs/terraform-docs/print" ) // WithSections appends show all sections to provided Settings. diff --git a/internal/cli/config.go b/print/config.go similarity index 70% rename from internal/cli/config.go rename to print/config.go index 9ce114a..ab59953 100644 --- a/internal/cli/config.go +++ b/print/config.go @@ -8,51 +8,17 @@ You may obtain a copy of the License at the LICENSE file in the root directory of this source tree. */ -package cli +package print import ( "fmt" "strings" - "github.com/terraform-docs/terraform-docs/internal/print" "github.com/terraform-docs/terraform-docs/terraform" ) -// Mappings of CLI flags to Viper config -var flagMappings = map[string]string{ - "header-from": "header-from", - "footer-from": "footer-from", - - "hide-empty": "hide-empty", - - "show": "sections.show", - "hide": "sections.hide", - - "output-file": "output.file", - "output-mode": "output.mode", - "output-template": "output.template", - - "output-values": "output-values.enabled", - "output-values-from": "output-values.from", - - "sort": "sort.enabled", - "sort-by": "sort.by", - "sort-by-required": "required", - "sort-by-type": "type", - - "anchor": "settings.anchor", - "color": "settings.color", - "default": "settings.default", - "description": "settings.description", - "escape": "settings.escape", - "indent": "settings.indent", - "read-comments": "settings.read-comments", - "required": "settings.required", - "sensitive": "settings.sensitive", - "type": "settings.type", -} - -// Config represents all the available config options that can be accessed and passed through CLI +// Config represents all the available config options that can be accessed and +// passed through CLI. type Config struct { File string `mapstructure:"-"` Recursive bool `mapstructure:"-"` @@ -68,11 +34,21 @@ type Config struct { Sort sort `mapstructure:"sort"` Settings settings `mapstructure:"settings"` - moduleRoot string - isFlagChanged func(string) bool + ModuleRoot string } -// DefaultConfig returns new instance of Config with default values set +// NewConfig returns neew instancee of Config with empty values. +func NewConfig() *Config { + return &Config{ + Sections: sections{}, + Output: output{}, + OutputValues: outputvalues{}, + Sort: sort{}, + Settings: settings{}, + } +} + +// DefaultConfig returns new instance of Config with default values set. func DefaultConfig() *Config { return &Config{ File: "", @@ -89,8 +65,7 @@ func DefaultConfig() *Config { Sort: defaultSort(), Settings: defaultSettings(), - moduleRoot: "", - isFlagChanged: func(name string) bool { return false }, + ModuleRoot: "", } } @@ -127,15 +102,15 @@ type sections struct { Show []string `mapstructure:"show"` Hide []string `mapstructure:"hide"` - dataSources bool - header bool - footer bool - inputs bool - modulecalls bool - outputs bool - providers bool - requirements bool - resources bool + DataSources bool + Header bool + Footer bool + Inputs bool + Modulecalls bool + Outputs bool + Providers bool + Requirements bool + Resources bool } func defaultSections() sections { @@ -143,15 +118,15 @@ func defaultSections() sections { Show: []string{}, Hide: []string{}, - dataSources: false, - header: false, - footer: false, - inputs: false, - modulecalls: false, - outputs: false, - providers: false, - requirements: false, - resources: false, + DataSources: true, + Header: true, + Footer: false, + Inputs: true, + Modulecalls: true, + Outputs: true, + Providers: true, + Requirements: true, + Resources: true, } } @@ -191,19 +166,23 @@ func (s *sections) visibility(section string) bool { return len(s.Hide) > 0 } +// Output modes. const ( - outputModeInject = "inject" - outputModeReplace = "replace" - - outputBeginComment = "" - outputContent = "{{ .Content }}" - outputEndComment = "" + OutputModeInject = "inject" + OutputModeReplace = "replace" ) -// Output to file template and modes +// Output template. +const ( + OutputBeginComment = "" + OutputContent = "{{ .Content }}" + OutputEndComment = "" +) + +// Output to file template and modes. var ( - OutputTemplate = fmt.Sprintf("%s\n%s\n%s", outputBeginComment, outputContent, outputEndComment) - OutputModes = strings.Join([]string{outputModeInject, outputModeReplace}, ", ") + OutputTemplate = fmt.Sprintf("%s\n%s\n%s", OutputBeginComment, OutputContent, OutputEndComment) + OutputModes = strings.Join([]string{OutputModeInject, OutputModeReplace}, ", ") ) type output struct { @@ -212,19 +191,19 @@ type output struct { Template string `mapstructure:"template"` Check bool - beginComment string - endComment string + BeginComment string + EndComment string } func defaultOutput() output { return output{ File: "", - Mode: outputModeInject, + Mode: OutputModeInject, Template: OutputTemplate, Check: false, - beginComment: outputBeginComment, - endComment: outputEndComment, + BeginComment: OutputBeginComment, + EndComment: OutputEndComment, } } @@ -238,7 +217,7 @@ func (o *output) validate() error { } // Template is optional for mode 'replace' - if o.Mode == outputModeReplace && o.Template == "" { + if o.Mode == OutputModeReplace && o.Template == "" { return nil } @@ -246,13 +225,13 @@ func (o *output) validate() error { return fmt.Errorf("value of '--output-template' can't be empty") } - if !strings.Contains(o.Template, outputContent) { + if !strings.Contains(o.Template, OutputContent) { return fmt.Errorf("value of '--output-template' doesn't have '{{ .Content }}' (note that spaces inside '{{ }}' are mandatory)") } // No extra validation is needed for mode 'replace', // the followings only apply for every other modes. - if o.Mode == outputModeReplace { + if o.Mode == OutputModeReplace { return nil } @@ -288,13 +267,13 @@ func (o *output) validate() error { } } - o.beginComment = strings.TrimSpace(lines[0]) - o.endComment = strings.TrimSpace(lines[len(lines)-1]) + o.BeginComment = strings.TrimSpace(lines[0]) + o.EndComment = strings.TrimSpace(lines[len(lines)-1]) return nil } -// Detect if a particular line is a Markdown comment +// Detect if a particular line is a Markdown comment. // // ref: https://www.jamestharpe.com/markdown-comments/ func isInlineComment(line string) bool { @@ -414,12 +393,27 @@ func (s *settings) validate() error { return nil } -// process provided Config and check for any misuse or misconfiguration -func (c *Config) process() error { //nolint:gocyclo - // NOTE(khos2ow): this function is over our cyclomatic complexity goal. - // Be wary when adding branches, and look for functionality that could - // be reasonably moved into an injected dependency. +// Parse process config and set sections visibility. +func (c *Config) Parse() { + // sections + c.Sections.DataSources = c.Sections.visibility("data-sources") + c.Sections.Header = c.Sections.visibility("header") + c.Sections.Inputs = c.Sections.visibility("inputs") + c.Sections.Modulecalls = c.Sections.visibility("modules") + c.Sections.Outputs = c.Sections.visibility("outputs") + c.Sections.Providers = c.Sections.visibility("providers") + c.Sections.Requirements = c.Sections.visibility("requirements") + c.Sections.Resources = c.Sections.visibility("resources") + // Footer section is optional and should only be enabled if --footer-from + // is explicitly set, either via CLI or config file. + if c.FooterFrom != "" { + c.Sections.Footer = c.Sections.visibility("footer") + } +} + +// Validate provided Config and check for any misuse or misconfiguration. +func (c *Config) Validate() error { // formatter if c.Formatter == "" { return fmt.Errorf("value of 'formatter' can't be empty") @@ -430,30 +424,13 @@ func (c *Config) process() error { //nolint:gocyclo return fmt.Errorf("value of '--recursive-path' can't be empty") } - // sections - c.Sections.dataSources = c.Sections.visibility("data-sources") - c.Sections.header = c.Sections.visibility("header") - c.Sections.footer = c.Sections.visibility("footer") - c.Sections.inputs = c.Sections.visibility("inputs") - c.Sections.modulecalls = c.Sections.visibility("modules") - c.Sections.outputs = c.Sections.visibility("outputs") - c.Sections.providers = c.Sections.visibility("providers") - c.Sections.requirements = c.Sections.visibility("requirements") - c.Sections.resources = c.Sections.visibility("resources") - - // Footer section is optional and should only be enabled if --footer-from - // is explicitly set, either via CLI or config file. - if c.FooterFrom == "" && !c.isFlagChanged("footer-from") { - c.Sections.footer = false - } - // header-from if c.HeaderFrom == "" { return fmt.Errorf("value of '--header-from' can't be empty") } // footer-from, not a 'default' section so can be empty - if c.Sections.footer && c.FooterFrom == "" { + if c.Sections.Footer && c.FooterFrom == "" { return fmt.Errorf("value of '--footer-from' can't be empty") } @@ -476,18 +453,21 @@ func (c *Config) process() error { //nolint:gocyclo return nil } -// extract and build print.Settings and terraform.Options out of Config -func (c *Config) extract() (*print.Settings, *terraform.Options) { - settings := print.DefaultSettings() +// Extract and build print.Settings and terraform.Options out of Config. +func (c *Config) Extract() (*Settings, *terraform.Options) { + settings := DefaultSettings() options := terraform.NewOptions() + // path + options.Path = c.ModuleRoot + // header-from - settings.ShowHeader = c.Sections.header + settings.ShowHeader = c.Sections.Header options.ShowHeader = settings.ShowHeader options.HeaderFromFile = c.HeaderFrom // footer-from - settings.ShowFooter = c.Sections.footer + settings.ShowFooter = c.Sections.Footer options.ShowFooter = settings.ShowFooter options.FooterFromFile = c.FooterFrom @@ -495,13 +475,13 @@ func (c *Config) extract() (*print.Settings, *terraform.Options) { options.UseLockFile = c.Settings.LockFile // sections - settings.ShowDataSources = c.Sections.dataSources - settings.ShowInputs = c.Sections.inputs - settings.ShowModuleCalls = c.Sections.modulecalls - settings.ShowOutputs = c.Sections.outputs - settings.ShowProviders = c.Sections.providers - settings.ShowRequirements = c.Sections.requirements - settings.ShowResources = c.Sections.resources + settings.ShowDataSources = c.Sections.DataSources + settings.ShowInputs = c.Sections.Inputs + settings.ShowModuleCalls = c.Sections.Modulecalls + settings.ShowOutputs = c.Sections.Outputs + settings.ShowProviders = c.Sections.Providers + settings.ShowRequirements = c.Sections.Requirements + settings.ShowResources = c.Sections.Resources settings.HideEmpty = c.Settings.HideEmpty // output values diff --git a/internal/cli/config_test.go b/print/config_test.go similarity index 92% rename from internal/cli/config_test.go rename to print/config_test.go index 7034ca7..b01f33a 100644 --- a/internal/cli/config_test.go +++ b/print/config_test.go @@ -7,7 +7,8 @@ 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 cli + +package print import ( "fmt" @@ -168,7 +169,7 @@ func TestConfigOutput(t *testing.T) { "TemplateEmptyModeReplace": { output: output{ File: "README.md", - Mode: outputModeReplace, + Mode: OutputModeReplace, Template: "", }, wantErr: false, @@ -177,8 +178,8 @@ func TestConfigOutput(t *testing.T) { "TemplateLiteralLineBreak": { output: output{ File: "README.md", - Mode: outputModeInject, - Template: fmt.Sprintf("%s\\n%s\\n%s", outputBeginComment, outputContent, outputEndComment), + Mode: OutputModeInject, + Template: fmt.Sprintf("%s\\n%s\\n%s", OutputBeginComment, OutputContent, OutputEndComment), }, wantErr: false, errMsg: "", @@ -186,8 +187,8 @@ func TestConfigOutput(t *testing.T) { "NoExtraValidationModeReplace": { output: output{ File: "README.md", - Mode: outputModeReplace, - Template: fmt.Sprintf("%s\\n%s\\n%s", outputBeginComment, outputContent, outputEndComment), + Mode: OutputModeReplace, + Template: fmt.Sprintf("%s\\n%s\\n%s", OutputBeginComment, OutputContent, OutputEndComment), }, wantErr: false, errMsg: "", @@ -205,7 +206,7 @@ func TestConfigOutput(t *testing.T) { "TemplateEmptyModeInject": { output: output{ File: "README.md", - Mode: outputModeInject, + Mode: OutputModeInject, Template: "", }, wantErr: true, @@ -214,8 +215,8 @@ func TestConfigOutput(t *testing.T) { "TemplateNotContent": { output: output{ File: "README.md", - Mode: outputModeInject, - Template: fmt.Sprintf("%s\n%s", outputBeginComment, outputEndComment), + Mode: OutputModeInject, + Template: fmt.Sprintf("%s\n%s", OutputBeginComment, OutputEndComment), }, wantErr: true, errMsg: "value of '--output-template' doesn't have '{{ .Content }}' (note that spaces inside '{{ }}' are mandatory)", @@ -223,8 +224,8 @@ func TestConfigOutput(t *testing.T) { "TemplateNotThreeLines": { output: output{ File: "README.md", - Mode: outputModeInject, - Template: fmt.Sprintf("%s%s%s", outputBeginComment, outputContent, outputEndComment), + Mode: OutputModeInject, + Template: fmt.Sprintf("%s%s%s", OutputBeginComment, OutputContent, OutputEndComment), }, wantErr: true, errMsg: "value of '--output-template' should contain at least 3 lines (begin comment, {{ .Content }}, and end comment)", @@ -232,8 +233,8 @@ func TestConfigOutput(t *testing.T) { "TemplateBeginCommentMissing": { output: output{ File: "README.md", - Mode: outputModeInject, - Template: fmt.Sprintf("no-begin-comment\n%s\n%s", outputContent, outputEndComment), + Mode: OutputModeInject, + Template: fmt.Sprintf("no-begin-comment\n%s\n%s", OutputContent, OutputEndComment), }, wantErr: true, errMsg: "value of '--output-template' is missing begin comment", @@ -241,8 +242,8 @@ func TestConfigOutput(t *testing.T) { "TemplateEndCommentMissing": { output: output{ File: "README.md", - Mode: outputModeInject, - Template: fmt.Sprintf("%s\n%s\nno-end-comment", outputBeginComment, outputContent), + Mode: OutputModeInject, + Template: fmt.Sprintf("%s\n%s\nno-end-comment", OutputBeginComment, OutputContent), }, wantErr: true, errMsg: "value of '--output-template' is missing end comment", @@ -540,7 +541,7 @@ func TestConfigOutputvalues(t *testing.T) { } } -func TestConfigProcess(t *testing.T) { +func TestConfigValidate(t *testing.T) { tests := map[string]struct { config func(c *Config) wantErr bool @@ -576,8 +577,7 @@ func TestConfigProcess(t *testing.T) { "FooterFrom": { config: func(c *Config) { c.FooterFrom = "" - c.Sections.footer = true - c.isFlagChanged = func(s string) bool { return true } + c.Sections.Footer = true }, wantErr: true, errMsg: "value of '--footer-from' can't be empty", @@ -599,7 +599,7 @@ func TestConfigProcess(t *testing.T) { config := DefaultConfig() config.Formatter = "foo" tt.config(config) - err := config.process() + err := config.Validate() if tt.wantErr { assert.NotNil(err) diff --git a/print/doc.go b/print/doc.go new file mode 100644 index 0000000..e5e3038 --- /dev/null +++ b/print/doc.go @@ -0,0 +1,51 @@ +/* +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 print provides configuration, and a Generator. +// +// Configuration +// +// `print.Config` is the data structure representation for `.terraform-docs.yml` +// which will be read and extracted upon execution of terraform-docs cli. On the +// other hand it can be used directly if you are using terraform-docs as a library. +// +// This will return an instance of `Config` with default values set: +// +// config := print.DefaultConfig() +// +// Alternatively this will return an empty instance of `Config`: +// +// config := print.NewConfig() +// +// Generator +// +// `Generator` is an abstract implementation of `format.Type`. It doesn't implement +// `Generate(*terraform.Module) error` function. It is used directly by different +// format types, i.e. each format extends `Generator` and provides its implementation +// of `Generate` function. +// +// Generator holds a reference to all the sections (e.g. header, footer, inputs, etc) +// and also it renders all of them, in a predefined order, in `Content()`. +// +// It also provides `ExecuteTemplate(string)` function to process and render the +// template to generate the final output content. Following variables and functions are +// available: +// +// • `{{ .Header }}` +// • `{{ .Footer }}` +// • `{{ .Inputs }}` +// • `{{ .Modules }}` +// • `{{ .Outputs }}` +// • `{{ .Providers }}` +// • `{{ .Requirements }}` +// • `{{ .Resources }}` +// • `{{ include "path/fo/file" }}` +// +package print diff --git a/internal/print/generator.go b/print/generator.go similarity index 58% rename from internal/print/generator.go rename to print/generator.go index 81dee3d..70ab34f 100644 --- a/internal/print/generator.go +++ b/print/generator.go @@ -30,56 +30,56 @@ func WithContent(content string) GenerateFunc { // WithHeader specifies how the Generator should add Header. func WithHeader(header string) GenerateFunc { return func(g *Generator) { - g.Header = header + g.header = header } } // WithFooter specifies how the Generator should add Footer. func WithFooter(footer string) GenerateFunc { return func(g *Generator) { - g.Footer = footer + g.footer = footer } } // WithInputs specifies how the Generator should add Inputs. func WithInputs(inputs string) GenerateFunc { return func(g *Generator) { - g.Inputs = inputs + g.inputs = inputs } } // WithModules specifies how the Generator should add Modules. func WithModules(modules string) GenerateFunc { return func(g *Generator) { - g.Modules = modules + g.modules = modules } } // WithOutputs specifies how the Generator should add Outputs. func WithOutputs(outputs string) GenerateFunc { return func(g *Generator) { - g.Outputs = outputs + g.outputs = outputs } } // WithProviders specifies how the Generator should add Providers. func WithProviders(providers string) GenerateFunc { return func(g *Generator) { - g.Providers = providers + g.providers = providers } } // WithRequirements specifies how the Generator should add Requirements. func WithRequirements(requirements string) GenerateFunc { return func(g *Generator) { - g.Requirements = requirements + g.requirements = requirements } } // WithResources specifies how the Generator should add Resources. func WithResources(resources string) GenerateFunc { return func(g *Generator) { - g.Resources = resources + g.resources = resources } } @@ -99,43 +99,85 @@ func WithResources(resources string) GenerateFunc { // - markdown document // - markdown table type Generator struct { - Header string - Footer string - Inputs string - Modules string - Outputs string - Providers string - Requirements string - Resources string + // all the content combined + content string + + // individual sections + header string + footer string + inputs string + modules string + outputs string + providers string + requirements string + resources string path string // module's path - content string // all the content combined - formatter string // name of the formatter + formatter string // formatter name + + funcs []GenerateFunc } // NewGenerator returns a Generator for specific formatter name and with // provided sets of GeneratorFunc functions to build and add individual // sections. -func NewGenerator(name string, fns ...GenerateFunc) *Generator { +func NewGenerator(name string, root string, fns ...GenerateFunc) *Generator { g := &Generator{ + path: root, formatter: name, + funcs: []GenerateFunc{}, } - for _, fn := range fns { - fn(g) - } + g.Funcs(fns...) return g } -// Path of module's directory. +// Content returns generted all the sections combined based on the underlying format. +func (g *Generator) Content() string { return g.content } + +// Header returns generted header section based on the underlying format. +func (g *Generator) Header() string { return g.header } + +// Footer returns generted footer section based on the underlying format. +func (g *Generator) Footer() string { return g.footer } + +// Inputs returns generted inputs section based on the underlying format. +func (g *Generator) Inputs() string { return g.inputs } + +// Modules returns generted modules section based on the underlying format. +func (g *Generator) Modules() string { return g.modules } + +// Outputs returns generted outputs section based on the underlying format. +func (g *Generator) Outputs() string { return g.outputs } + +// Providers returns generted providers section based on the underlying format. +func (g *Generator) Providers() string { return g.providers } + +// Requirements returns generted resources section based on the underlying format. +func (g *Generator) Requirements() string { return g.requirements } + +// Resources returns generted requirements section based on the underlying format. +func (g *Generator) Resources() string { return g.resources } + +// Funcs adds GenerateFunc to the list of available functions, for further use +// if need be, and then runs them. +func (g *Generator) Funcs(fns ...GenerateFunc) { + for _, fn := range fns { + g.funcs = append(g.funcs, fn) + fn(g) + } +} + +// Path set path of module's root directory. func (g *Generator) Path(root string) { g.path = root } -// ExecuteTemplate applies the template with Generator known items. If template -// is empty Generator.content is returned as is. If template is not empty this -// still returns Generator.content for incompatible formatters. +// ExecuteTemplate applies the template with Renderer known items. If template +// is empty Renderer.content is returned as is. If template is not empty this +// still returns Renderer.content for incompatible formatters. +// func (g *Renderer) Render(contentTmpl string) (string, error) { func (g *Generator) ExecuteTemplate(contentTmpl string) (string, error) { if !g.isCompatible() { return g.content, nil @@ -174,15 +216,15 @@ func (g *Generator) isCompatible() bool { return false } -// GeneratorCallback renders a Terraform module and creates a GenerateFunc. -type GeneratorCallback func(string) GenerateFunc +// generatorCallback renders a Terraform module and creates a GenerateFunc. +type generatorCallback func(string) GenerateFunc -// ForEach section executes GeneratorCallback to render the content for that +// ForEach section executes generatorCallback to render the content for that // section and create corresponding GeneratorFunc. If there is any error in // the executing the template for the section ForEach function immediately // returns it and exit. -func ForEach(callback func(string, GeneratorCallback) error) error { - mappings := map[string]GeneratorCallback{ +func (g *Generator) ForEach(render func(string) (string, error)) error { + mappings := map[string]generatorCallback{ "all": WithContent, "header": WithHeader, "footer": WithFooter, @@ -193,10 +235,14 @@ func ForEach(callback func(string, GeneratorCallback) error) error { "requirements": WithRequirements, "resources": WithResources, } - for name, fn := range mappings { - if err := callback(name, fn); err != nil { + for name, callback := range mappings { + result, err := render(name) + if err != nil { return err } + fn := callback(result) + g.funcs = append(g.funcs, fn) + fn(g) } return nil } diff --git a/internal/print/generator_test.go b/print/generator_test.go similarity index 78% rename from internal/print/generator_test.go rename to print/generator_test.go index 1a1be3c..10dbc4a 100644 --- a/internal/print/generator_test.go +++ b/print/generator_test.go @@ -61,7 +61,7 @@ func TestIsCompatible(t *testing.T) { t.Run(name, func(t *testing.T) { assert := assert.New(t) - generator := NewGenerator(name) + generator := NewGenerator(name, "") actual := generator.isCompatible() assert.Equal(tt.expected, actual) @@ -140,10 +140,10 @@ func TestExecuteTemplate(t *testing.T) { t.Run(name, func(t *testing.T) { assert := assert.New(t) - generator := NewGenerator(tt.name) + generator := NewGenerator(tt.name, "") generator.content = tt.content - generator.Header = header - generator.Footer = footer + generator.header = header + generator.footer = footer actual, err := generator.ExecuteTemplate(tt.template) @@ -165,46 +165,46 @@ func TestGeneratorFunc(t *testing.T) { }{ "WithContent": { fn: WithContent, - actual: func(g *Generator) string { return g.content }, + actual: func(r *Generator) string { return r.content }, }, "WithHeader": { fn: WithHeader, - actual: func(g *Generator) string { return g.Header }, + actual: func(r *Generator) string { return r.header }, }, "WithFooter": { fn: WithFooter, - actual: func(g *Generator) string { return g.Footer }, + actual: func(r *Generator) string { return r.footer }, }, "WithInputs": { fn: WithInputs, - actual: func(g *Generator) string { return g.Inputs }, + actual: func(r *Generator) string { return r.inputs }, }, "WithModules": { fn: WithModules, - actual: func(g *Generator) string { return g.Modules }, + actual: func(r *Generator) string { return r.modules }, }, "WithOutputs": { fn: WithOutputs, - actual: func(g *Generator) string { return g.Outputs }, + actual: func(r *Generator) string { return r.outputs }, }, "WithProviders": { fn: WithProviders, - actual: func(g *Generator) string { return g.Providers }, + actual: func(r *Generator) string { return r.providers }, }, "WithRequirements": { fn: WithRequirements, - actual: func(g *Generator) string { return g.Requirements }, + actual: func(r *Generator) string { return r.requirements }, }, "WithResources": { fn: WithResources, - actual: func(g *Generator) string { return g.Resources }, + actual: func(r *Generator) string { return r.resources }, }, } for name, tt := range tests { t.Run(name, func(t *testing.T) { assert := assert.New(t) - generator := NewGenerator(name, tt.fn(text)) + generator := NewGenerator(name, "", tt.fn(text)) assert.Equal(text, tt.actual(generator)) }) @@ -212,27 +212,23 @@ func TestGeneratorFunc(t *testing.T) { } func TestForEach(t *testing.T) { - // text := "foo" - fns := []GenerateFunc{} - ForEach(func(name string, fn GeneratorCallback) error { - fns = append(fns, fn(name)) - return nil + generator := NewGenerator("foo", "") + generator.ForEach(func(name string) (string, error) { + return name, nil }) - generator := NewGenerator("foo", fns...) - tests := map[string]struct { actual string }{ "all": {actual: generator.content}, - "header": {actual: generator.Header}, - "footer": {actual: generator.Footer}, - "inputs": {actual: generator.Inputs}, - "modules": {actual: generator.Modules}, - "outputs": {actual: generator.Outputs}, - "providers": {actual: generator.Providers}, - "requirements": {actual: generator.Requirements}, - "resources": {actual: generator.Resources}, + "header": {actual: generator.header}, + "footer": {actual: generator.footer}, + "inputs": {actual: generator.inputs}, + "modules": {actual: generator.modules}, + "outputs": {actual: generator.outputs}, + "providers": {actual: generator.providers}, + "requirements": {actual: generator.requirements}, + "resources": {actual: generator.resources}, } for name, tt := range tests { t.Run(name, func(t *testing.T) { diff --git a/internal/print/settings.go b/print/settings.go similarity index 75% rename from internal/print/settings.go rename to print/settings.go index 25943fc..995c019 100644 --- a/internal/print/settings.go +++ b/print/settings.go @@ -12,7 +12,6 @@ package print import ( printsdk "github.com/terraform-docs/plugin-sdk/print" - "github.com/terraform-docs/terraform-docs/terraform" ) // Settings represents all settings. @@ -53,7 +52,7 @@ type Settings struct { // scope: Pretty ShowColor bool - // ShowDatasources show the data sources on the "Resources" section + // ShowDataSources show the data sources on the "Resources" section // // default: true // scope: Global @@ -144,7 +143,7 @@ type Settings struct { ShowType bool } -// DefaultSettings returns new instance of Settings +// DefaultSettings returns new instance of Settings. func DefaultSettings() *Settings { return &Settings{ EscapeCharacters: true, @@ -171,7 +170,38 @@ func DefaultSettings() *Settings { } } -// Convert internal Settings to its equivalent in plugin-sdk +// ToConfig converts Settings to Config. +func (s *Settings) ToConfig() *Config { + config := NewConfig() + + config.Settings.Anchor = s.ShowAnchor + config.Settings.Color = s.ShowColor + config.Settings.Default = s.ShowDefault + config.Settings.Description = s.ShowDescription + config.Settings.Escape = s.EscapeCharacters + config.Settings.HideEmpty = s.HideEmpty + config.Settings.HTML = s.ShowHTML + config.Settings.Indent = s.IndentLevel + config.Settings.Required = s.ShowRequired + config.Settings.Sensitive = s.ShowSensitivity + config.Settings.Type = s.ShowType + + config.OutputValues.Enabled = s.OutputValues + + config.Sections.DataSources = s.ShowDataSources + config.Sections.Footer = s.ShowFooter + config.Sections.Header = s.ShowHeader + config.Sections.Inputs = s.ShowInputs + config.Sections.Outputs = s.ShowOutputs + config.Sections.Modulecalls = s.ShowModuleCalls + config.Sections.Providers = s.ShowProviders + config.Sections.Requirements = s.ShowRequirements + config.Sections.Resources = s.ShowResources + + return config +} + +// Convert Settings to its equivalent in plugin-sdk. func (s *Settings) Convert() *printsdk.Settings { return &printsdk.Settings{ EscapeCharacters: s.EscapeCharacters, @@ -195,45 +225,3 @@ func (s *Settings) Convert() *printsdk.Settings { ShowType: s.ShowType, } } - -// CopySections sets the sections that'll be printed -func CopySections(settings *Settings, src *terraform.Module, dest *terraform.Module) { - if settings.ShowHeader { - dest.Header = src.Header - } - if settings.ShowFooter { - dest.Footer = src.Footer - } - if settings.ShowInputs { - dest.Inputs = src.Inputs - } - if settings.ShowModuleCalls { - dest.ModuleCalls = src.ModuleCalls - } - if settings.ShowOutputs { - dest.Outputs = src.Outputs - } - if settings.ShowProviders { - dest.Providers = src.Providers - } - if settings.ShowRequirements { - dest.Requirements = src.Requirements - } - if settings.ShowResources || settings.ShowDataSources { - dest.Resources = filterResourcesByMode(settings, src.Resources) - } -} - -// filterResourcesByMode returns the managed or data resources defined by the show argument -func filterResourcesByMode(settings *Settings, module []*terraform.Resource) []*terraform.Resource { - resources := make([]*terraform.Resource, 0) - for _, r := range module { - if settings.ShowResources && r.Mode == "managed" { - resources = append(resources, r) - } - if settings.ShowDataSources && r.Mode == "data" { - resources = append(resources, r) - } - } - return resources -} diff --git a/internal/print/testdata/sample-file.txt b/print/testdata/sample-file.txt similarity index 100% rename from internal/print/testdata/sample-file.txt rename to print/testdata/sample-file.txt diff --git a/internal/cli/util.go b/print/util.go similarity index 98% rename from internal/cli/util.go rename to print/util.go index 31cc56d..3d64102 100644 --- a/internal/cli/util.go +++ b/print/util.go @@ -8,7 +8,7 @@ You may obtain a copy of the License at the LICENSE file in the root directory of this source tree. */ -package cli +package print func contains(list []string, name string) bool { for _, v := range list { diff --git a/internal/cli/util_test.go b/print/util_test.go similarity index 99% rename from internal/cli/util_test.go rename to print/util_test.go index eced044..23c84be 100644 --- a/internal/cli/util_test.go +++ b/print/util_test.go @@ -8,7 +8,7 @@ You may obtain a copy of the License at the LICENSE file in the root directory of this source tree. */ -package cli +package print import ( "testing" diff --git a/scripts/docs/generate.go b/scripts/docs/generate.go index fc2a1c7..1796908 100644 --- a/scripts/docs/generate.go +++ b/scripts/docs/generate.go @@ -24,7 +24,7 @@ import ( "github.com/terraform-docs/terraform-docs/cmd" "github.com/terraform-docs/terraform-docs/format" - "github.com/terraform-docs/terraform-docs/internal/print" + "github.com/terraform-docs/terraform-docs/print" "github.com/terraform-docs/terraform-docs/terraform" ) @@ -171,9 +171,9 @@ func example(ref *reference) error { ref.Usage = fmt.Sprintf("%s%s ./examples/", ref.Command, flag) - settings := print.DefaultSettings() - settings.ShowColor = false - settings.ShowFooter = true + config := print.DefaultConfig() + config.Formatter = ref.Name + config.Settings.Color = false options := &terraform.Options{ Path: "./examples", ShowHeader: true, @@ -186,26 +186,21 @@ func example(ref *reference) error { ReadComments: true, } - formatter, err := format.Factory(ref.Name, settings) - if err != nil { - return err - } - tfmodule, err := terraform.LoadWithOptions(options) if err != nil { log.Fatal(err) } - generator, err := formatter.Generate(tfmodule) - if err != nil { - return err - } - output, err := generator.ExecuteTemplate("") + formatter, err := format.New(config) if err != nil { return err } - segments := strings.Split(output, "\n") + if err := formatter.Generate(tfmodule); err != nil { + return err + } + + segments := strings.Split(formatter.Content(), "\n") buf := new(bytes.Buffer) for _, s := range segments { if s == "" { diff --git a/template/anchor.go b/template/anchor.go index 74163c6..a10c46a 100644 --- a/template/anchor.go +++ b/template/anchor.go @@ -13,7 +13,7 @@ package template import ( "fmt" - "github.com/terraform-docs/terraform-docs/internal/print" + "github.com/terraform-docs/terraform-docs/print" ) // CreateAnchorMarkdown creates HTML anchor for Markdown format. diff --git a/template/anchor_test.go b/template/anchor_test.go index 418d5c8..6536ea1 100644 --- a/template/anchor_test.go +++ b/template/anchor_test.go @@ -15,7 +15,7 @@ import ( "github.com/stretchr/testify/assert" - "github.com/terraform-docs/terraform-docs/internal/print" + "github.com/terraform-docs/terraform-docs/print" ) func TestAnchorMarkdown(t *testing.T) { diff --git a/template/doc.go b/template/doc.go index e003672..bffbd29 100644 --- a/template/doc.go +++ b/template/doc.go @@ -16,7 +16,7 @@ the root directory of this source tree. // "fmt" // gotemplate "text/template" // -// "github.com/terraform-docs/terraform-docs/internal/print" +// "github.com/terraform-docs/terraform-docs/print" // "github.com/terraform-docs/terraform-docs/template" // "github.com/terraform-docs/terraform-docs/terraform" // ) diff --git a/template/sanitizer.go b/template/sanitizer.go index 9ab836f..9a2d80f 100644 --- a/template/sanitizer.go +++ b/template/sanitizer.go @@ -19,7 +19,7 @@ import ( "mvdan.cc/xurls/v2" - "github.com/terraform-docs/terraform-docs/internal/print" + "github.com/terraform-docs/terraform-docs/print" ) // SanitizeName escapes underscore character which have special meaning in Markdown. diff --git a/template/sanitizer_test.go b/template/sanitizer_test.go index 8ca9749..53c4c85 100644 --- a/template/sanitizer_test.go +++ b/template/sanitizer_test.go @@ -17,7 +17,7 @@ import ( "github.com/stretchr/testify/assert" - "github.com/terraform-docs/terraform-docs/internal/print" + "github.com/terraform-docs/terraform-docs/print" ) func TestSanitizeName(t *testing.T) { diff --git a/template/template.go b/template/template.go index 49462f4..3caf9f0 100644 --- a/template/template.go +++ b/template/template.go @@ -16,8 +16,8 @@ import ( "strings" gotemplate "text/template" - "github.com/terraform-docs/terraform-docs/internal/print" "github.com/terraform-docs/terraform-docs/internal/types" + "github.com/terraform-docs/terraform-docs/print" "github.com/terraform-docs/terraform-docs/terraform" ) diff --git a/template/template_test.go b/template/template_test.go index e451a0b..978a5da 100644 --- a/template/template_test.go +++ b/template/template_test.go @@ -20,8 +20,8 @@ import ( "github.com/stretchr/testify/assert" - "github.com/terraform-docs/terraform-docs/internal/print" "github.com/terraform-docs/terraform-docs/internal/types" + "github.com/terraform-docs/terraform-docs/print" "github.com/terraform-docs/terraform-docs/terraform" )