summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Edmunds <medmunds@gmail.com>2026-06-08 14:43:44 -0700
committernessita <124304+nessita@users.noreply.github.com>2026-06-09 21:56:35 -0300
commit9b1db9cb2c38c75b8fb0fc64ba5f73a6012e5b2d (patch)
tree7b8976389754f69cee4c0ecea8542f61fa43672b
parent867c7c0451f2e67e715da5b55b5bf6696747fdc3 (diff)
Fixed #37150 -- Made djangodocs Sphinx extension work with any html builder.
Changed djangodocs extension to register DjangoHTMLTranslator for any html-format builder (in the builder-inited hook), rather than a limited list of builders at startup. That fixes missing content in dirhtml and standard html builds (including ReadTheDocs PR previews): - Missing console tabs - Empty divs for versionadded and versionchanged directives Removed JS code that depended on jQuery, which hasn't worked since Sphinx 6.0 dropped jQuery in 2023: - Unnecessary console tabs click handling. (Console tab behavior is implemented purely in CSS.) - Client-side hyperlinking of Django template tags and filters in code examples. (This is also not supported on docs.djangoproject.com.) Removed custom DjangoStandaloneHTMLBuilder and "djangohtml" builder type. Its sole purpose was to generate the "templatebuiltins.js" file used for the (non-functional) client-side template filter/tag linking. Changed docs "make html" target from "djangohtml" to standard "html".
-rw-r--r--docs/Makefile2
-rw-r--r--docs/_ext/djangodocs.py54
-rw-r--r--docs/_theme/djangodocs/layout.html54
3 files changed, 12 insertions, 98 deletions
diff --git a/docs/Makefile b/docs/Makefile
index 41ed522daf..736cab6d7f 100644
--- a/docs/Makefile
+++ b/docs/Makefile
@@ -58,7 +58,7 @@ clean:
-rm -rf $(BUILDDIR)/*
html:
- $(SPHINXBUILD) -b djangohtml $(ALLSPHINXOPTS) $(BUILDDIR)/html
+ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
diff --git a/docs/_ext/djangodocs.py b/docs/_ext/djangodocs.py
index a979a8e30a..a82cb5df96 100644
--- a/docs/_ext/djangodocs.py
+++ b/docs/_ext/djangodocs.py
@@ -2,8 +2,6 @@
Sphinx plugins for Django documentation.
"""
-import json
-import os
import re
from docutils import nodes
@@ -11,12 +9,10 @@ from docutils.parsers.rst import Directive
from docutils.statemachine import ViewList
from sphinx import addnodes
from sphinx import version_info as sphinx_version
-from sphinx.builders.html import StandaloneHTMLBuilder
from sphinx.directives.code import CodeBlock
from sphinx.domains.std import Cmdoption
from sphinx.errors import ExtensionError
from sphinx.util import logging
-from sphinx.util.console import bold
from sphinx.writers.html import HTMLTranslator
logger = logging.getLogger(__name__)
@@ -55,9 +51,7 @@ def setup(app):
app.add_config_value("django_next_version", "0.0", True)
app.add_directive("versionadded", VersionDirective)
app.add_directive("versionchanged", VersionDirective)
- app.add_builder(DjangoStandaloneHTMLBuilder)
- app.set_translator("djangohtml", DjangoHTMLTranslator)
- app.set_translator("json", DjangoHTMLTranslator)
+ app.connect("builder-inited", set_django_html_translator)
app.add_node(
ConsoleNode,
html=(visit_console_html, None),
@@ -72,6 +66,11 @@ def setup(app):
return {"parallel_read_safe": True}
+def set_django_html_translator(app):
+ if app.builder.format == "html":
+ app.set_translator(app.builder.name, DjangoHTMLTranslator, override=True)
+
+
class VersionDirective(Directive):
has_content = True
required_arguments = 1
@@ -189,36 +188,6 @@ def parse_django_admin_node(env, sig, signode):
return command
-class DjangoStandaloneHTMLBuilder(StandaloneHTMLBuilder):
- """
- Subclass to add some extra things we need.
- """
-
- name = "djangohtml"
-
- def finish(self):
- super().finish()
- logger.info(bold("writing templatebuiltins.js..."))
- xrefs = self.env.domaindata["std"]["objects"]
- templatebuiltins = {
- "ttags": [
- n
- for ((t, n), (k, a)) in xrefs.items()
- if t == "templatetag" and k == "ref/templates/builtins"
- ],
- "tfilters": [
- n
- for ((t, n), (k, a)) in xrefs.items()
- if t == "templatefilter" and k == "ref/templates/builtins"
- ],
- }
- outfilename = os.path.join(self.outdir, "templatebuiltins.js")
- with open(outfilename, "w") as fp:
- fp.write("var django_template_builtins = ")
- json.dump(templatebuiltins, fp)
- fp.write(";\n")
-
-
class ConsoleNode(nodes.literal_block):
"""
Custom node to override the visit/depart event handlers at registration
@@ -248,7 +217,7 @@ def depart_console_dummy(self, node):
def visit_console_html(self, node):
"""Generate HTML for the console directive."""
- if self.builder.name in ("djangohtml", "json") and node["win_console_text"]:
+ if self.builder.format == "html" and node["win_console_text"]:
# Put a mark on the document object signaling the fact the directive
# has been used on it.
self.document._console_directive_used_flag = True
@@ -363,9 +332,9 @@ class ConsoleDirective(CodeBlock):
self.arguments = ["console"]
lit_blk_obj = super().run()[0]
- # Only do work when the djangohtml HTML Sphinx builder is being used,
+ # Only do work when an HTML-format Sphinx builder is being used,
# invoke the default behavior for the rest.
- if env.app.builder.name not in ("djangohtml", "json"):
+ if env.app.builder.format != "html":
return [lit_blk_obj]
lit_blk_obj["uid"] = str(env.new_serialno("console"))
@@ -385,9 +354,8 @@ class ConsoleDirective(CodeBlock):
def html_page_context_hook(app, pagename, templatename, context, doctree):
# Put a bool on the context used to render the template. It's used to
- # control inclusion of console-tabs.css and activation of the JavaScript.
- # This way it's include only from HTML files rendered from reST files where
- # the ConsoleDirective is used.
+ # control inclusion of console-tabs.css. This way it's included only from
+ # HTML files rendered from reST files where the ConsoleDirective is used.
context["include_console_assets"] = getattr(
doctree, "_console_directive_used_flag", False
)
diff --git a/docs/_theme/djangodocs/layout.html b/docs/_theme/djangodocs/layout.html
index 487c2b4922..6d07375d07 100644
--- a/docs/_theme/djangodocs/layout.html
+++ b/docs/_theme/djangodocs/layout.html
@@ -17,60 +17,6 @@
{%- endmacro %}
{% block extrahead %}
-{# When building htmlhelp (CHM format) disable jQuery inclusion, #}
-{# as it causes problems in compiled CHM files. #}
-{% if builder != "htmlhelp" %}
-{{ super() }}
-<script src="{{ pathto('templatebuiltins.js', 1) }}"></script>
-<script>
-(function($) {
- if (!django_template_builtins) {
- // templatebuiltins.js missing, do nothing.
- return;
- }
- $(document).ready(function() {
- // Hyperlink Django template tags and filters
- var base = "{{ pathto('ref/templates/builtins') }}";
- if (base == "#") {
- // Special case for builtins.html itself
- base = "";
- }
- // Tags are keywords, class '.k'
- $("div.highlight\\-html\\+django span.k").each(function(i, elem) {
- var tagname = $(elem).text();
- if ($.inArray(tagname, django_template_builtins.ttags) != -1) {
- var fragment = tagname.replace(/_/, '-');
- $(elem).html("<a href='" + base + "#" + fragment + "'>" + tagname + "</a>");
- }
- });
- // Filters are functions, class '.nf'
- $("div.highlight\\-html\\+django span.nf").each(function(i, elem) {
- var filtername = $(elem).text();
- if ($.inArray(filtername, django_template_builtins.tfilters) != -1) {
- var fragment = filtername.replace(/_/, '-');
- $(elem).html("<a href='" + base + "#" + fragment + "'>" + filtername + "</a>");
- }
- });
- });
-})(jQuery);
-{%- if include_console_assets -%}
-(function($) {
- $(document).ready(function() {
- $(".c-tab-unix").on("click", function() {
- $("section.c-content-unix").show();
- $("section.c-content-win").hide();
- $(".c-tab-unix").prop("checked", true);
- });
- $(".c-tab-win").on("click", function() {
- $("section.c-content-win").show();
- $("section.c-content-unix").hide();
- $(".c-tab-win").prop("checked", true);
- });
- });
-})(jQuery);
-{%- endif -%}
-</script>
-{% endif %}
{%- if include_console_assets -%}
<link rel="stylesheet" href="{{ pathto('_static/console-tabs.css', 1) }}">
{%- endif -%}