Repository: terraform-docs/terraform-docs
Pull request #409 (2021-02-26 16:32:24)

Anchors
<!--
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":
-->

Fixes https://github.com/terraform-docs/terraform-docs/issues/408

<!-- Fixes # -->

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.
-->

[contribution process]: https://git.io/JtEzg

Tested this locally and seems to work well with a single test case. Not all test cases pass. Waiting for more discussion.

Is there a way to regenerate the testdata or should I be updating that manually ?

khos2ow: Please hold off any major work on testing until #410 is done.
nitrocode: Ah I just added the `--anchors` switch and pushed it. I will hold off on making additional changes.
nitrocode: I'm having issues running test on the `master` branch.

```
$ make test
package github.com/nitrocode/terraform-docs/scripts/docs
	scripts/docs/generate.go:28:2: use of internal package github.com/terraform-docs/terraform-docs/internal/terraform not allowed
```
khos2ow: I'm wondering why it says `package github.com/nitrocode/terraform-docs/scripts/docs`? Technically you cannot access internal packages from `github.com/terraform-docs/terraform-docs` from `github.com/nitrocode/terraform-docs`.

Are you in GOPATH? If yes, `$GOPATH/src/github.com/terraform-docs/terraform-docs` should be your local cloned folder.
nitrocode: Thanks. I upgraded golang outside of homebrew and it's working now. 
nitrocode: I was able to fix the commit history by basically deleting my branch and updating the files again... squashing commits before and after an in-between merge does not seem possible.

The asciidoc template doesn't look like it will work currently as anchors are different in asciidoc vs markdown.

Docs
* https://docs.asciidoctor.org/asciidoc/latest/syntax-quick-reference/#links
* https://powerman.name/doc/asciidoc#anchor-1

```asciidoc
[[anchor-1]]
Paragraph or block 1.

anchor:anchor-2[]
Paragraph or block 2.

<<anchor-1>>,
<<anchor-1,First anchor>>,
xref:anchor-2[],
xref:anchor-2[Second anchor].
```

I'll use the above model to update the asciidoc anchors.
nitrocode: @khos2ow could you review this again please ?
khos2ow: - codecov coverage dropped by 0.29% which can be ignored, but you also can add cases into `templates_test.go#TestBuiltinFunc` to cover newly added functions too.
- that's weird. what does `make docs` do, same error? and why do you have `GOOS=linux`? I thought you were using macos.
nitrocode: Thanks for reviewing. I'll jump on it today.

Yes, I'm on OSX and the issue was related to the `go1.16` issue again...

Not to add too much scope creep to this PR but it would be nice to use an env var in the `Makefile` like `GOBINARY=go` which can be used in every target then if I need to overwrite it, I can simply do either

```
export GOBINARY=go1.16
make docs
```

or

```
GOBINARY=go1.16 make docs
```

khos2ow: That's a really good point, I'll add it in another PR! :+1: 

Patch:
diff --git a/cmd/asciidoc/asciidoc.go b/cmd/asciidoc/asciidoc.go
index ae286a0..4937936 100644
--- a/cmd/asciidoc/asciidoc.go
+++ b/cmd/asciidoc/asciidoc.go
@@ -34,6 +34,7 @@ func NewCommand(config *cli.Config) *cobra.Command {
 	cmd.PersistentFlags().BoolVar(&config.Settings.Required, "required", true, "show Required column or section")
 	cmd.PersistentFlags().BoolVar(&config.Settings.Sensitive, "sensitive", true, "show Sensitive column or section")
 	cmd.PersistentFlags().IntVar(&config.Settings.Indent, "indent", 2, "indention level of AsciiDoc sections [1, 2, 3, 4, 5]")
+	cmd.PersistentFlags().BoolVar(&config.Settings.Anchor, "anchor", true, "create anchor links")
 
 	// subcommands
 	cmd.AddCommand(document.NewCommand(config))
diff --git a/cmd/markdown/markdown.go b/cmd/markdown/markdown.go
index 054b042..f9522d8 100644
--- a/cmd/markdown/markdown.go
+++ b/cmd/markdown/markdown.go
@@ -35,6 +35,7 @@ func NewCommand(config *cli.Config) *cobra.Command {
 	cmd.PersistentFlags().BoolVar(&config.Settings.Sensitive, "sensitive", true, "show Sensitive column or section")
 	cmd.PersistentFlags().BoolVar(&config.Settings.Escape, "escape", true, "escape special characters")
 	cmd.PersistentFlags().IntVar(&config.Settings.Indent, "indent", 2, "indention level of Markdown sections [1, 2, 3, 4, 5]")
+	cmd.PersistentFlags().BoolVar(&config.Settings.Anchor, "anchor", true, "create anchor links")
 
 	// subcommands
 	cmd.AddCommand(document.NewCommand(config))
diff --git a/docs/reference/asciidoc-document.md b/docs/reference/asciidoc-document.md
index 510799f..3fb933c 100644
--- a/docs/reference/asciidoc-document.md
+++ b/docs/reference/asciidoc-document.md
@@ -25,6 +25,7 @@ terraform-docs asciidoc document [PATH] [flags]
 ## Inherited Options
 
 ```console
+      --anchor                      create anchor links (default true)
   -c, --config string               config file name (default ".terraform-docs.yml")
       --header-from string          relative path of a file to read header from (default "main.tf")
       --hide strings                hide section [header, inputs, modules, outputs, providers, requirements, resources]
@@ -93,41 +94,41 @@ generates the following output:
 
     The following requirements are needed by this module:
 
-    - terraform (>= 0.12)
+    - [[requirement_terraform]] <<requirement_terraform,terraform>> (>= 0.12)
 
-    - aws (>= 2.15.0)
+    - [[requirement_aws]] <<requirement_aws,aws>> (>= 2.15.0)
 
-    - random (>= 2.2.0)
+    - [[requirement_random]] <<requirement_random,random>> (>= 2.2.0)
 
     == Providers
 
     The following providers are used by this module:
 
-    - aws (>= 2.15.0)
+    - [[provider_aws]] <<provider_aws,aws>> (>= 2.15.0)
 
-    - aws.ident (>= 2.15.0)
+    - [[provider_aws.ident]] <<provider_aws.ident,aws.ident>> (>= 2.15.0)
 
-    - null
+    - [[provider_null]] <<provider_null,null>>
 
-    - tls
+    - [[provider_tls]] <<provider_tls,tls>>
 
     == Modules
 
     The following Modules are called:
 
-    === bar
+    === [[module_bar]] <<module_bar,bar>>
 
     Source: baz
 
     Version: 4.5.6
 
-    === baz
+    === [[module_baz]] <<module_baz,baz>>
 
     Source: baz
 
     Version: 4.5.6
 
-    === foo
+    === [[module_foo]] <<module_foo,foo>>
 
     Source: bar
 
@@ -145,43 +146,43 @@ generates the following output:
 
     The following input variables are required:
 
-    === input_with_underscores
+    === [[input_input_with_underscores]] <<input_input_with_underscores,input_with_underscores>>
 
     Description: A variable with underscores.
 
     Type: `any`
 
-    === list-2
+    === [[input_list-2]] <<input_list-2,list-2>>
 
     Description: It's list number two.
 
     Type: `list`
 
-    === map-2
+    === [[input_map-2]] <<input_map-2,map-2>>
 
     Description: It's map number two.
 
     Type: `map`
 
-    === number-2
+    === [[input_number-2]] <<input_number-2,number-2>>
 
     Description: It's number number two.
 
     Type: `number`
 
-    === string-2
+    === [[input_string-2]] <<input_string-2,string-2>>
 
     Description: It's string number two.
 
     Type: `string`
 
-    === string_no_default
+    === [[input_string_no_default]] <<input_string_no_default,string_no_default>>
 
     Description: n/a
 
     Type: `string`
 
-    === unquoted
+    === [[input_unquoted]] <<input_unquoted,unquoted>>
 
     Description: n/a
 
@@ -191,7 +192,7 @@ generates the following output:
 
     The following input variables are optional (have default values):
 
-    === bool-1
+    === [[input_bool-1]] <<input_bool-1,bool-1>>
 
     Description: It's bool number one.
 
@@ -199,7 +200,7 @@ generates the following output:
 
     Default: `true`
 
-    === bool-2
+    === [[input_bool-2]] <<input_bool-2,bool-2>>
 
     Description: It's bool number two.
 
@@ -207,7 +208,7 @@ generates the following output:
 
     Default: `false`
 
-    === bool-3
+    === [[input_bool-3]] <<input_bool-3,bool-3>>
 
     Description: n/a
 
@@ -215,7 +216,7 @@ generates the following output:
 
     Default: `true`
 
-    === bool_default_false
+    === [[input_bool_default_false]] <<input_bool_default_false,bool_default_false>>
 
     Description: n/a
 
@@ -223,7 +224,7 @@ generates the following output:
 
     Default: `false`
 
-    === input-with-code-block
+    === [[input_input-with-code-block]] <<input_input-with-code-block,input-with-code-block>>
 
     Description: This is a complicated one. We need a newline.  
     And an example in a code block
@@ -243,7 +244,7 @@ generates the following output:
     ]
     ----
 
-    === input-with-pipe
+    === [[input_input-with-pipe]] <<input_input-with-pipe,input-with-pipe>>
 
     Description: It includes v1 | v2 | v3
 
@@ -251,7 +252,7 @@ generates the following output:
 
     Default: `"v1"`
 
-    === list-1
+    === [[input_list-1]] <<input_list-1,list-1>>
 
     Description: It's list number one.
 
@@ -267,7 +268,7 @@ generates the following output:
     ]
     ----
 
-    === list-3
+    === [[input_list-3]] <<input_list-3,list-3>>
 
     Description: n/a
 
@@ -275,7 +276,7 @@ generates the following output:
 
     Default: `[]`
 
-    === list_default_empty
+    === [[input_list_default_empty]] <<input_list_default_empty,list_default_empty>>
 
     Description: n/a
 
@@ -283,7 +284,7 @@ generates the following output:
 
     Default: `[]`
 
-    === long_type
+    === [[input_long_type]] <<input_long_type,long_type>>
 
     Description: This description is itself markdown.
 
@@ -322,7 +323,7 @@ generates the following output:
     }
     ----
 
-    === map-1
+    === [[input_map-1]] <<input_map-1,map-1>>
 
     Description: It's map number one.
 
@@ -338,7 +339,7 @@ generates the following output:
     }
     ----
 
-    === map-3
+    === [[input_map-3]] <<input_map-3,map-3>>
 
     Description: n/a
 
@@ -346,7 +347,7 @@ generates the following output:
 
     Default: `{}`
 
-    === no-escape-default-value
+    === [[input_no-escape-default-value]] <<input_no-escape-default-value,no-escape-default-value>>
 
     Description: The description contains `something_with_underscore`. Defaults to 'VALUE_WITH_UNDERSCORE'.
 
@@ -354,7 +355,7 @@ generates the following output:
 
     Default: `"VALUE_WITH_UNDERSCORE"`
 
-    === number-1
+    === [[input_number-1]] <<input_number-1,number-1>>
 
     Description: It's number number one.
 
@@ -362,7 +363,7 @@ generates the following output:
 
     Default: `42`
 
-    === number-3
+    === [[input_number-3]] <<input_number-3,number-3>>
 
     Description: n/a
 
@@ -370,7 +371,7 @@ generates the following output:
 
     Default: `"19"`
 
-    === number-4
+    === [[input_number-4]] <<input_number-4,number-4>>
 
     Description: n/a
 
@@ -378,7 +379,7 @@ generates the following output:
 
     Default: `15.75`
 
-    === number_default_zero
+    === [[input_number_default_zero]] <<input_number_default_zero,number_default_zero>>
 
     Description: n/a
 
@@ -386,7 +387,7 @@ generates the following output:
 
     Default: `0`
 
-    === object_default_empty
+    === [[input_object_default_empty]] <<input_object_default_empty,object_default_empty>>
 
     Description: n/a
 
@@ -394,7 +395,7 @@ generates the following output:
 
     Default: `{}`
 
-    === string-1
+    === [[input_string-1]] <<input_string-1,string-1>>
 
     Description: It's string number one.
 
@@ -402,7 +403,7 @@ generates the following output:
 
     Default: `"bar"`
 
-    === string-3
+    === [[input_string-3]] <<input_string-3,string-3>>
 
     Description: n/a
 
@@ -410,7 +411,7 @@ generates the following output:
 
     Default: `""`
 
-    === string-special-chars
+    === [[input_string-special-chars]] <<input_string-special-chars,string-special-chars>>
 
     Description: n/a
 
@@ -418,7 +419,7 @@ generates the following output:
 
     Default: `"\\.<>[]{}_-"`
 
-    === string_default_empty
+    === [[input_string_default_empty]] <<input_string_default_empty,string_default_empty>>
 
     Description: n/a
 
@@ -426,7 +427,7 @@ generates the following output:
 
     Default: `""`
 
-    === string_default_null
+    === [[input_string_default_null]] <<input_string_default_null,string_default_null>>
 
     Description: n/a
 
@@ -434,7 +435,7 @@ generates the following output:
 
     Default: `null`
 
-    === with-url
+    === [[input_with-url]] <<input_with-url,with-url>>
 
     Description: The description contains url. https://www.domain.com/foo/bar_baz.html
 
@@ -446,19 +447,19 @@ generates the following output:
 
     The following outputs are exported:
 
-    === output-0.12
+    === [[output_output-0.12]] <<output_output-0.12,output-0.12>>
 
     Description: terraform 0.12 only
 
-    === output-1
+    === [[output_output-1]] <<output_output-1,output-1>>
 
     Description: It's output number one.
 
-    === output-2
+    === [[output_output-2]] <<output_output-2,output-2>>
 
     Description: It's output number two.
 
-    === unquoted
+    === [[output_unquoted]] <<output_unquoted,unquoted>>
 
     Description: It's unquoted output.
 
diff --git a/docs/reference/asciidoc-table.md b/docs/reference/asciidoc-table.md
index 1168854..07b7475 100644
--- a/docs/reference/asciidoc-table.md
+++ b/docs/reference/asciidoc-table.md
@@ -25,6 +25,7 @@ terraform-docs asciidoc table [PATH] [flags]
 ## Inherited Options
 
 ```console
+      --anchor                      create anchor links (default true)
   -c, --config string               config file name (default ".terraform-docs.yml")
       --header-from string          relative path of a file to read header from (default "main.tf")
       --hide strings                hide section [header, inputs, modules, outputs, providers, requirements, resources]
@@ -94,9 +95,9 @@ generates the following output:
     [cols="a,a",options="header,autowidth"]
     |===
     |Name |Version
-    |terraform |>= 0.12
-    |aws |>= 2.15.0
-    |random |>= 2.2.0
+    |[[requirement_terraform]] <<requirement_terraform,terraform>> |>= 0.12
+    |[[requirement_aws]] <<requirement_aws,aws>> |>= 2.15.0
+    |[[requirement_random]] <<requirement_random,random>> |>= 2.2.0
     |===
 
     == Providers
@@ -104,10 +105,10 @@ generates the following output:
     [cols="a,a",options="header,autowidth"]
     |===
     |Name |Version
-    |aws |>= 2.15.0
-    |aws.ident |>= 2.15.0
-    |null |n/a
-    |tls |n/a
+    |[[provider_aws]] <<provider_aws,aws>> |>= 2.15.0
+    |[[provider_aws.ident]] <<provider_aws.ident,aws.ident>> |>= 2.15.0
+    |[[provider_null]] <<provider_null,null>> |n/a
+    |[[provider_tls]] <<provider_tls,tls>> |n/a
     |===
 
     == Modules
@@ -115,9 +116,9 @@ generates the following output:
     [cols="a,a,a",options="header,autowidth"]
     |===
     |Name|Source|Version|
-    |bar|baz|4.5.6
-    |baz|baz|4.5.6
-    |foo|bar|1.2.3
+    |[[module_bar]] <<module_bar,bar>>|baz|4.5.6
+    |[[module_baz]] <<module_baz,baz>>|baz|4.5.6
+    |[[module_foo]] <<module_foo,foo>>|bar|1.2.3
     |===
 
     == Resources
@@ -135,31 +136,31 @@ generates the following output:
     [cols="a,a,a,a,a",options="header,autowidth"]
     |===
     |Name |Description |Type |Default |Required
-    |bool-1
+    |[[input_bool-1]] <<input_bool-1,bool-1>>
     |It's bool number one.
     |`bool`
     |`true`
     |no
 
-    |bool-2
+    |[[input_bool-2]] <<input_bool-2,bool-2>>
     |It's bool number two.
     |`bool`
     |`false`
     |no
 
-    |bool-3
+    |[[input_bool-3]] <<input_bool-3,bool-3>>
     |n/a
     |`bool`
     |`true`
     |no
 
-    |bool_default_false
+    |[[input_bool_default_false]] <<input_bool_default_false,bool_default_false>>
     |n/a
     |`bool`
     |`false`
     |no
 
-    |input-with-code-block
+    |[[input_input-with-code-block]] <<input_input-with-code-block,input-with-code-block>>
     |This is a complicated one. We need a newline.  
     And an example in a code block
     [source]
@@ -181,19 +182,19 @@ generates the following output:
 
     |no
 
-    |input-with-pipe
+    |[[input_input-with-pipe]] <<input_input-with-pipe,input-with-pipe>>
     |It includes v1 \| v2 \| v3
     |`string`
     |`"v1"`
     |no
 
-    |input_with_underscores
+    |[[input_input_with_underscores]] <<input_input_with_underscores,input_with_underscores>>
     |A variable with underscores.
     |`any`
     |n/a
     |yes
 
-    |list-1
+    |[[input_list-1]] <<input_list-1,list-1>>
     |It's list number one.
     |`list`
     |
@@ -209,25 +210,25 @@ generates the following output:
 
     |no
 
-    |list-2
+    |[[input_list-2]] <<input_list-2,list-2>>
     |It's list number two.
     |`list`
     |n/a
     |yes
 
-    |list-3
+    |[[input_list-3]] <<input_list-3,list-3>>
     |n/a
     |`list`
     |`[]`
     |no
 
-    |list_default_empty
+    |[[input_list_default_empty]] <<input_list_default_empty,list_default_empty>>
     |n/a
     |`list(string)`
     |`[]`
     |no
 
-    |long_type
+    |[[input_long_type]] <<input_long_type,long_type>>
     |This description is itself markdown.
 
     It spans over multiple lines.
@@ -269,7 +270,7 @@ generates the following output:
 
     |no
 
-    |map-1
+    |[[input_map-1]] <<input_map-1,map-1>>
     |It's map number one.
     |`map`
     |
@@ -285,109 +286,109 @@ generates the following output:
 
     |no
 
-    |map-2
+    |[[input_map-2]] <<input_map-2,map-2>>
     |It's map number two.
     |`map`
     |n/a
     |yes
 
-    |map-3
+    |[[input_map-3]] <<input_map-3,map-3>>
     |n/a
     |`map`
     |`{}`
     |no
 
-    |no-escape-default-value
+    |[[input_no-escape-default-value]] <<input_no-escape-default-value,no-escape-default-value>>
     |The description contains `something_with_underscore`. Defaults to 'VALUE_WITH_UNDERSCORE'.
     |`string`
     |`"VALUE_WITH_UNDERSCORE"`
     |no
 
-    |number-1
+    |[[input_number-1]] <<input_number-1,number-1>>
     |It's number number one.
     |`number`
     |`42`
     |no
 
-    |number-2
+    |[[input_number-2]] <<input_number-2,number-2>>
     |It's number number two.
     |`number`
     |n/a
     |yes
 
-    |number-3
+    |[[input_number-3]] <<input_number-3,number-3>>
     |n/a
     |`number`
     |`"19"`
     |no
 
-    |number-4
+    |[[input_number-4]] <<input_number-4,number-4>>
     |n/a
     |`number`
     |`15.75`
     |no
 
-    |number_default_zero
+    |[[input_number_default_zero]] <<input_number_default_zero,number_default_zero>>
     |n/a
     |`number`
     |`0`
     |no
 
-    |object_default_empty
+    |[[input_object_default_empty]] <<input_object_default_empty,object_default_empty>>
     |n/a
     |`object({})`
     |`{}`
     |no
 
-    |string-1
+    |[[input_string-1]] <<input_string-1,string-1>>
     |It's string number one.
     |`string`
     |`"bar"`
     |no
 
-    |string-2
+    |[[input_string-2]] <<input_string-2,string-2>>
     |It's string number two.
     |`string`
     |n/a
     |yes
 
-    |string-3
+    |[[input_string-3]] <<input_string-3,string-3>>
     |n/a
     |`string`
     |`""`
     |no
 
-    |string-special-chars
+    |[[input_string-special-chars]] <<input_string-special-chars,string-special-chars>>
     |n/a
     |`string`
     |`"\\.<>[]{}_-"`
     |no
 
-    |string_default_empty
+    |[[input_string_default_empty]] <<input_string_default_empty,string_default_empty>>
     |n/a
     |`string`
     |`""`
     |no
 
-    |string_default_null
+    |[[input_string_default_null]] <<input_string_default_null,string_default_null>>
     |n/a
     |`string`
     |`null`
     |no
 
-    |string_no_default
+    |[[input_string_no_default]] <<input_string_no_default,string_no_default>>
     |n/a
     |`string`
     |n/a
     |yes
 
-    |unquoted
+    |[[input_unquoted]] <<input_unquoted,unquoted>>
     |n/a
     |`any`
     |n/a
     |yes
 
-    |with-url
+    |[[input_with-url]] <<input_with-url,with-url>>
     |The description contains url. https://www.domain.com/foo/bar_baz.html
     |`string`
     |`""`
@@ -400,10 +401,10 @@ generates the following output:
     [cols="a,a",options="header,autowidth"]
     |===
     |Name |Description
-    |output-0.12 |terraform 0.12 only
-    |output-1 |It's output number one.
-    |output-2 |It's output number two.
-    |unquoted |It's unquoted output.
+    |[[output_output-0.12]] <<output_output-0.12,output-0.12>> |terraform 0.12 only
+    |[[output_output-1]] <<output_output-1,output-1>> |It's output number one.
+    |[[output_output-2]] <<output_output-2,output-2>> |It's output number two.
+    |[[output_unquoted]] <<output_unquoted,unquoted>> |It's unquoted output.
     |===
 
 [examples]: https://github.com/terraform-docs/terraform-docs/tree/master/examples
diff --git a/docs/reference/asciidoc.md b/docs/reference/asciidoc.md
index d77a3e8..d458046 100644
--- a/docs/reference/asciidoc.md
+++ b/docs/reference/asciidoc.md
@@ -19,6 +19,7 @@ terraform-docs asciidoc [PATH] [flags]
 ## Options
 
 ```console
+      --anchor       create anchor links (default true)
   -h, --help         help for asciidoc
       --indent int   indention level of AsciiDoc sections [1, 2, 3, 4, 5] (default 2)
       --required     show Required column or section (default true)
diff --git a/docs/reference/config-file.md b/docs/reference/config-file.md
index 7999f3b..2b00bb4 100644
--- a/docs/reference/config-file.md
+++ b/docs/reference/config-file.md
@@ -36,6 +36,7 @@ sort:
     - type
 
 settings:
+  anchors: true
   color: true
   escape: true
   indent: 2
diff --git a/docs/reference/markdown-document.md b/docs/reference/markdown-document.md
index cd1b266..febbe87 100644
--- a/docs/reference/markdown-document.md
+++ b/docs/reference/markdown-document.md
@@ -25,6 +25,7 @@ terraform-docs markdown document [PATH] [flags]
 ## Inherited Options
 
 ```console
+      --anchor                      create anchor links (default true)
   -c, --config string               config file name (default ".terraform-docs.yml")
       --escape                      escape special characters (default true)
       --header-from string          relative path of a file to read header from (default "main.tf")
@@ -94,41 +95,41 @@ generates the following output:
 
     The following requirements are needed by this module:
 
-    - terraform (>= 0.12)
+    - <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) (>= 0.12)
 
-    - aws (>= 2.15.0)
+    - <a name="requirement_aws"></a> [aws](#requirement\_aws) (>= 2.15.0)
 
-    - random (>= 2.2.0)
+    - <a name="requirement_random"></a> [random](#requirement\_random) (>= 2.2.0)
 
     ## Providers
 
     The following providers are used by this module:
 
-    - aws (>= 2.15.0)
+    - <a name="provider_aws"></a> [aws](#provider\_aws) (>= 2.15.0)
 
-    - aws.ident (>= 2.15.0)
+    - <a name="provider_aws.ident"></a> [aws.ident](#provider\_aws.ident) (>= 2.15.0)
 
-    - null
+    - <a name="provider_null"></a> [null](#provider\_null)
 
-    - tls
+    - <a name="provider_tls"></a> [tls](#provider\_tls)
 
     ## Modules
 
     The following Modules are called:
 
-    ### bar
+    ### <a name="module_bar"></a> [bar](#module\_bar)
 
     Source: baz
 
     Version: 4.5.6
 
-    ### baz
+    ### <a name="module_baz"></a> [baz](#module\_baz)
 
     Source: baz
 
     Version: 4.5.6
 
-    ### foo
+    ### <a name="module_foo"></a> [foo](#module\_foo)
 
     Source: bar
 
@@ -146,43 +147,43 @@ generates the following output:
 
     The following input variables are required:
 
-    ### input\_with\_underscores
+    ### <a name="input_input_with_underscores"></a> [input\_with\_underscores](#input\_input\_with\_underscores)
 
     Description: A variable with underscores.
 
     Type: `any`
 
-    ### list-2
+    ### <a name="input_list-2"></a> [list-2](#input\_list-2)
 
     Description: It's list number two.
 
     Type: `list`
 
-    ### map-2
+    ### <a name="input_map-2"></a> [map-2](#input\_map-2)
 
     Description: It's map number two.
 
     Type: `map`
 
-    ### number-2
+    ### <a name="input_number-2"></a> [number-2](#input\_number-2)
 
     Description: It's number number two.
 
     Type: `number`
 
-    ### string-2
+    ### <a name="input_string-2"></a> [string-2](#input\_string-2)
 
     Description: It's string number two.
 
     Type: `string`
 
-    ### string\_no\_default
+    ### <a name="input_string_no_default"></a> [string\_no\_default](#input\_string\_no\_default)
 
     Description: n/a
 
     Type: `string`
 
-    ### unquoted
+    ### <a name="input_unquoted"></a> [unquoted](#input\_unquoted)
 
     Description: n/a
 
@@ -192,7 +193,7 @@ generates the following output:
 
     The following input variables are optional (have default values):
 
-    ### bool-1
+    ### <a name="input_bool-1"></a> [bool-1](#input\_bool-1)
 
     Description: It's bool number one.
 
@@ -200,7 +201,7 @@ generates the following output:
 
     Default: `true`
 
-    ### bool-2
+    ### <a name="input_bool-2"></a> [bool-2](#input\_bool-2)
 
     Description: It's bool number two.
 
@@ -208,7 +209,7 @@ generates the following output:
 
     Default: `false`
 
-    ### bool-3
+    ### <a name="input_bool-3"></a> [bool-3](#input\_bool-3)
 
     Description: n/a
 
@@ -216,7 +217,7 @@ generates the following output:
 
     Default: `true`
 
-    ### bool\_default\_false
+    ### <a name="input_bool_default_false"></a> [bool\_default\_false](#input\_bool\_default\_false)
 
     Description: n/a
 
@@ -224,7 +225,7 @@ generates the following output:
 
     Default: `false`
 
-    ### input-with-code-block
+    ### <a name="input_input-with-code-block"></a> [input-with-code-block](#input\_input-with-code-block)
 
     Description: This is a complicated one. We need a newline.  
     And an example in a code block
@@ -244,7 +245,7 @@ generates the following output:
     ]
     ```
 
-    ### input-with-pipe
+    ### <a name="input_input-with-pipe"></a> [input-with-pipe](#input\_input-with-pipe)
 
     Description: It includes v1 | v2 | v3
 
@@ -252,7 +253,7 @@ generates the following output:
 
     Default: `"v1"`
 
-    ### list-1
+    ### <a name="input_list-1"></a> [list-1](#input\_list-1)
 
     Description: It's list number one.
 
@@ -268,7 +269,7 @@ generates the following output:
     ]
     ```
 
-    ### list-3
+    ### <a name="input_list-3"></a> [list-3](#input\_list-3)
 
     Description: n/a
 
@@ -276,7 +277,7 @@ generates the following output:
 
     Default: `[]`
 
-    ### list\_default\_empty
+    ### <a name="input_list_default_empty"></a> [list\_default\_empty](#input\_list\_default\_empty)
 
     Description: n/a
 
@@ -284,7 +285,7 @@ generates the following output:
 
     Default: `[]`
 
-    ### long\_type
+    ### <a name="input_long_type"></a> [long\_type](#input\_long\_type)
 
     Description: This description is itself markdown.
 
@@ -323,7 +324,7 @@ generates the following output:
     }
     ```
 
-    ### map-1
+    ### <a name="input_map-1"></a> [map-1](#input\_map-1)
 
     Description: It's map number one.
 
@@ -339,7 +340,7 @@ generates the following output:
     }
     ```
 
-    ### map-3
+    ### <a name="input_map-3"></a> [map-3](#input\_map-3)
 
     Description: n/a
 
@@ -347,7 +348,7 @@ generates the following output:
 
     Default: `{}`
 
-    ### no-escape-default-value
+    ### <a name="input_no-escape-default-value"></a> [no-escape-default-value](#input\_no-escape-default-value)
 
     Description: The description contains `something_with_underscore`. Defaults to 'VALUE\_WITH\_UNDERSCORE'.
 
@@ -355,7 +356,7 @@ generates the following output:
 
     Default: `"VALUE_WITH_UNDERSCORE"`
 
-    ### number-1
+    ### <a name="input_number-1"></a> [number-1](#input\_number-1)
 
     Description: It's number number one.
 
@@ -363,7 +364,7 @@ generates the following output:
 
     Default: `42`
 
-    ### number-3
+    ### <a name="input_number-3"></a> [number-3](#input\_number-3)
 
     Description: n/a
 
@@ -371,7 +372,7 @@ generates the following output:
 
     Default: `"19"`
 
-    ### number-4
+    ### <a name="input_number-4"></a> [number-4](#input\_number-4)
 
     Description: n/a
 
@@ -379,7 +380,7 @@ generates the following output:
 
     Default: `15.75`
 
-    ### number\_default\_zero
+    ### <a name="input_number_default_zero"></a> [number\_default\_zero](#input\_number\_default\_zero)
 
     Description: n/a
 
@@ -387,7 +388,7 @@ generates the following output:
 
     Default: `0`
 
-    ### object\_default\_empty
+    ### <a name="input_object_default_empty"></a> [object\_default\_empty](#input\_object\_default\_empty)
 
     Description: n/a
 
@@ -395,7 +396,7 @@ generates the following output:
 
     Default: `{}`
 
-    ### string-1
+    ### <a name="input_string-1"></a> [string-1](#input\_string-1)
 
     Description: It's string number one.
 
@@ -403,7 +404,7 @@ generates the following output:
 
     Default: `"bar"`
 
-    ### string-3
+    ### <a name="input_string-3"></a> [string-3](#input\_string-3)
 
     Description: n/a
 
@@ -411,7 +412,7 @@ generates the following output:
 
     Default: `""`
 
-    ### string-special-chars
+    ### <a name="input_string-special-chars"></a> [string-special-chars](#input\_string-special-chars)
 
     Description: n/a
 
@@ -419,7 +420,7 @@ generates the following output:
 
     Default: `"\\.<>[]{}_-"`
 
-    ### string\_default\_empty
+    ### <a name="input_string_default_empty"></a> [string\_default\_empty](#input\_string\_default\_empty)
 
     Description: n/a
 
@@ -427,7 +428,7 @@ generates the following output:
 
     Default: `""`
 
-    ### string\_default\_null
+    ### <a name="input_string_default_null"></a> [string\_default\_null](#input\_string\_default\_null)
 
     Description: n/a
 
@@ -435,7 +436,7 @@ generates the following output:
 
     Default: `null`
 
-    ### with-url
+    ### <a name="input_with-url"></a> [with-url](#input\_with-url)
 
     Description: The description contains url. https://www.domain.com/foo/bar_baz.html
 
@@ -447,19 +448,19 @@ generates the following output:
 
     The following outputs are exported:
 
-    ### output-0.12
+    ### <a name="output_output-0.12"></a> [output-0.12](#output\_output-0.12)
 
     Description: terraform 0.12 only
 
-    ### output-1
+    ### <a name="output_output-1"></a> [output-1](#output\_output-1)
 
     Description: It's output number one.
 
-    ### output-2
+    ### <a name="output_output-2"></a> [output-2](#output\_output-2)
 
     Description: It's output number two.
 
-    ### unquoted
+    ### <a name="output_unquoted"></a> [unquoted](#output\_unquoted)
 
     Description: It's unquoted output.
 
diff --git a/docs/reference/markdown-table.md b/docs/reference/markdown-table.md
index f387623..8fa822f 100644
--- a/docs/reference/markdown-table.md
+++ b/docs/reference/markdown-table.md
@@ -25,6 +25,7 @@ terraform-docs markdown table [PATH] [flags]
 ## Inherited Options
 
 ```console
+      --anchor                      create anchor links (default true)
   -c, --config string               config file name (default ".terraform-docs.yml")
       --escape                      escape special characters (default true)
       --header-from string          relative path of a file to read header from (default "main.tf")
@@ -94,26 +95,26 @@ generates the following output:
 
     | Name | Version |
     |------|---------|
-    | terraform | >= 0.12 |
-    | aws | >= 2.15.0 |
-    | random | >= 2.2.0 |
+    | <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 0.12 |
+    | <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 2.15.0 |
+    | <a name="requirement_random"></a> [random](#requirement\_random) | >= 2.2.0 |
 
     ## Providers
 
     | Name | Version |
     |------|---------|
-    | aws | >= 2.15.0 |
-    | aws.ident | >= 2.15.0 |
-    | null | n/a |
-    | tls | n/a |
+    | <a name="provider_aws"></a> [aws](#provider\_aws) | >= 2.15.0 |
+    | <a name="provider_aws.ident"></a> [aws.ident](#provider\_aws.ident) | >= 2.15.0 |
+    | <a name="provider_null"></a> [null](#provider\_null) | n/a |
+    | <a name="provider_tls"></a> [tls](#provider\_tls) | n/a |
 
     ## Modules
 
     | Name | Source | Version |
     |------|--------|---------|
-    | bar | baz | 4.5.6 |
-    | baz | baz | 4.5.6 |
-    | foo | bar | 1.2.3 |
+    | <a name="module_bar"></a> [bar](#module\_bar) | baz | 4.5.6 |
+    | <a name="module_baz"></a> [baz](#module\_baz) | baz | 4.5.6 |
+    | <a name="module_foo"></a> [foo](#module\_foo) | bar | 1.2.3 |
 
     ## Resources
 
@@ -127,45 +128,45 @@ generates the following output:
 
     | Name | Description | Type | Default | Required |
     |------|-------------|------|---------|:--------:|
-    | bool-1 | It's bool number one. | `bool` | `true` | no |
-    | bool-2 | It's bool number two. | `bool` | `false` | no |
-    | bool-3 | n/a | `bool` | `true` | no |
-    | bool\_default\_false | n/a | `bool` | `false` | no |
-    | input-with-code-block | This is a complicated one. We need a newline.<br>And an example in a code block<pre>default     = [<br>  "machine rack01:neptune"<br>]</pre> | `list` | <pre>[<br>  "name rack:location"<br>]</pre> | no |
-    | input-with-pipe | It includes v1 \| v2 \| v3 | `string` | `"v1"` | no |
-    | input\_with\_underscores | A variable with underscores. | `any` | n/a | yes |
-    | list-1 | It's list number one. | `list` | <pre>[<br>  "a",<br>  "b",<br>  "c"<br>]</pre> | no |
-    | list-2 | It's list number two. | `list` | n/a | yes |
-    | list-3 | n/a | `list` | `[]` | no |
-    | list\_default\_empty | n/a | `list(string)` | `[]` | no |
-    | long\_type | This description is itself markdown.<br><br>It spans over multiple lines. | <pre>object({<br>    name = string,<br>    foo  = object({ foo = string, bar = string }),<br>    bar  = object({ foo = string, bar = string }),<br>    fizz = list(string),<br>    buzz = list(string)<br>  })</pre> | <pre>{<br>  "bar": {<br>    "bar": "bar",<br>    "foo": "bar"<br>  },<br>  "buzz": [<br>    "fizz",<br>    "buzz"<br>  ],<br>  "fizz": [],<br>  "foo": {<br>    "bar": "foo",<br>    "foo": "foo"<br>  },<br>  "name": "hello"<br>}</pre> | no |
-    | map-1 | It's map number one. | `map` | <pre>{<br>  "a": 1,<br>  "b": 2,<br>  "c": 3<br>}</pre> | no |
-    | map-2 | It's map number two. | `map` | n/a | yes |
-    | map-3 | n/a | `map` | `{}` | no |
-    | no-escape-default-value | The description contains `something_with_underscore`. Defaults to 'VALUE\_WITH\_UNDERSCORE'. | `string` | `"VALUE_WITH_UNDERSCORE"` | no |
-    | number-1 | It's number number one. | `number` | `42` | no |
-    | number-2 | It's number number two. | `number` | n/a | yes |
-    | number-3 | n/a | `number` | `"19"` | no |
-    | number-4 | n/a | `number` | `15.75` | no |
-    | number\_default\_zero | n/a | `number` | `0` | no |
-    | object\_default\_empty | n/a | `object({})` | `{}` | no |
-    | string-1 | It's string number one. | `string` | `"bar"` | no |
-    | string-2 | It's string number two. | `string` | n/a | yes |
-    | string-3 | n/a | `string` | `""` | no |
-    | string-special-chars | n/a | `string` | `"\\.<>[]{}_-"` | no |
-    | string\_default\_empty | n/a | `string` | `""` | no |
-    | string\_default\_null | n/a | `string` | `null` | no |
-    | string\_no\_default | n/a | `string` | n/a | yes |
-    | unquoted | n/a | `any` | n/a | yes |
-    | with-url | The description contains url. https://www.domain.com/foo/bar_baz.html | `string` | `""` | no |
+    | <a name="input_bool-1"></a> [bool-1](#input\_bool-1) | It's bool number one. | `bool` | `true` | no |
+    | <a name="input_bool-2"></a> [bool-2](#input\_bool-2) | It's bool number two. | `bool` | `false` | no |
+    | <a name="input_bool-3"></a> [bool-3](#input\_bool-3) | n/a | `bool` | `true` | no |
+    | <a name="input_bool_default_false"></a> [bool\_default\_false](#input\_bool\_default\_false) | n/a | `bool` | `false` | no |
+    | <a name="input_input-with-code-block"></a> [input-with-code-block](#input\_input-with-code-block) | This is a complicated one. We need a newline.<br>And an example in a code block<pre>default     = [<br>  "machine rack01:neptune"<br>]</pre> | `list` | <pre>[<br>  "name rack:location"<br>]</pre> | no |
+    | <a name="input_input-with-pipe"></a> [input-with-pipe](#input\_input-with-pipe) | It includes v1 \| v2 \| v3 | `string` | `"v1"` | no |
+    | <a name="input_input_with_underscores"></a> [input\_with\_underscores](#input\_input\_with\_underscores) | A variable with underscores. | `any` | n/a | yes |
+    | <a name="input_list-1"></a> [list-1](#input\_list-1) | It's list number one. | `list` | <pre>[<br>  "a",<br>  "b",<br>  "c"<br>]</pre> | no |
+    | <a name="input_list-2"></a> [list-2](#input\_list-2) | It's list number two. | `list` | n/a | yes |
+    | <a name="input_list-3"></a> [list-3](#input\_list-3) | n/a | `list` | `[]` | no |
+    | <a name="input_list_default_empty"></a> [list\_default\_empty](#input\_list\_default\_empty) | n/a | `list(string)` | `[]` | no |
+    | <a name="input_long_type"></a> [long\_type](#input\_long\_type) | This description is itself markdown.<br><br>It spans over multiple lines. | <pre>object({<br>    name = string,<br>    foo  = object({ foo = string, bar = string }),<br>    bar  = object({ foo = string, bar = string }),<br>    fizz = list(string),<br>    buzz = list(string)<br>  })</pre> | <pre>{<br>  "bar": {<br>    "bar": "bar",<br>    "foo": "bar"<br>  },<br>  "buzz": [<br>    "fizz",<br>    "buzz"<br>  ],<br>  "fizz": [],<br>  "foo": {<br>    "bar": "foo",<br>    "foo": "foo"<br>  },<br>  "name": "hello"<br>}</pre> | no |
+    | <a name="input_map-1"></a> [map-1](#input\_map-1) | It's map number one. | `map` | <pre>{<br>  "a": 1,<br>  "b": 2,<br>  "c": 3<br>}</pre> | no |
+    | <a name="input_map-2"></a> [map-2](#input\_map-2) | It's map number two. | `map` | n/a | yes |
+    | <a name="input_map-3"></a> [map-3](#input\_map-3) | n/a | `map` | `{}` | no |
+    | <a name="input_no-escape-default-value"></a> [no-escape-default-value](#input\_no-escape-default-value) | The description contains `something_with_underscore`. Defaults to 'VALUE\_WITH\_UNDERSCORE'. | `string` | `"VALUE_WITH_UNDERSCORE"` | no |
+    | <a name="input_number-1"></a> [number-1](#input\_number-1) | It's number number one. | `number` | `42` | no |
+    | <a name="input_number-2"></a> [number-2](#input\_number-2) | It's number number two. | `number` | n/a | yes |
+    | <a name="input_number-3"></a> [number-3](#input\_number-3) | n/a | `number` | `"19"` | no |
+    | <a name="input_number-4"></a> [number-4](#input\_number-4) | n/a | `number` | `15.75` | no |
+    | <a name="input_number_default_zero"></a> [number\_default\_zero](#input\_number\_default\_zero) | n/a | `number` | `0` | no |
+    | <a name="input_object_default_empty"></a> [object\_default\_empty](#input\_object\_default\_empty) | n/a | `object({})` | `{}` | no |
+    | <a name="input_string-1"></a> [string-1](#input\_string-1) | It's string number one. | `string` | `"bar"` | no |
+    | <a name="input_string-2"></a> [string-2](#input\_string-2) | It's string number two. | `string` | n/a | yes |
+    | <a name="input_string-3"></a> [string-3](#input\_string-3) | n/a | `string` | `""` | no |
+    | <a name="input_string-special-chars"></a> [string-special-chars](#input\_string-special-chars) | n/a | `string` | `"\\.<>[]{}_-"` | no |
+    | <a name="input_string_default_empty"></a> [string\_default\_empty](#input\_string\_default\_empty) | n/a | `string` | `""` | no |
+    | <a name="input_string_default_null"></a> [string\_default\_null](#input\_string\_default\_null) | n/a | `string` | `null` | no |
+    | <a name="input_string_no_default"></a> [string\_no\_default](#input\_string\_no\_default) | n/a | `string` | n/a | yes |
+    | <a name="input_unquoted"></a> [unquoted](#input\_unquoted) | n/a | `any` | n/a | yes |
+    | <a name="input_with-url"></a> [with-url](#input\_with-url) | The description contains url. https://www.domain.com/foo/bar_baz.html | `string` | `""` | no |
 
     ## Outputs
 
     | Name | Description |
     |------|-------------|
-    | output-0.12 | terraform 0.12 only |
-    | output-1 | It's output number one. |
-    | output-2 | It's output number two. |
-    | unquoted | It's unquoted output. |
+    | <a name="output_output-0.12"></a> [output-0.12](#output\_output-0.12) | terraform 0.12 only |
+    | <a name="output_output-1"></a> [output-1](#output\_output-1) | It's output number one. |
+    | <a name="output_output-2"></a> [output-2](#output\_output-2) | It's output number two. |
+    | <a name="output_unquoted"></a> [unquoted](#output\_unquoted) | It's unquoted output. |
 
 [examples]: https://github.com/terraform-docs/terraform-docs/tree/master/examples
diff --git a/docs/reference/markdown.md b/docs/reference/markdown.md
index d0c7f64..4142fe2 100644
--- a/docs/reference/markdown.md
+++ b/docs/reference/markdown.md
@@ -19,6 +19,7 @@ terraform-docs markdown [PATH] [flags]
 ## Options
 
 ```console
+      --anchor       create anchor links (default true)
       --escape       escape special characters (default true)
   -h, --help         help for markdown
       --indent int   indention level of Markdown sections [1, 2, 3, 4, 5] (default 2)
diff --git a/internal/cli/config.go b/internal/cli/config.go
index 1782e10..476e302 100644
--- a/internal/cli/config.go
+++ b/internal/cli/config.go
@@ -158,6 +158,7 @@ func (s *sort) validate() error {
 }
 
 type settings struct {
+	Anchor    bool `yaml:"anchor"`
 	Color     bool `yaml:"color"`
 	Escape    bool `yaml:"escape"`
 	Indent    int  `yaml:"indent"`
@@ -167,6 +168,7 @@ type settings struct {
 
 func defaultSettings() settings {
 	return settings{
+		Anchor:    true,
 		Color:     true,
 		Escape:    true,
 		Indent:    2,
@@ -290,6 +292,7 @@ func (c *Config) extract() (*print.Settings, *terraform.Options) {
 	settings.ShowColor = c.Settings.Color
 	settings.ShowRequired = c.Settings.Required
 	settings.ShowSensitivity = c.Settings.Sensitive
+	settings.ShowAnchor = c.Settings.Anchor
 
 	return settings, options
 }
diff --git a/internal/cli/reader.go b/internal/cli/reader.go
index 5e50f2a..6508d80 100644
--- a/internal/cli/reader.go
+++ b/internal/cli/reader.go
@@ -93,7 +93,7 @@ func (c *cfgreader) parse() error {
 			if err := c.overrideValue(mapping[flag], &c.config.OutputValues, &c.overrides.OutputValues); err != nil {
 				return err
 			}
-		case "color", "escape", "indent", "required", "sensitive":
+		case "anchor", "color", "escape", "indent", "required", "sensitive":
 			if err := c.overrideValue(flag, &c.config.Settings, &c.overrides.Settings); err != nil {
 				return err
 			}
diff --git a/internal/format/templates/asciidoc_document.tmpl b/internal/format/templates/asciidoc_document.tmpl
index dfee649..fc01d1b 100644
--- a/internal/format/templates/asciidoc_document.tmpl
+++ b/internal/format/templates/asciidoc_document.tmpl
@@ -13,7 +13,7 @@
         The following requirements are needed by this module:
         {{- range .Module.Requirements }}
             {{ $version := ternary (tostring .Version) (printf " (%s)" .Version) "" }}
-            - {{ name .Name }}{{ $version }}
+            - {{ anchorNameAsciidoc "requirement" .Name }}{{ $version }}
         {{- end }}
     {{ end }}
 {{ end -}}
@@ -26,7 +26,7 @@
         The following providers are used by this module:
         {{- range .Module.Providers }}
             {{ $version := ternary (tostring .Version) (printf " (%s)" .Version) "" }}
-            - {{ name .FullName }}{{ $version }}
+            - {{ anchorNameAsciidoc "provider" .FullName }}{{ $version }}
         {{- end }}
     {{ end }}
 {{ end -}}
@@ -39,7 +39,7 @@
         The following Modules are called:
         {{- range .Module.ModuleCalls }}
 
-            {{ indent 1 "=" }} {{ name .Name }}
+            {{ indent 1 "=" }} {{ anchorNameAsciidoc "module" .Name }}
 
             Source: {{ .Source }}
 
@@ -73,7 +73,7 @@
             The following input variables are required:
             {{- range .Module.RequiredInputs }}
                 {{ printf "\n" }}
-                {{ indent 1 "=" }} {{ name .Name }}
+                {{ indent 1 "=" }} {{ anchorNameAsciidoc "input" .Name }}
 
                 Description: {{ tostring .Description | sanitizeDoc }}
 
@@ -91,7 +91,7 @@
             The following input variables are optional (have default values):
             {{- range .Module.OptionalInputs }}
                 {{ printf "\n" }}
-                {{ indent 1 "=" }} {{ name .Name }}
+                {{ indent 1 "=" }} {{ anchorNameAsciidoc "input" .Name }}
 
                 Description: {{ tostring .Description | sanitizeDoc }}
 
@@ -110,7 +110,7 @@
             The following input variables are supported:
             {{- range .Module.Inputs }}
                 {{ printf "\n" }}
-                {{ indent 1 "=" }} {{ name .Name }}
+                {{ indent 1 "=" }} {{ anchorNameAsciidoc "input" .Name }}
 
                 Description: {{ tostring .Description | sanitizeDoc }}
 
@@ -132,7 +132,7 @@
         The following outputs are exported:
         {{- range .Module.Outputs }}
 
-            {{ indent 1 "=" }} {{ name .Name }}
+            {{ indent 1 "=" }} {{ anchorNameAsciidoc "output" .Name }}
 
             Description: {{ tostring .Description | sanitizeDoc }}
 
diff --git a/internal/format/templates/asciidoc_table.tmpl b/internal/format/templates/asciidoc_table.tmpl
index 1fcb54b..d65e5da 100644
--- a/internal/format/templates/asciidoc_table.tmpl
+++ b/internal/format/templates/asciidoc_table.tmpl
@@ -14,7 +14,7 @@
         |===
         |Name |Version
         {{- range .Module.Requirements }}
-            |{{ .Name }} |{{ tostring .Version | default "n/a" }}
+            |{{ anchorNameAsciidoc "requirement" .Name }} |{{ tostring .Version | default "n/a" }}
         {{- end }}
         |===
     {{ end }}
@@ -29,7 +29,7 @@
         |===
         |Name |Version
         {{- range .Module.Providers }}
-            |{{ .FullName }} |{{ tostring .Version | default "n/a" }}
+            |{{ anchorNameAsciidoc "provider" .FullName }} |{{ tostring .Version | default "n/a" }}
         {{- end }}
         |===
     {{ end }}
@@ -44,7 +44,7 @@
         |===
         |Name|Source|Version|
         {{- range .Module.ModuleCalls }}
-            |{{ .Name }}|{{ .Source }}|{{ .Version }}
+            |{{ anchorNameAsciidoc "module" .Name }}|{{ .Source }}|{{ .Version }}
         {{- end }}
         |===
     {{ end }}
@@ -78,7 +78,7 @@
         |===
         |Name |Description |Type |Default{{ if .Settings.ShowRequired }} |Required{{ end }}
         {{- range .Module.Inputs }}
-            |{{ .Name }}
+            |{{ anchorNameAsciidoc "input" .Name }}
             |{{ tostring .Description | sanitizeAsciidocTbl }}
             |{{ tostring .Type | type | sanitizeAsciidocTbl }}
             |{{ value .GetValue | sanitizeAsciidocTbl }}
@@ -97,7 +97,7 @@
         |===
         |Name |Description{{ if .Settings.OutputValues }} |Value{{ if $.Settings.ShowSensitivity }} |Sensitive{{ end }}{{ end }}
         {{- range .Module.Outputs }}
-            |{{ .Name }} |{{ tostring .Description | sanitizeAsciidocTbl }}
+            |{{ anchorNameAsciidoc "output" .Name }} |{{ tostring .Description | sanitizeAsciidocTbl }}
             {{- if $.Settings.OutputValues -}}
                 {{- $sensitive := ternary .Sensitive "<sensitive>" .GetValue -}}
                 {{ printf " " }}|{{ value $sensitive }}
diff --git a/internal/format/templates/markdown_document.tmpl b/internal/format/templates/markdown_document.tmpl
index 4f49baa..801f916 100644
--- a/internal/format/templates/markdown_document.tmpl
+++ b/internal/format/templates/markdown_document.tmpl
@@ -13,7 +13,7 @@
         The following requirements are needed by this module:
         {{- range .Module.Requirements }}
             {{ $version := ternary (tostring .Version) (printf " (%s)" .Version) "" }}
-            - {{ name .Name }}{{ $version }}
+            - {{ anchorName "requirement" .Name }}{{ $version }}
         {{- end }}
     {{ end }}
 {{ end -}}
@@ -26,7 +26,7 @@
         The following providers are used by this module:
         {{- range .Module.Providers }}
             {{ $version := ternary (tostring .Version) (printf " (%s)" .Version) "" }}
-            - {{ name .FullName }}{{ $version }}
+            - {{ anchorName "provider" .FullName }}{{ $version }}
         {{- end }}
     {{ end }}
 {{ end -}}
@@ -39,7 +39,7 @@
         The following Modules are called:
         {{- range .Module.ModuleCalls }}
 
-            {{ indent 1 "#" }} {{ name .Name }}
+            {{ indent 1 "#" }} {{ anchorName "module" .Name }}
 
             Source: {{ .Source }}
 
@@ -74,7 +74,7 @@
             The following input variables are required:
             {{- range .Module.RequiredInputs }}
                 {{ printf "\n" }}
-                {{ indent 1 "#" }} {{ name .Name }}
+                {{ indent 1 "#" }} {{ anchorName "input" .Name }}
 
                 Description: {{ tostring .Description | sanitizeDoc }}
 
@@ -92,7 +92,7 @@
             The following input variables are optional (have default values):
             {{- range .Module.OptionalInputs }}
                 {{ printf "\n" }}
-                {{ indent 1 "#" }} {{ name .Name }}
+                {{ indent 1 "#" }} {{ anchorName "input" .Name }}
 
                 Description: {{ tostring .Description | sanitizeDoc }}
 
@@ -111,7 +111,7 @@
             The following input variables are supported:
             {{- range .Module.Inputs }}
                 {{ printf "\n" }}
-                {{ indent 1 "#" }} {{ name .Name }}
+                {{ indent 1 "#" }} {{ anchorName "input" .Name }}
 
                 Description: {{ tostring .Description | sanitizeDoc }}
 
@@ -133,7 +133,7 @@
         The following outputs are exported:
         {{- range .Module.Outputs }}
 
-            {{ indent 1 "#" }} {{ name .Name }}
+            {{ indent 1 "#" }} {{ anchorName "output" .Name }}
 
             Description: {{ tostring .Description | sanitizeDoc }}
 
diff --git a/internal/format/templates/markdown_table.tmpl b/internal/format/templates/markdown_table.tmpl
index 09fa11b..6d081ff 100644
--- a/internal/format/templates/markdown_table.tmpl
+++ b/internal/format/templates/markdown_table.tmpl
@@ -13,7 +13,7 @@
         | Name | Version |
         |------|---------|
         {{- range .Module.Requirements }}
-            | {{ name .Name }} | {{ tostring .Version | default "n/a" }} |
+            | {{ anchorName "requirement" .Name }} | {{ tostring .Version | default "n/a" }} |
         {{- end }}
     {{ end }}
 {{ end -}}
@@ -26,7 +26,7 @@
         | Name | Version |
         |------|---------|
         {{- range .Module.Providers }}
-            | {{ name .FullName }} | {{ tostring .Version | default "n/a" }} |
+            | {{ anchorName "provider" .FullName }} | {{ tostring .Version | default "n/a" }} |
         {{- end }}
     {{ end }}
 {{ end -}}
@@ -39,7 +39,7 @@
         | Name | Source | Version |
         |------|--------|---------|
         {{- range .Module.ModuleCalls }}
-            | {{ .Name }} | {{ .Source }} | {{ .Version }} |
+            | {{ anchorName "module" .Name }} | {{ .Source }} | {{ .Version }} |
         {{- end }}
     {{ end }}
 {{ end -}}
@@ -69,7 +69,7 @@
         | Name | Description | Type | Default |{{ if .Settings.ShowRequired }} Required |{{ end }}
         |------|-------------|------|---------|{{ if .Settings.ShowRequired }}:--------:|{{ end }}
         {{- range .Module.Inputs }}
-            | {{ name .Name }} | {{ tostring .Description | sanitizeTbl }} | {{ tostring .Type | type | sanitizeTbl }} | {{ value .GetValue | sanitizeTbl }} |
+            | {{ anchorName "input" .Name }} | {{ tostring .Description | sanitizeTbl }} | {{ tostring .Type | type | sanitizeTbl }} | {{ value .GetValue | sanitizeTbl }} |
             {{- if $.Settings.ShowRequired -}}
                 {{ printf " " }}{{ ternary .Required "yes" "no" }} |
             {{- end -}}
@@ -85,7 +85,7 @@
         | Name | Description |{{ if .Settings.OutputValues }} Value |{{ if $.Settings.ShowSensitivity }} Sensitive |{{ end }}{{ end }}
         |------|-------------|{{ if .Settings.OutputValues }}-------|{{ if $.Settings.ShowSensitivity }}:---------:|{{ end }}{{ end }}
         {{- range .Module.Outputs }}
-            | {{ name .Name }} | {{ tostring .Description | sanitizeTbl }} |
+            | {{ anchorName "output" .Name }} | {{ tostring .Description | sanitizeTbl }} |
             {{- if $.Settings.OutputValues -}}
                 {{- $sensitive := ternary .Sensitive "<sensitive>" .GetValue -}}
                 {{ printf " " }}{{ value $sensitive | sanitizeTbl }} |
diff --git a/internal/print/settings.go b/internal/print/settings.go
index aca5f3c..69ad69c 100644
--- a/internal/print/settings.go
+++ b/internal/print/settings.go
@@ -34,6 +34,12 @@ type Settings struct {
 	// scope: Global
 	OutputValues bool
 
+	// ShowAnchor show html anchor
+	//
+	// default: true
+	// scope: Asciidoc, Markdown
+	ShowAnchor bool
+
 	// ShowColor print "colorized" version of result in the terminal
 	//
 	// default: true
@@ -101,6 +107,7 @@ func DefaultSettings() *Settings {
 		EscapeCharacters: true,
 		IndentLevel:      2,
 		OutputValues:     false,
+		ShowAnchor:       true,
 		ShowColor:        true,
 		ShowHeader:       true,
 		ShowInputs:       true,
diff --git a/internal/template/anchor.go b/internal/template/anchor.go
new file mode 100644
index 0000000..362bad5
--- /dev/null
+++ b/internal/template/anchor.go
@@ -0,0 +1,42 @@
+/*
+Copyright 2021 The terraform-docs Authors.
+
+Licensed under the MIT license (the "License"); you may not
+use this file except in compliance with the License.
+
+You may obtain a copy of the License at the LICENSE file in
+the root directory of this source tree.
+*/
+
+package template
+
+import (
+	"fmt"
+
+	"github.com/terraform-docs/terraform-docs/internal/print"
+)
+
+// createAnchor
+func createAnchorMarkdown(t string, s string, settings *print.Settings) string {
+	sanitizedName := sanitizeName(s, settings)
+	if settings.ShowAnchor {
+		anchorName := fmt.Sprintf("%s_%s", t, s)
+		sanitizedAnchorName := sanitizeName(anchorName, settings)
+		// the <a> link is purposely not sanitized as this breaks markdown formatting
+		return fmt.Sprintf("<a name=\"%s\"></a> [%s](#%s)", anchorName, sanitizedName, sanitizedAnchorName)
+	}
+
+	return sanitizedName
+}
+
+// createAnchorAsciidoc
+func createAnchorAsciidoc(t string, s string, settings *print.Settings) string {
+	sanitizedName := sanitizeName(s, settings)
+	if settings.ShowAnchor {
+		anchorName := fmt.Sprintf("%s_%s", t, s)
+		sanitizedAnchorName := sanitizeName(anchorName, settings)
+		return fmt.Sprintf("[[%s]] <<%s,%s>>", sanitizedAnchorName, sanitizedAnchorName, sanitizedName)
+	}
+
+	return sanitizedName
+}
diff --git a/internal/template/template.go b/internal/template/template.go
index aeb3b76..4947071 100644
--- a/internal/template/template.go
+++ b/internal/template/template.go
@@ -58,6 +58,12 @@ func New(settings *print.Settings, items ...*Item) *Template {
 		"sanitizeAsciidocTbl": func(s string) string {
 			return sanitizeItemForAsciidocTable(s, settings)
 		},
+		"anchorName": func(s string, t string) string {
+			return createAnchorMarkdown(s, t, settings)
+		},
+		"anchorNameAsciidoc": func(s string, t string) string {
+			return createAnchorAsciidoc(s, t, settings)
+		},
 	})
 
 	return &Template{


Test patch:
diff --git a/internal/format/asciidoc_document_test.go b/internal/format/asciidoc_document_test.go
index f9953c5..9f3bd16 100644
--- a/internal/format/asciidoc_document_test.go
+++ b/internal/format/asciidoc_document_test.go
@@ -53,6 +53,14 @@ func TestAsciidocDocument(t *testing.T) {
 			),
 			options: terraform.Options{},
 		},
+		"WithAnchor": {
+			settings: testutil.WithSections(
+				print.Settings{
+					ShowAnchor: true,
+				},
+			),
+			options: terraform.Options{},
+		},
 		"IndentationOfFour": {
 			settings: testutil.WithSections(
 				print.Settings{
diff --git a/internal/format/asciidoc_table_test.go b/internal/format/asciidoc_table_test.go
index 33a3f10..945a0fc 100644
--- a/internal/format/asciidoc_table_test.go
+++ b/internal/format/asciidoc_table_test.go
@@ -53,6 +53,14 @@ func TestAsciidocTable(t *testing.T) {
 			),
 			options: terraform.Options{},
 		},
+		"WithAnchor": {
+			settings: testutil.WithSections(
+				print.Settings{
+					ShowAnchor: true,
+				},
+			),
+			options: terraform.Options{},
+		},
 		"IndentationOfFour": {
 			settings: testutil.WithSections(
 				print.Settings{
diff --git a/internal/format/markdown_document_test.go b/internal/format/markdown_document_test.go
index 6950ae4..2ed113a 100644
--- a/internal/format/markdown_document_test.go
+++ b/internal/format/markdown_document_test.go
@@ -53,6 +53,14 @@ func TestMarkdownDocument(t *testing.T) {
 			),
 			options: terraform.Options{},
 		},
+		"WithAnchor": {
+			settings: testutil.WithSections(
+				print.Settings{
+					ShowAnchor: true,
+				},
+			),
+			options: terraform.Options{},
+		},
 		"EscapeCharacters": {
 			settings: testutil.WithSections(
 				print.Settings{
diff --git a/internal/format/markdown_table_test.go b/internal/format/markdown_table_test.go
index 80ab358..a672de9 100644
--- a/internal/format/markdown_table_test.go
+++ b/internal/format/markdown_table_test.go
@@ -53,6 +53,14 @@ func TestMarkdownTable(t *testing.T) {
 			),
 			options: terraform.Options{},
 		},
+		"WithAnchor": {
+			settings: testutil.WithSections(
+				print.Settings{
+					ShowAnchor: true,
+				},
+			),
+			options: terraform.Options{},
+		},
 		"EscapeCharacters": {
 			settings: testutil.WithSections(
 				print.Settings{
diff --git a/internal/format/testdata/asciidoc/document-WithAnchor.golden b/internal/format/testdata/asciidoc/document-WithAnchor.golden
new file mode 100644
index 0000000..901c5c6
--- /dev/null
+++ b/internal/format/testdata/asciidoc/document-WithAnchor.golden
@@ -0,0 +1,420 @@
+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 |
+
+== Requirements
+
+The following requirements are needed by this module:
+
+- [[requirement_terraform]] <<requirement_terraform,terraform>> (>= 0.12)
+
+- [[requirement_aws]] <<requirement_aws,aws>> (>= 2.15.0)
+
+- [[requirement_random]] <<requirement_random,random>> (>= 2.2.0)
+
+== Providers
+
+The following providers are used by this module:
+
+- [[provider_tls]] <<provider_tls,tls>>
+
+- [[provider_aws]] <<provider_aws,aws>> (>= 2.15.0)
+
+- [[provider_aws.ident]] <<provider_aws.ident,aws.ident>> (>= 2.15.0)
+
+- [[provider_null]] <<provider_null,null>>
+
+== Modules
+
+The following Modules are called:
+
+=== [[module_foo]] <<module_foo,foo>>
+
+Source: bar
+
+Version: 1.2.3
+
+=== [[module_bar]] <<module_bar,bar>>
+
+Source: baz
+
+Version: 4.5.6
+
+=== [[module_baz]] <<module_baz,baz>>
+
+Source: baz
+
+Version: 4.5.6
+
+== Resources
+
+The following resources are used by this module:
+
+- https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity[aws_caller_identity]
+- https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource[null_resource]
+- https://registry.terraform.io/providers/hashicorp/tls/latest/docs/resources/private_key[tls_private_key]
+
+== Inputs
+
+The following input variables are supported:
+
+=== [[input_unquoted]] <<input_unquoted,unquoted>>
+
+Description: n/a
+
+Type: `any`
+
+Default: n/a
+
+=== [[input_bool-3]] <<input_bool-3,bool-3>>
+
+Description: n/a
+
+Type: `bool`
+
+Default: `true`
+
+=== [[input_bool-2]] <<input_bool-2,bool-2>>
+
+Description: It's bool number two.
+
+Type: `bool`
+
+Default: `false`
+
+=== [[input_bool-1]] <<input_bool-1,bool-1>>
+
+Description: It's bool number one.
+
+Type: `bool`
+
+Default: `true`
+
+=== [[input_string-3]] <<input_string-3,string-3>>
+
+Description: n/a
+
+Type: `string`
+
+Default: `""`
+
+=== [[input_string-2]] <<input_string-2,string-2>>
+
+Description: It's string number two.
+
+Type: `string`
+
+Default: n/a
+
+=== [[input_string-1]] <<input_string-1,string-1>>
+
+Description: It's string number one.
+
+Type: `string`
+
+Default: `"bar"`
+
+=== [[input_string-special-chars]] <<input_string-special-chars,string-special-chars>>
+
+Description: n/a
+
+Type: `string`
+
+Default: `"\\.<>[]{}_-"`
+
+=== [[input_number-3]] <<input_number-3,number-3>>
+
+Description: n/a
+
+Type: `number`
+
+Default: `"19"`
+
+=== [[input_number-4]] <<input_number-4,number-4>>
+
+Description: n/a
+
+Type: `number`
+
+Default: `15.75`
+
+=== [[input_number-2]] <<input_number-2,number-2>>
+
+Description: It's number number two.
+
+Type: `number`
+
+Default: n/a
+
+=== [[input_number-1]] <<input_number-1,number-1>>
+
+Description: It's number number one.
+
+Type: `number`
+
+Default: `42`
+
+=== [[input_map-3]] <<input_map-3,map-3>>
+
+Description: n/a
+
+Type: `map`
+
+Default: `{}`
+
+=== [[input_map-2]] <<input_map-2,map-2>>
+
+Description: It's map number two.
+
+Type: `map`
+
+Default: n/a
+
+=== [[input_map-1]] <<input_map-1,map-1>>
+
+Description: It's map number one.
+
+Type: `map`
+
+Default:
+[source,json]
+----
+{
+  "a": 1,
+  "b": 2,
+  "c": 3
+}
+----
+
+=== [[input_list-3]] <<input_list-3,list-3>>
+
+Description: n/a
+
+Type: `list`
+
+Default: `[]`
+
+=== [[input_list-2]] <<input_list-2,list-2>>
+
+Description: It's list number two.
+
+Type: `list`
+
+Default: n/a
+
+=== [[input_list-1]] <<input_list-1,list-1>>
+
+Description: It's list number one.
+
+Type: `list`
+
+Default:
+[source,json]
+----
+[
+  "a",
+  "b",
+  "c"
+]
+----
+
+=== [[input_input_with_underscores]] <<input_input_with_underscores,input_with_underscores>>
+
+Description: A variable with underscores.
+
+Type: `any`
+
+Default: n/a
+
+=== [[input_input-with-pipe]] <<input_input-with-pipe,input-with-pipe>>
+
+Description: It includes v1 | v2 | v3
+
+Type: `string`
+
+Default: `"v1"`
+
+=== [[input_input-with-code-block]] <<input_input-with-code-block,input-with-code-block>>
+
+Description: This is a complicated one. We need a newline.  
+And an example in a code block
+```
+default     = [
+  "machine rack01:neptune"
+]
+```
+
+Type: `list`
+
+Default:
+[source,json]
+----
+[
+  "name rack:location"
+]
+----
+
+=== [[input_long_type]] <<input_long_type,long_type>>
+
+Description: This description is itself markdown.
+
+It spans over multiple lines.
+
+Type:
+[source,hcl]
+----
+object({
+    name = string,
+    foo  = object({ foo = string, bar = string }),
+    bar  = object({ foo = string, bar = string }),
+    fizz = list(string),
+    buzz = list(string)
+  })
+----
+
+Default:
+[source,json]
+----
+{
+  "bar": {
+    "bar": "bar",
+    "foo": "bar"
+  },
+  "buzz": [
+    "fizz",
+    "buzz"
+  ],
+  "fizz": [],
+  "foo": {
+    "bar": "foo",
+    "foo": "foo"
+  },
+  "name": "hello"
+}
+----
+
+=== [[input_no-escape-default-value]] <<input_no-escape-default-value,no-escape-default-value>>
+
+Description: The description contains `something_with_underscore`. Defaults to 'VALUE_WITH_UNDERSCORE'.
+
+Type: `string`
+
+Default: `"VALUE_WITH_UNDERSCORE"`
+
+=== [[input_with-url]] <<input_with-url,with-url>>
+
+Description: The description contains url. https://www.domain.com/foo/bar_baz.html
+
+Type: `string`
+
+Default: `""`
+
+=== [[input_string_default_empty]] <<input_string_default_empty,string_default_empty>>
+
+Description: n/a
+
+Type: `string`
+
+Default: `""`
+
+=== [[input_string_default_null]] <<input_string_default_null,string_default_null>>
+
+Description: n/a
+
+Type: `string`
+
+Default: `null`
+
+=== [[input_string_no_default]] <<input_string_no_default,string_no_default>>
+
+Description: n/a
+
+Type: `string`
+
+Default: n/a
+
+=== [[input_number_default_zero]] <<input_number_default_zero,number_default_zero>>
+
+Description: n/a
+
+Type: `number`
+
+Default: `0`
+
+=== [[input_bool_default_false]] <<input_bool_default_false,bool_default_false>>
+
+Description: n/a
+
+Type: `bool`
+
+Default: `false`
+
+=== [[input_list_default_empty]] <<input_list_default_empty,list_default_empty>>
+
+Description: n/a
+
+Type: `list(string)`
+
+Default: `[]`
+
+=== [[input_object_default_empty]] <<input_object_default_empty,object_default_empty>>
+
+Description: n/a
+
+Type: `object({})`
+
+Default: `{}`
+
+== Outputs
+
+The following outputs are exported:
+
+=== [[output_unquoted]] <<output_unquoted,unquoted>>
+
+Description: It's unquoted output.
+
+=== [[output_output-2]] <<output_output-2,output-2>>
+
+Description: It's output number two.
+
+=== [[output_output-1]] <<output_output-1,output-1>>
+
+Description: It's output number one.
+
+=== [[output_output-0.12]] <<output_output-0.12,output-0.12>>
+
+Description: terraform 0.12 only
\ No newline at end of file
diff --git a/internal/format/testdata/asciidoc/table-WithAnchor.golden b/internal/format/testdata/asciidoc/table-WithAnchor.golden
new file mode 100644
index 0000000..27d3640
--- /dev/null
+++ b/internal/format/testdata/asciidoc/table-WithAnchor.golden
@@ -0,0 +1,319 @@
+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 |
+
+== Requirements
+
+[cols="a,a",options="header,autowidth"]
+|===
+|Name |Version
+|[[requirement_terraform]] <<requirement_terraform,terraform>> |>= 0.12
+|[[requirement_aws]] <<requirement_aws,aws>> |>= 2.15.0
+|[[requirement_random]] <<requirement_random,random>> |>= 2.2.0
+|===
+
+== Providers
+
+[cols="a,a",options="header,autowidth"]
+|===
+|Name |Version
+|[[provider_tls]] <<provider_tls,tls>> |n/a
+|[[provider_aws]] <<provider_aws,aws>> |>= 2.15.0
+|[[provider_aws.ident]] <<provider_aws.ident,aws.ident>> |>= 2.15.0
+|[[provider_null]] <<provider_null,null>> |n/a
+|===
+
+== Modules
+
+[cols="a,a,a",options="header,autowidth"]
+|===
+|Name|Source|Version|
+|[[module_foo]] <<module_foo,foo>>|bar|1.2.3
+|[[module_bar]] <<module_bar,bar>>|baz|4.5.6
+|[[module_baz]] <<module_baz,baz>>|baz|4.5.6
+|===
+
+== Resources
+
+[cols="a",options="header,autowidth"]
+|===
+|Name
+|https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity[aws_caller_identity]
+|https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource[null_resource]
+|https://registry.terraform.io/providers/hashicorp/tls/latest/docs/resources/private_key[tls_private_key]
+|===
+
+== Inputs
+
+[cols="a,a,a,a",options="header,autowidth"]
+|===
+|Name |Description |Type |Default
+|[[input_unquoted]] <<input_unquoted,unquoted>>
+|n/a
+|`any`
+|n/a
+
+|[[input_bool-3]] <<input_bool-3,bool-3>>
+|n/a
+|`bool`
+|`true`
+
+|[[input_bool-2]] <<input_bool-2,bool-2>>
+|It's bool number two.
+|`bool`
+|`false`
+
+|[[input_bool-1]] <<input_bool-1,bool-1>>
+|It's bool number one.
+|`bool`
+|`true`
+
+|[[input_string-3]] <<input_string-3,string-3>>
+|n/a
+|`string`
+|`""`
+
+|[[input_string-2]] <<input_string-2,string-2>>
+|It's string number two.
+|`string`
+|n/a
+
+|[[input_string-1]] <<input_string-1,string-1>>
+|It's string number one.
+|`string`
+|`"bar"`
+
+|[[input_string-special-chars]] <<input_string-special-chars,string-special-chars>>
+|n/a
+|`string`
+|`"\\.<>[]{}_-"`
+
+|[[input_number-3]] <<input_number-3,number-3>>
+|n/a
+|`number`
+|`"19"`
+
+|[[input_number-4]] <<input_number-4,number-4>>
+|n/a
+|`number`
+|`15.75`
+
+|[[input_number-2]] <<input_number-2,number-2>>
+|It's number number two.
+|`number`
+|n/a
+
+|[[input_number-1]] <<input_number-1,number-1>>
+|It's number number one.
+|`number`
+|`42`
+
+|[[input_map-3]] <<input_map-3,map-3>>
+|n/a
+|`map`
+|`{}`
+
+|[[input_map-2]] <<input_map-2,map-2>>
+|It's map number two.
+|`map`
+|n/a
+
+|[[input_map-1]] <<input_map-1,map-1>>
+|It's map number one.
+|`map`
+|
+
+[source]
+----
+{
+  "a": 1,
+  "b": 2,
+  "c": 3
+}
+----
+
+|[[input_list-3]] <<input_list-3,list-3>>
+|n/a
+|`list`
+|`[]`
+
+|[[input_list-2]] <<input_list-2,list-2>>
+|It's list number two.
+|`list`
+|n/a
+
+|[[input_list-1]] <<input_list-1,list-1>>
+|It's list number one.
+|`list`
+|
+
+[source]
+----
+[
+  "a",
+  "b",
+  "c"
+]
+----
+
+|[[input_input_with_underscores]] <<input_input_with_underscores,input_with_underscores>>
+|A variable with underscores.
+|`any`
+|n/a
+
+|[[input_input-with-pipe]] <<input_input-with-pipe,input-with-pipe>>
+|It includes v1 \| v2 \| v3
+|`string`
+|`"v1"`
+
+|[[input_input-with-code-block]] <<input_input-with-code-block,input-with-code-block>>
+|This is a complicated one. We need a newline.  
+And an example in a code block
+[source]
+----
+default     = [
+  "machine rack01:neptune"
+]
+----
+
+|`list`
+|
+
+[source]
+----
+[
+  "name rack:location"
+]
+----
+
+|[[input_long_type]] <<input_long_type,long_type>>
+|This description is itself markdown.
+
+It spans over multiple lines.
+
+|
+
+[source]
+----
+object({
+    name = string,
+    foo  = object({ foo = string, bar = string }),
+    bar  = object({ foo = string, bar = string }),
+    fizz = list(string),
+    buzz = list(string)
+  })
+----
+
+|
+
+[source]
+----
+{
+  "bar": {
+    "bar": "bar",
+    "foo": "bar"
+  },
+  "buzz": [
+    "fizz",
+    "buzz"
+  ],
+  "fizz": [],
+  "foo": {
+    "bar": "foo",
+    "foo": "foo"
+  },
+  "name": "hello"
+}
+----
+
+|[[input_no-escape-default-value]] <<input_no-escape-default-value,no-escape-default-value>>
+|The description contains `something_with_underscore`. Defaults to 'VALUE_WITH_UNDERSCORE'.
+|`string`
+|`"VALUE_WITH_UNDERSCORE"`
+
+|[[input_with-url]] <<input_with-url,with-url>>
+|The description contains url. https://www.domain.com/foo/bar_baz.html
+|`string`
+|`""`
+
+|[[input_string_default_empty]] <<input_string_default_empty,string_default_empty>>
+|n/a
+|`string`
+|`""`
+
+|[[input_string_default_null]] <<input_string_default_null,string_default_null>>
+|n/a
+|`string`
+|`null`
+
+|[[input_string_no_default]] <<input_string_no_default,string_no_default>>
+|n/a
+|`string`
+|n/a
+
+|[[input_number_default_zero]] <<input_number_default_zero,number_default_zero>>
+|n/a
+|`number`
+|`0`
+
+|[[input_bool_default_false]] <<input_bool_default_false,bool_default_false>>
+|n/a
+|`bool`
+|`false`
+
+|[[input_list_default_empty]] <<input_list_default_empty,list_default_empty>>
+|n/a
+|`list(string)`
+|`[]`
+
+|[[input_object_default_empty]] <<input_object_default_empty,object_default_empty>>
+|n/a
+|`object({})`
+|`{}`
+
+|===
+
+== Outputs
+
+[cols="a,a",options="header,autowidth"]
+|===
+|Name |Description
+|[[output_unquoted]] <<output_unquoted,unquoted>> |It's unquoted output.
+|[[output_output-2]] <<output_output-2,output-2>> |It's output number two.
+|[[output_output-1]] <<output_output-1,output-1>> |It's output number one.
+|[[output_output-0.12]] <<output_output-0.12,output-0.12>> |terraform 0.12 only
+|===
\ No newline at end of file
diff --git a/internal/format/testdata/markdown/document-WithAnchor.golden b/internal/format/testdata/markdown/document-WithAnchor.golden
new file mode 100644
index 0000000..29c1cca
--- /dev/null
+++ b/internal/format/testdata/markdown/document-WithAnchor.golden
@@ -0,0 +1,420 @@
+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 |
+
+## Requirements
+
+The following requirements are needed by this module:
+
+- <a name="requirement_terraform"></a> [terraform](#requirement_terraform) (>= 0.12)
+
+- <a name="requirement_aws"></a> [aws](#requirement_aws) (>= 2.15.0)
+
+- <a name="requirement_random"></a> [random](#requirement_random) (>= 2.2.0)
+
+## Providers
+
+The following providers are used by this module:
+
+- <a name="provider_tls"></a> [tls](#provider_tls)
+
+- <a name="provider_aws"></a> [aws](#provider_aws) (>= 2.15.0)
+
+- <a name="provider_aws.ident"></a> [aws.ident](#provider_aws.ident) (>= 2.15.0)
+
+- <a name="provider_null"></a> [null](#provider_null)
+
+## Modules
+
+The following Modules are called:
+
+### <a name="module_foo"></a> [foo](#module_foo)
+
+Source: bar
+
+Version: 1.2.3
+
+### <a name="module_bar"></a> [bar](#module_bar)
+
+Source: baz
+
+Version: 4.5.6
+
+### <a name="module_baz"></a> [baz](#module_baz)
+
+Source: baz
+
+Version: 4.5.6
+
+## Resources
+
+The following resources are used by this module:
+
+- [aws_caller_identity](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity)
+- [null_resource](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource)
+- [tls_private_key](https://registry.terraform.io/providers/hashicorp/tls/latest/docs/resources/private_key)
+
+## Inputs
+
+The following input variables are supported:
+
+### <a name="input_unquoted"></a> [unquoted](#input_unquoted)
+
+Description: n/a
+
+Type: `any`
+
+Default: n/a
+
+### <a name="input_bool-3"></a> [bool-3](#input_bool-3)
+
+Description: n/a
+
+Type: `bool`
+
+Default: `true`
+
+### <a name="input_bool-2"></a> [bool-2](#input_bool-2)
+
+Description: It's bool number two.
+
+Type: `bool`
+
+Default: `false`
+
+### <a name="input_bool-1"></a> [bool-1](#input_bool-1)
+
+Description: It's bool number one.
+
+Type: `bool`
+
+Default: `true`
+
+### <a name="input_string-3"></a> [string-3](#input_string-3)
+
+Description: n/a
+
+Type: `string`
+
+Default: `""`
+
+### <a name="input_string-2"></a> [string-2](#input_string-2)
+
+Description: It's string number two.
+
+Type: `string`
+
+Default: n/a
+
+### <a name="input_string-1"></a> [string-1](#input_string-1)
+
+Description: It's string number one.
+
+Type: `string`
+
+Default: `"bar"`
+
+### <a name="input_string-special-chars"></a> [string-special-chars](#input_string-special-chars)
+
+Description: n/a
+
+Type: `string`
+
+Default: `"\\.<>[]{}_-"`
+
+### <a name="input_number-3"></a> [number-3](#input_number-3)
+
+Description: n/a
+
+Type: `number`
+
+Default: `"19"`
+
+### <a name="input_number-4"></a> [number-4](#input_number-4)
+
+Description: n/a
+
+Type: `number`
+
+Default: `15.75`
+
+### <a name="input_number-2"></a> [number-2](#input_number-2)
+
+Description: It's number number two.
+
+Type: `number`
+
+Default: n/a
+
+### <a name="input_number-1"></a> [number-1](#input_number-1)
+
+Description: It's number number one.
+
+Type: `number`
+
+Default: `42`
+
+### <a name="input_map-3"></a> [map-3](#input_map-3)
+
+Description: n/a
+
+Type: `map`
+
+Default: `{}`
+
+### <a name="input_map-2"></a> [map-2](#input_map-2)
+
+Description: It's map number two.
+
+Type: `map`
+
+Default: n/a
+
+### <a name="input_map-1"></a> [map-1](#input_map-1)
+
+Description: It's map number one.
+
+Type: `map`
+
+Default:
+
+```json
+{
+  "a": 1,
+  "b": 2,
+  "c": 3
+}
+```
+
+### <a name="input_list-3"></a> [list-3](#input_list-3)
+
+Description: n/a
+
+Type: `list`
+
+Default: `[]`
+
+### <a name="input_list-2"></a> [list-2](#input_list-2)
+
+Description: It's list number two.
+
+Type: `list`
+
+Default: n/a
+
+### <a name="input_list-1"></a> [list-1](#input_list-1)
+
+Description: It's list number one.
+
+Type: `list`
+
+Default:
+
+```json
+[
+  "a",
+  "b",
+  "c"
+]
+```
+
+### <a name="input_input_with_underscores"></a> [input_with_underscores](#input_input_with_underscores)
+
+Description: A variable with underscores.
+
+Type: `any`
+
+Default: n/a
+
+### <a name="input_input-with-pipe"></a> [input-with-pipe](#input_input-with-pipe)
+
+Description: It includes v1 | v2 | v3
+
+Type: `string`
+
+Default: `"v1"`
+
+### <a name="input_input-with-code-block"></a> [input-with-code-block](#input_input-with-code-block)
+
+Description: This is a complicated one. We need a newline.  
+And an example in a code block
+```
+default     = [
+  "machine rack01:neptune"
+]
+```
+
+Type: `list`
+
+Default:
+
+```json
+[
+  "name rack:location"
+]
+```
+
+### <a name="input_long_type"></a> [long_type](#input_long_type)
+
+Description: This description is itself markdown.
+
+It spans over multiple lines.
+
+Type:
+
+```hcl
+object({
+    name = string,
+    foo  = object({ foo = string, bar = string }),
+    bar  = object({ foo = string, bar = string }),
+    fizz = list(string),
+    buzz = list(string)
+  })
+```
+
+Default:
+
+```json
+{
+  "bar": {
+    "bar": "bar",
+    "foo": "bar"
+  },
+  "buzz": [
+    "fizz",
+    "buzz"
+  ],
+  "fizz": [],
+  "foo": {
+    "bar": "foo",
+    "foo": "foo"
+  },
+  "name": "hello"
+}
+```
+
+### <a name="input_no-escape-default-value"></a> [no-escape-default-value](#input_no-escape-default-value)
+
+Description: The description contains `something_with_underscore`. Defaults to 'VALUE_WITH_UNDERSCORE'.
+
+Type: `string`
+
+Default: `"VALUE_WITH_UNDERSCORE"`
+
+### <a name="input_with-url"></a> [with-url](#input_with-url)
+
+Description: The description contains url. https://www.domain.com/foo/bar_baz.html
+
+Type: `string`
+
+Default: `""`
+
+### <a name="input_string_default_empty"></a> [string_default_empty](#input_string_default_empty)
+
+Description: n/a
+
+Type: `string`
+
+Default: `""`
+
+### <a name="input_string_default_null"></a> [string_default_null](#input_string_default_null)
+
+Description: n/a
+
+Type: `string`
+
+Default: `null`
+
+### <a name="input_string_no_default"></a> [string_no_default](#input_string_no_default)
+
+Description: n/a
+
+Type: `string`
+
+Default: n/a
+
+### <a name="input_number_default_zero"></a> [number_default_zero](#input_number_default_zero)
+
+Description: n/a
+
+Type: `number`
+
+Default: `0`
+
+### <a name="input_bool_default_false"></a> [bool_default_false](#input_bool_default_false)
+
+Description: n/a
+
+Type: `bool`
+
+Default: `false`
+
+### <a name="input_list_default_empty"></a> [list_default_empty](#input_list_default_empty)
+
+Description: n/a
+
+Type: `list(string)`
+
+Default: `[]`
+
+### <a name="input_object_default_empty"></a> [object_default_empty](#input_object_default_empty)
+
+Description: n/a
+
+Type: `object({})`
+
+Default: `{}`
+
+## Outputs
+
+The following outputs are exported:
+
+### <a name="output_unquoted"></a> [unquoted](#output_unquoted)
+
+Description: It's unquoted output.
+
+### <a name="output_output-2"></a> [output-2](#output_output-2)
+
+Description: It's output number two.
+
+### <a name="output_output-1"></a> [output-1](#output_output-1)
+
+Description: It's output number one.
+
+### <a name="output_output-0.12"></a> [output-0.12](#output_output-0.12)
+
+Description: terraform 0.12 only
\ No newline at end of file
diff --git a/internal/format/testdata/markdown/table-WithAnchor.golden b/internal/format/testdata/markdown/table-WithAnchor.golden
new file mode 100644
index 0000000..128cd9d
--- /dev/null
+++ b/internal/format/testdata/markdown/table-WithAnchor.golden
@@ -0,0 +1,115 @@
+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 |
+
+## Requirements
+
+| Name | Version |
+|------|---------|
+| <a name="requirement_terraform"></a> [terraform](#requirement_terraform) | >= 0.12 |
+| <a name="requirement_aws"></a> [aws](#requirement_aws) | >= 2.15.0 |
+| <a name="requirement_random"></a> [random](#requirement_random) | >= 2.2.0 |
+
+## Providers
+
+| Name | Version |
+|------|---------|
+| <a name="provider_tls"></a> [tls](#provider_tls) | n/a |
+| <a name="provider_aws"></a> [aws](#provider_aws) | >= 2.15.0 |
+| <a name="provider_aws.ident"></a> [aws.ident](#provider_aws.ident) | >= 2.15.0 |
+| <a name="provider_null"></a> [null](#provider_null) | n/a |
+
+## Modules
+
+| Name | Source | Version |
+|------|--------|---------|
+| <a name="module_foo"></a> [foo](#module_foo) | bar | 1.2.3 |
+| <a name="module_bar"></a> [bar](#module_bar) | baz | 4.5.6 |
+| <a name="module_baz"></a> [baz](#module_baz) | baz | 4.5.6 |
+
+## Resources
+
+| Name |
+|------|
+| [aws_caller_identity](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) |
+| [null_resource](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) |
+| [tls_private_key](https://registry.terraform.io/providers/hashicorp/tls/latest/docs/resources/private_key) |
+
+## Inputs
+
+| Name | Description | Type | Default |
+|------|-------------|------|---------|
+| <a name="input_unquoted"></a> [unquoted](#input_unquoted) | n/a | `any` | n/a |
+| <a name="input_bool-3"></a> [bool-3](#input_bool-3) | n/a | `bool` | `true` |
+| <a name="input_bool-2"></a> [bool-2](#input_bool-2) | It's bool number two. | `bool` | `false` |
+| <a name="input_bool-1"></a> [bool-1](#input_bool-1) | It's bool number one. | `bool` | `true` |
+| <a name="input_string-3"></a> [string-3](#input_string-3) | n/a | `string` | `""` |
+| <a name="input_string-2"></a> [string-2](#input_string-2) | It's string number two. | `string` | n/a |
+| <a name="input_string-1"></a> [string-1](#input_string-1) | It's string number one. | `string` | `"bar"` |
+| <a name="input_string-special-chars"></a> [string-special-chars](#input_string-special-chars) | n/a | `string` | `"\\.<>[]{}_-"` |
+| <a name="input_number-3"></a> [number-3](#input_number-3) | n/a | `number` | `"19"` |
+| <a name="input_number-4"></a> [number-4](#input_number-4) | n/a | `number` | `15.75` |
+| <a name="input_number-2"></a> [number-2](#input_number-2) | It's number number two. | `number` | n/a |
+| <a name="input_number-1"></a> [number-1](#input_number-1) | It's number number one. | `number` | `42` |
+| <a name="input_map-3"></a> [map-3](#input_map-3) | n/a | `map` | `{}` |
+| <a name="input_map-2"></a> [map-2](#input_map-2) | It's map number two. | `map` | n/a |
+| <a name="input_map-1"></a> [map-1](#input_map-1) | It's map number one. | `map` | <pre>{<br>  "a": 1,<br>  "b": 2,<br>  "c": 3<br>}</pre> |
+| <a name="input_list-3"></a> [list-3](#input_list-3) | n/a | `list` | `[]` |
+| <a name="input_list-2"></a> [list-2](#input_list-2) | It's list number two. | `list` | n/a |
+| <a name="input_list-1"></a> [list-1](#input_list-1) | It's list number one. | `list` | <pre>[<br>  "a",<br>  "b",<br>  "c"<br>]</pre> |
+| <a name="input_input_with_underscores"></a> [input_with_underscores](#input_input_with_underscores) | A variable with underscores. | `any` | n/a |
+| <a name="input_input-with-pipe"></a> [input-with-pipe](#input_input-with-pipe) | It includes v1 \| v2 \| v3 | `string` | `"v1"` |
+| <a name="input_input-with-code-block"></a> [input-with-code-block](#input_input-with-code-block) | This is a complicated one. We need a newline.<br>And an example in a code block<pre>default     = [<br>  "machine rack01:neptune"<br>]</pre> | `list` | <pre>[<br>  "name rack:location"<br>]</pre> |
+| <a name="input_long_type"></a> [long_type](#input_long_type) | This description is itself markdown.<br><br>It spans over multiple lines. | <pre>object({<br>    name = string,<br>    foo  = object({ foo = string, bar = string }),<br>    bar  = object({ foo = string, bar = string }),<br>    fizz = list(string),<br>    buzz = list(string)<br>  })</pre> | <pre>{<br>  "bar": {<br>    "bar": "bar",<br>    "foo": "bar"<br>  },<br>  "buzz": [<br>    "fizz",<br>    "buzz"<br>  ],<br>  "fizz": [],<br>  "foo": {<br>    "bar": "foo",<br>    "foo": "foo"<br>  },<br>  "name": "hello"<br>}</pre> |
+| <a name="input_no-escape-default-value"></a> [no-escape-default-value](#input_no-escape-default-value) | The description contains `something_with_underscore`. Defaults to 'VALUE_WITH_UNDERSCORE'. | `string` | `"VALUE_WITH_UNDERSCORE"` |
+| <a name="input_with-url"></a> [with-url](#input_with-url) | The description contains url. https://www.domain.com/foo/bar_baz.html | `string` | `""` |
+| <a name="input_string_default_empty"></a> [string_default_empty](#input_string_default_empty) | n/a | `string` | `""` |
+| <a name="input_string_default_null"></a> [string_default_null](#input_string_default_null) | n/a | `string` | `null` |
+| <a name="input_string_no_default"></a> [string_no_default](#input_string_no_default) | n/a | `string` | n/a |
+| <a name="input_number_default_zero"></a> [number_default_zero](#input_number_default_zero) | n/a | `number` | `0` |
+| <a name="input_bool_default_false"></a> [bool_default_false](#input_bool_default_false) | n/a | `bool` | `false` |
+| <a name="input_list_default_empty"></a> [list_default_empty](#input_list_default_empty) | n/a | `list(string)` | `[]` |
+| <a name="input_object_default_empty"></a> [object_default_empty](#input_object_default_empty) | n/a | `object({})` | `{}` |
+
+## Outputs
+
+| Name | Description |
+|------|-------------|
+| <a name="output_unquoted"></a> [unquoted](#output_unquoted) | It's unquoted output. |
+| <a name="output_output-2"></a> [output-2](#output_output-2) | It's output number two. |
+| <a name="output_output-1"></a> [output-1](#output_output-1) | It's output number one. |
+| <a name="output_output-0.12"></a> [output-0.12](#output_output-0.12) | terraform 0.12 only |
\ No newline at end of file
diff --git a/internal/template/anchor_test.go b/internal/template/anchor_test.go
new file mode 100644
index 0000000..fbfb7ab
--- /dev/null
+++ b/internal/template/anchor_test.go
@@ -0,0 +1,121 @@
+/*
+Copyright 2021 The terraform-docs Authors.
+
+Licensed under the MIT license (the "License"); you may not
+use this file except in compliance with the License.
+
+You may obtain a copy of the License at the LICENSE file in
+the root directory of this source tree.
+*/
+
+package template
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+
+	"github.com/terraform-docs/terraform-docs/internal/print"
+)
+
+func TestAnchorMarkdown(t *testing.T) {
+	tests := []struct {
+		typeSection string
+		name        string
+		anchor      bool
+		escape      bool
+		expected    string
+	}{
+		{
+			typeSection: "module",
+			name:        "banana_anchor_escape",
+			anchor:      true,
+			escape:      true,
+			expected:    "<a name=\"module_banana_anchor_escape\"></a> [banana\\_anchor\\_escape](#module\\_banana\\_anchor\\_escape)",
+		},
+		{
+			typeSection: "module",
+			name:        "banana_anchor_noescape",
+			anchor:      true,
+			escape:      false,
+			expected:    "<a name=\"module_banana_anchor_noescape\"></a> [banana_anchor_noescape](#module_banana_anchor_noescape)",
+		},
+		{
+			typeSection: "module",
+			name:        "banana_anchor_escape",
+			anchor:      false,
+			escape:      true,
+			expected:    "banana\\_anchor\\_escape",
+		},
+		{
+			typeSection: "module",
+			name:        "banana_anchor_noescape",
+			anchor:      false,
+			escape:      false,
+			expected:    "banana_anchor_noescape",
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			assert := assert.New(t)
+			settings := &print.Settings{
+				ShowAnchor:       tt.anchor,
+				EscapeCharacters: tt.escape,
+			}
+			actual := createAnchorMarkdown(tt.typeSection, tt.name, settings)
+
+			assert.Equal(tt.expected, actual)
+		})
+	}
+}
+
+func TestAnchorAsciidoc(t *testing.T) {
+	tests := []struct {
+		typeSection string
+		name        string
+		anchor      bool
+		escape      bool
+		expected    string
+	}{
+		{
+			typeSection: "module",
+			name:        "banana_anchor_escape",
+			anchor:      true,
+			escape:      true,
+			expected:    "[[module\\_banana\\_anchor\\_escape]] <<module\\_banana\\_anchor\\_escape,banana\\_anchor\\_escape>>",
+		},
+		{
+			typeSection: "module",
+			name:        "banana_anchor_noescape",
+			anchor:      true,
+			escape:      false,
+			expected:    "[[module_banana_anchor_noescape]] <<module_banana_anchor_noescape,banana_anchor_noescape>>",
+		},
+		{
+			typeSection: "module",
+			name:        "banana_anchor_escape",
+			anchor:      false,
+			escape:      true,
+			expected:    "banana\\_anchor\\_escape",
+		},
+		{
+			typeSection: "module",
+			name:        "banana_anchor_noescape",
+			anchor:      false,
+			escape:      false,
+			expected:    "banana_anchor_noescape",
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			assert := assert.New(t)
+			settings := &print.Settings{
+				ShowAnchor:       tt.anchor,
+				EscapeCharacters: tt.escape,
+			}
+			actual := createAnchorAsciidoc(tt.typeSection, tt.name, settings)
+
+			assert.Equal(tt.expected, actual)
+		})
+	}
+}