Repository: terraform-docs/terraform-docs (go)

Issue:
Inconsinstent markdown generation when using heredoc in terraform output (CRLF vs LF)
<!--
Thank you for helping to improve terraform-docs!

Please be sure to search for open issues before raising a new one. We use issues
for bug reports and feature requests. Please note, this template is for bugs
report, not feature requests. For more information, see the Contributing Guidelines
at https://git.io/JtEzg. Please find us at https://slack.terraform-docs.io/ for
questions, support, and discussion.
-->

### Describe the bug

<!--
Please let us know what behaviour you expected and how terraform-docs diverged
from that behaviour.
-->

Inconsistent markdown generation when using multi-line strings (heredoc) in outputs, currently dependant on the line ending. 

When using with Windows line ending(CRLF) in outputs, it makes the markdown output multiline, but when using linux line ending, it generates a single line.

I think that this problem is related to https://github.com/terraform-docs/terraform-docs/issues/305. Maybe the fix should be applied to the outputs too?

### How can we reproduce it?

1. Create a `main.tf` with this content and save it with Windows line endings (CRLF):
```hcl
output "example" {
  value       = "this is an example"
  description = <<EOT
Lorem ipsum dolor sit amet, 
consectetur adipiscing elit, 
sed do eiusmod tempor incididunt 
ut labore et dolore magna aliqua. 
Ut enim ad minim veniam, 
quis nostrud exercitation ullamco 
laboris nisi ut aliquip ex ea commodo consequat. 
Duis aute irure dolor in reprehenderit in voluptate 
velit esse cillum dolore eu fugiat nulla pariatur. 
Excepteur sint occaecat cupidatat non proident, 
sunt in culpa qui officia deserunt mollit anim id est laborum.
EOT
  sensitive   = false
}

```

2. Run `terraform-docs markdown .` 
```md
## Requirements

No requirements.

## Providers

No providers.

## Modules

No modules.

## Resources

No resources.

## Inputs

No inputs.

## Outputs

| Name | Description |
|------|-------------|
| <a name="output_example"></a> [example](#output\_example) | Lorem ipsum dolor sit amet,   
<br>consectetur adipiscing elit,   
<br>sed do eiusmod tempor incididunt   
<br>ut labore et dolore magna aliqua.   
<br>Ut enim ad minim veniam,   
<br>quis nostrud exercitation ullamco   
<br>laboris nisi ut aliquip ex ea commodo consequat.   
<br>Duis aute irure dolor in reprehenderit in voluptate   
<br>velit esse cillum dolore eu fugiat nulla pariatur.   
<br>Excepteur sint occaecat cupidatat non proident,   
<br>sunt in culpa qui officia deserunt mollit anim id est laborum. |

```
3. Now, replace the `main.tf` line endings to the linux type (LF) and re-run the command `terraform-docs markdown .` 
```md
## Requirements

No requirements.

## Providers

No providers.

## Modules

No modules.

## Resources

No resources.

## Inputs

No inputs.

## Outputs

| Name | Description |
|------|-------------|
| <a name="output_example"></a> [example](#output\_example) | Lorem ipsum dolor sit amet, <br>consectetur adipiscing elit, <br>sed do eiusmod tempor incididunt <br>ut labore et dolore magna aliqua. <br>Ut enim ad minim veniam, <br>quis nostrud exercitation ullamco <br>laboris nisi ut aliquip ex ea commodo consequat. <br>Duis aute irure dolor in reprehenderit in voluptate <br>velit esse cillum dolore eu fugiat nulla pariatur. <br>Excepteur sint occaecat cupidatat non proident, <br>sunt in culpa qui officia deserunt mollit anim id est laborum. |

```

<!--
Help us to reproduce your bug as succinctly and precisely as possible. Any and
all steps or script that triggers the issue are highly appreciated!

Do you have long logs to share? Please go to https://ghostbin.com and insert the
link here.
-->


### Environment information
- terraform-docs version: tested on v0.12.1 and 0.16.0
- OS: Windows 10

Pull request description:
Always convert CRLF to LF for output description
<!--
Thank you for helping to improve terraform-docs!

Please read through https://git.io/JtEzg if this is your first time opening a
terraform-docs pull request. Find us in https://slack.terraform-docs.io/messages/dev if
you need any help contributing.
-->

### Description of your changes

<!--
Briefly describe what this pull request does. Be sure to direct your reviewers'
attention to anything that needs special consideration.

We love pull requests that resolve an open terraform-docs issue. If yours does, you
can uncomment the below line to indicate which issue your PR fixes, for example
"Fixes #500":
-->

Always convert CRLF to LF in output description before generating the result. This will make sure the output result is always consistent.

Fixes #584 

I have:

- [x] Read and followed terraform-docs' [contribution process].
- [x] All tests pass when I run `make test`.

### How has this code been tested

<!--
Before reviewers can be confident in the correctness of this pull request, it
needs to tested and shown to be correct. Briefly describe the testing that has
already been done or which is planned for this change.
-->

Added new `TestLoadOutputsLineEnding` test cases.

[contribution process]: https://git.io/JtEzg


Patch:
diff --git a/.editorconfig b/.editorconfig
index 50b04ac..e54d215 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -40,5 +40,8 @@ trim_trailing_whitespace = false
 [**/inputs-crlf/variables.tf]
 end_of_line = crlf
 
+[**/outputs-crlf/outputs.tf]
+end_of_line = crlf
+
 [Makefile]
 indent_style = tab
diff --git a/terraform/load.go b/terraform/load.go
index 7cfa1f7..162c59e 100644
--- a/terraform/load.go
+++ b/terraform/load.go
@@ -278,7 +278,8 @@ func loadOutputs(tfmodule *tfconfig.Module, config *print.Config) ([]*Output, er
 		}
 	}
 	for _, o := range tfmodule.Outputs {
-		description := o.Description
+		// convert CRLF to LF early on (https://github.com/terraform-docs/terraform-docs/issues/584)
+		description := strings.ReplaceAll(o.Description, "\r\n", "\n")
 		if description == "" && config.Settings.ReadComments {
 			description = loadComments(o.Pos.Filename, o.Pos.Line)
 		}


Test patch:
diff --git a/terraform/load_test.go b/terraform/load_test.go
index 984acd5..cbce6e8 100644
--- a/terraform/load_test.go
+++ b/terraform/load_test.go
@@ -618,6 +618,37 @@ func TestLoadOutputs(t *testing.T) {
 	}
 }
 
+func TestLoadOutputsLineEnding(t *testing.T) {
+	tests := []struct {
+		name     string
+		path     string
+		expected string
+	}{
+		{
+			name:     "load module outputs from file with lf line ending",
+			path:     "outputs-lf",
+			expected: "The quick brown fox jumps\nover the lazy dog\n",
+		},
+		{
+			name:     "load module outputs from file with crlf line ending",
+			path:     "outputs-crlf",
+			expected: "The quick brown fox jumps\nover the lazy dog\n",
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			assert := assert.New(t)
+
+			config := print.NewConfig()
+			module, _ := loadModule(filepath.Join("testdata", tt.path))
+			outputs, _ := loadOutputs(module, config)
+
+			assert.Equal(1, len(outputs))
+			assert.Equal(tt.expected, string(outputs[0].Description))
+		})
+	}
+}
+
 func TestLoadOutputsValues(t *testing.T) {
 	type expected struct {
 		outputs int
diff --git a/terraform/testdata/inputs-crlf/variables.tf b/terraform/testdata/inputs-crlf/variables.tf
index 2333cc8..6304af7 100644
--- a/terraform/testdata/inputs-crlf/variables.tf
+++ b/terraform/testdata/inputs-crlf/variables.tf
@@ -1,4 +1,4 @@
-variable "multi-line-lf" {
+variable "multi-line-crlf" {
   type = string
   description = <<-EOT
   The quick brown fox jumps
diff --git a/terraform/testdata/inputs-lf/variables.tf b/terraform/testdata/inputs-lf/variables.tf
index b2cbf52..fbc0958 100644
--- a/terraform/testdata/inputs-lf/variables.tf
+++ b/terraform/testdata/inputs-lf/variables.tf
@@ -1,4 +1,4 @@
-variable "multi-line-crlf" {
+variable "multi-line-lf" {
   type = string
   description = <<-EOT
   The quick brown fox jumps
diff --git a/terraform/testdata/outputs-crlf/outputs.tf b/terraform/testdata/outputs-crlf/outputs.tf
new file mode 100644
index 0000000..18266be
--- /dev/null
+++ b/terraform/testdata/outputs-crlf/outputs.tf
@@ -0,0 +1,7 @@
+output "multi-line-crlf" {
+  value = "foo"
+  description = <<-EOT
+  The quick brown fox jumps
+  over the lazy dog
+  EOT
+}
diff --git a/terraform/testdata/outputs-lf/outputs.tf b/terraform/testdata/outputs-lf/outputs.tf
new file mode 100644
index 0000000..ab5daf6
--- /dev/null
+++ b/terraform/testdata/outputs-lf/outputs.tf
@@ -0,0 +1,7 @@
+output "multi-line-lf" {
+  value = "foo"
+  description = <<-EOT
+  The quick brown fox jumps
+  over the lazy dog
+  EOT
+}