This is an automated email from the ASF dual-hosted git repository.
davidarthur pushed a commit to branch markdown
in repository https://gitbox.apache.org/repos/asf/kafka-site.git
The following commit(s) were added to refs/heads/markdown by this push:
new bf71e9dcb Implement dynamic version linking for documentation. README
updates (#780)
bf71e9dcb is described below
commit bf71e9dcba5d91528d67c34215d56e89d35cb659
Author: Harish Vishwanath <[email protected]>
AuthorDate: Fri Jan 9 12:30:39 2026 -0800
Implement dynamic version linking for documentation. README updates (#780)
---
README.md | 82 +++++++++++++++++++++++++++++--
layouts/_default/_markup/render-link.html | 17 +++++++
layouts/shortcodes/include-html.html | 18 +++++--
scripts/replace-version-links.sh | 34 +++++++++++++
4 files changed, 144 insertions(+), 7 deletions(-)
diff --git a/README.md b/README.md
index 61831be46..1bedfa322 100644
--- a/README.md
+++ b/README.md
@@ -50,14 +50,45 @@ Each version directory contains the complete documentation
for that specific Kaf
## Updating the Documentation Website
+
### Adding documentation for a new release
-When releasing a new documentation version (e.g., version 4.2 / "42"), follow
these steps:
+When releasing a new documentation version (e.g., version 4.2 / "42"), follow
these steps. For this example, we assume you are adding version **42** from the
Kafka source branch `4.2`.
+
+In the below examples, we assume the `apache/kafka` repository is checked out
at `../kafka` relative to the `kafka-site` root.
+
+#### 1. Setup Content Directory
+Copy the documentation source files from the Kafka codebase to the website
content directory, excluding images (which go to static).
+
+```bash
+# Verify you are in the kafka-site root
+mkdir -p content/en/42
+
+# Copy docs from kafka repo (excluding images)
+rsync -av --exclude 'images' ../kafka/docs/ content/en/42/
+```
+
+#### 2. Setup Static Assets
+Copy the generated artifacts, images, and Javadocs to the static directory.
-#### 1. Create Content Directory
-Create a new directory in `content/en/` for the new version (e.g., `42/` for
version 4.2)
+```bash
+# Create versioned static directory
+mkdir -p static/42
+
+# Copy assets from kafka repo
+cp -r ../kafka/docs/images static/42/
+# Copy `generated` directory into `static/42`
+# Copy `javadoc` directory into `static/42`
+```
+
+#### 3. Run Replacement Script
+Run the helper script to replace hardcoded version strings with dynamic
placeholders (`{version}`) in the new content if needed. If we don't have any
hardcoded version strings, we can skip this step.
+
+```bash
+./scripts/replace-version-links.sh 42
+```
-#### 2. Update Version Parameters in `hugo.yaml`
+#### 4. Update Version Parameters in `hugo.yaml`
Locate the **Version Configuration** block at the top of the `params` section
(around line 245). Update the following fields:
@@ -165,6 +196,49 @@ Detailed information about the Front Matter fields used in
this site:
For more details, see the [Hugo Front Matter
Documentation](https://gohugo.io/content-management/front-matter/).
+### Dynamic Version Linking
+
+To maintain version-agnostic documentation, we use a custom system that
dynamically resolves version numbers in links and included files. This avoids
the need to manually update hundreds of version strings (e.g., from "43" to
"44") when releasing a new version.
+
+The system relies on the special placeholder `{version}`.
+
+#### How it Works
+
+When the site is built, Hugo identifies the context of the current page (e.g.,
a file located in `content/en/43/`).
+- If the page is in a versioned directory (like `43/`), `{version}` resolves
to that version (`43`).
+- If the page is outside a versioned directory (like `content/en/community/`),
`{version}` falls back to the `latest_version` defined in `hugo.yaml`.
+
+#### Supported Features
+
+1. **Markdown Links**:
+ Use `{version}` in standard Markdown links.
+ ```markdown
+
[ConfigProvider]({version}/javadoc/org/apache/kafka/common/config/provider/ConfigProvider.html)
+ => /43/javadoc/org/apache/kafka/common/config/provider/ConfigProvider.html
+ ```
+ *Implemented via the Render Hook:
`layouts/_default/_markup/render-link.html`*
+
+2. **Include HTML Shortcode**:
+ Use `{version}` in the `file` path for the `include-html` shortcode.
+ ```markdown
+ {{< include-html
file="/static/{version}/generated/admin_client_config.html" >}}
+ => reads content from /static/43/generated/admin_client_config.html
+ ```
+ *Implemented in: `layouts/shortcodes/include-html.html`*
+
+#### Helper Script
+
+A script is available to automate the replacement of hardcoded version strings
with dynamic placeholders for a specific version directory.
+
+```bash
+# Usage: ./scripts/replace-version-links.sh <version>
+./scripts/replace-version-links.sh 43
+```
+
+This will recursively find and replace:
+- `/<version>/javadoc` -> `/{version}/javadoc`
+- `static/<version>/generated` -> `static/{version}/generated`
+
### Adding a New Blog Post
Blog posts are located in `content/en/blog/`. The most common use case is
adding a release announcement.
diff --git a/layouts/_default/_markup/render-link.html
b/layouts/_default/_markup/render-link.html
new file mode 100644
index 000000000..759fa9714
--- /dev/null
+++ b/layouts/_default/_markup/render-link.html
@@ -0,0 +1,17 @@
+{{- $dest := .Destination -}}
+{{- if in $dest "{version}" -}}
+{{- $version := "" -}}
+{{- /* Try to infer version from the top-level section (e.g. "43" from
content/en/43/...) */ -}}
+{{- $sectionName := .Page.Section -}}
+{{- if findRE "^\\d+$" $sectionName -}}
+{{- $version = $sectionName -}}
+{{- else -}}
+{{- /* Fallback to site variable if section is not a version number */ -}}
+{{- $version = site.Params.latest_version -}}
+{{- end -}}
+{{- $dest = replace $dest "{version}" $version -}}
+{{- end -}}
+<a href="{{ $dest | safeURL }}" {{- with .Title }} title="{{ . }}" {{ end -}}
{{- if strings.HasPrefix $dest "http" }}
+ target="_blank" rel="noopener" {{ end -}}>
+ {{- .Text | safeHTML -}}
+</a>
\ No newline at end of file
diff --git a/layouts/shortcodes/include-html.html
b/layouts/shortcodes/include-html.html
index 8d141c0d5..ec514397a 100644
--- a/layouts/shortcodes/include-html.html
+++ b/layouts/shortcodes/include-html.html
@@ -1,3 +1,15 @@
-{{ $file := .Get "file" }}
-{{ $content := readFile $file }}
-{{ $content | safeHTML }}
\ No newline at end of file
+{{- $file := .Get "file" -}}
+{{- if in $file "{version}" -}}
+{{- $version := "" -}}
+{{- /* Try to infer version from the top-level section (e.g. "43" from
content/en/43/...) */ -}}
+{{- $sectionName := .Page.Section -}}
+{{- if findRE "^\\d+$" $sectionName -}}
+{{- $version = $sectionName -}}
+{{- else -}}
+{{- /* Fallback to site variable if section is not a version number */ -}}
+{{- $version = site.Params.latest_version -}}
+{{- end -}}
+{{- $file = replace $file "{version}" $version -}}
+{{- end -}}
+{{- $content := readFile $file -}}
+{{- $content | safeHTML -}}
\ No newline at end of file
diff --git a/scripts/replace-version-links.sh b/scripts/replace-version-links.sh
new file mode 100755
index 000000000..4ec6a1b02
--- /dev/null
+++ b/scripts/replace-version-links.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+
+# Script to replace hardcoded version links with {version} placeholder
+# Usage: ./scripts/replace-version-links.sh <version>
+
+set -e
+
+if [ -z "$1" ]; then
+ echo "Usage: $0 <version>"
+ echo "Example: $0 39"
+ exit 1
+fi
+
+VERSION=$1
+CONTENT_DIR="content/en/$VERSION"
+
+if [ ! -d "$CONTENT_DIR" ]; then
+ echo "Error: Directory $CONTENT_DIR does not exist."
+ exit 1
+fi
+
+echo "Processing version: $VERSION in $CONTENT_DIR"
+
+# 1. Replace Javadoc links
+# Pattern: /<VERSION>/javadoc -> /{version}/javadoc
+echo "Replacing /$VERSION/javadoc with /{version}/javadoc..."
+find "$CONTENT_DIR" -name "*.md" -type f -print0 | xargs -0 sed -i ''
"s|/$VERSION/javadoc|/{version}/javadoc|g"
+
+# 2. Replace generated static include paths
+# Pattern: static/<VERSION>/generated -> static/{version}/generated
+echo "Replacing static/$VERSION/generated with static/{version}/generated..."
+find "$CONTENT_DIR" -name "*.md" -type f -print0 | xargs -0 sed -i ''
"s|static/$VERSION/generated|static/{version}/generated|g"
+
+echo "Done!"