diff --git a/glfm_specification/example_snapshots/examples_index.yml b/glfm_specification/example_snapshots/examples_index.yml
index 3d4efcfbd7a904b24655ccf478a4efcc95318f53..fd3e350f58a02fdf40123106c3fc7bb52460660e 100644
--- a/glfm_specification/example_snapshots/examples_index.yml
+++ b/glfm_specification/example_snapshots/examples_index.yml
@@ -2054,21 +2054,33 @@
 07_05_00__gitlab_specific_markdown__video__002:
   spec_txt_example_position: 687
   source_specification: gitlab
-08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__001:
+07_06_00__gitlab_specific_markdown__table_of_contents__001:
   spec_txt_example_position: 688
   source_specification: gitlab
-08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__002:
+07_06_00__gitlab_specific_markdown__table_of_contents__002:
   spec_txt_example_position: 689
   source_specification: gitlab
-08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__003:
+07_06_00__gitlab_specific_markdown__table_of_contents__003:
   spec_txt_example_position: 690
   source_specification: gitlab
-08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__004:
+07_06_00__gitlab_specific_markdown__table_of_contents__004:
   spec_txt_example_position: 691
   source_specification: gitlab
-08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__005:
+08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__001:
   spec_txt_example_position: 692
   source_specification: gitlab
-08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__006:
+08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__002:
   spec_txt_example_position: 693
   source_specification: gitlab
+08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__003:
+  spec_txt_example_position: 694
+  source_specification: gitlab
+08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__004:
+  spec_txt_example_position: 695
+  source_specification: gitlab
+08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__005:
+  spec_txt_example_position: 696
+  source_specification: gitlab
+08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__006:
+  spec_txt_example_position: 697
+  source_specification: gitlab
diff --git a/glfm_specification/example_snapshots/html.yml b/glfm_specification/example_snapshots/html.yml
index 1df9354822a9b0ccb855b9698dd973f8bb409ff2..e683c37a7ac2a3e77678dfb38d1c75dbfa0afdbc 100644
--- a/glfm_specification/example_snapshots/html.yml
+++ b/glfm_specification/example_snapshots/html.yml
@@ -7850,6 +7850,83 @@
   wysiwyg: |-
     <pre>[video]: video.mov "video title"</pre>
     <p><span class="media-container video-container"><video src="video.mov" controls="true" data-setup="{}" data-title="video"></video><a href="video.mov">video</a></span></p>
+07_06_00__gitlab_specific_markdown__table_of_contents__001:
+  canonical: |
+    <nav>
+      <ul>
+        <li><a href="#heading-1">Heading 1</a></li>
+        <ul>
+          <li><a href="#heading-2">Heading 2</a></li>
+        </ul>
+      </ul>
+    </nav>
+    <h1>Heading 1</h1>
+    <h2>Heading 2</h2>
+  static: |-
+    <ul class="section-nav"><li>
+    <a href="#heading-1">Heading 1</a><ul><li><a href="#heading-2">Heading 2</a></li></ul>
+    </li></ul>
+    <h1 data-sourcepos="3:1-3:11" dir="auto">
+    <a id="user-content-heading-1" class="anchor" href="#heading-1" aria-hidden="true"></a>Heading 1</h1>
+    <h2 data-sourcepos="5:1-5:12" dir="auto">
+    <a id="user-content-heading-2" class="anchor" href="#heading-2" aria-hidden="true"></a>Heading 2</h2>
+  wysiwyg: |-
+    <div class="table-of-contents gl-border-1 gl-border-solid gl-text-center gl-border-gray-100 gl-mb-5">Table of contents</div>
+    <h1>Heading 1</h1>
+    <h2>Heading 2</h2>
+07_06_00__gitlab_specific_markdown__table_of_contents__002:
+  canonical: |
+    <nav>
+      <ul>
+        <li><a href="#heading-1">Heading 1</a></li>
+        <ul>
+          <li><a href="#heading-2">Heading 2</a></li>
+        </ul>
+      </ul>
+    </nav>
+    <h1>Heading 1</h1>
+    <h2>Heading 2</h2>
+  static: |-
+    <ul class="section-nav"><li>
+    <a href="#heading-1">Heading 1</a><ul><li><a href="#heading-2">Heading 2</a></li></ul>
+    </li></ul>
+    <h1 data-sourcepos="3:1-3:11" dir="auto">
+    <a id="user-content-heading-1" class="anchor" href="#heading-1" aria-hidden="true"></a>Heading 1</h1>
+    <h2 data-sourcepos="5:1-5:12" dir="auto">
+    <a id="user-content-heading-2" class="anchor" href="#heading-2" aria-hidden="true"></a>Heading 2</h2>
+  wysiwyg: |-
+    <div class="table-of-contents gl-border-1 gl-border-solid gl-text-center gl-border-gray-100 gl-mb-5">Table of contents</div>
+    <h1>Heading 1</h1>
+    <h2>Heading 2</h2>
+07_06_00__gitlab_specific_markdown__table_of_contents__003:
+  canonical: |
+    <p>[[<em>TOC</em>]]text</p>
+    <p>text[TOC]</p>
+  static: |-
+    <p data-sourcepos="1:1-2:4" dir="auto">[[<em>TOC</em>]]
+    text</p>
+    <p data-sourcepos="4:1-5:5" dir="auto">text
+    [TOC]</p>
+  wysiwyg: |-
+    <p>[[<em>TOC</em>]]
+    text</p>
+    <p>text
+    [TOC]</p>
+07_06_00__gitlab_specific_markdown__table_of_contents__004:
+  canonical: |
+    <nav>
+      <ul>
+        <li><a href="#heading-1">Heading 1</a></li>
+      </ul>
+    </nav>
+    <h1>Heading 1</h1>
+  static: |-
+    <ul class="section-nav"><li><a href="#heading-1">Heading 1</a></li></ul>
+    <h1 data-sourcepos="3:1-3:11" dir="auto">
+    <a id="user-content-heading-1" class="anchor" href="#heading-1" aria-hidden="true"></a>Heading 1</h1>
+  wysiwyg: |-
+    <div class="table-of-contents gl-border-1 gl-border-solid gl-text-center gl-border-gray-100 gl-mb-5">Table of contents</div>
+    <h1>Heading 1</h1>
 08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__001:
   canonical: |
     <p><a href="groups-test-file">groups-test-file</a></p>
diff --git a/glfm_specification/example_snapshots/markdown.yml b/glfm_specification/example_snapshots/markdown.yml
index e928c5a977e0763cc310a6a15b1b7641dbf21bc6..9af824e120fc7ed1024d2203b763cc392384339c 100644
--- a/glfm_specification/example_snapshots/markdown.yml
+++ b/glfm_specification/example_snapshots/markdown.yml
@@ -2239,6 +2239,28 @@
   [video]: video.mov "video title"
 
   ![video][video]
+07_06_00__gitlab_specific_markdown__table_of_contents__001: |
+  [TOC]
+
+  # Heading 1
+
+  ## Heading 2
+07_06_00__gitlab_specific_markdown__table_of_contents__002: |
+  [[_TOC_]]
+
+  # Heading 1
+
+  ## Heading 2
+07_06_00__gitlab_specific_markdown__table_of_contents__003: |
+  [[_TOC_]]
+  text
+
+  text
+  [TOC]
+07_06_00__gitlab_specific_markdown__table_of_contents__004: |2
+     [[_TOC_]]
+
+  # Heading 1
 08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__001: |
   [groups-test-file](/uploads/groups-test-file)
 08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__002: |
diff --git a/glfm_specification/example_snapshots/prosemirror_json.yml b/glfm_specification/example_snapshots/prosemirror_json.yml
index 7928d50ae961c71c72c913ada69622d5b941e7d7..1051b5ccdd7f35e4e5d022725d11a6052f3ba32b 100644
--- a/glfm_specification/example_snapshots/prosemirror_json.yml
+++ b/glfm_specification/example_snapshots/prosemirror_json.yml
@@ -20890,6 +20890,130 @@
       }
     ]
   }
+07_06_00__gitlab_specific_markdown__table_of_contents__001: |-
+  {
+    "type": "doc",
+    "content": [
+      {
+        "type": "tableOfContents"
+      },
+      {
+        "type": "heading",
+        "attrs": {
+          "level": 1
+        },
+        "content": [
+          {
+            "type": "text",
+            "text": "Heading 1"
+          }
+        ]
+      },
+      {
+        "type": "heading",
+        "attrs": {
+          "level": 2
+        },
+        "content": [
+          {
+            "type": "text",
+            "text": "Heading 2"
+          }
+        ]
+      }
+    ]
+  }
+07_06_00__gitlab_specific_markdown__table_of_contents__002: |-
+  {
+    "type": "doc",
+    "content": [
+      {
+        "type": "tableOfContents"
+      },
+      {
+        "type": "heading",
+        "attrs": {
+          "level": 1
+        },
+        "content": [
+          {
+            "type": "text",
+            "text": "Heading 1"
+          }
+        ]
+      },
+      {
+        "type": "heading",
+        "attrs": {
+          "level": 2
+        },
+        "content": [
+          {
+            "type": "text",
+            "text": "Heading 2"
+          }
+        ]
+      }
+    ]
+  }
+07_06_00__gitlab_specific_markdown__table_of_contents__003: |-
+  {
+    "type": "doc",
+    "content": [
+      {
+        "type": "paragraph",
+        "content": [
+          {
+            "type": "text",
+            "text": "[["
+          },
+          {
+            "type": "text",
+            "marks": [
+              {
+                "type": "italic"
+              }
+            ],
+            "text": "TOC"
+          },
+          {
+            "type": "text",
+            "text": "]]\ntext"
+          }
+        ]
+      },
+      {
+        "type": "paragraph",
+        "content": [
+          {
+            "type": "text",
+            "text": "text\n[TOC]"
+          }
+        ]
+      }
+    ]
+  }
+07_06_00__gitlab_specific_markdown__table_of_contents__004: |-
+  {
+    "type": "doc",
+    "content": [
+      {
+        "type": "tableOfContents"
+      },
+      {
+        "type": "heading",
+        "attrs": {
+          "level": 1
+        },
+        "content": [
+          {
+            "type": "text",
+            "text": "Heading 1"
+          }
+        ]
+      }
+    ]
+  }
 08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__001: |-
   Not yet implemented. See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92507#note_1068159236
 08_01_00__examples_using_internal_extensions__markdown_preview_api_request_overrides__002: |-
diff --git a/glfm_specification/input/gitlab_flavored_markdown/glfm_canonical_examples.txt b/glfm_specification/input/gitlab_flavored_markdown/glfm_canonical_examples.txt
index d27f809aaf350e169cee198a731d65282220b1d1..f6c7bdbcb904654f0c7bf7baea3e5650eff6eb19 100644
--- a/glfm_specification/input/gitlab_flavored_markdown/glfm_canonical_examples.txt
+++ b/glfm_specification/input/gitlab_flavored_markdown/glfm_canonical_examples.txt
@@ -209,7 +209,7 @@ GLFM renders image elements as an audio player as long as the resource’s file
 one of the following supported audio extensions `.mp3`, `.oga`, `.ogg`, `.spx`, and `.wav`.
 Audio ignore the alternative text part of an image declaration.
 
-```````````````````````````````` example gitlab audio
+```````````````````````````````` example gitlab
 ![audio](audio.oga "audio title")
 .
 <p><audio src="audio.oga" title="audio title"></audio></p>
@@ -217,7 +217,7 @@ Audio ignore the alternative text part of an image declaration.
 
 Reference definitions work audio as well:
 
-```````````````````````````````` example gitlab audio
+```````````````````````````````` example gitlab
 [audio]: audio.oga "audio title"
 
 ![audio][audio]
@@ -235,7 +235,7 @@ one of the following supported video extensions  `.mp4`, `.m4v`, `.mov`, `.webm`
 Videos ignore the alternative text part of an image declaration.
 
 
-```````````````````````````````` example gitlab video
+```````````````````````````````` example gitlab
 ![video](video.m4v "video title")
 .
 <p><video src="video.m4v" title="video title"></video></p>
@@ -243,7 +243,7 @@ Videos ignore the alternative text part of an image declaration.
 
 Reference definitions work video as well:
 
-```````````````````````````````` example gitlab video
+```````````````````````````````` example gitlab
 [video]: video.mov "video title"
 
 ![video][video]
@@ -251,6 +251,82 @@ Reference definitions work video as well:
 <p><video src="video.mov" title="video title"></video></p>
 ````````````````````````````````
 
+## Table of contents
+
+See
+[table of contents ](https://docs.gitlab.com/ee/user/markdown.html#table-of-contents)
+in the GitLab Flavored Markdown documentation.
+
+A table of contents is an unordered list that links to subheadings in the document.
+Add either the `[[_TOC_]]` or `[TOC]` tag on its own line.
+
+```````````````````````````````` example gitlab
+[TOC]
+
+# Heading 1
+
+## Heading 2
+.
+<nav>
+  <ul>
+    <li><a href="#heading-1">Heading 1</a></li>
+    <ul>
+      <li><a href="#heading-2">Heading 2</a></li>
+    </ul>
+  </ul>
+</nav>
+<h1>Heading 1</h1>
+<h2>Heading 2</h2>
+````````````````````````````````
+
+```````````````````````````````` example gitlab
+[[_TOC_]]
+
+# Heading 1
+
+## Heading 2
+.
+<nav>
+  <ul>
+    <li><a href="#heading-1">Heading 1</a></li>
+    <ul>
+      <li><a href="#heading-2">Heading 2</a></li>
+    </ul>
+  </ul>
+</nav>
+<h1>Heading 1</h1>
+<h2>Heading 2</h2>
+````````````````````````````````
+
+A table of contents is a block element. It should preceded and followed by a blank
+line.
+
+```````````````````````````````` example gitlab
+[[_TOC_]]
+text
+
+text
+[TOC]
+.
+<p>[[<em>TOC</em>]]text</p>
+<p>text[TOC]</p>
+````````````````````````````````
+
+A table of contents can be indented with up to three spaces.
+
+```````````````````````````````` example gitlab
+   [[_TOC_]]
+
+# Heading 1
+.
+<nav>
+  <ul>
+    <li><a href="#heading-1">Heading 1</a></li>
+  </ul>
+</nav>
+<h1>Heading 1</h1>
+````````````````````````````````
+
 # Examples Using Internal Extensions
 
 ## Markdown Preview API Request Overrides
diff --git a/glfm_specification/output/spec.txt b/glfm_specification/output/spec.txt
index d79a8d6b6758ab81c66a74cfbc1654506ae55ec0..d4c437decd14c4243c307dd9a074ffa9ccdc6511 100644
--- a/glfm_specification/output/spec.txt
+++ b/glfm_specification/output/spec.txt
@@ -9811,7 +9811,7 @@ GLFM renders image elements as an audio player as long as the resource’s file
 one of the following supported audio extensions `.mp3`, `.oga`, `.ogg`, `.spx`, and `.wav`.
 Audio ignore the alternative text part of an image declaration.
 
-```````````````````````````````` example gitlab audio
+```````````````````````````````` example gitlab
 ![audio](audio.oga "audio title")
 .
 <p><audio src="audio.oga" title="audio title"></audio></p>
@@ -9819,7 +9819,7 @@ Audio ignore the alternative text part of an image declaration.
 
 Reference definitions work audio as well:
 
-```````````````````````````````` example gitlab audio
+```````````````````````````````` example gitlab
 [audio]: audio.oga "audio title"
 
 ![audio][audio]
@@ -9837,7 +9837,7 @@ one of the following supported video extensions  `.mp4`, `.m4v`, `.mov`, `.webm`
 Videos ignore the alternative text part of an image declaration.
 
 
-```````````````````````````````` example gitlab video
+```````````````````````````````` example gitlab
 ![video](video.m4v "video title")
 .
 <p><video src="video.m4v" title="video title"></video></p>
@@ -9845,7 +9845,7 @@ Videos ignore the alternative text part of an image declaration.
 
 Reference definitions work video as well:
 
-```````````````````````````````` example gitlab video
+```````````````````````````````` example gitlab
 [video]: video.mov "video title"
 
 ![video][video]
@@ -9853,6 +9853,82 @@ Reference definitions work video as well:
 <p><video src="video.mov" title="video title"></video></p>
 ````````````````````````````````
 
+## Table of contents
+
+See
+[table of contents ](https://docs.gitlab.com/ee/user/markdown.html#table-of-contents)
+in the GitLab Flavored Markdown documentation.
+
+A table of contents is an unordered list that links to subheadings in the document.
+Add either the `[[_TOC_]]` or `[TOC]` tag on its own line.
+
+```````````````````````````````` example gitlab
+[TOC]
+
+# Heading 1
+
+## Heading 2
+.
+<nav>
+  <ul>
+    <li><a href="#heading-1">Heading 1</a></li>
+    <ul>
+      <li><a href="#heading-2">Heading 2</a></li>
+    </ul>
+  </ul>
+</nav>
+<h1>Heading 1</h1>
+<h2>Heading 2</h2>
+````````````````````````````````
+
+```````````````````````````````` example gitlab
+[[_TOC_]]
+
+# Heading 1
+
+## Heading 2
+.
+<nav>
+  <ul>
+    <li><a href="#heading-1">Heading 1</a></li>
+    <ul>
+      <li><a href="#heading-2">Heading 2</a></li>
+    </ul>
+  </ul>
+</nav>
+<h1>Heading 1</h1>
+<h2>Heading 2</h2>
+````````````````````````````````
+
+A table of contents is a block element. It should preceded and followed by a blank
+line.
+
+```````````````````````````````` example gitlab
+[[_TOC_]]
+text
+
+text
+[TOC]
+.
+<p>[[<em>TOC</em>]]text</p>
+<p>text[TOC]</p>
+````````````````````````````````
+
+A table of contents can be indented with up to three spaces.
+
+```````````````````````````````` example gitlab
+   [[_TOC_]]
+
+# Heading 1
+.
+<nav>
+  <ul>
+    <li><a href="#heading-1">Heading 1</a></li>
+  </ul>
+</nav>
+<h1>Heading 1</h1>
+````````````````````````````````
+
 # Examples Using Internal Extensions
 
 ## Markdown Preview API Request Overrides