[llvm-branch-commits] [clang] [libc] [llvm] [clang][docs] Adopt the furo theme used by llvm and libc (PR #214869)
Reid Kleckner via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Aug 17 20:09:01 PDT 2026
https://github.com/rnk updated https://github.com/llvm/llvm-project/pull/214869
>From 0528852677c5e6c6d7dd38d475c1ae8c695b1889 Mon Sep 17 00:00:00 2001
From: Reid Kleckner <rkleckner at nvidia.com>
Date: Thu, 6 Aug 2026 21:10:29 +0000
Subject: [PATCH 1/3] [clang][docs] Prototype Furo theme setup
---
clang/docs/LifetimeSafety.md | 16 --
clang/docs/analyzer/conf.py | 44 ++----
clang/docs/conf.py | 26 +---
libc/docs/conf.py | 33 +----
llvm/docs/_static/copybutton.css | 39 -----
llvm/docs/_static/copybutton.js | 56 -------
llvm/docs/_static/custom.css | 71 ---------
llvm/docs/conf.py | 39 +----
utils/docs/llvm_sphinx/__init__.py | 36 ++++-
.../docs/llvm_sphinx}/_static/copybutton.css | 0
.../docs/llvm_sphinx}/_static/copybutton.js | 2 +-
.../docs/llvm_sphinx/_static/furo-common.css | 140 ++++++++++++++++++
utils/docs/llvm_sphinx/ext/furo.py | 37 +++++
13 files changed, 241 insertions(+), 298 deletions(-)
delete mode 100644 llvm/docs/_static/copybutton.css
delete mode 100644 llvm/docs/_static/copybutton.js
delete mode 100644 llvm/docs/_static/custom.css
rename {libc/docs => utils/docs/llvm_sphinx}/_static/copybutton.css (100%)
rename {libc/docs => utils/docs/llvm_sphinx}/_static/copybutton.js (98%)
create mode 100644 utils/docs/llvm_sphinx/_static/furo-common.css
create mode 100644 utils/docs/llvm_sphinx/ext/furo.py
diff --git a/clang/docs/LifetimeSafety.md b/clang/docs/LifetimeSafety.md
index 5b643feb4224b..dcf206547643d 100644
--- a/clang/docs/LifetimeSafety.md
+++ b/clang/docs/LifetimeSafety.md
@@ -207,22 +207,6 @@ For more details, see [noescape](https://clang.llvm.org/docs/AttributeReference.
## Checks Performed
-```{raw} html
-<style>
-/* Align text to left and add red/green colors */
-table.colored-code-table td, table.colored-code-table th { text-align: left !important; }
-table.colored-code-table td:first-child, table.colored-code-table th:first-child { background-color: #ffeaea !important; }
-table.colored-code-table td:nth-child(2), table.colored-code-table th:nth-child(2) { background-color: #eafaea !important; }
-table.colored-code-table td .highlight, table.colored-code-table td pre { background-color: transparent !important; border: none !important; }
-
-div.bad-code { background-color: #ffeaea !important; padding: 5px; border-left: 4px solid #ff6b6b; text-align: left !important; }
-div.bad-code .highlight, div.bad-code pre { background-color: transparent !important; border: none !important; }
-
-div.good-code { background-color: #eafaea !important; padding: 5px; border-left: 4px solid #51cf66; text-align: left !important; }
-div.good-code .highlight, div.good-code pre { background-color: transparent !important; border: none !important; }
-</style>
-```
-
### Use after scope
This check warns when a pointer or reference is used after the stack variable
diff --git a/clang/docs/analyzer/conf.py b/clang/docs/analyzer/conf.py
index 509aa857c4d52..c9ecbec5118f0 100644
--- a/clang/docs/analyzer/conf.py
+++ b/clang/docs/analyzer/conf.py
@@ -14,6 +14,10 @@
import sys, os
from datetime import date
+from llvm_sphinx import * # see llvm-project/utils/docs/README.md
+
+globals().update(common_conf(tags, markdown=Markdown.NEVER))
+
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
@@ -21,25 +25,13 @@
# -- General configuration -----------------------------------------------------
-# If your documentation needs a minimal Sphinx version, state it here.
-# needs_sphinx = '1.0'
-
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = ["sphinx.ext.todo", "sphinx.ext.mathjax"]
-
-# Add any paths that contain templates here, relative to this directory.
-templates_path = ["_templates"]
-
-# The suffix of source filenames.
-source_suffix = ".rst"
+extensions += ["sphinx.ext.todo", "sphinx.ext.mathjax"]
# The encoding of source files.
# source_encoding = 'utf-8-sig'
-# The master toctree document.
-master_doc = "index"
-
# General information about the project.
project = "Clang Static Analyzer"
copyright = "2013-%d, Analyzer Team" % date.today().year
@@ -87,39 +79,23 @@
# -- Options for HTML output ---------------------------------------------------
-# The theme to use for HTML and HTML Help pages. See the documentation for
-# a list of builtin themes.
-html_theme = "haiku"
-
-# Theme options are theme-specific and customize the look and feel of a theme
-# further. For a list of options available for each theme, see the
-# documentation.
-# html_theme_options = {}
+configure_furo(
+ globals(),
+ source_directory="clang/docs/analyzer/",
+ html_title="Clang Static Analyzer",
+)
# Add any paths that contain custom themes here, relative to this directory.
# html_theme_path = []
-# The name for this set of Sphinx documents. If None, it defaults to
-# "<project> v<release> documentation".
-# html_title = None
-
# A shorter title for the navigation bar. Default is the same as html_title.
# html_short_title = None
-# The name of an image file (relative to this directory) to place at the top
-# of the sidebar.
-# html_logo = None
-
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
# html_favicon = None
-# Add any paths that contain custom static files (such as style sheets) here,
-# relative to this directory. They are copied after the builtin static files,
-# so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = []
-
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
# html_last_updated_fmt = '%b %d, %Y'
diff --git a/clang/docs/conf.py b/clang/docs/conf.py
index b80c859d1dbdf..269dc98d2ac59 100644
--- a/clang/docs/conf.py
+++ b/clang/docs/conf.py
@@ -77,39 +77,23 @@
# -- Options for HTML output ---------------------------------------------------
-# The theme to use for HTML and HTML Help pages. See the documentation for
-# a list of builtin themes.
-html_theme = "haiku"
-
-# Theme options are theme-specific and customize the look and feel of a theme
-# further. For a list of options available for each theme, see the
-# documentation.
-# html_theme_options = {}
+configure_furo(
+ globals(),
+ source_directory="clang/docs/",
+ html_title="Clang",
+)
# Add any paths that contain custom themes here, relative to this directory.
# html_theme_path = []
-# The name for this set of Sphinx documents. If None, it defaults to
-# "<project> v<release> documentation".
-# html_title = None
-
# A shorter title for the navigation bar. Default is the same as html_title.
# html_short_title = None
-# The name of an image file (relative to this directory) to place at the top
-# of the sidebar.
-# html_logo = None
-
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
# html_favicon = None
-# Add any paths that contain custom static files (such as style sheets) here,
-# relative to this directory. They are copied after the builtin static files,
-# so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = []
-
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
# html_last_updated_fmt = '%b %d, %Y'
diff --git a/libc/docs/conf.py b/libc/docs/conf.py
index 0aec05980b6f0..47d0d6c917a88 100644
--- a/libc/docs/conf.py
+++ b/libc/docs/conf.py
@@ -90,28 +90,16 @@
# -- Options for HTML output ---------------------------------------------------
-# The theme to use for HTML and HTML Help pages. See the documentation for
-# a list of builtin themes.
-# html_theme = 'haiku'
-html_theme = "furo"
-
-# Theme options are theme-specific and customize the look and feel of a theme
-# further. For a list of options available for each theme, see the
-# documentation.
-html_theme_options = {
- # "Edit this page" links
- "source_repository": "https://github.com/llvm/llvm-project/",
- "source_branch": "main",
- "source_directory": "libc/docs/",
-}
+configure_furo(
+ globals(),
+ source_directory="libc/docs/",
+ html_title="The LLVM C Library",
+ local_static_path=["_static"],
+)
# Add any paths that contain custom themes here, relative to this directory.
# html_theme_path = []
-# The name for this set of Sphinx documents. If None, it defaults to
-# "<project> v<release> documentation".
-html_title = "The LLVM C Library"
-
# A shorter title for the navigation bar. Default is the same as html_title.
# html_short_title = None
@@ -124,15 +112,6 @@
# pixels large.
# html_favicon = None
-# Add any paths that contain custom static files (such as style sheets) here,
-# relative to this directory. They are copied after the builtin static files,
-# so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = ["_static"]
-
-# Custom JS/CSS files
-html_js_files = ["copybutton.js"]
-html_css_files = ["copybutton.css"]
-
# html_context = {
# 'css_files': [
# '_static/libc.css'
diff --git a/llvm/docs/_static/copybutton.css b/llvm/docs/_static/copybutton.css
deleted file mode 100644
index 6851a1a9dd4b2..0000000000000
--- a/llvm/docs/_static/copybutton.css
+++ /dev/null
@@ -1,39 +0,0 @@
-/* Copy-to-clipboard button styles */
-div.highlight {
- position: relative;
-}
-
-button.copybutton {
- position: absolute;
- top: 0.4em;
- right: 0.4em;
- padding: 0.3em 0.4em;
- background: var(--color-background-secondary, #f0f0f0);
- border: 1px solid var(--color-foreground-border, #ccc);
- border-radius: 4px;
- cursor: pointer;
- opacity: 0;
- transition: opacity 0.2s, background 0.15s;
- line-height: 1;
- color: var(--color-foreground-secondary, #555);
-}
-
-div.highlight:hover button.copybutton,
-button.copybutton:focus {
- opacity: 1;
-}
-
-button.copybutton:hover {
- background: var(--color-background-hover, #e0e0e0);
-}
-
-button.copybutton.copied {
- color: var(--color-brand-primary, #2980b9);
- opacity: 1;
-}
-
-button.copybutton svg {
- display: block;
- pointer-events: none;
- fill: currentColor;
-}
diff --git a/llvm/docs/_static/copybutton.js b/llvm/docs/_static/copybutton.js
deleted file mode 100644
index 6103fec62b6f8..0000000000000
--- a/llvm/docs/_static/copybutton.js
+++ /dev/null
@@ -1,56 +0,0 @@
-// Simple "copy to clipboard" button for code blocks.
-// Adds a button to each <div class="highlight"> block.
-(function () {
- "use strict";
-
- function addCopyButton(block) {
- var button = document.createElement("button");
- button.className = "copybutton";
- button.title = "Copy";
- button.setAttribute("aria-label", "Copy code to clipboard");
- button.innerHTML =
- '<svg aria-hidden="true" height="16" viewBox="0 0 16 16" width="16">' +
- '<path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 ' +
- "0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 " +
- "0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z" +
- '"/><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 ' +
- "1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 " +
- ".138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z" +
- '"/></svg>';
-
- button.addEventListener("click", function () {
- var code = block.querySelector("pre").innerText;
- navigator.clipboard.writeText(code).then(
- function () {
- button.classList.add("copied");
- setTimeout(function () {
- button.classList.remove("copied");
- }, 2000);
- },
- function () {
- // Fallback for older browsers
- var ta = document.createElement("textarea");
- ta.value = code;
- ta.style.position = "fixed";
- ta.style.opacity = "0";
- document.body.appendChild(ta);
- ta.focus();
- ta.select();
- document.execCommand("copy");
- document.body.removeChild(ta);
- button.classList.add("copied");
- setTimeout(function () {
- button.classList.remove("copied");
- }, 2000);
- }
- );
- });
-
- block.style.position = "relative";
- block.appendChild(button);
- }
-
- document.addEventListener("DOMContentLoaded", function () {
- document.querySelectorAll("div.highlight").forEach(addCopyButton);
- });
-})();
diff --git a/llvm/docs/_static/custom.css b/llvm/docs/_static/custom.css
deleted file mode 100644
index 91ff8f26bb8c0..0000000000000
--- a/llvm/docs/_static/custom.css
+++ /dev/null
@@ -1,71 +0,0 @@
-/* Enable flexible wide-viewing for Furo theme. */
-:root {
- /* Remove Furo's default max-width for the content area. */
- --content-width: none;
-}
-
-/* These settings seem to reasonably balance between readability and content
- * density for wide screens. */
-.page .sidebar-drawer {
- width: unset;
-}
-.main .toc-drawer {
- min-width: 15em;
-}
-
-/* Ensure the main content area is allowed to shrink/not-overflow
- its grid cell, preventing it from pushing the TOC sidebar away. */
-.main, .content {
- min-width: 0;
- max-width: 100%;
-
- /* Remove default width setting from furo's content. */
- width: unset;
-}
-
-/* Disable small margin added by various UA stylesheets to prevent
- * scrolling artifacts. */
-body {
- margin: 0;
-}
-
-/* Allow the top-level container to fill the entire browser width. */
-.page {
- max-width: none;
-}
-
-/* Ensure wide tables and code blocks have their own scrollbars
- instead of forcing the container to expand beyond the viewport. */
-.content table,
-.content .literal-block,
-.content .highlight {
- max-width: 100%;
- overflow-x: auto;
- display: block;
-}
-
-/* Ensure paragraphs wrap within the content area. */
-.content p {
- overflow-wrap: break-word;
-}
-
-/* Pygments emits Error tokens that the theme's style renders as
- red-bordered boxes. Render them like ordinary code text instead. */
-body[data-theme="dark"] .highlight .err,
-.highlight .err {
- border: none;
- background-color: transparent;
- color: inherit;
-}
-
-/* Printing support. */
- at media print {
- pre {
- white-space: pre-wrap !important;
- }
- .content-icon-container,
- .skip-to-content,
- .back-to-top {
- display: none !important;
- }
-}
diff --git a/llvm/docs/conf.py b/llvm/docs/conf.py
index f12ba64ec1203..c9cc4dd333700 100644
--- a/llvm/docs/conf.py
+++ b/llvm/docs/conf.py
@@ -75,50 +75,25 @@
# -- Options for HTML output ---------------------------------------------------
-# The theme to use for HTML and HTML Help pages. See the documentation for
-# a list of builtin themes.
-html_theme = "furo"
-
-# Theme options are theme-specific and customize the look and feel of a theme
-# further. For a list of options available for each theme, see the
-# documentation.
-html_theme_options = {
- "source_repository": "https://github.com/llvm/llvm-project",
- "source_branch": "main",
- "source_directory": "llvm/docs/",
-}
+configure_furo(
+ globals(),
+ source_directory="llvm/docs/",
+ html_title="LLVM",
+ html_logo="_static/LLVMWyvernSmall.png",
+ local_static_path=["_static"],
+)
# Add any paths that contain custom themes here, relative to this directory.
# html_theme_path = ["_themes"]
-# The name for this set of Sphinx documents. If None, it defaults to
-# "<project> v<release> documentation".
-html_title = "LLVM"
-
# A shorter title for the navigation bar. Default is the same as html_title.
# html_short_title = None
-# The name of an image file (relative to this directory) to place at the top
-# of the sidebar.
-html_logo = "_static/LLVMWyvernSmall.png"
-
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
# html_favicon = None
-# Add any paths that contain custom static files (such as style sheets) here,
-# relative to this directory. They are copied after the builtin static files,
-# so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = ["_static"]
-
-html_js_files = ["copybutton.js"]
-
-html_css_files = [
- "copybutton.css",
- "custom.css",
-]
-
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
html_last_updated_fmt = "%Y-%m-%d"
diff --git a/utils/docs/llvm_sphinx/__init__.py b/utils/docs/llvm_sphinx/__init__.py
index 18aa330dc071b..a97d945611047 100644
--- a/utils/docs/llvm_sphinx/__init__.py
+++ b/utils/docs/llvm_sphinx/__init__.py
@@ -18,7 +18,7 @@
"""
import sys
-from typing import Any, Dict, TYPE_CHECKING
+from typing import Any, Dict, Iterable, Optional
from enum import Enum, auto
from sphinx.util.tags import Tags
from llvm_sphinx.help import venv_help
@@ -65,6 +65,40 @@ def common_conf(tags: Tags, markdown=Markdown.ALWAYS) -> Dict[str, Any]:
return locals()
+def _append_unique(target, entries):
+ for entry in entries:
+ if entry not in target:
+ target.append(entry)
+
+
+def configure_furo(
+ conf: Dict[str, Any],
+ *,
+ source_directory: str,
+ html_title: str,
+ html_logo: Optional[str] = None,
+ local_static_path: Iterable[str] = (),
+ extra_css_files: Iterable[str] = (),
+ extra_js_files: Iterable[str] = (),
+) -> None:
+ """Configure the shared Furo theme setup for LLVM Sphinx projects."""
+ extensions = conf.setdefault("extensions", [])
+ _append_unique(extensions, ["llvm_sphinx.ext.furo"])
+
+ conf["html_theme"] = "furo"
+ conf["html_theme_options"] = {
+ "source_repository": "https://github.com/llvm/llvm-project",
+ "source_branch": "main",
+ "source_directory": source_directory,
+ }
+ conf["html_title"] = html_title
+ if html_logo is not None:
+ conf["html_logo"] = html_logo
+ conf["html_static_path"] = list(local_static_path)
+ conf["html_css_files"] = list(extra_css_files)
+ conf["html_js_files"] = list(extra_js_files)
+
+
# Some of our markdown documentation numbers section titles
# This helpers is used by myst to remove that numbering from the anchor links.
def make_slug(s: str) -> str:
diff --git a/libc/docs/_static/copybutton.css b/utils/docs/llvm_sphinx/_static/copybutton.css
similarity index 100%
rename from libc/docs/_static/copybutton.css
rename to utils/docs/llvm_sphinx/_static/copybutton.css
diff --git a/libc/docs/_static/copybutton.js b/utils/docs/llvm_sphinx/_static/copybutton.js
similarity index 98%
rename from libc/docs/_static/copybutton.js
rename to utils/docs/llvm_sphinx/_static/copybutton.js
index 6103fec62b6f8..92f730aca8172 100644
--- a/libc/docs/_static/copybutton.js
+++ b/utils/docs/llvm_sphinx/_static/copybutton.js
@@ -28,7 +28,7 @@
}, 2000);
},
function () {
- // Fallback for older browsers
+ // Fallback for older browsers.
var ta = document.createElement("textarea");
ta.value = code;
ta.style.position = "fixed";
diff --git a/utils/docs/llvm_sphinx/_static/furo-common.css b/utils/docs/llvm_sphinx/_static/furo-common.css
new file mode 100644
index 0000000000000..26d3da3445de0
--- /dev/null
+++ b/utils/docs/llvm_sphinx/_static/furo-common.css
@@ -0,0 +1,140 @@
+/* Enable flexible wide-viewing for Furo theme. */
+:root {
+ /* Remove Furo's default max-width for the content area. */
+ --content-width: none;
+}
+
+/* These settings seem to reasonably balance between readability and content
+ * density for wide screens. */
+.page .sidebar-drawer {
+ width: unset;
+}
+
+.main .toc-drawer {
+ min-width: 15em;
+}
+
+/* Ensure the main content area is allowed to shrink/not-overflow
+ its grid cell, preventing it from pushing the TOC sidebar away. */
+.main,
+.content {
+ min-width: 0;
+ max-width: 100%;
+
+ /* Remove default width setting from Furo's content. */
+ width: unset;
+}
+
+.main > .content {
+ box-sizing: border-box;
+ flex: 1 1 auto;
+}
+
+/* Disable small margin added by various UA stylesheets to prevent
+ * scrolling artifacts. */
+body {
+ margin: 0;
+}
+
+/* Allow the top-level container to fill the entire browser width. */
+.page {
+ max-width: none;
+}
+
+/* Ensure wide tables and code blocks have their own scrollbars
+ instead of forcing the container to expand beyond the viewport. */
+.content table,
+.content .literal-block,
+.content .highlight {
+ max-width: 100%;
+ overflow-x: auto;
+ display: block;
+}
+
+/* Ensure paragraphs wrap within the content area. */
+.content p {
+ overflow-wrap: break-word;
+}
+
+/* Pygments emits Error tokens that the theme's style renders as
+ red-bordered boxes. Render them like ordinary code text instead. */
+body[data-theme="dark"] .highlight .err,
+.highlight .err {
+ border: none;
+ background-color: transparent;
+ color: inherit;
+}
+
+/* Some pages use red/green comparison tables for bad and corrected code.
+ Keep the surfaces theme-aware so Pygments colors stay readable. */
+body {
+ --llvm-code-comparison-bad-background: #fff1f1;
+ --llvm-code-comparison-bad-border: #d73a49;
+ --llvm-code-comparison-good-background: #eef9ee;
+ --llvm-code-comparison-good-border: #2da44e;
+}
+
+body[data-theme="dark"] {
+ --llvm-code-comparison-bad-background: rgba(248, 81, 73, 0.16);
+ --llvm-code-comparison-bad-border: #f85149;
+ --llvm-code-comparison-good-background: rgba(63, 185, 80, 0.16);
+ --llvm-code-comparison-good-border: #3fb950;
+}
+
+.content table.colored-code-table td,
+.content table.colored-code-table th {
+ text-align: left;
+}
+
+.content table.colored-code-table td:first-child,
+.content table.colored-code-table th:first-child {
+ background-color: var(--llvm-code-comparison-bad-background);
+}
+
+.content table.colored-code-table td:nth-child(2),
+.content table.colored-code-table th:nth-child(2) {
+ background-color: var(--llvm-code-comparison-good-background);
+}
+
+.content table.colored-code-table td .highlight,
+.content table.colored-code-table td pre {
+ background-color: transparent;
+ border: none;
+}
+
+.content div.bad-code,
+.content div.good-code {
+ padding: 5px;
+ text-align: left;
+}
+
+.content div.bad-code {
+ background-color: var(--llvm-code-comparison-bad-background);
+ border-left: 4px solid var(--llvm-code-comparison-bad-border);
+}
+
+.content div.good-code {
+ background-color: var(--llvm-code-comparison-good-background);
+ border-left: 4px solid var(--llvm-code-comparison-good-border);
+}
+
+.content div.bad-code .highlight,
+.content div.bad-code pre,
+.content div.good-code .highlight,
+.content div.good-code pre {
+ background-color: transparent;
+ border: none;
+}
+
+/* Printing support. */
+ at media print {
+ pre {
+ white-space: pre-wrap !important;
+ }
+
+ .content-icon-container,
+ .skip-to-content,
+ .back-to-top {
+ display: none !important;
+ }
+}
diff --git a/utils/docs/llvm_sphinx/ext/furo.py b/utils/docs/llvm_sphinx/ext/furo.py
new file mode 100644
index 0000000000000..13c76fe4865ab
--- /dev/null
+++ b/utils/docs/llvm_sphinx/ext/furo.py
@@ -0,0 +1,37 @@
+"""Shared Furo theme assets for LLVM Sphinx projects."""
+
+from pathlib import Path
+
+from sphinx.util.fileutil import copy_asset
+
+_SHARED_STATIC_PREFIX = "llvm-sphinx"
+_SHARED_STATIC_DIR = Path(__file__).parents[1] / "_static"
+
+
+def _add_shared_static_files(app):
+ if app.builder.format != "html":
+ return
+
+ app.add_js_file(f"{_SHARED_STATIC_PREFIX}/copybutton.js")
+ app.add_css_file(f"{_SHARED_STATIC_PREFIX}/copybutton.css")
+ app.add_css_file(f"{_SHARED_STATIC_PREFIX}/furo-common.css")
+
+
+def _copy_shared_static_files(app, exception):
+ if exception is not None or app.builder.format != "html":
+ return
+
+ copy_asset(
+ str(_SHARED_STATIC_DIR),
+ str(Path(app.builder.outdir) / "_static" / _SHARED_STATIC_PREFIX),
+ )
+
+
+def setup(app):
+ app.connect("builder-inited", _add_shared_static_files)
+ app.connect("build-finished", _copy_shared_static_files)
+ return {
+ "version": "1.0",
+ "parallel_read_safe": True,
+ "parallel_write_safe": True,
+ }
>From 2aa7480daece5a6cf64d84be6bf7057dc8702172 Mon Sep 17 00:00:00 2001
From: Reid Kleckner <rkleckner at nvidia.com>
Date: Mon, 17 Aug 2026 18:00:39 +0000
Subject: [PATCH 2/3] [docs] Restore project-specific Furo CSS
---
clang/docs/_static/custom.css | 60 ++++++++
clang/docs/analyzer/conf.py | 3 +
clang/docs/conf.py | 3 +
llvm/docs/_static/custom.css | 71 +++++++++
llvm/docs/conf.py | 3 +-
utils/docs/llvm_sphinx/__init__.py | 8 +
.../llvm_sphinx}/_static/LLVMWyvernSmall.png | Bin
.../docs/llvm_sphinx/_static/furo-common.css | 140 ------------------
utils/docs/llvm_sphinx/ext/furo.py | 1 -
9 files changed, 147 insertions(+), 142 deletions(-)
create mode 100644 clang/docs/_static/custom.css
create mode 100644 llvm/docs/_static/custom.css
rename {llvm/docs => utils/docs/llvm_sphinx}/_static/LLVMWyvernSmall.png (100%)
delete mode 100644 utils/docs/llvm_sphinx/_static/furo-common.css
diff --git a/clang/docs/_static/custom.css b/clang/docs/_static/custom.css
new file mode 100644
index 0000000000000..960c1dd5e5f9f
--- /dev/null
+++ b/clang/docs/_static/custom.css
@@ -0,0 +1,60 @@
+/* Some Clang pages use red/green comparison tables for bad and corrected code.
+ Keep the surfaces theme-aware so Pygments colors stay readable. */
+body {
+ --clang-code-comparison-bad-background: #fff1f1;
+ --clang-code-comparison-bad-border: #d73a49;
+ --clang-code-comparison-good-background: #eef9ee;
+ --clang-code-comparison-good-border: #2da44e;
+}
+
+body[data-theme="dark"] {
+ --clang-code-comparison-bad-background: rgba(248, 81, 73, 0.16);
+ --clang-code-comparison-bad-border: #f85149;
+ --clang-code-comparison-good-background: rgba(63, 185, 80, 0.16);
+ --clang-code-comparison-good-border: #3fb950;
+}
+
+.content table.colored-code-table td,
+.content table.colored-code-table th {
+ text-align: left;
+}
+
+.content table.colored-code-table td:first-child,
+.content table.colored-code-table th:first-child {
+ background-color: var(--clang-code-comparison-bad-background);
+}
+
+.content table.colored-code-table td:nth-child(2),
+.content table.colored-code-table th:nth-child(2) {
+ background-color: var(--clang-code-comparison-good-background);
+}
+
+.content table.colored-code-table td .highlight,
+.content table.colored-code-table td pre {
+ background-color: transparent;
+ border: none;
+}
+
+.content div.bad-code,
+.content div.good-code {
+ padding: 5px;
+ text-align: left;
+}
+
+.content div.bad-code {
+ background-color: var(--clang-code-comparison-bad-background);
+ border-left: 4px solid var(--clang-code-comparison-bad-border);
+}
+
+.content div.good-code {
+ background-color: var(--clang-code-comparison-good-background);
+ border-left: 4px solid var(--clang-code-comparison-good-border);
+}
+
+.content div.bad-code .highlight,
+.content div.bad-code pre,
+.content div.good-code .highlight,
+.content div.good-code pre {
+ background-color: transparent;
+ border: none;
+}
diff --git a/clang/docs/analyzer/conf.py b/clang/docs/analyzer/conf.py
index c9ecbec5118f0..38cf375920bde 100644
--- a/clang/docs/analyzer/conf.py
+++ b/clang/docs/analyzer/conf.py
@@ -83,6 +83,9 @@
globals(),
source_directory="clang/docs/analyzer/",
html_title="Clang Static Analyzer",
+ html_logo=shared_static_asset("LLVMWyvernSmall.png"),
+ local_static_path=["../_static"],
+ extra_css_files=["custom.css"],
)
# Add any paths that contain custom themes here, relative to this directory.
diff --git a/clang/docs/conf.py b/clang/docs/conf.py
index 269dc98d2ac59..898fd0ec5d513 100644
--- a/clang/docs/conf.py
+++ b/clang/docs/conf.py
@@ -81,6 +81,9 @@
globals(),
source_directory="clang/docs/",
html_title="Clang",
+ html_logo=shared_static_asset("LLVMWyvernSmall.png"),
+ local_static_path=["_static"],
+ extra_css_files=["custom.css"],
)
# Add any paths that contain custom themes here, relative to this directory.
diff --git a/llvm/docs/_static/custom.css b/llvm/docs/_static/custom.css
new file mode 100644
index 0000000000000..91ff8f26bb8c0
--- /dev/null
+++ b/llvm/docs/_static/custom.css
@@ -0,0 +1,71 @@
+/* Enable flexible wide-viewing for Furo theme. */
+:root {
+ /* Remove Furo's default max-width for the content area. */
+ --content-width: none;
+}
+
+/* These settings seem to reasonably balance between readability and content
+ * density for wide screens. */
+.page .sidebar-drawer {
+ width: unset;
+}
+.main .toc-drawer {
+ min-width: 15em;
+}
+
+/* Ensure the main content area is allowed to shrink/not-overflow
+ its grid cell, preventing it from pushing the TOC sidebar away. */
+.main, .content {
+ min-width: 0;
+ max-width: 100%;
+
+ /* Remove default width setting from furo's content. */
+ width: unset;
+}
+
+/* Disable small margin added by various UA stylesheets to prevent
+ * scrolling artifacts. */
+body {
+ margin: 0;
+}
+
+/* Allow the top-level container to fill the entire browser width. */
+.page {
+ max-width: none;
+}
+
+/* Ensure wide tables and code blocks have their own scrollbars
+ instead of forcing the container to expand beyond the viewport. */
+.content table,
+.content .literal-block,
+.content .highlight {
+ max-width: 100%;
+ overflow-x: auto;
+ display: block;
+}
+
+/* Ensure paragraphs wrap within the content area. */
+.content p {
+ overflow-wrap: break-word;
+}
+
+/* Pygments emits Error tokens that the theme's style renders as
+ red-bordered boxes. Render them like ordinary code text instead. */
+body[data-theme="dark"] .highlight .err,
+.highlight .err {
+ border: none;
+ background-color: transparent;
+ color: inherit;
+}
+
+/* Printing support. */
+ at media print {
+ pre {
+ white-space: pre-wrap !important;
+ }
+ .content-icon-container,
+ .skip-to-content,
+ .back-to-top {
+ display: none !important;
+ }
+}
diff --git a/llvm/docs/conf.py b/llvm/docs/conf.py
index c9cc4dd333700..0a618b2643e0a 100644
--- a/llvm/docs/conf.py
+++ b/llvm/docs/conf.py
@@ -79,8 +79,9 @@
globals(),
source_directory="llvm/docs/",
html_title="LLVM",
- html_logo="_static/LLVMWyvernSmall.png",
+ html_logo=shared_static_asset("LLVMWyvernSmall.png"),
local_static_path=["_static"],
+ extra_css_files=["custom.css"],
)
# Add any paths that contain custom themes here, relative to this directory.
diff --git a/utils/docs/llvm_sphinx/__init__.py b/utils/docs/llvm_sphinx/__init__.py
index a97d945611047..2693218931b43 100644
--- a/utils/docs/llvm_sphinx/__init__.py
+++ b/utils/docs/llvm_sphinx/__init__.py
@@ -18,11 +18,14 @@
"""
import sys
+from pathlib import Path
from typing import Any, Dict, Iterable, Optional
from enum import Enum, auto
from sphinx.util.tags import Tags
from llvm_sphinx.help import venv_help
+_SHARED_STATIC_DIR = Path(__file__).parent / "_static"
+
class Markdown(Enum):
ALWAYS = auto()
@@ -99,6 +102,11 @@ def configure_furo(
conf["html_js_files"] = list(extra_js_files)
+def shared_static_asset(filename: str) -> str:
+ """Return an absolute path to a shared LLVM Sphinx static asset."""
+ return str(_SHARED_STATIC_DIR / filename)
+
+
# Some of our markdown documentation numbers section titles
# This helpers is used by myst to remove that numbering from the anchor links.
def make_slug(s: str) -> str:
diff --git a/llvm/docs/_static/LLVMWyvernSmall.png b/utils/docs/llvm_sphinx/_static/LLVMWyvernSmall.png
similarity index 100%
rename from llvm/docs/_static/LLVMWyvernSmall.png
rename to utils/docs/llvm_sphinx/_static/LLVMWyvernSmall.png
diff --git a/utils/docs/llvm_sphinx/_static/furo-common.css b/utils/docs/llvm_sphinx/_static/furo-common.css
deleted file mode 100644
index 26d3da3445de0..0000000000000
--- a/utils/docs/llvm_sphinx/_static/furo-common.css
+++ /dev/null
@@ -1,140 +0,0 @@
-/* Enable flexible wide-viewing for Furo theme. */
-:root {
- /* Remove Furo's default max-width for the content area. */
- --content-width: none;
-}
-
-/* These settings seem to reasonably balance between readability and content
- * density for wide screens. */
-.page .sidebar-drawer {
- width: unset;
-}
-
-.main .toc-drawer {
- min-width: 15em;
-}
-
-/* Ensure the main content area is allowed to shrink/not-overflow
- its grid cell, preventing it from pushing the TOC sidebar away. */
-.main,
-.content {
- min-width: 0;
- max-width: 100%;
-
- /* Remove default width setting from Furo's content. */
- width: unset;
-}
-
-.main > .content {
- box-sizing: border-box;
- flex: 1 1 auto;
-}
-
-/* Disable small margin added by various UA stylesheets to prevent
- * scrolling artifacts. */
-body {
- margin: 0;
-}
-
-/* Allow the top-level container to fill the entire browser width. */
-.page {
- max-width: none;
-}
-
-/* Ensure wide tables and code blocks have their own scrollbars
- instead of forcing the container to expand beyond the viewport. */
-.content table,
-.content .literal-block,
-.content .highlight {
- max-width: 100%;
- overflow-x: auto;
- display: block;
-}
-
-/* Ensure paragraphs wrap within the content area. */
-.content p {
- overflow-wrap: break-word;
-}
-
-/* Pygments emits Error tokens that the theme's style renders as
- red-bordered boxes. Render them like ordinary code text instead. */
-body[data-theme="dark"] .highlight .err,
-.highlight .err {
- border: none;
- background-color: transparent;
- color: inherit;
-}
-
-/* Some pages use red/green comparison tables for bad and corrected code.
- Keep the surfaces theme-aware so Pygments colors stay readable. */
-body {
- --llvm-code-comparison-bad-background: #fff1f1;
- --llvm-code-comparison-bad-border: #d73a49;
- --llvm-code-comparison-good-background: #eef9ee;
- --llvm-code-comparison-good-border: #2da44e;
-}
-
-body[data-theme="dark"] {
- --llvm-code-comparison-bad-background: rgba(248, 81, 73, 0.16);
- --llvm-code-comparison-bad-border: #f85149;
- --llvm-code-comparison-good-background: rgba(63, 185, 80, 0.16);
- --llvm-code-comparison-good-border: #3fb950;
-}
-
-.content table.colored-code-table td,
-.content table.colored-code-table th {
- text-align: left;
-}
-
-.content table.colored-code-table td:first-child,
-.content table.colored-code-table th:first-child {
- background-color: var(--llvm-code-comparison-bad-background);
-}
-
-.content table.colored-code-table td:nth-child(2),
-.content table.colored-code-table th:nth-child(2) {
- background-color: var(--llvm-code-comparison-good-background);
-}
-
-.content table.colored-code-table td .highlight,
-.content table.colored-code-table td pre {
- background-color: transparent;
- border: none;
-}
-
-.content div.bad-code,
-.content div.good-code {
- padding: 5px;
- text-align: left;
-}
-
-.content div.bad-code {
- background-color: var(--llvm-code-comparison-bad-background);
- border-left: 4px solid var(--llvm-code-comparison-bad-border);
-}
-
-.content div.good-code {
- background-color: var(--llvm-code-comparison-good-background);
- border-left: 4px solid var(--llvm-code-comparison-good-border);
-}
-
-.content div.bad-code .highlight,
-.content div.bad-code pre,
-.content div.good-code .highlight,
-.content div.good-code pre {
- background-color: transparent;
- border: none;
-}
-
-/* Printing support. */
- at media print {
- pre {
- white-space: pre-wrap !important;
- }
-
- .content-icon-container,
- .skip-to-content,
- .back-to-top {
- display: none !important;
- }
-}
diff --git a/utils/docs/llvm_sphinx/ext/furo.py b/utils/docs/llvm_sphinx/ext/furo.py
index 13c76fe4865ab..7bb876c448daa 100644
--- a/utils/docs/llvm_sphinx/ext/furo.py
+++ b/utils/docs/llvm_sphinx/ext/furo.py
@@ -14,7 +14,6 @@ def _add_shared_static_files(app):
app.add_js_file(f"{_SHARED_STATIC_PREFIX}/copybutton.js")
app.add_css_file(f"{_SHARED_STATIC_PREFIX}/copybutton.css")
- app.add_css_file(f"{_SHARED_STATIC_PREFIX}/furo-common.css")
def _copy_shared_static_files(app, exception):
>From 7299aafbc2c084a99e7a7088cae2207675389cfd Mon Sep 17 00:00:00 2001
From: Reid Kleckner <rkleckner at nvidia.com>
Date: Tue, 18 Aug 2026 02:52:28 +0000
Subject: [PATCH 3/3] Fix text color in dark mode
---
clang/docs/UsersManual.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/docs/UsersManual.md b/clang/docs/UsersManual.md
index a6c11683f5395..e8070277dd958 100644
--- a/clang/docs/UsersManual.md
+++ b/clang/docs/UsersManual.md
@@ -275,7 +275,7 @@ specific parts of the diagnostic, e.g.,
::::{raw} html
<pre>
- <b><span style="color:black">test.c:28:8: <span style="color:magenta">warning</span>: extra tokens at end of #endif directive [-Wextra-tokens]</span></b>
+ <b>test.c:28:8: <span style="color:magenta">warning</span>: extra tokens at end of #endif directive [-Wextra-tokens]</b>
#endif bad
<span style="color:green">^</span>
<span style="color:green">//</span>
More information about the llvm-branch-commits
mailing list