Skip to content

Commit 5341e60

Browse files
akien-mgaCalinou
andcommitted
Allow dehardcoding documentation branch and URL in docs links
This makes it possible to change the branch of the documentation that URLs are pointing to without having to modify all class reference files. In the XML class reference, the `$DOCS_URL` placeholder should be used, and will be replaced automatically in the editor and when generating the RST class reference. The documentation branch string is set in `version.py`. Co-authored-by: Hugo Locurcio <[email protected]>
1 parent 9e1c190 commit 5341e60

File tree

7 files changed

+46
-34
lines changed

7 files changed

+46
-34
lines changed

core/string/ustring.cpp

+11-5
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "core/string/translation.h"
3939
#include "core/string/ucaps.h"
4040
#include "core/variant/variant.h"
41+
#include "core/version_generated.gen.h"
4142

4243
#include <stdio.h>
4344
#include <stdlib.h>
@@ -4868,30 +4869,35 @@ String TTRN(const String &p_text, const String &p_text_plural, int p_n, const St
48684869
return p_text_plural;
48694870
}
48704871

4872+
/* DTR and DTRN are used for the documentation, handling descriptions extracted
4873+
* from the XML.
4874+
* They also replace `$DOCS_URL` with the actual URL to the documentation's branch,
4875+
* to allow dehardcoding it in the XML and doing proper substitutions everywhere.
4876+
*/
48714877
String DTR(const String &p_text, const String &p_context) {
48724878
// Comes straight from the XML, so remove indentation and any trailing whitespace.
48734879
const String text = p_text.dedent().strip_edges();
48744880

48754881
if (TranslationServer::get_singleton()) {
4876-
return TranslationServer::get_singleton()->doc_translate(text, p_context);
4882+
return String(TranslationServer::get_singleton()->doc_translate(text, p_context)).replace("$DOCS_URL", VERSION_DOCS_URL);
48774883
}
48784884

4879-
return text;
4885+
return text.replace("$DOCS_URL", VERSION_DOCS_URL);
48804886
}
48814887

48824888
String DTRN(const String &p_text, const String &p_text_plural, int p_n, const String &p_context) {
48834889
const String text = p_text.dedent().strip_edges();
48844890
const String text_plural = p_text_plural.dedent().strip_edges();
48854891

48864892
if (TranslationServer::get_singleton()) {
4887-
return TranslationServer::get_singleton()->doc_translate_plural(text, text_plural, p_n, p_context);
4893+
return String(TranslationServer::get_singleton()->doc_translate_plural(text, text_plural, p_n, p_context)).replace("$DOCS_URL", VERSION_DOCS_URL);
48884894
}
48894895

48904896
// Return message based on English plural rule if translation is not possible.
48914897
if (p_n == 1) {
4892-
return text;
4898+
return text.replace("$DOCS_URL", VERSION_DOCS_URL);
48934899
}
4894-
return text_plural;
4900+
return text_plural.replace("$DOCS_URL", VERSION_DOCS_URL);
48954901
}
48964902
#endif
48974903

doc/tools/make_rst.py

+26-26
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,8 @@
1111
# Uncomment to do type checks. I have it commented out so it works below Python 3.5
1212
# from typing import List, Dict, TextIO, Tuple, Iterable, Optional, DefaultDict, Any, Union
1313

14-
# http(s)://docs.godotengine.org/<langcode>/<tag>/path/to/page.html(#fragment-tag)
15-
GODOT_DOCS_PATTERN = re.compile(
16-
r"^http(?:s)?://docs\.godotengine\.org/(?:[a-zA-Z0-9.\-_]*)/(?:[a-zA-Z0-9.\-_]*)/(.*)\.html(#.*)?$"
17-
)
14+
# $DOCS_URL/path/to/page.html(#fragment-tag)
15+
GODOT_DOCS_PATTERN = re.compile(r"^\$DOCS_URL/(.*)\.html(#.*)?$")
1816

1917

2018
def print_error(error, state): # type: (str, State) -> None
@@ -857,16 +855,11 @@ def rstize_text(text, state): # type: (str, State) -> str
857855

858856
# Handle [tags]
859857
inside_code = False
860-
inside_url = False
861-
url_has_name = False
862-
url_link = ""
863858
pos = 0
864859
tag_depth = 0
865860
previous_pos = 0
866861
while True:
867862
pos = text.find("[", pos)
868-
if inside_url and (pos > previous_pos):
869-
url_has_name = True
870863
if pos == -1:
871864
break
872865

@@ -995,17 +988,23 @@ def rstize_text(text, state): # type: (str, State) -> str
995988
elif cmd.find("image=") == 0:
996989
tag_text = "" # '![](' + cmd[6:] + ')'
997990
elif cmd.find("url=") == 0:
998-
url_link = cmd[4:]
999-
tag_text = "`"
1000-
tag_depth += 1
1001-
inside_url = True
1002-
url_has_name = False
1003-
elif cmd == "/url":
1004-
tag_text = ("" if url_has_name else url_link) + " <" + url_link + ">`__"
1005-
tag_depth -= 1
1006-
escape_post = True
1007-
inside_url = False
1008-
url_has_name = False
991+
# URLs are handled in full here as we need to extract the optional link
992+
# title to use `make_link`.
993+
link_url = cmd[4:]
994+
endurl_pos = text.find("[/url]", endq_pos + 1)
995+
if endurl_pos == -1:
996+
print_error(
997+
"Tag depth mismatch for [url]: no closing [/url], file: {}".format(state.current_class), state
998+
)
999+
break
1000+
link_title = text[endq_pos + 1 : endurl_pos]
1001+
tag_text = make_link(link_url, link_title)
1002+
1003+
pre_text = text[:pos]
1004+
text = pre_text + tag_text + text[endurl_pos + 6 :]
1005+
pos = len(pre_text) + len(tag_text)
1006+
previous_pos = pos
1007+
continue
10091008
elif cmd == "center":
10101009
tag_depth += 1
10111010
tag_text = ""
@@ -1252,21 +1251,22 @@ def make_link(url, title): # type: (str, str) -> str
12521251
if match.lastindex == 2:
12531252
# Doc reference with fragment identifier: emit direct link to section with reference to page, for example:
12541253
# `#calling-javascript-from-script in Exporting For Web`
1255-
return "`" + groups[1] + " <../" + groups[0] + ".html" + groups[1] + ">`_ in :doc:`../" + groups[0] + "`"
1256-
# Commented out alternative: Instead just emit:
1257-
# `Subsection in Exporting For Web`
1258-
# return "`Subsection <../" + groups[0] + ".html" + groups[1] + ">`__ in :doc:`../" + groups[0] + "`"
1254+
# Or use the title if provided.
1255+
if title != "":
1256+
return "`" + title + " <../" + groups[0] + ".html" + groups[1] + ">`__"
1257+
return "`" + groups[1] + " <../" + groups[0] + ".html" + groups[1] + ">`__ in :doc:`../" + groups[0] + "`"
12591258
elif match.lastindex == 1:
12601259
# Doc reference, for example:
12611260
# `Math`
1261+
if title != "":
1262+
return ":doc:`" + title + " <../" + groups[0] + ">`"
12621263
return ":doc:`../" + groups[0] + "`"
12631264
else:
12641265
# External link, for example:
12651266
# `http://enet.bespin.org/usergroup0.html`
12661267
if title != "":
12671268
return "`" + title + " <" + url + ">`__"
1268-
else:
1269-
return "`" + url + " <" + url + ">`__"
1269+
return "`" + url + " <" + url + ">`__"
12701270

12711271

12721272
def sanitize_operator_name(dirty_name, state): # type: (str, State) -> str

editor/editor_help.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,14 @@
3333
#include "core/core_constants.h"
3434
#include "core/input/input.h"
3535
#include "core/os/keyboard.h"
36+
#include "core/version_generated.gen.h"
3637
#include "doc_data_compressed.gen.h"
3738
#include "editor/plugins/script_editor_plugin.h"
3839
#include "editor_node.h"
3940
#include "editor_scale.h"
4041
#include "editor_settings.h"
4142

42-
#define CONTRIBUTE_URL "https://docs.godotengine.org/en/latest/community/contributing/updating_the_class_reference.html"
43+
#define CONTRIBUTE_URL vformat("%s/community/contributing/updating_the_class_reference.html", VERSION_DOCS_URL)
4344

4445
DocTools *EditorHelp::doc = nullptr;
4546

editor/plugins/shader_editor_plugin.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "core/io/resource_saver.h"
3535
#include "core/os/keyboard.h"
3636
#include "core/os/os.h"
37+
#include "core/version_generated.gen.h"
3738
#include "editor/editor_node.h"
3839
#include "editor/editor_scale.h"
3940
#include "editor/editor_settings.h"
@@ -384,7 +385,7 @@ void ShaderEditor::_menu_option(int p_option) {
384385
shader_editor->remove_all_bookmarks();
385386
} break;
386387
case HELP_DOCS: {
387-
OS::get_singleton()->shell_open("https://docs.godotengine.org/en/latest/tutorials/shaders/shader_reference/index.html");
388+
OS::get_singleton()->shell_open(vformat("%s/tutorials/shaders/shader_reference/index.html", VERSION_DOCS_URL));
388389
} break;
389390
}
390391
if (p_option != SEARCH_FIND && p_option != SEARCH_REPLACE && p_option != SEARCH_GOTO_LINE) {

editor/project_export.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "core/io/resource_saver.h"
3939
#include "core/os/os.h"
4040
#include "core/string/optimized_translation.h"
41+
#include "core/version_generated.gen.h"
4142
#include "editor_data.h"
4243
#include "editor_node.h"
4344
#include "editor_scale.h"
@@ -456,7 +457,7 @@ void ProjectExportDialog::_enc_filters_changed(const String &p_filters) {
456457
}
457458

458459
void ProjectExportDialog::_open_key_help_link() {
459-
OS::get_singleton()->shell_open("https://docs.godotengine.org/en/latest/development/compiling/compiling_with_script_encryption_key.html");
460+
OS::get_singleton()->shell_open(vformat("%s/development/compiling/compiling_with_script_encryption_key.html", VERSION_DOCS_URL));
460461
}
461462

462463
void ProjectExportDialog::_enc_pck_changed(bool p_pressed) {

methods.py

+2
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ def update_version(module_version_string=""):
105105
f.write('#define VERSION_MODULE_CONFIG "' + str(version.module_config) + module_version_string + '"\n')
106106
f.write("#define VERSION_YEAR " + str(version.year) + "\n")
107107
f.write('#define VERSION_WEBSITE "' + str(version.website) + '"\n')
108+
f.write('#define VERSION_DOCS_BRANCH "' + str(version.docs) + '"\n')
109+
f.write('#define VERSION_DOCS_URL "https://docs.godotengine.org/en/" VERSION_DOCS_BRANCH\n')
108110
f.write("#endif // VERSION_GENERATED_GEN_H\n")
109111
f.close()
110112

version.py

+1
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@
77
module_config = ""
88
year = 2021
99
website = "https://godotengine.org"
10+
docs = "latest"

0 commit comments

Comments
 (0)