From e4ced4004bd78e51069c69788fa485c8f2965947 Mon Sep 17 00:00:00 2001
From: Hugo Locurcio
Date: Thu, 18 Sep 2025 01:50:57 +0200
Subject: [PATCH 1/3] Add JavaScript-based redirects to supplement Read the
Docs redirects
Read the Docs redirects don't reliably apply when there is a
large amount of redirects defined. While this JavaScript-based
solution is not as seamless, it has no limit on how many redirects
can be defined.
---
_static/js/custom.js | 32 ++++++++++++++++++++-
{_tools/redirects => _static}/redirects.csv | 28 +++++++++---------
_tools/redirects/README.md | 21 +++++++++-----
_tools/redirects/create_redirects.py | 2 +-
4 files changed, 60 insertions(+), 23 deletions(-)
rename {_tools/redirects => _static}/redirects.csv (97%)
diff --git a/_static/js/custom.js b/_static/js/custom.js
index d028dd0f329..860deb940ad 100644
--- a/_static/js/custom.js
+++ b/_static/js/custom.js
@@ -1,4 +1,3 @@
-
// Handle page scroll and adjust sidebar accordingly.
// Each page has two scrolls: the main scroll, which is moving the content of the page;
@@ -298,6 +297,37 @@ const registerGiscus = function () {
};
$(document).ready(() => {
+ const httpResponseStatus = window.performance.getEntries()[0].responseStatus;
+ if (httpResponseStatus === 404) {
+ // Check for redirects if on a currently invalid page.
+ // This is done in JavaScript, as we exceed Read the Docs' limit for the amount of redirects configurable.
+ // When testing this feature on a local web server, replace the URL below with just `/_static/redirects.csv`.
+ fetch("/en/latest/_static/redirects.csv")
+ .then(response => response.text())
+ .then(csvText => {
+ const lines = csvText.trim().split('\n');
+ for (const line of lines) {
+ if (!line.trim()) {
+ continue;
+ }
+ const [from, to] = line.split(',').map(s => s.trim());
+ if (from && to) {
+ if (window.location.pathname.endsWith(from)) {
+ if (to.startsWith('https://')) {
+ window.location.replace(to);
+ } else {
+ const newUrl = window.location.href.replace(window.location.pathname, to);
+ window.location.replace(newUrl);
+ }
+ }
+ }
+ }
+ })
+ .catch(err => {
+ console.error("Couldn't fetch redirects list:", err);
+ });
+ }
+
// Remove the search match highlights from the page, and adjust the URL in the
// navigation history.
const url = new URL(location.href);
diff --git a/_tools/redirects/redirects.csv b/_static/redirects.csv
similarity index 97%
rename from _tools/redirects/redirects.csv
rename to _static/redirects.csv
index 14f19a965c9..664ab8ce08b 100644
--- a/_tools/redirects/redirects.csv
+++ b/_static/redirects.csv
@@ -431,20 +431,20 @@ source,destination
/contributing/workflow/testing_pull_requests.html,https://contributing.godotengine.org/en/latest/organization/pull_requests/testing.html
/contributing/development/core_and_modules/2d_coordinate_systems.html,/engine_details/architecture/2d_coordinate_systems.html
/contributing/development/core_and_modules/common_engine_methods_and_macros.html,/engine_details/architecture/common_engine_methods_and_macros.html
-/contributing/development/core_and_modules/core_types.html,//architecture/core_types.html
-/contributing/development/core_and_modules/custom_audiostreams.html,//architecture/custom_audiostreams.html
-/contributing/development/core_and_modules/custom_godot_servers.html,//architecture/custom_godot_servers.html
-/contributing/development/core_and_modules/custom_modules_in_cpp.html,//architecture/custom_modules_in_cpp.html
-/contributing/development/core_and_modules/custom_platform_ports.html,//architecture/custom_platform_ports.html
-/contributing/development/core_and_modules/custom_resource_format_loaders.html,//architecture/custom_resource_format_loaders.html
-/contributing/development/core_and_modules/godot_architecture_diagram.html,//architecture/godot_architecture_diagram.html
-/contributing/development/core_and_modules/index.html,//architecture/index.html
-/contributing/development/core_and_modules/inheritance_class_tree.html,//architecture/inheritance_class_tree.html
-/contributing/development/core_and_modules/internal_rendering_architecture.html,//architecture/internal_rendering_architecture.html
-/contributing/development/core_and_modules/object_class.html,//architecture/object_class.html
-/contributing/development/core_and_modules/scripting_development.html,//architecture/scripting_development.html
-/contributing/development/core_and_modules/unit_testing.html,//architecture/unit_testing.html
-/contributing/development/core_and_modules/variant_class.html,//architecture/variant_class.html
+/contributing/development/core_and_modules/core_types.html,/engine_details/architecture/core_types.html
+/contributing/development/core_and_modules/custom_audiostreams.html,/engine_details/architecture/custom_audiostreams.html
+/contributing/development/core_and_modules/custom_godot_servers.html,/engine_details/architecture/custom_godot_servers.html
+/contributing/development/core_and_modules/custom_modules_in_cpp.html,/engine_details/architecture/custom_modules_in_cpp.html
+/contributing/development/core_and_modules/custom_platform_ports.html,/engine_details/architecture/custom_platform_ports.html
+/contributing/development/core_and_modules/custom_resource_format_loaders.html,/engine_details/architecture/custom_resource_format_loaders.html
+/contributing/development/core_and_modules/godot_architecture_diagram.html,/engine_details/architecture/godot_architecture_diagram.html
+/contributing/development/core_and_modules/index.html,/engine_details/architecture/index.html
+/contributing/development/core_and_modules/inheritance_class_tree.html,/engine_details/architecture/inheritance_class_tree.html
+/contributing/development/core_and_modules/internal_rendering_architecture.html,/engine_details/architecture/internal_rendering_architecture.html
+/contributing/development/core_and_modules/object_class.html,/engine_details/architecture/object_class.html
+/contributing/development/core_and_modules/scripting_development.html,/engine_details/architecture/scripting_development.html
+/contributing/development/core_and_modules/unit_testing.html,/engine_details/architecture/unit_testing.html
+/contributing/development/core_and_modules/variant_class.html,/engine_details/architecture/variant_class.html
/contributing/documentation/class_reference_primer.html,engine_details/class_reference/index.html
/contributing/development/compiling/compiling_for_android.html,/engine_details/development/compiling/compiling_for_android.html,
/contributing/development/compiling/compiling_for_ios.html,/engine_details/development/compiling/compiling_for_ios.html
diff --git a/_tools/redirects/README.md b/_tools/redirects/README.md
index af31b2f2a3f..c991b956426 100644
--- a/_tools/redirects/README.md
+++ b/_tools/redirects/README.md
@@ -21,19 +21,26 @@ To interact with the Read the Docs API, a valid API key must be set as
## Usage
-Let's say we recently renamed some files in the Git branch `3.4` (compared to the `stable` branch), and now we want to create redirects for these.
-For this, we would (after setting up the API token and requirements, see Setup above):
+Let's say we recently renamed some files in the Git branch `3.4` (compared to the `stable` branch),
+and now we want to create redirects for these. For this, we would (after setting up the API token
+and requirements, see Setup above):
-> python convert_git_renames_to_csv.py stable 3.4
+```
+python convert_git_renames_to_csv.py stable 3.4
+```
This should output a list of the redirects to create. Let's append these to the redirects file:
-> python convert_git_renames_to_csv.py stable 3.4 >> redirects.csv
+```
+python convert_git_renames_to_csv.py stable 3.4 >> ../../_tools/redirects.csv
+```
-After this, redirects for renamed files should have been appended to `redirects.csv`. You may want to double-check that!
-Now let's submit these to ReadTheDocs and create redirects there:
+After this, redirects for renamed files should have been appended to `../../_tools/redirects.csv`.
+You may want to double-check that! Now let's submit these to ReadTheDocs and create redirects there:
-> python create_redirects.py
+```
+python create_redirects.py
+```
And that should be it!
diff --git a/_tools/redirects/create_redirects.py b/_tools/redirects/create_redirects.py
index baef253c4e6..67c5fd9563b 100644
--- a/_tools/redirects/create_redirects.py
+++ b/_tools/redirects/create_redirects.py
@@ -50,7 +50,7 @@ def parse_command_line_args():
"-f",
"--file",
metavar="file",
- default="redirects.csv",
+ default="../../_static/redirects.csv",
type=str,
help="Path to a CSV file used to keep a list of redirects, containing two columns: source and destination.",
)
From 0535cd544318ba5c9a125b8679bfd65e31196d55 Mon Sep 17 00:00:00 2001
From: Lukas Tenbrink
Date: Sat, 4 Oct 2025 11:29:07 +0200
Subject: [PATCH 2/3] Fix redirects in safari, by moving the redirect js script
into the 404 page instead of checking if we're on 404 via the API.
---
404.rst | 30 ++++++++++++++++++++++++++++++
_static/js/custom.js | 31 -------------------------------
2 files changed, 30 insertions(+), 31 deletions(-)
diff --git a/404.rst b/404.rst
index 21960757c60..a7507b38c5f 100644
--- a/404.rst
+++ b/404.rst
@@ -22,3 +22,33 @@ Page not found
Search docs
box on the left or go to the homepage.
+
+
diff --git a/_static/js/custom.js b/_static/js/custom.js
index 860deb940ad..49cd5fc2618 100644
--- a/_static/js/custom.js
+++ b/_static/js/custom.js
@@ -297,37 +297,6 @@ const registerGiscus = function () {
};
$(document).ready(() => {
- const httpResponseStatus = window.performance.getEntries()[0].responseStatus;
- if (httpResponseStatus === 404) {
- // Check for redirects if on a currently invalid page.
- // This is done in JavaScript, as we exceed Read the Docs' limit for the amount of redirects configurable.
- // When testing this feature on a local web server, replace the URL below with just `/_static/redirects.csv`.
- fetch("/en/latest/_static/redirects.csv")
- .then(response => response.text())
- .then(csvText => {
- const lines = csvText.trim().split('\n');
- for (const line of lines) {
- if (!line.trim()) {
- continue;
- }
- const [from, to] = line.split(',').map(s => s.trim());
- if (from && to) {
- if (window.location.pathname.endsWith(from)) {
- if (to.startsWith('https://')) {
- window.location.replace(to);
- } else {
- const newUrl = window.location.href.replace(window.location.pathname, to);
- window.location.replace(newUrl);
- }
- }
- }
- }
- })
- .catch(err => {
- console.error("Couldn't fetch redirects list:", err);
- });
- }
-
// Remove the search match highlights from the page, and adjust the URL in the
// navigation history.
const url = new URL(location.href);
From 16e84a8d76b9a6fbf6044c5aaa9a15a71f532e14 Mon Sep 17 00:00:00 2001
From: Hugo Locurcio
Date: Mon, 6 Oct 2025 22:46:45 +0200
Subject: [PATCH 3/3] Fix RTD language switcher redirecting to nonexistent
`/en/4.x/` branch
If we were redirected to `/en/4.x/` as a result of the RTD language selector,
redirect to `/en/stable/` instead, as English does not have a `4.x` branch.
For maintenance reasons, non-English languages have a single `4.x` branch
that is the counterpart of `4.3`, `4.4`, `4.5` and so on.).
---
404.rst | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/404.rst b/404.rst
index a7507b38c5f..0cf80c065a4 100644
--- a/404.rst
+++ b/404.rst
@@ -24,6 +24,15 @@ Page not found