Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 32115c4

Browse filesBrowse files
authored
Update python-docs-theme to work with Sphinx 5 & 6 (#99)
* Use double quotation marks in ``__init__.py`` * Drop semicolons in ``menu.js`` * Use braces for if-statements in ``menu.js`` * Use double quotation marks in ``menu.js`` * Mark a parameter as unused in ``menu.js`` * Drop jQuery in ``sidebars.js`` * Drop jQuery in ``copybutton.js`` * Introduce ``getHideableCopyButtonElements()`` * Mild JavaScript refactor
1 parent 4609599 commit 32115c4
Copy full SHA for 32115c4

File tree

Expand file treeCollapse file tree

6 files changed

+230
-210
lines changed
Filter options
Expand file treeCollapse file tree

6 files changed

+230
-210
lines changed

‎python_docs_theme/__init__.py

Copy file name to clipboardExpand all lines: python_docs_theme/__init__.py
+3-4Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,11 @@ def _html_page_context(
5252

5353
def setup(app):
5454
current_dir = os.path.abspath(os.path.dirname(__file__))
55-
app.add_html_theme(
56-
'python_docs_theme', current_dir)
55+
app.add_html_theme("python_docs_theme", current_dir)
5756

5857
app.connect("html-page-context", _html_page_context)
5958

6059
return {
61-
'parallel_read_safe': True,
62-
'parallel_write_safe': True,
60+
"parallel_read_safe": True,
61+
"parallel_write_safe": True,
6362
}
+84-56Lines changed: 84 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,92 @@
1-
$(document).ready(function() {
2-
/* Add a [>>>] button on the top-right corner of code samples to hide
1+
// ``function*`` denotes a generator in JavaScript, see
2+
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*
3+
function* getHideableCopyButtonElements(rootElement) {
4+
// yield all elements with the "go" (Generic.Output),
5+
// "gp" (Generic.Prompt), or "gt" (Generic.Traceback) CSS class
6+
for (const el of rootElement.querySelectorAll('.go, .gp, .gt')) {
7+
yield el
8+
}
9+
// tracebacks (.gt) contain bare text elements that need to be
10+
// wrapped in a span to hide or show the element
11+
for (let el of rootElement.querySelectorAll('.gt')) {
12+
while ((el = el.nextSibling) && el.nodeType !== Node.DOCUMENT_NODE) {
13+
// stop wrapping text nodes when we hit the next output or
14+
// prompt element
15+
if (el.nodeType === Node.ELEMENT_NODE && el.matches(".gp, .go")) {
16+
break
17+
}
18+
// if the node is a text node with content, wrap it in a
19+
// span element so that we can control visibility
20+
if (el.nodeType === Node.TEXT_NODE && el.textContent.trim()) {
21+
const wrapper = document.createElement("span")
22+
el.after(wrapper)
23+
wrapper.appendChild(el)
24+
el = wrapper
25+
}
26+
yield el
27+
}
28+
}
29+
}
30+
31+
32+
const loadCopyButton = () => {
33+
/* Add a [>>>] button in the top-right corner of code samples to hide
334
* the >>> and ... prompts and the output and thus make the code
435
* copyable. */
5-
var div = $('.highlight-python .highlight,' +
6-
'.highlight-python3 .highlight,' +
7-
'.highlight-pycon .highlight,' +
8-
'.highlight-pycon3 .highlight,' +
9-
'.highlight-default .highlight');
10-
var pre = div.find('pre');
36+
const hide_text = "Hide the prompts and output"
37+
const show_text = "Show the prompts and output"
1138

12-
// get the styles from the current theme
13-
pre.parent().parent().css('position', 'relative');
14-
var hide_text = 'Hide the prompts and output';
15-
var show_text = 'Show the prompts and output';
16-
var border_width = pre.css('border-top-width');
17-
var border_style = pre.css('border-top-style');
18-
var border_color = pre.css('border-top-color');
19-
var button_styles = {
20-
'cursor':'pointer', 'position': 'absolute', 'top': '0', 'right': '0',
21-
'border-color': border_color, 'border-style': border_style,
22-
'border-width': border_width, 'color': border_color, 'text-size': '75%',
23-
'font-family': 'monospace', 'padding-left': '0.2em', 'padding-right': '0.2em',
24-
'border-radius': '0 3px 0 0'
39+
const button = document.createElement("span")
40+
button.classList.add("copybutton")
41+
button.innerText = ">>>"
42+
button.title = hide_text
43+
button.dataset.hidden = "false"
44+
const buttonClick = event => {
45+
// define the behavior of the button when it's clicked
46+
event.preventDefault()
47+
const buttonEl = event.currentTarget
48+
const codeEl = buttonEl.nextElementSibling
49+
if (buttonEl.dataset.hidden === "false") {
50+
// hide the code output
51+
for (const el of getHideableCopyButtonElements(codeEl)) {
52+
el.hidden = true
53+
}
54+
buttonEl.title = show_text
55+
buttonEl.dataset.hidden = "true"
56+
} else {
57+
// show the code output
58+
for (const el of getHideableCopyButtonElements(codeEl)) {
59+
el.hidden = false
60+
}
61+
buttonEl.title = hide_text
62+
buttonEl.dataset.hidden = "false"
63+
}
2564
}
2665

66+
const highlightedElements = document.querySelectorAll(
67+
".highlight-python .highlight,"
68+
+ ".highlight-python3 .highlight,"
69+
+ ".highlight-pycon .highlight,"
70+
+ ".highlight-pycon3 .highlight,"
71+
+ ".highlight-default .highlight"
72+
)
73+
2774
// create and add the button to all the code blocks that contain >>>
28-
div.each(function(index) {
29-
var jthis = $(this);
30-
if (jthis.find('.gp').length > 0) {
31-
var button = $('<span class="copybutton">&gt;&gt;&gt;</span>');
32-
button.css(button_styles)
33-
button.attr('title', hide_text);
34-
button.data('hidden', 'false');
35-
jthis.prepend(button);
36-
}
37-
// tracebacks (.gt) contain bare text elements that need to be
38-
// wrapped in a span to work with .nextUntil() (see later)
39-
jthis.find('pre:has(.gt)').contents().filter(function() {
40-
return ((this.nodeType == 3) && (this.data.trim().length > 0));
41-
}).wrap('<span>');
42-
});
75+
highlightedElements.forEach(el => {
76+
el.style.position = "relative"
4377

44-
// define the behavior of the button when it's clicked
45-
$('.copybutton').click(function(e){
46-
e.preventDefault();
47-
var button = $(this);
48-
if (button.data('hidden') === 'false') {
49-
// hide the code output
50-
button.parent().find('.go, .gp, .gt').hide();
51-
button.next('pre').find('.gt').nextUntil('.gp, .go').css('visibility', 'hidden');
52-
button.css('text-decoration', 'line-through');
53-
button.attr('title', show_text);
54-
button.data('hidden', 'true');
55-
} else {
56-
// show the code output
57-
button.parent().find('.go, .gp, .gt').show();
58-
button.next('pre').find('.gt').nextUntil('.gp, .go').css('visibility', 'visible');
59-
button.css('text-decoration', 'none');
60-
button.attr('title', hide_text);
61-
button.data('hidden', 'false');
78+
// if we find a console prompt (.gp), prepend the (deeply cloned) button
79+
const clonedButton = button.cloneNode(true)
80+
// the onclick attribute is not cloned, set it on the new element
81+
clonedButton.onclick = buttonClick
82+
if (el.querySelector(".gp") !== null) {
83+
el.prepend(clonedButton)
6284
}
63-
});
64-
});
85+
})
86+
}
87+
88+
if (document.readyState !== "loading") {
89+
loadCopyButton()
90+
} else {
91+
document.addEventListener("DOMContentLoaded", loadCopyButton)
92+
}

‎python_docs_theme/static/menu.js

Copy file name to clipboard
+33-31Lines changed: 33 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,57 @@
1-
document.addEventListener('DOMContentLoaded', function () {
1+
document.addEventListener("DOMContentLoaded", function () {
22

33
// Make tables responsive by wrapping them in a div and making them scrollable
4-
const tables = document.querySelectorAll('table.docutils');
4+
const tables = document.querySelectorAll("table.docutils")
55
tables.forEach(function(table){
6-
table.outerHTML = '<div class="responsive-table__container">' + table.outerHTML + '</div>'
7-
});
6+
table.outerHTML = '<div class="responsive-table__container">' + table.outerHTML + "</div>"
7+
})
88

9-
const togglerInput = document.querySelector('.toggler__input');
10-
const togglerLabel = document.querySelector('.toggler__label');
11-
const sideMenu = document.querySelector('.menu-wrapper');
12-
const menuItems = document.querySelectorAll('.menu')
13-
const doc = document.querySelector('.document');
14-
const body = document.querySelector('body');
9+
const togglerInput = document.querySelector(".toggler__input")
10+
const togglerLabel = document.querySelector(".toggler__label")
11+
const sideMenu = document.querySelector(".menu-wrapper")
12+
const menuItems = document.querySelectorAll(".menu")
13+
const doc = document.querySelector(".document")
14+
const body = document.querySelector("body")
1515

1616
function closeMenu() {
17-
togglerInput.checked = false;
18-
sideMenu.setAttribute("aria-expanded", 'false');
19-
sideMenu.setAttribute('aria-hidden', 'true');
20-
togglerLabel.setAttribute('aria-pressed', 'false');
21-
body.style.overflow = 'visible';
17+
togglerInput.checked = false
18+
sideMenu.setAttribute("aria-expanded", "false")
19+
sideMenu.setAttribute("aria-hidden", "true")
20+
togglerLabel.setAttribute("aria-pressed", "false")
21+
body.style.overflow = "visible"
2222
}
2323
function openMenu() {
24-
togglerInput.checked = true;
25-
sideMenu.setAttribute("aria-expanded", 'true');
26-
sideMenu.setAttribute('aria-hidden', 'false');
27-
togglerLabel.setAttribute('aria-pressed', 'true');
28-
body.style.overflow = 'hidden';
24+
togglerInput.checked = true
25+
sideMenu.setAttribute("aria-expanded", "true")
26+
sideMenu.setAttribute("aria-hidden", "false")
27+
togglerLabel.setAttribute("aria-pressed", "true")
28+
body.style.overflow = "hidden"
2929
}
3030

3131
// Close menu when link on the sideMenu is clicked
32-
sideMenu.addEventListener('click', function (event) {
33-
let target = event.target;
34-
if (target.tagName.toLowerCase() !== 'a') return;
35-
closeMenu();
32+
sideMenu.addEventListener("click", function (event) {
33+
let target = event.target
34+
if (target.tagName.toLowerCase() !== "a") {
35+
return
36+
}
37+
closeMenu()
3638
})
3739
// Add accessibility data when sideMenu is opened/closed
38-
togglerInput.addEventListener('change', function (e) {
39-
togglerInput.checked ? openMenu() : closeMenu();
40-
});
40+
togglerInput.addEventListener("change", function (_event) {
41+
togglerInput.checked ? openMenu() : closeMenu()
42+
})
4143
// Make sideMenu links tabbable only when visible
4244
for(let menuItem of menuItems) {
4345
if(togglerInput.checked) {
44-
menuItem.setAttribute('tabindex', '0');
46+
menuItem.setAttribute("tabindex", "0")
4547
} else {
46-
menuItem.setAttribute('tabindex', '-1');
48+
menuItem.setAttribute("tabindex", "-1")
4749
}
4850
}
4951
// Close sideMenu when document body is clicked
50-
doc.addEventListener('click', function () {
52+
doc.addEventListener("click", function () {
5153
if (togglerInput.checked) {
52-
closeMenu();
54+
closeMenu()
5355
}
5456
})
5557
})

‎python_docs_theme/static/pydoctheme.css

Copy file name to clipboardExpand all lines: python_docs_theme/static/pydoctheme.css
+49Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,10 +104,12 @@ div.sphinxsidebar h4 {
104104
}
105105

106106
div.sphinxsidebarwrapper {
107+
width: 217px;
107108
box-sizing: border-box;
108109
height: 100%;
109110
overflow-x: hidden;
110111
overflow-y: auto;
112+
float: left;
111113
}
112114

113115
div.sphinxsidebarwrapper > h3:first-child {
@@ -135,6 +137,33 @@ div.sphinxsidebar input[type='text'] {
135137
max-width: 150px;
136138
}
137139

140+
#sidebarbutton {
141+
/* Sphinx 4.x and earlier compat */
142+
height: 100%;
143+
background-color: #CCCCCC;
144+
margin-left: 0;
145+
color: #444444;
146+
font-size: 1.2em;
147+
cursor: pointer;
148+
padding-top: 1px;
149+
float: right;
150+
display: table;
151+
/* after Sphinx 4.x and earlier is dropped, only the below is needed */
152+
width: 12px;
153+
border-radius: 0 5px 5px 0;
154+
border-left: none;
155+
}
156+
157+
#sidebarbutton span {
158+
/* Sphinx 4.x and earlier compat */
159+
display: table-cell;
160+
vertical-align: middle;
161+
}
162+
163+
#sidebarbutton:hover {
164+
background-color: #AAAAAA;
165+
}
166+
138167
div.body {
139168
padding: 0 0 0 1.2em;
140169
}
@@ -279,6 +308,26 @@ div.genindex-jumpbox a {
279308
text-align: center;
280309
}
281310

311+
.copybutton {
312+
cursor: pointer;
313+
position: absolute;
314+
top: 0;
315+
right: 0;
316+
text-size: 75%;
317+
font-family: monospace;
318+
padding-left: 0.2em;
319+
padding-right: 0.2em;
320+
border-radius: 0 3px 0 0;
321+
color: #ac9; /* follows div.body pre */
322+
border-color: #ac9; /* follows div.body pre */
323+
border-style: solid; /* follows div.body pre */
324+
border-width: 1px; /* follows div.body pre */
325+
}
326+
327+
.copybutton[data-hidden='true'] {
328+
text-decoration: line-through;
329+
}
330+
282331
@media (max-width: 1023px) {
283332
/* Body layout */
284333
div.body {

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.