Skip to content

Commit 9335f7e

Browse files
humitosagjohnson
andcommitted
Redirect: syntax highlight for $variable (#634)
<img width="607" height="320" alt="Screenshot_2025-07-16_16-42-23" src="https://github.com/user-attachments/assets/3eb38c81-6c88-4772-a234-39dc62e55252" /> Closes #82 --------- Co-authored-by: Anthony Johnson <[email protected]>
1 parent 7e78ad6 commit 9335f7e

File tree

3 files changed

+64
-31
lines changed

3 files changed

+64
-31
lines changed

readthedocsext/theme/static/readthedocsext/theme/js/site.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,48 @@
11
{% extends "projects/redirect_list.html" %}
22

3-
{% load i18n %}
4-
{% load crispy_forms_tags %}
5-
{% load ext_theme_tags %}
3+
{% load trans from i18n %}
4+
{% load crispy from crispy_forms_tags %}
5+
{% load alter_field from ext_theme_tags %}
66

77
{% block project_edit_content_subheader %}
88
{% if object %}
99
{% trans "Update redirect" %}
1010
{% else %}
1111
{% trans "Add redirect" %}
1212
{% endif %}
13-
{% endblock %}
13+
{% endblock project_edit_content_subheader %}
1414

1515
{% block project_edit_content %}
16-
<form class="ui form" method="post" action="." data-bind="using: ProjectRedirectView()">
16+
<form class="ui form"
17+
method="post"
18+
action="."
19+
data-bind="using: ProjectRedirectView()">
1720
{% csrf_token %}
1821
{% alter_field form.redirect_type data_bind="valueInit: redirect_type" %}
1922
{% alter_field form.from_url data_bind="valueInit: from_url, textInput: from_url, enable: is_from_url_visible" %}
2023
{% alter_field form.to_url data_bind="valueInit: to_url, textInput: to_url, enable: is_to_url_visible" %}
2124
{{ form|crispy }}
2225

23-
<div class="ui disabled segment" data-bind="css: {disabled: is_example_disabled}">
24-
<div data-bind="visible: !is_example_disabled()" style="display: none;">
26+
<div class="ui disabled segment"
27+
data-bind="css: {disabled: is_example_disabled}">
28+
<div class="ko hidden" data-bind="css: {hidden: is_example_disabled()}">
2529
<div class="ui list">
2630
<div class="item">
27-
<div class="sub header">
28-
{% trans "Redirect from" %}
29-
</div>
30-
<code data-bind="text: redirect_from"></code>
31+
<div class="sub header">{% trans "Redirect from" %}</div>
32+
<code>
33+
<span data-bind="html: redirect_from_prefix"></span><span data-bind="text: redirect_from"></span>
34+
</code>
3135
</div>
3236
<div class="item">
33-
<div class="sub header">
34-
{% trans "Redirect to" %}
35-
</div>
36-
<code data-bind="text: redirect_to"></code>
37+
<div class="sub header">{% trans "Redirect to" %}</div>
38+
<code>
39+
<span data-bind="html: redirect_to_prefix"></span><span data-bind="text: redirect_to"></span>
40+
</code>
3741
</div>
3842
</div>
3943
</div>
4044
</div>
4145

4246
<input class="ui primary button" type="submit" value="{% trans "Save" %}">
4347
</form>
44-
{% endblock %}
48+
{% endblock project_edit_content %}

src/js/project/admin.js

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -47,35 +47,63 @@ export class ProjectRedirectView {
4747
this.is_from_url_visible = ko.observable();
4848
this.is_to_url_visible = ko.observable();
4949

50+
// HTML prefix content for from field, don't use user input here
51+
this.redirect_from_prefix = ko.computed(() => {
52+
const redirect_type = this.redirect_type();
53+
const lang_part = `/<span class="ui violet text">$lang</span>`;
54+
const version_part = `/<span class="ui violet text">$version</span>`;
55+
56+
if (redirect_type === "page") {
57+
return `${lang_part}${version_part}/`;
58+
} else if (redirect_type === "clean_url_to_html") {
59+
return `${lang_part}${version_part}/<span class="ui violet text">$file</span>/`;
60+
} else if (redirect_type === "clean_url_without_trailing_slash_to_html") {
61+
return `${lang_part}${version_part}/<span class="ui violet text">$file</span>`;
62+
} else if (redirect_type === "html_to_clean_url") {
63+
return `${lang_part}${version_part}/<span class="ui violet text">$file</span>.html`;
64+
}
65+
return "";
66+
});
67+
// User input for from field as text, no HTML allowed
5068
this.redirect_from = ko.computed(() => {
51-
var from_url = this.from_url();
52-
var redirect_type = this.redirect_type();
69+
const from_url = this.from_url();
70+
const redirect_type = this.redirect_type();
5371
if (redirect_type === "prefix") {
5472
return from_url + "faq.html";
5573
} else if (redirect_type === "page") {
56-
return "/$lang/$version/" + from_url.replace(/^\/+/, "");
74+
return from_url.replace(/^\/+/, "");
5775
} else if (redirect_type === "exact") {
5876
return from_url;
77+
}
78+
return "";
79+
});
80+
// HTML prefix content for to field, don't use user input here.
81+
this.redirect_to_prefix = ko.computed(() => {
82+
const redirect_type = this.redirect_type();
83+
const lang_part = `/<span class="ui violet text">$lang</span>`;
84+
const version_part = `/<span class="ui violet text">$version</span>`;
85+
86+
if (redirect_type === "prefix") {
87+
return `${lang_part}${version_part}/faq.html`;
88+
} else if (redirect_type === "page") {
89+
return `${lang_part}${version_part}/`;
5990
} else if (redirect_type === "clean_url_to_html") {
60-
return "/$lang/$version/$file/";
91+
return `${lang_part}${version_part}/<span class="ui violet text">$file</span>.html`;
6192
} else if (redirect_type === "clean_url_without_trailing_slash_to_html") {
62-
return "/$lang/$version/$file";
93+
return `${lang_part}${version_part}/<span class="ui violet text">$file</span>.html`;
94+
} else if (redirect_type === "html_to_clean_url") {
95+
return `${lang_part}${version_part}/<span class="ui violet text">$file</span>/`;
6396
}
6497
return "";
6598
});
99+
// User input for to field as text, no HTML allowed
66100
this.redirect_to = ko.computed(() => {
67101
const to_url = this.to_url();
68102
const redirect_type = this.redirect_type();
69-
if (redirect_type === "prefix") {
70-
return "/$lang/$version/faq.html";
71-
} else if (redirect_type === "page") {
72-
return "/$lang/$version/" + to_url.replace(/^\/+/, "");
103+
if (redirect_type === "page") {
104+
return to_url.replace(/^\/+/, "");
73105
} else if (redirect_type === "exact") {
74106
return to_url;
75-
} else if (redirect_type === "clean_url_to_html") {
76-
return "/$lang/$version/$file.html";
77-
} else if (redirect_type === "clean_url_without_trailing_slash_to_html") {
78-
return "/$lang/$version/$file.html";
79107
}
80108
return "";
81109
});
@@ -95,6 +123,7 @@ export class ProjectRedirectView {
95123
[
96124
"clean_url_to_html",
97125
"clean_url_without_trailing_slash_to_html",
126+
"html_to_clean_url",
98127
].includes(redirect_type)
99128
) {
100129
this.is_example_disabled(false);

0 commit comments

Comments
 (0)