-
Notifications
You must be signed in to change notification settings - Fork 6.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
doc: extensions: Add Doxygen tooltips to main documentation
Add Doxygen tooltips in the main documentation. The tooltips are triggered when hovering over C symbols in the documentation and display a preview of the Doxygen documentation for the symbol. Some shadow DOM magic is needed to style the tooltips correctly, without affecting the rest of the page. Signed-off-by: Benjamin Cabé <benjamin@zephyrproject.org>
- Loading branch information
Showing
6 changed files
with
221 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
""" | ||
Doxygen Tooltip Extension | ||
######################### | ||
Copyright (c) 2024 The Linux Foundation | ||
SPDX-License-Identifier: Apache-2.0 | ||
A simple Sphinx extension that adds JS and CSS resources to the app | ||
to enable tooltips for C domain links. | ||
""" | ||
|
||
from pathlib import Path | ||
|
||
from typing import Any, Dict | ||
|
||
from sphinx.application import Sphinx | ||
from sphinx.util import logging | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
RESOURCES_DIR = Path(__file__).parent / "static" | ||
|
||
def setup(app: Sphinx) -> Dict[str, Any]: | ||
app.config.html_static_path.append(RESOURCES_DIR.as_posix()) | ||
|
||
app.add_js_file("tippy/popper.min.js") | ||
app.add_js_file("tippy/tippy-bundle.umd.min.js") | ||
|
||
app.add_js_file("doxytooltip.js") | ||
app.add_css_file("doxytooltip.css") | ||
|
||
return { | ||
"version": "0.1", | ||
"parallel_read_safe": True, | ||
"parallel_write_safe": True, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
.tippy-box[data-theme~='doxytooltip'] { | ||
/* provide minimal definition of the CSS variables used by Doxygen Awesome so that we have a | ||
look and feel that's consistent with the rest of the documentation without necessarily aiming | ||
for full fidelity */ | ||
--font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', Courier, monospace; | ||
--primary-color: var(--navbar-heading-color); | ||
--param-color: var(--code-literal-color); | ||
--border-radius-small: 4px; | ||
--border-radius-medium: 6px; | ||
--border-radius-large: 8px; | ||
|
||
background-color: var(--content-wrap-background-color); | ||
color: var(--body-color); | ||
} | ||
|
||
.tippy-box[data-theme~='doxytooltip'][data-placement^='top']>.tippy-arrow::before { | ||
border-top-color: var(--content-wrap-background-color); | ||
} | ||
|
||
.tippy-box[data-theme~='doxytooltip'][data-placement^='bottom']>.tippy-arrow::before { | ||
border-bottom-color: var(--content-wrap-background-color); | ||
} | ||
|
||
.tippy-box[data-theme~='doxytooltip'][data-placement^='left']>.tippy-arrow::before { | ||
border-left-color: var(--content-wrap-background-color); | ||
} | ||
|
||
.tippy-box[data-theme~='doxytooltip'][data-placement^='right']>.tippy-arrow::before { | ||
border-right-color: var(--content-wrap-background-color); | ||
} | ||
|
||
.tippy-box[data-theme~='doxytooltip'] .tippy-content { | ||
font-size: 0.9em; | ||
max-height: 300px; | ||
overflow-y: scroll; | ||
} |
133 changes: 133 additions & 0 deletions
133
doc/_extensions/zephyr/doxytooltip/static/doxytooltip.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
/** | ||
* Copyright (c) 2024, Benjamin Cabé <benjamin@zephyrproject.org> | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* This script adds mouse hover hooks to the current page to display | ||
* Doxygen documentation as tooltips when hovering over a symbol in the | ||
* documentation. | ||
*/ | ||
|
||
registerDoxygenTooltip = function () { | ||
const parser = new DOMParser(); | ||
|
||
const tooltip = document.createElement('div'); | ||
tooltip.id = 'doxytooltip'; | ||
document.body.appendChild(tooltip); | ||
|
||
const tooltipShadow = document.createElement('div'); | ||
tooltipShadow.id = 'doxytooltip-shadow'; | ||
tooltip.attachShadow({ mode: 'open' }).appendChild(tooltipShadow); | ||
|
||
/* tippy's JS code automatically adds a <style> tag to the document's <head> with the | ||
* styles for the tooltips. We need to copy it to the tooltip's shadow DOM for it to apply to the | ||
* tooltip's content. | ||
*/ | ||
const tippyStyle = document.querySelector('style[data-tippy-stylesheet]'); | ||
if (tippyStyle) { | ||
tooltipShadow.appendChild(tippyStyle.cloneNode(true)); | ||
tippyStyle.remove(); | ||
} | ||
|
||
/* | ||
* similarly, doxytooltip.css is added to the document's <head> by the Sphinx extension, but we | ||
* need it in the shadow DOM. | ||
*/ | ||
const doxytooltipStyle = document.querySelector('link[href*="doxytooltip.css"]'); | ||
if (doxytooltipStyle) { | ||
tooltipShadow.appendChild(doxytooltipStyle.cloneNode(true)); | ||
doxytooltipStyle.remove(); | ||
} | ||
|
||
let firstTimeShowingTooltip = true; | ||
let links = Array.from(document.querySelectorAll('a.reference.internal')).filter((a) => | ||
a.querySelector('code.c') | ||
); | ||
links.forEach((link) => { | ||
tippy(link, { | ||
content: "Loading...", | ||
allowHTML: true, | ||
maxWidth: '500px', | ||
placement: 'auto', | ||
trigger: 'mouseenter', | ||
touch: false, | ||
theme: 'doxytooltip', | ||
interactive: true, | ||
appendTo: () => | ||
document | ||
.querySelector('#doxytooltip') | ||
.shadowRoot.getElementById('doxytooltip-shadow'), | ||
|
||
onShow(instance) { | ||
const url = link.getAttribute('href'); | ||
const targetId = link.getAttribute('href').split('#')[1]; | ||
|
||
fetch(url) | ||
.then((response) => response.text()) | ||
.then((data) => { | ||
const parsedDoc = parser.parseFromString(data, 'text/html'); | ||
|
||
if (firstTimeShowingTooltip) { | ||
/* Grab the main stylesheets from the Doxygen page and inject them in the tooltip's | ||
shadow DOM */ | ||
const doxygenCSSNames = ['doxygen-awesome.css', 'doxygen-awesome-zephyr.css']; | ||
for (const cssName of doxygenCSSNames) { | ||
const cssLink = parsedDoc.querySelector(`link[href$="${cssName}"]`); | ||
if (cssLink) { | ||
const link = document.createElement('link'); | ||
link.rel = 'stylesheet'; | ||
link.href = new URL( | ||
cssLink.getAttribute('href'), | ||
new URL(url, window.location.href) | ||
); | ||
tooltipShadow.appendChild(link); | ||
} | ||
} | ||
|
||
firstTimeShowingTooltip = false; | ||
} | ||
|
||
const codeClasses = link.getElementsByTagName('code')[0].classList; | ||
let content; | ||
if (codeClasses.contains('c-enumerator')) { | ||
const target = parsedDoc.querySelector(`tr td a[id="${targetId}"]`); | ||
if (target) { | ||
content = target.parentElement.nextElementSibling; | ||
} | ||
} else if (codeClasses.contains('c-struct')) { | ||
content = parsedDoc.querySelector(`#details ~ div.textblock`); | ||
} else { | ||
/* c-function, c-type, etc. */ | ||
const target = parsedDoc.querySelector( | ||
`h2.memtitle span.permalink a[href="#${targetId}"]` | ||
); | ||
if (target) { | ||
content = target.closest('h2').nextElementSibling; | ||
} | ||
} | ||
|
||
if (content) { | ||
// rewrite all relative links as they are originally relative to the Doxygen page | ||
content.querySelectorAll('a').forEach((a) => { | ||
const href = a.getAttribute('href'); | ||
if (href && !href.startsWith('http')) { | ||
a.href = new URL(href, new URL(url, window.location.href)); | ||
} | ||
}); | ||
|
||
// set the tooltip content | ||
instance.setContent(content.cloneNode(true).innerHTML); | ||
} else { | ||
// don't show tooltip if no meaningful content was found (ex. no brief description) | ||
instance.setContent(null); | ||
return false; | ||
} | ||
}) | ||
.catch((err) => { | ||
console.error('Failed to fetch the documentation:', err); | ||
}); | ||
}, | ||
}); | ||
}); | ||
}; | ||
|
||
document.addEventListener('DOMContentLoaded', registerDoxygenTooltip); |
8 changes: 8 additions & 0 deletions
8
doc/_extensions/zephyr/doxytooltip/static/tippy/popper.min.js
Large diffs are not rendered by default.
Oops, something went wrong.
7 changes: 7 additions & 0 deletions
7
doc/_extensions/zephyr/doxytooltip/static/tippy/tippy-bundle.umd.min.js
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters