diff --git a/Dockerfile b/Dockerfile
index aa4957bce567..2ec633711fc3 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -51,6 +51,7 @@ ARG DOCS_URL="https://docs.docker.com"
ENV HUGO_CACHEDIR="/tmp/hugo_cache"
RUN --mount=type=cache,target=/tmp/hugo_cache \
hugo --gc --minify -e $HUGO_ENV -b $DOCS_URL
+RUN ./hack/flatten-markdown.sh public
# lint lints markdown files
FROM ghcr.io/igorshubovych/markdownlint-cli:v0.45.0 AS lint
diff --git a/hack/flatten-markdown.sh b/hack/flatten-markdown.sh
new file mode 100755
index 000000000000..d055dc9bdb34
--- /dev/null
+++ b/hack/flatten-markdown.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+set -e
+
+# Flatten markdown files from public/path/to/page/index.md to public/path/to/page.md
+# This makes markdown output links work correctly
+
+PUBLIC_DIR="${1:-public}"
+
+[ -d "$PUBLIC_DIR" ] || { echo "Error: Directory $PUBLIC_DIR does not exist"; exit 1; }
+
+find "$PUBLIC_DIR" -type f -name 'index.md' | while read -r file; do
+ # Skip the root index.md
+ [ "$file" = "$PUBLIC_DIR/index.md" ] && continue
+
+ # Get the directory containing index.md
+ dir="${file%/*}"
+
+ # Move index.md to parent directory with directory name
+ mv "$file" "${dir%/*}/${dir##*/}.md"
+done
+
+echo "Flattened markdown files in $PUBLIC_DIR"
diff --git a/hack/releaser/cloudfront-lambda-redirects.js b/hack/releaser/cloudfront-lambda-redirects.js
index a214d7ee560c..186824aa6474 100644
--- a/hack/releaser/cloudfront-lambda-redirects.js
+++ b/hack/releaser/cloudfront-lambda-redirects.js
@@ -52,20 +52,31 @@ exports.handler = (event, context, callback) => {
return
}
- // Handle directory requests by appending index.html for requests without file extensions
+ // Check Accept header for markdown/text requests
+ const headers = request.headers;
+ const acceptHeader = headers.accept ? headers.accept[0].value : '';
+ const wantsMarkdown = acceptHeader.includes('text/markdown') ||
+ acceptHeader.includes('text/plain');
+
+ // Handle directory requests by appending index.html or index.md for requests without file extensions
let uri = request.uri;
// Check if the URI has a dot after the last slash (indicating a filename)
// This is more accurate than just checking the end of the URI
const hasFileExtension = /\.[^/]*$/.test(uri.split('/').pop());
- // If it's not a file, treat it as a directory and append index.html
+ // If it's not a file, treat it as a directory
if (!hasFileExtension) {
- // Ensure the URI ends with a slash before appending index.html
+ // Ensure the URI ends with a slash before appending index file
if (!uri.endsWith("/")) {
uri += "/";
}
- uri += "index.html";
+ // Serve markdown if Accept header requests it, otherwise serve HTML
+ uri += wantsMarkdown ? "index.md" : "index.html";
+ request.uri = uri;
+ } else if (wantsMarkdown && uri.endsWith('.html')) {
+ // If requesting a specific HTML file but wants markdown, try the .md version
+ uri = uri.replace(/\.html$/, '.md');
request.uri = uri;
}
diff --git a/hugo.yaml b/hugo.yaml
index 369dc8d8c411..19dbcca1edf9 100644
--- a/hugo.yaml
+++ b/hugo.yaml
@@ -92,6 +92,10 @@ outputs:
section:
- html
- markdown
+ taxonomy:
+ - html
+ term:
+ - html
languages:
en:
diff --git a/layouts/_default/api.markdown.md b/layouts/_default/api.markdown.md
new file mode 100644
index 000000000000..ff3bef069369
--- /dev/null
+++ b/layouts/_default/api.markdown.md
@@ -0,0 +1,41 @@
+---
+title: {{ .Title }}
+url: {{ .Permalink }}
+{{- range .Ancestors }}
+ {{- if and (not .IsHome) .Permalink }}
+parent:
+ title: {{ .Title }}
+ url: {{ .Permalink }}
+ {{- break }}
+ {{- end }}
+{{- end }}
+{{- if .Ancestors }}
+breadcrumbs:
+{{- range .Ancestors.Reverse }}
+ {{- if and (not .IsHome) .Permalink }}
+ - title: {{ .Title }}
+ url: {{ .Permalink }}
+ {{- end }}
+{{- end }}
+ - title: {{ .Title }}
+ url: {{ .Permalink }}
+{{- end }}
+{{- with .NextInSection }}
+next:
+ title: {{ .Title }}
+ url: {{ .Permalink }}
+{{- end }}
+{{- with .PrevInSection }}
+prev:
+ title: {{ .Title }}
+ url: {{ .Permalink }}
+{{- end }}
+{{- $specURL := urls.Parse (printf "/%s%s.yaml" .File.Dir .File.ContentBaseName) }}
+openapi_spec: {{ $specURL.String | absURL }}
+---
+
+{{ .Content }}
+
+**OpenAPI Specification:** [{{ .Title }} API Spec]({{ $specURL.String | absURL }})
+
+This page provides interactive API documentation. For the machine-readable OpenAPI specification, see the link above.
diff --git a/layouts/_default/cli.html b/layouts/_default/cli.html
index 7f12bdab1151..97e52e09bff5 100644
--- a/layouts/_default/cli.html
+++ b/layouts/_default/cli.html
@@ -10,7 +10,12 @@
{{ partial "breadcrumbs.html" . }}
- {{ .Title }}
+
+
{{ .Title }}
+
+ {{ partial "md-dropdown.html" . }}
+
+
diff --git a/layouts/_default/cli.markdown.md b/layouts/_default/cli.markdown.md
new file mode 100644
index 000000000000..99cfd9ecc06e
--- /dev/null
+++ b/layouts/_default/cli.markdown.md
@@ -0,0 +1,88 @@
+{{- $data := "" }}
+{{- if .Params.datafolder }}
+ {{- $data = index (index site.Data .Params.datafolder) .Params.datafile }}
+{{- else }}
+ {{- $data = index site.Data .Params.datafile }}
+{{- end -}}
+---
+title: {{ .Title }}
+url: {{ .Permalink }}
+{{- range .Ancestors }}
+ {{- if and (not .IsHome) .Permalink }}
+parent:
+ title: {{ .Title }}
+ url: {{ .Permalink }}
+ {{- break }}
+ {{- end }}
+{{- end }}
+{{- if .Ancestors }}
+breadcrumbs:
+{{- range .Ancestors.Reverse }}
+ {{- if and (not .IsHome) .Permalink }}
+ - title: {{ .Title }}
+ url: {{ .Permalink }}
+ {{- end }}
+{{- end }}
+ - title: {{ .Title }}
+ url: {{ .Permalink }}
+{{- end }}
+{{- with .NextInSection }}
+next:
+ title: {{ .Title }}
+ url: {{ .Permalink }}
+{{- end }}
+{{- with .PrevInSection }}
+prev:
+ title: {{ .Title }}
+ url: {{ .Permalink }}
+{{- end }}
+---
+
+{{ with $data.short }}**Description:** {{ . }}{{ end }}
+
+{{ with $data.usage }}**Usage:** `{{ . }}`{{ end }}
+
+{{ with $data.aliases }}{{ $aliases := strings.Replace . (printf "%s, " $.Title) "" }}**Aliases:** {{ range $i, $alias := (strings.Split $aliases ", ") }}{{ if $i }}, {{ end }}`{{ $alias }}`{{ end }}{{ end }}
+
+{{ .Content }}
+
+{{ if $data.deprecated }}> [!WARNING]
+> **Deprecated**
+>
+> This command is deprecated. It may be removed in a future Docker version.
+{{ end }}
+
+{{ if or $data.experimental $data.experimentalcli }}> [!NOTE]
+> **Experimental**
+>
+> This command is experimental. Experimental features are intended for testing and feedback as their functionality or design may change between releases without warning or can be removed entirely in a future release.
+{{ end }}
+
+{{ with $data.kubernetes }}**Orchestrator:** Kubernetes{{ end }}
+{{ with $data.swarm }}**Orchestrator:** Swarm{{ end }}
+
+{{ with $data.long }}## Description
+
+{{ . }}
+{{ end }}
+
+{{ with $data.options }}{{ $opts := where . "hidden" false }}{{ with $opts }}## Options
+
+| Option | Default | Description |
+|--------|---------|-------------|
+{{ range . }}{{ $short := .shorthand }}{{ $long := .option }}| {{ with $short }}`-{{ . }}`, {{ end }}`--{{ $long }}` | {{ with .default_value }}{{ $skipDefault := `[],map[],false,0,0s,default,'',""` }}{{ cond (in $skipDefault .) "" (printf "`%s`" .) }}{{ end }} | {{ with .min_api_version }}API {{ . }}+{{ end }}{{ with .deprecated }} **Deprecated**{{ end }}{{ with .experimental }} **experimental (daemon)**{{ end }}{{ with .experimentalcli }} **experimental (CLI)**{{ end }}{{ with .kubernetes }} **Kubernetes**{{ end }}{{ with .swarm }} **Swarm**{{ end }}{{ if .description }} {{ strings.Replace .description "\n" "
" }}{{ end }} |
+{{ end }}
+{{ end }}{{ end }}
+
+{{ with $data.examples }}## Examples
+
+{{ . }}
+{{ end }}
+
+{{ if eq .Kind "section" }}## Subcommands
+
+| Command | Description |
+|---------|-------------|
+{{ range .Pages }}{{ if and .Params.datafolder .Params.datafile }}{{ $subdata := index (index site.Data .Params.datafolder) .Params.datafile }}| [`{{ .Title }}`]({{ .Permalink }}) | {{ $subdata.short }} |
+{{ end }}{{ end }}
+{{ end }}
diff --git a/layouts/_default/list.markdown.md b/layouts/_default/list.markdown.md
index 0cbb619e2522..ab2747bc38c9 100644
--- a/layouts/_default/list.markdown.md
+++ b/layouts/_default/list.markdown.md
@@ -1,5 +1,36 @@
-# {{ .Title }}
+---
+title: {{ .Title }}
+url: {{ .Permalink }}
+{{- range .Ancestors }}
+ {{- if and (not .IsHome) .Permalink }}
+parent:
+ title: {{ .Title }}
+ url: {{ .Permalink }}
+ {{- break }}
+ {{- end }}
+{{- end }}
+{{- if .Ancestors }}
+breadcrumbs:
+{{- range .Ancestors.Reverse }}
+ {{- if and (not .IsHome) .Permalink }}
+ - title: {{ .Title }}
+ url: {{ .Permalink }}
+ {{- end }}
+{{- end }}
+ - title: {{ .Title }}
+ url: {{ .Permalink }}
+{{- end }}
+{{- $children := where .Pages "Permalink" "ne" "" }}
+{{- if $children }}
+children:
+{{- range $children }}
+ - title: {{ .Title }}
+ url: {{ .Permalink }}
+ {{- with .Description }}
+ description: {{ . }}
+ {{- end }}
+{{- end }}
+{{- end }}
+---
+
{{ .RenderShortcodes }}
-{{ range where .Pages "Permalink" "ne" "" }}
-- [{{ .Title }}]({{ .Permalink }})
-{{ end }}
diff --git a/layouts/_default/single.markdown.md b/layouts/_default/single.markdown.md
index 2e89e09128f5..40c1778180d4 100644
--- a/layouts/_default/single.markdown.md
+++ b/layouts/_default/single.markdown.md
@@ -1,2 +1,35 @@
-# {{ .Title }}
+---
+title: {{ .Title }}
+url: {{ .Permalink }}
+{{- range .Ancestors }}
+ {{- if and (not .IsHome) .Permalink }}
+parent:
+ title: {{ .Title }}
+ url: {{ .Permalink }}
+ {{- break }}
+ {{- end }}
+{{- end }}
+{{- if .Ancestors }}
+breadcrumbs:
+{{- range .Ancestors.Reverse }}
+ {{- if and (not .IsHome) .Permalink }}
+ - title: {{ .Title }}
+ url: {{ .Permalink }}
+ {{- end }}
+{{- end }}
+ - title: {{ .Title }}
+ url: {{ .Permalink }}
+{{- end }}
+{{- with .NextInSection }}
+next:
+ title: {{ .Title }}
+ url: {{ .Permalink }}
+{{- end }}
+{{- with .PrevInSection }}
+prev:
+ title: {{ .Title }}
+ url: {{ .Permalink }}
+{{- end }}
+---
+
{{ .RenderShortcodes }}
diff --git a/layouts/partials/head.html b/layouts/partials/head.html
index 4c1455512c37..18bdb010b718 100644
--- a/layouts/partials/head.html
+++ b/layouts/partials/head.html
@@ -1,6 +1,9 @@
{{ partial "meta.html" . }}
+{{- range .AlternativeOutputFormats -}}
+
+{{ end -}}
{{ partial "utils/css.html" "-" }}
{{- if hugo.IsProduction -}}