Initial commit

This commit is contained in:
2026-05-09 21:06:07 +10:00
commit 6e6be47891
24 changed files with 6416 additions and 0 deletions

843
theme/book.js Normal file
View File

@@ -0,0 +1,843 @@
'use strict';
/* global default_theme, default_dark_theme, default_light_theme, hljs, ClipboardJS */
// Fix back button cache problem
window.onunload = function() { };
// Global variable, shared between modules
function playground_text(playground, hidden = true) {
const code_block = playground.querySelector('code');
if (window.ace && code_block.classList.contains('editable')) {
const editor = window.ace.edit(code_block);
return editor.getValue();
} else if (hidden) {
return code_block.textContent;
} else {
return code_block.innerText;
}
}
(function codeSnippets() {
function fetch_with_timeout(url, options, timeout = 6000) {
return Promise.race([
fetch(url, options),
new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), timeout)),
]);
}
const playgrounds = Array.from(document.querySelectorAll('.playground'));
if (playgrounds.length > 0) {
fetch_with_timeout('https://play.rust-lang.org/meta/crates', {
headers: {
'Content-Type': 'application/json',
},
method: 'POST',
mode: 'cors',
})
.then(response => response.json())
.then(response => {
// get list of crates available in the rust playground
const playground_crates = response.crates.map(item => item['id']);
playgrounds.forEach(block => handle_crate_list_update(block, playground_crates));
});
}
function handle_crate_list_update(playground_block, playground_crates) {
// update the play buttons after receiving the response
update_play_button(playground_block, playground_crates);
// and install on change listener to dynamically update ACE editors
if (window.ace) {
const code_block = playground_block.querySelector('code');
if (code_block.classList.contains('editable')) {
const editor = window.ace.edit(code_block);
editor.addEventListener('change', () => {
update_play_button(playground_block, playground_crates);
});
// add Ctrl-Enter command to execute rust code
editor.commands.addCommand({
name: 'run',
bindKey: {
win: 'Ctrl-Enter',
mac: 'Ctrl-Enter',
},
exec: _editor => run_rust_code(playground_block),
});
}
}
}
// updates the visibility of play button based on `no_run` class and
// used crates vs ones available on https://play.rust-lang.org
function update_play_button(pre_block, playground_crates) {
const play_button = pre_block.querySelector('.play-button');
// skip if code is `no_run`
if (pre_block.querySelector('code').classList.contains('no_run')) {
play_button.classList.add('hidden');
return;
}
// get list of `extern crate`'s from snippet
const txt = playground_text(pre_block);
const re = /extern\s+crate\s+([a-zA-Z_0-9]+)\s*;/g;
const snippet_crates = [];
let item;
while (item = re.exec(txt)) {
snippet_crates.push(item[1]);
}
// check if all used crates are available on play.rust-lang.org
const all_available = snippet_crates.every(function(elem) {
return playground_crates.indexOf(elem) > -1;
});
if (all_available) {
play_button.classList.remove('hidden');
play_button.hidden = false;
} else {
play_button.classList.add('hidden');
}
}
function run_rust_code(code_block) {
let result_block = code_block.querySelector('.result');
if (!result_block) {
result_block = document.createElement('code');
result_block.className = 'result hljs language-bash';
code_block.append(result_block);
}
const text = playground_text(code_block);
const classes = code_block.querySelector('code').classList;
let edition = '2015';
classes.forEach(className => {
if (className.startsWith('edition')) {
edition = className.slice(7);
}
});
const params = {
version: 'stable',
optimize: '0',
code: text,
edition: edition,
};
if (text.indexOf('#![feature') !== -1) {
params.version = 'nightly';
}
result_block.innerText = 'Running...';
fetch_with_timeout('https://play.rust-lang.org/evaluate.json', {
headers: {
'Content-Type': 'application/json',
},
method: 'POST',
mode: 'cors',
body: JSON.stringify(params),
})
.then(response => response.json())
.then(response => {
if (response.result.trim() === '') {
result_block.innerText = 'No output';
result_block.classList.add('result-no-output');
} else {
result_block.innerText = response.result;
result_block.classList.remove('result-no-output');
}
})
.catch(error => result_block.innerText = 'Playground Communication: ' + error.message);
}
// Syntax highlighting Configuration
hljs.configure({
tabReplace: ' ', // 4 spaces
languages: [], // Languages used for auto-detection
});
const code_nodes = Array
.from(document.querySelectorAll('code'))
// Don't highlight `inline code` blocks in headers.
.filter(function(node) {
return !node.parentElement.classList.contains('header');
});
if (window.ace) {
// language-rust class needs to be removed for editable
// blocks or highlightjs will capture events
code_nodes
.filter(function(node) {
return node.classList.contains('editable');
})
.forEach(function(block) {
block.classList.remove('language-rust');
});
code_nodes
.filter(function(node) {
return !node.classList.contains('editable');
})
.forEach(function(block) {
hljs.highlightBlock(block);
});
} else {
code_nodes.forEach(function(block) {
hljs.highlightBlock(block);
});
}
// Adding the hljs class gives code blocks the color css
// even if highlighting doesn't apply
code_nodes.forEach(function(block) {
block.classList.add('hljs');
});
Array.from(document.querySelectorAll('code.hljs')).forEach(function(block) {
const lines = Array.from(block.querySelectorAll('.boring'));
// If no lines were hidden, return
if (!lines.length) {
return;
}
block.classList.add('hide-boring');
const buttons = document.createElement('div');
buttons.className = 'buttons';
buttons.innerHTML = '<button title="Show hidden lines" \
aria-label="Show hidden lines"></button>';
buttons.firstChild.innerHTML = document.getElementById('fa-eye').innerHTML;
// add expand button
const pre_block = block.parentNode;
pre_block.insertBefore(buttons, pre_block.firstChild);
buttons.firstChild.addEventListener('click', function(e) {
if (this.title === 'Show hidden lines') {
this.innerHTML = document.getElementById('fa-eye-slash').innerHTML;
this.title = 'Hide lines';
this.setAttribute('aria-label', e.target.title);
block.classList.remove('hide-boring');
} else if (this.title === 'Hide lines') {
this.innerHTML = document.getElementById('fa-eye').innerHTML;
this.title = 'Show hidden lines';
this.setAttribute('aria-label', e.target.title);
block.classList.add('hide-boring');
}
});
});
if (window.playground_copyable) {
Array.from(document.querySelectorAll('pre code')).forEach(function(block) {
const pre_block = block.parentNode;
if (!pre_block.classList.contains('playground')) {
let buttons = pre_block.querySelector('.buttons');
if (!buttons) {
buttons = document.createElement('div');
buttons.className = 'buttons';
pre_block.insertBefore(buttons, pre_block.firstChild);
}
const clipButton = document.createElement('button');
clipButton.className = 'clip-button';
clipButton.title = 'Copy to clipboard';
clipButton.setAttribute('aria-label', clipButton.title);
clipButton.innerHTML = '<i class="tooltiptext"></i>';
buttons.insertBefore(clipButton, buttons.firstChild);
}
});
}
// Process playground code blocks
Array.from(document.querySelectorAll('.playground')).forEach(function(pre_block) {
// Add play button
let buttons = pre_block.querySelector('.buttons');
if (!buttons) {
buttons = document.createElement('div');
buttons.className = 'buttons';
pre_block.insertBefore(buttons, pre_block.firstChild);
}
const runCodeButton = document.createElement('button');
runCodeButton.className = 'play-button';
runCodeButton.hidden = true;
runCodeButton.title = 'Run this code';
runCodeButton.setAttribute('aria-label', runCodeButton.title);
runCodeButton.innerHTML = document.getElementById('fa-play').innerHTML;
buttons.insertBefore(runCodeButton, buttons.firstChild);
runCodeButton.addEventListener('click', () => {
run_rust_code(pre_block);
});
if (window.playground_copyable) {
const copyCodeClipboardButton = document.createElement('button');
copyCodeClipboardButton.className = 'clip-button';
copyCodeClipboardButton.innerHTML = '<i class="tooltiptext"></i>';
copyCodeClipboardButton.title = 'Copy to clipboard';
copyCodeClipboardButton.setAttribute('aria-label', copyCodeClipboardButton.title);
buttons.insertBefore(copyCodeClipboardButton, buttons.firstChild);
}
const code_block = pre_block.querySelector('code');
if (window.ace && code_block.classList.contains('editable')) {
const undoChangesButton = document.createElement('button');
undoChangesButton.className = 'reset-button';
undoChangesButton.title = 'Undo changes';
undoChangesButton.setAttribute('aria-label', undoChangesButton.title);
undoChangesButton.innerHTML +=
document.getElementById('fa-clock-rotate-left').innerHTML;
buttons.insertBefore(undoChangesButton, buttons.firstChild);
undoChangesButton.addEventListener('click', function() {
const editor = window.ace.edit(code_block);
editor.setValue(editor.originalCode);
editor.clearSelection();
});
}
});
})();
(function themes() {
const html = document.querySelector('html');
const themeToggleButton = document.getElementById('mdbook-theme-toggle');
const themePopup = document.getElementById('mdbook-theme-list');
const themeColorMetaTag = document.querySelector('meta[name="theme-color"]');
const themeIds = [];
themePopup.querySelectorAll('button.theme').forEach(function(el) {
themeIds.push(el.id);
});
const stylesheets = {
ayuHighlight: document.querySelector('#mdbook-ayu-highlight-css'),
tomorrowNight: document.querySelector('#mdbook-tomorrow-night-css'),
highlight: document.querySelector('#mdbook-highlight-css'),
};
function showThemes() {
themePopup.style.display = 'block';
themeToggleButton.setAttribute('aria-expanded', true);
themePopup.querySelector('button#mdbook-theme-' + get_theme()).focus();
}
function updateThemeSelected() {
themePopup.querySelectorAll('.theme-selected').forEach(function(el) {
el.classList.remove('theme-selected');
});
const selected = get_saved_theme() ?? 'default_theme';
let element = themePopup.querySelector('button#mdbook-theme-' + selected);
if (element === null) {
// Fall back in case there is no "Default" item.
element = themePopup.querySelector('button#mdbook-theme-' + get_theme());
}
element.classList.add('theme-selected');
}
function hideThemes() {
themePopup.style.display = 'none';
themeToggleButton.setAttribute('aria-expanded', false);
themeToggleButton.focus();
}
function get_saved_theme() {
let theme = null;
try {
theme = localStorage.getItem('mdbook-theme');
} catch {
// ignore error.
}
return theme;
}
function delete_saved_theme() {
localStorage.removeItem('mdbook-theme');
}
function get_theme() {
const theme = get_saved_theme();
if (theme === null || theme === undefined || !themeIds.includes('mdbook-theme-' + theme)) {
if (typeof default_dark_theme === 'undefined') {
// A customized index.hbs might not define this, so fall back to
// old behavior of determining the default on page load.
return default_theme;
}
return window.matchMedia('(prefers-color-scheme: dark)').matches
? default_dark_theme
: default_light_theme;
} else {
return theme;
}
}
let previousTheme = default_theme;
function set_theme(theme, store = true) {
let ace_theme;
if (theme === 'coal' || theme === 'navy') {
stylesheets.ayuHighlight.disabled = true;
stylesheets.tomorrowNight.disabled = false;
stylesheets.highlight.disabled = true;
ace_theme = 'ace/theme/tomorrow_night';
} else if (theme === 'ayu') {
stylesheets.ayuHighlight.disabled = false;
stylesheets.tomorrowNight.disabled = true;
stylesheets.highlight.disabled = true;
ace_theme = 'ace/theme/tomorrow_night';
} else {
stylesheets.ayuHighlight.disabled = true;
stylesheets.tomorrowNight.disabled = true;
stylesheets.highlight.disabled = false;
ace_theme = 'ace/theme/dawn';
}
setTimeout(function() {
themeColorMetaTag.content = getComputedStyle(document.documentElement).backgroundColor;
}, 1);
if (window.ace && window.editors) {
window.editors.forEach(function(editor) {
editor.setTheme(ace_theme);
});
}
if (store) {
try {
localStorage.setItem('mdbook-theme', theme);
} catch {
// ignore error.
}
}
html.classList.remove(previousTheme);
html.classList.add(theme);
previousTheme = theme;
updateThemeSelected();
}
const query = window.matchMedia('(prefers-color-scheme: dark)');
query.onchange = function() {
set_theme(get_theme(), false);
};
// Set theme.
set_theme(get_theme(), false);
themeToggleButton.addEventListener('click', function() {
if (themePopup.style.display === 'block') {
hideThemes();
} else {
showThemes();
}
});
themePopup.addEventListener('click', function(e) {
let theme;
if (e.target.className === 'theme') {
theme = e.target.id;
} else if (e.target.parentElement.className === 'theme') {
theme = e.target.parentElement.id;
} else {
return;
}
theme = theme.replace(/^mdbook-theme-/, '');
if (theme === 'default_theme' || theme === null) {
delete_saved_theme();
set_theme(get_theme(), false);
} else {
set_theme(theme);
}
});
themePopup.addEventListener('focusout', function(e) {
// e.relatedTarget is null in Safari and Firefox on macOS (see workaround below)
if (!!e.relatedTarget &&
!themeToggleButton.contains(e.relatedTarget) &&
!themePopup.contains(e.relatedTarget)
) {
hideThemes();
}
});
// Should not be needed, but it works around an issue on macOS & iOS:
// https://github.com/rust-lang/mdBook/issues/628
document.addEventListener('click', function(e) {
if (themePopup.style.display === 'block' &&
!themeToggleButton.contains(e.target) &&
!themePopup.contains(e.target)
) {
hideThemes();
}
});
document.addEventListener('keydown', function(e) {
if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) {
return;
}
if (!themePopup.contains(e.target)) {
return;
}
let li;
switch (e.key) {
case 'Escape':
e.preventDefault();
hideThemes();
break;
case 'ArrowUp':
e.preventDefault();
li = document.activeElement.parentElement;
if (li && li.previousElementSibling) {
li.previousElementSibling.querySelector('button').focus();
}
break;
case 'ArrowDown':
e.preventDefault();
li = document.activeElement.parentElement;
if (li && li.nextElementSibling) {
li.nextElementSibling.querySelector('button').focus();
}
break;
case 'Home':
e.preventDefault();
themePopup.querySelector('li:first-child button').focus();
break;
case 'End':
e.preventDefault();
themePopup.querySelector('li:last-child button').focus();
break;
}
});
})();
(function sidebar() {
const sidebar = document.getElementById('mdbook-sidebar');
const sidebarLinks = document.querySelectorAll('#mdbook-sidebar a');
const sidebarToggleButton = document.getElementById('mdbook-sidebar-toggle');
const sidebarResizeHandle = document.getElementById('mdbook-sidebar-resize-handle');
const sidebarCheckbox = document.getElementById('mdbook-sidebar-toggle-anchor');
let firstContact = null;
/* Because we cannot change the `display` using only CSS after/before the transition, we
need JS to do it. We change the display to prevent the browsers search to find text inside
the collapsed sidebar. */
if (!document.documentElement.classList.contains('sidebar-visible')) {
sidebar.style.display = 'none';
}
sidebar.addEventListener('transitionend', () => {
/* We only change the display to "none" if we're collapsing the sidebar. */
if (!sidebarCheckbox.checked) {
sidebar.style.display = 'none';
}
});
sidebarToggleButton.addEventListener('click', () => {
/* To allow the sidebar expansion animation, we first need to put back the display. */
if (!sidebarCheckbox.checked) {
sidebar.style.display = '';
// Workaround for Safari skipping the animation when changing
// `display` and a transform in the same event loop. This forces a
// reflow after updating the display.
sidebar.offsetHeight;
}
});
function showSidebar() {
document.documentElement.classList.add('sidebar-visible');
Array.from(sidebarLinks).forEach(function(link) {
link.setAttribute('tabIndex', 0);
});
sidebarToggleButton.setAttribute('aria-expanded', true);
sidebar.setAttribute('aria-hidden', false);
try {
localStorage.setItem('mdbook-sidebar', 'visible');
} catch {
// Ignore error.
}
}
function hideSidebar() {
document.documentElement.classList.remove('sidebar-visible');
Array.from(sidebarLinks).forEach(function(link) {
link.setAttribute('tabIndex', -1);
});
sidebarToggleButton.setAttribute('aria-expanded', false);
sidebar.setAttribute('aria-hidden', true);
try {
localStorage.setItem('mdbook-sidebar', 'hidden');
} catch {
// Ignore error.
}
}
// Toggle sidebar
sidebarCheckbox.addEventListener('change', function sidebarToggle() {
if (sidebarCheckbox.checked) {
const current_width = parseInt(
document.documentElement.style.getPropertyValue('--sidebar-target-width'), 10);
if (current_width < 150) {
document.documentElement.style.setProperty('--sidebar-target-width', '150px');
}
showSidebar();
} else {
hideSidebar();
}
});
sidebarResizeHandle.addEventListener('mousedown', initResize, false);
function initResize() {
window.addEventListener('mousemove', resize, false);
window.addEventListener('mouseup', stopResize, false);
document.documentElement.classList.add('sidebar-resizing');
}
function resize(e) {
let pos = e.clientX - sidebar.offsetLeft;
if (pos < 20) {
hideSidebar();
} else {
if (!document.documentElement.classList.contains('sidebar-visible')) {
showSidebar();
}
pos = Math.min(pos, window.innerWidth - 100);
document.documentElement.style.setProperty('--sidebar-target-width', pos + 'px');
}
}
//on mouseup remove windows functions mousemove & mouseup
function stopResize() {
document.documentElement.classList.remove('sidebar-resizing');
window.removeEventListener('mousemove', resize, false);
window.removeEventListener('mouseup', stopResize, false);
}
document.addEventListener('touchstart', function(e) {
firstContact = {
x: e.touches[0].clientX,
time: Date.now(),
};
}, { passive: true });
document.addEventListener('touchmove', function(e) {
if (!firstContact) {
return;
}
const curX = e.touches[0].clientX;
const xDiff = curX - firstContact.x,
tDiff = Date.now() - firstContact.time;
if (tDiff < 250 && Math.abs(xDiff) >= 150) {
if (xDiff >= 0 && firstContact.x < Math.min(document.body.clientWidth * 0.25, 300)) {
showSidebar();
} else if (xDiff < 0 && curX < 300) {
hideSidebar();
}
firstContact = null;
}
}, { passive: true });
})();
(function chapterNavigation() {
document.addEventListener('keydown', function(e) {
if (e.altKey || e.ctrlKey || e.metaKey) {
return;
}
if (window.search && window.search.hasFocus()) {
return;
}
const html = document.querySelector('html');
function next() {
const nextButton = document.querySelector('.nav-chapters.next');
if (nextButton) {
window.location.href = nextButton.href;
}
}
function prev() {
const previousButton = document.querySelector('.nav-chapters.previous');
if (previousButton) {
window.location.href = previousButton.href;
}
}
function showHelp() {
const container = document.getElementById('mdbook-help-container');
const overlay = document.getElementById('mdbook-help-popup');
container.style.display = 'flex';
// Clicking outside the popup will dismiss it.
const mouseHandler = event => {
if (overlay.contains(event.target)) {
return;
}
if (event.button !== 0) {
return;
}
event.preventDefault();
event.stopPropagation();
document.removeEventListener('mousedown', mouseHandler);
hideHelp();
};
// Pressing esc will dismiss the popup.
const escapeKeyHandler = event => {
if (event.key === 'Escape') {
event.preventDefault();
event.stopPropagation();
document.removeEventListener('keydown', escapeKeyHandler, true);
hideHelp();
}
};
document.addEventListener('keydown', escapeKeyHandler, true);
document.getElementById('mdbook-help-container')
.addEventListener('mousedown', mouseHandler);
}
function hideHelp() {
document.getElementById('mdbook-help-container').style.display = 'none';
}
// Usually needs the Shift key to be pressed
switch (e.key) {
case '?':
e.preventDefault();
showHelp();
break;
}
// Rest of the keys are only active when the Shift key is not pressed
if (e.shiftKey) {
return;
}
switch (e.key) {
case 'ArrowRight':
e.preventDefault();
if (html.dir === 'rtl') {
prev();
} else {
next();
}
break;
case 'ArrowLeft':
e.preventDefault();
if (html.dir === 'rtl') {
next();
} else {
prev();
}
break;
}
});
})();
(function clipboard() {
const clipButtons = document.querySelectorAll('.clip-button');
function hideTooltip(elem) {
elem.firstChild.innerText = '';
elem.className = 'clip-button';
}
function showTooltip(elem, msg) {
elem.firstChild.innerText = msg;
elem.className = 'clip-button tooltipped';
}
const clipboardSnippets = new ClipboardJS('.clip-button', {
text: function(trigger) {
hideTooltip(trigger);
const playground = trigger.closest('pre');
return playground_text(playground, false);
},
});
Array.from(clipButtons).forEach(function(clipButton) {
clipButton.addEventListener('mouseout', function(e) {
hideTooltip(e.currentTarget);
});
});
clipboardSnippets.on('success', function(e) {
e.clearSelection();
showTooltip(e.trigger, 'Copied!');
});
clipboardSnippets.on('error', function(e) {
showTooltip(e.trigger, 'Clipboard error!');
});
})();
(function scrollToTop() {
const menuTitle = document.querySelector('.menu-title');
menuTitle.addEventListener('click', function() {
document.scrollingElement.scrollTo({ top: 0, behavior: 'smooth' });
});
})();
(function controllMenu() {
const menu = document.getElementById('mdbook-menu-bar');
(function controllPosition() {
let scrollTop = document.scrollingElement.scrollTop;
let prevScrollTop = scrollTop;
const minMenuY = -menu.clientHeight - 50;
// When the script loads, the page can be at any scroll (e.g. if you refresh it).
menu.style.top = scrollTop + 'px';
// Same as parseInt(menu.style.top.slice(0, -2), but faster
let topCache = menu.style.top.slice(0, -2);
menu.classList.remove('sticky');
let stickyCache = false; // Same as menu.classList.contains('sticky'), but faster
document.addEventListener('scroll', function() {
scrollTop = Math.max(document.scrollingElement.scrollTop, 0);
// `null` means that it doesn't need to be updated
let nextSticky = null;
let nextTop = null;
const scrollDown = scrollTop > prevScrollTop;
const menuPosAbsoluteY = topCache - scrollTop;
if (scrollDown) {
nextSticky = false;
if (menuPosAbsoluteY > 0) {
nextTop = prevScrollTop;
}
} else {
if (menuPosAbsoluteY > 0) {
nextSticky = true;
} else if (menuPosAbsoluteY < minMenuY) {
nextTop = prevScrollTop + minMenuY;
}
}
if (nextSticky === true && stickyCache === false) {
menu.classList.add('sticky');
stickyCache = true;
} else if (nextSticky === false && stickyCache === true) {
menu.classList.remove('sticky');
stickyCache = false;
}
if (nextTop !== null) {
menu.style.top = nextTop + 'px';
topCache = nextTop;
}
prevScrollTop = scrollTop;
}, { passive: true });
})();
(function controllBorder() {
function updateBorder() {
if (menu.offsetTop === 0) {
menu.classList.remove('bordered');
} else {
menu.classList.add('bordered');
}
}
updateBorder();
document.addEventListener('scroll', updateBorder, { passive: true });
})();
})();

756
theme/css/chrome.css Normal file
View File

@@ -0,0 +1,756 @@
/* CSS for UI elements (a.k.a. chrome) */
html {
scrollbar-color: var(--scrollbar) transparent;
}
#mdbook-searchresults a,
.content a:link,
a:visited,
a > .hljs {
color: var(--links);
}
/*
mdbook-body-container is necessary because mobile browsers don't seem to like
overflow-x on the body tag when there is a <meta name="viewport"> tag.
*/
#mdbook-body-container {
/*
This is used when the sidebar pushes the body content off the side of
the screen on small screens. Without it, dragging on mobile Safari
will want to reposition the viewport in a weird way.
*/
overflow-x: clip;
}
/* Menu Bar */
#mdbook-menu-bar,
#mdbook-menu-bar-hover-placeholder {
z-index: 101;
margin: auto calc(0px - var(--page-padding));
}
#mdbook-menu-bar {
position: relative;
display: flex;
flex-wrap: wrap;
background-color: var(--bg);
border-block-end-color: var(--bg);
border-block-end-width: 1px;
border-block-end-style: solid;
}
#mdbook-menu-bar.sticky,
#mdbook-menu-bar-hover-placeholder:hover + #mdbook-menu-bar,
#mdbook-menu-bar:hover,
html.sidebar-visible #mdbook-menu-bar {
position: -webkit-sticky;
position: sticky;
top: 0 !important;
}
#mdbook-menu-bar-hover-placeholder {
position: sticky;
position: -webkit-sticky;
top: 0;
height: var(--menu-bar-height);
}
#mdbook-menu-bar.bordered {
border-block-end-color: var(--table-border-color);
}
#mdbook-menu-bar .fa-svg, #mdbook-menu-bar .icon-button {
position: relative;
padding: 0 8px;
z-index: 10;
line-height: var(--menu-bar-height);
cursor: pointer;
transition: color 0.5s;
}
@media only screen and (max-width: 420px) {
#mdbook-menu-bar .fa-svg, #mdbook-menu-bar .icon-button {
padding: 0 5px;
}
}
.icon-button {
border: none;
background: none;
padding: 0;
color: inherit;
}
.icon-button .fa-svg {
margin: 0;
}
.right-buttons {
margin: 0 15px;
}
.right-buttons a {
text-decoration: none;
}
.left-buttons {
display: flex;
margin: 0 5px;
}
html:not(.js) .left-buttons button {
display: none;
}
.menu-title {
display: inline-block;
font-weight: 200;
font-size: 2.4rem;
line-height: var(--menu-bar-height);
text-align: center;
margin: 0;
flex: 1;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.menu-title {
cursor: pointer;
}
.menu-bar,
.menu-bar:visited,
.nav-chapters,
.nav-chapters:visited,
.mobile-nav-chapters,
.mobile-nav-chapters:visited,
.menu-bar .icon-button,
.menu-bar a .fa-svg {
color: var(--icons);
}
.menu-bar .fa-svg:hover,
.menu-bar .icon-button:hover,
.nav-chapters:hover,
.mobile-nav-chapters .fa-svg:hover {
color: var(--icons-hover);
}
/* Nav Icons */
.nav-chapters {
font-size: 2.5em;
text-align: center;
text-decoration: none;
position: fixed;
top: 0;
bottom: 0;
margin: 0;
max-width: 150px;
min-width: 90px;
display: flex;
justify-content: center;
align-content: center;
flex-direction: column;
transition: color 0.5s, background-color 0.5s;
}
.nav-chapters:hover {
text-decoration: none;
background-color: var(--theme-hover);
transition: background-color 0.15s, color 0.15s;
}
.nav-wrapper {
margin-block-start: 50px;
display: none;
}
.mobile-nav-chapters {
font-size: 2.5em;
text-align: center;
text-decoration: none;
width: 90px;
border-radius: 5px;
background-color: var(--sidebar-bg);
}
/* Only Firefox supports flow-relative values */
.previous { float: left; }
[dir=rtl] .previous { float: right; }
/* Only Firefox supports flow-relative values */
.next {
float: right;
right: var(--page-padding);
}
[dir=rtl] .next {
float: left;
right: unset;
left: var(--page-padding);
}
@media only screen and (max-width: 1080px) {
.nav-wide-wrapper { display: none; }
.nav-wrapper { display: block; }
}
/* sidebar-visible */
@media only screen and (max-width: 1380px) {
#mdbook-sidebar-toggle-anchor:checked ~ .page-wrapper .nav-wide-wrapper { display: none; }
#mdbook-sidebar-toggle-anchor:checked ~ .page-wrapper .nav-wrapper { display: block; }
}
/* Inline code */
:not(pre) > .hljs {
display: inline;
padding: 0.1em 0.3em;
border-radius: 3px;
}
:not(pre):not(a) > .hljs {
color: var(--inline-code-color);
overflow-x: initial;
}
a:hover > .hljs {
text-decoration: underline;
}
pre {
position: relative;
}
pre > .buttons {
position: absolute;
z-index: 100;
right: 0px;
top: 2px;
margin: 0px;
padding: 2px 0px;
color: var(--sidebar-fg);
cursor: pointer;
visibility: hidden;
opacity: 0;
transition: visibility 0.1s linear, opacity 0.1s linear;
}
pre:hover > .buttons {
visibility: visible;
opacity: 1
}
pre > .buttons :hover {
color: var(--sidebar-active);
border-color: var(--icons-hover);
background-color: var(--theme-hover);
}
pre > .buttons button {
cursor: inherit;
margin: 0px 5px;
padding: 2px 3px 0px 4px;
font-size: 23px;
border-style: solid;
border-width: 1px;
border-radius: 4px;
border-color: var(--icons);
background-color: var(--theme-popup-bg);
transition: 100ms;
transition-property: color,border-color,background-color;
color: var(--icons);
}
pre > .buttons button.clip-button {
padding: 2px 4px 0px 6px;
}
pre > .buttons button.clip-button::before {
/* clipboard image from octicons (https://github.com/primer/octicons/tree/v2.0.0) MIT license
*/
content: url('data:image/svg+xml,<svg width="21" height="20" viewBox="0 0 24 25" \
xmlns="http://www.w3.org/2000/svg" aria-label="Copy to clipboard">\
<path d="M18 20h2v3c0 1-1 2-2 2H2c-.998 0-2-1-2-2V5c0-.911.755-1.667 1.667-1.667h5A3.323 3.323 0 \
0110 0a3.323 3.323 0 013.333 3.333h5C19.245 3.333 20 4.09 20 5v8.333h-2V9H2v14h16v-3zM3 \
7h14c0-.911-.793-1.667-1.75-1.667H13.5c-.957 0-1.75-.755-1.75-1.666C11.75 2.755 10.957 2 10 \
2s-1.75.755-1.75 1.667c0 .911-.793 1.666-1.75 1.666H4.75C3.793 5.333 3 6.09 3 7z"/>\
<path d="M4 19h6v2H4zM12 11H4v2h8zM4 17h4v-2H4zM15 15v-3l-4.5 4.5L15 21v-3l8.027-.032L23 15z"/>\
</svg>');
filter: var(--copy-button-filter);
}
pre > .buttons button.clip-button:hover::before {
filter: var(--copy-button-filter-hover);
}
@media (pointer: coarse) {
pre > .buttons button {
/* On mobile, make it easier to tap buttons. */
padding: 0.3rem 1rem;
}
.sidebar-resize-indicator {
/* Hide resize indicator on devices with limited accuracy */
display: none;
}
}
pre > code {
display: block;
padding: 1rem;
}
/* FIXME: ACE editors overlap their buttons because ACE does absolute
positioning within the code block which breaks padding. The only solution I
can think of is to move the padding to the outer pre tag (or insert a div
wrapper), but that would require fixing a whole bunch of CSS rules.
*/
.hljs.ace_editor {
padding: 0rem 0rem;
}
pre > .result {
margin-block-start: 10px;
}
/* Search */
#mdbook-searchresults a {
text-decoration: none;
}
mark {
border-radius: 2px;
padding-block-start: 0;
padding-block-end: 1px;
padding-inline-start: 3px;
padding-inline-end: 3px;
margin-block-start: 0;
margin-block-end: -1px;
margin-inline-start: -3px;
margin-inline-end: -3px;
background-color: var(--search-mark-bg);
transition: background-color 300ms linear;
cursor: pointer;
}
mark.fade-out {
background-color: rgba(0,0,0,0) !important;
cursor: auto;
}
.searchbar-outer {
margin-inline-start: auto;
margin-inline-end: auto;
max-width: var(--content-max-width);
}
#mdbook-searchbar-outer.searching #mdbook-searchbar {
padding-right: 30px;
}
#mdbook-searchbar-outer .spinner-wrapper {
display: none;
}
#mdbook-searchbar-outer.searching .spinner-wrapper {
display: block;
}
.search-wrapper {
position: relative;
}
.spinner-wrapper {
--spinner-margin: 2px;
position: absolute;
margin-block-start: calc(var(--searchbar-margin-block-start) + var(--spinner-margin));
right: var(--spinner-margin);
top: 0;
bottom: var(--spinner-margin);
padding: 6px;
background-color: var(--bg);
}
#fa-spin {
animation: rotating 2s linear infinite;
display: inline-block;
}
@keyframes rotating {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
#mdbook-searchbar {
width: 100%;
margin-block-start: var(--searchbar-margin-block-start);
margin-block-end: 0;
margin-inline-start: auto;
margin-inline-end: auto;
padding: 10px 16px;
transition: box-shadow 300ms ease-in-out;
border: 1px solid var(--searchbar-border-color);
border-radius: 3px;
background-color: var(--searchbar-bg);
color: var(--searchbar-fg);
}
#mdbook-searchbar:focus,
#mdbook-searchbar.active {
box-shadow: 0 0 3px var(--searchbar-shadow-color);
}
.searchresults-header {
font-weight: bold;
font-size: 1em;
padding-block-start: 18px;
padding-block-end: 0;
padding-inline-start: 5px;
padding-inline-end: 0;
color: var(--searchresults-header-fg);
}
.searchresults-outer {
margin-inline-start: auto;
margin-inline-end: auto;
max-width: var(--content-max-width);
border-block-end: 1px dashed var(--searchresults-border-color);
}
ul#mdbook-searchresults {
list-style: none;
padding-inline-start: 20px;
}
ul#mdbook-searchresults li {
margin: 10px 0px;
padding: 2px;
border-radius: 2px;
}
ul#mdbook-searchresults li.focus {
background-color: var(--searchresults-li-bg);
}
ul#mdbook-searchresults span.teaser {
display: block;
clear: both;
margin-block-start: 5px;
margin-block-end: 0;
margin-inline-start: 20px;
margin-inline-end: 0;
font-size: 0.8em;
}
ul#mdbook-searchresults span.teaser em {
font-weight: bold;
font-style: normal;
}
/* Sidebar */
.sidebar {
position: fixed;
left: 0;
top: 0;
bottom: 0;
width: var(--sidebar-width);
font-size: 0.875em;
box-sizing: border-box;
-webkit-overflow-scrolling: touch;
overscroll-behavior-y: contain;
background-color: var(--sidebar-bg);
color: var(--sidebar-fg);
}
.sidebar-iframe-inner {
--padding: 10px;
background-color: var(--sidebar-bg);
padding: var(--padding);
margin: 0;
font-size: 1.4rem;
color: var(--sidebar-fg);
min-height: calc(100vh - var(--padding) * 2);
}
.sidebar-iframe-outer {
border: none;
height: 100%;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
[dir=rtl] .sidebar { left: unset; right: 0; }
.sidebar-resizing {
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
user-select: none;
}
html:not(.sidebar-resizing) .sidebar {
transition: transform 0.3s; /* Animation: slide away */
}
.sidebar code {
line-height: 2em;
}
.sidebar .sidebar-scrollbox {
overflow-y: auto;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
padding: 10px 10px;
}
.sidebar .sidebar-resize-handle {
position: absolute;
cursor: col-resize;
width: 0;
right: calc(var(--sidebar-resize-indicator-width) * -1);
top: 0;
bottom: 0;
display: flex;
align-items: center;
}
.sidebar-resize-handle .sidebar-resize-indicator {
width: 100%;
height: 16px;
color: var(--icons);
margin-inline-start: var(--sidebar-resize-indicator-space);
display: flex;
align-items: center;
justify-content: flex-start;
}
.sidebar-resize-handle .sidebar-resize-indicator::before {
content: "";
width: 2px;
height: 12px;
border-left: dotted 2px currentColor;
}
.sidebar-resize-handle .sidebar-resize-indicator::after {
content: "";
width: 2px;
height: 16px;
border-left: dotted 2px currentColor;
}
[dir=rtl] .sidebar .sidebar-resize-handle {
left: calc(var(--sidebar-resize-indicator-width) * -1);
right: unset;
}
.js .sidebar .sidebar-resize-handle {
cursor: col-resize;
width: calc(var(--sidebar-resize-indicator-width) - var(--sidebar-resize-indicator-space));
}
html:not(.js) .sidebar-resize-handle {
display: none;
}
/* sidebar-hidden */
#mdbook-sidebar-toggle-anchor:not(:checked) ~ .sidebar {
transform: translateX(calc(0px - var(--sidebar-width) - var(--sidebar-resize-indicator-width)));
}
[dir=rtl] #mdbook-sidebar-toggle-anchor:not(:checked) ~ .sidebar {
transform: translateX(calc(var(--sidebar-width) + var(--sidebar-resize-indicator-width)));
}
.sidebar::-webkit-scrollbar {
background: var(--sidebar-bg);
}
.sidebar::-webkit-scrollbar-thumb {
background: var(--scrollbar);
}
/* sidebar-visible */
#mdbook-sidebar-toggle-anchor:checked ~ .page-wrapper {
transform: translateX(calc(var(--sidebar-width) + var(--sidebar-resize-indicator-width)));
}
[dir=rtl] #mdbook-sidebar-toggle-anchor:checked ~ .page-wrapper {
transform: translateX(calc(0px - var(--sidebar-width) - var(--sidebar-resize-indicator-width)));
}
@media only screen and (min-width: 620px) {
#mdbook-sidebar-toggle-anchor:checked ~ .page-wrapper {
transform: none;
margin-inline-start: calc(var(--sidebar-width) + var(--sidebar-resize-indicator-width));
}
[dir=rtl] #mdbook-sidebar-toggle-anchor:checked ~ .page-wrapper {
transform: none;
}
}
.chapter {
list-style: none outside none;
padding-inline-start: 0;
line-height: 2.2em;
}
.chapter li {
color: var(--sidebar-non-existant);
}
/* This is a span wrapping the chapter link and the fold chevron. */
.chapter-link-wrapper {
/* Used to position the chevron to the right, allowing the text to wrap before it. */
display: flex;
}
.chapter li a {
/* Remove underlines. */
text-decoration: none;
color: var(--sidebar-fg);
}
.chapter li a:hover {
color: var(--sidebar-active);
}
.chapter li a.active {
color: var(--sidebar-active);
}
/* This is the toggle chevron. */
.chapter-fold-toggle {
cursor: pointer;
/* Positions the chevron to the side. */
margin-inline-start: auto;
padding: 0 10px;
user-select: none;
opacity: 0.68;
}
.chapter-fold-toggle div {
transition: transform 0.5s;
}
/* collapse the section */
.chapter li:not(.expanded) > ol {
display: none;
}
.chapter li.chapter-item {
line-height: 1.5em;
margin-block-start: 0.6em;
}
/* When expanded, rotate the chevron to point down. */
.chapter li.expanded > span > .chapter-fold-toggle div {
transform: rotate(90deg);
}
.chapter a.current-header {
color: var(--sidebar-active);
}
.on-this-page {
margin-left: 22px;
border-inline-start: 4px solid var(--sidebar-header-border-color);
padding-left: 8px;
}
.on-this-page > ol {
padding-left: 0;
}
/* Horizontal line in chapter list. */
.spacer {
width: 100%;
height: 3px;
margin: 5px 0px;
}
.chapter .spacer {
background-color: var(--sidebar-spacer);
}
/* On touch devices, add more vertical spacing to make it easier to tap links. */
@media (-moz-touch-enabled: 1), (pointer: coarse) {
.chapter li a { padding: 5px 0; }
.spacer { margin: 10px 0; }
}
.section {
list-style: none outside none;
padding-inline-start: 20px;
line-height: 1.9em;
}
/* Theme Menu Popup */
.theme-popup {
position: absolute;
left: 10px;
top: var(--menu-bar-height);
z-index: 1000;
border-radius: 4px;
font-size: 0.7em;
color: var(--fg);
background: var(--theme-popup-bg);
border: 1px solid var(--theme-popup-border);
margin: 0;
padding: 0;
list-style: none;
display: none;
/* Don't let the children's background extend past the rounded corners. */
overflow: hidden;
}
[dir=rtl] .theme-popup { left: unset; right: 10px; }
.theme-popup .default {
color: var(--icons);
}
.theme-popup .theme {
width: 100%;
border: 0;
margin: 0;
padding: 2px 20px;
line-height: 25px;
white-space: nowrap;
text-align: start;
cursor: pointer;
color: inherit;
background: inherit;
font-size: inherit;
}
.theme-popup .theme:hover {
background-color: var(--theme-hover);
}
.theme-selected::before {
display: inline-block;
content: "✓";
margin-inline-start: -14px;
width: 14px;
}
/* The container for the help popup that covers the whole window. */
#mdbook-help-container {
/* Position and size for the whole window. */
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
/* This uses flex layout (which is set in book.js), and centers the popup
in the window.*/
display: none;
align-items: center;
justify-content: center;
z-index: 1000;
/* Dim out the book while the popup is visible. */
background: var(--overlay-bg);
}
/* The popup help box. */
#mdbook-help-popup {
box-shadow: 0 4px 24px rgba(0,0,0,0.15);
min-width: 300px;
max-width: 500px;
width: 100%;
box-sizing: border-box;
display: flex;
flex-direction: column;
align-items: center;
background-color: var(--bg);
color: var(--fg);
border-width: 1px;
border-color: var(--theme-popup-border);
border-style: solid;
border-radius: 8px;
padding: 10px;
}
.mdbook-help-title {
text-align: center;
/* mdbook's margin for h2 is way too large. */
margin: 10px;
}

408
theme/css/general.css Normal file
View File

@@ -0,0 +1,408 @@
/* Base styles and content styles */
:root {
/* Browser default font-size is 16px, this way 1 rem = 10px */
font-size: 62.5%;
color-scheme: var(--color-scheme);
}
html {
font-family: "Inter", sans-serif;
color: var(--fg);
background-color: var(--bg);
text-size-adjust: none;
-webkit-text-size-adjust: none;
}
body {
margin: 0;
font-size: 1.6rem;
overflow-x: hidden;
}
code {
font-family: var(--mono-font) !important;
font-size: var(--code-font-size);
direction: ltr !important;
}
/* make long words/inline code not x overflow */
main {
overflow-wrap: break-word;
}
/* make wide tables scroll if they overflow */
.table-wrapper {
overflow-x: auto;
}
/* Don't change font size in headers. */
h1 code, h2 code, h3 code, h4 code, h5 code, h6 code {
font-size: unset;
}
.left { float: left; }
.right { float: right; }
.boring { opacity: 0.6; }
.hide-boring .boring { display: none; }
.hidden { display: none !important; }
h2, h3 { margin-block-start: 2.5em; }
h4, h5 { margin-block-start: 2em; }
.header + .header h3,
.header + .header h4,
.header + .header h5 {
margin-block-start: 1em;
}
h1:target::before,
h2:target::before,
h3:target::before,
h4:target::before,
h5:target::before,
h6:target::before,
dt:target::before {
display: inline-block;
content: "»";
margin-inline-start: -30px;
width: 30px;
}
/* This is broken on Safari as of version 14, but is fixed
in Safari Technology Preview 117 which I think will be Safari 14.2.
https://bugs.webkit.org/show_bug.cgi?id=218076
*/
:target {
/* Safari does not support logical properties */
scroll-margin-top: calc(var(--menu-bar-height) + 0.5em);
}
.page {
outline: 0;
padding: 0 var(--page-padding);
margin-block-start: calc(0px - var(--menu-bar-height)); /* Compensate for the #mdbook-menu-bar-hover-placeholder */
}
.page-wrapper {
box-sizing: border-box;
background-color: var(--bg);
}
html:not(.js) .page-wrapper,
.js:not(.sidebar-resizing) .page-wrapper {
transition: margin-left 0.3s ease, transform 0.3s ease; /* Animation: slide away */
}
[dir=rtl]:not(.js) .page-wrapper,
[dir=rtl].js:not(.sidebar-resizing) .page-wrapper {
transition: margin-right 0.3s ease, transform 0.3s ease; /* Animation: slide away */
}
.content {
overflow-y: auto;
padding: 0 5px 50px 5px;
}
.content main {
margin-inline-start: auto;
margin-inline-end: auto;
max-width: var(--content-max-width);
}
.content p { line-height: 1.45em; }
.content ol { line-height: 1.45em; }
.content ul { line-height: 1.45em; }
.content a { text-decoration: none; }
.content a:hover { text-decoration: underline; }
.content img, .content video { max-width: 100%; }
.content .header:link,
.content .header:visited {
color: var(--fg);
}
.content .header:link,
.content .header:visited:hover {
text-decoration: none;
}
table {
margin: 0 auto;
border-collapse: collapse;
}
table td {
padding: 3px 20px;
border: 1px var(--table-border-color) solid;
}
table thead {
background: var(--table-header-bg);
}
table thead td {
font-weight: 700;
border: none;
}
table thead th {
padding: 3px 20px;
}
table thead tr {
border: 1px var(--table-header-bg) solid;
}
/* Alternate background colors for rows */
table tbody tr:nth-child(2n) {
background: var(--table-alternate-bg);
}
blockquote {
margin: 20px 0;
padding: 0 20px;
color: var(--fg);
background-color: var(--quote-bg);
border-block-start: .1em solid var(--quote-border);
border-block-end: .1em solid var(--quote-border);
}
/* TODO: Remove .warning in a future version of mdbook, it is replaced by
blockquote tags. */
.warning {
margin: 20px;
padding: 0 20px;
border-inline-start: 2px solid var(--warning-border);
}
.warning:before {
position: absolute;
width: 3rem;
height: 3rem;
margin-inline-start: calc(-1.5rem - 21px);
content: "ⓘ";
text-align: center;
background-color: var(--bg);
color: var(--warning-border);
font-weight: bold;
font-size: 2rem;
}
blockquote .warning:before {
background-color: var(--quote-bg);
}
kbd {
background-color: var(--table-border-color);
border-radius: 4px;
border: solid 1px var(--theme-popup-border);
box-shadow: inset 0 -1px 0 var(--theme-hover);
display: inline-block;
font-size: var(--code-font-size);
font-family: var(--mono-font);
line-height: 10px;
padding: 4px 5px;
vertical-align: middle;
}
sup {
/* Set the line-height for superscript and footnote references so that there
isn't an awkward space appearing above lines that contain the footnote.
See https://github.com/rust-lang/mdBook/pull/2443#discussion_r1813773583
for an explanation.
*/
line-height: 0;
}
.footnote-definition {
font-size: 0.9em;
}
/* The default spacing for a list is a little too large. */
.footnote-definition ul,
.footnote-definition ol {
padding-left: 20px;
}
.footnote-definition > li {
/* Required to position the ::before target */
position: relative;
}
.footnote-definition > li:target {
scroll-margin-top: 50vh;
}
.footnote-reference:target {
scroll-margin-top: 50vh;
}
/* Draws a border around the footnote (including the marker) when it is selected.
TODO: If there are multiple linkbacks, highlight which one you just came
from so you know which one to click.
*/
.footnote-definition > li:target::before {
border: 2px solid var(--footnote-highlight);
border-radius: 6px;
position: absolute;
top: -8px;
right: -8px;
bottom: -8px;
left: -32px;
pointer-events: none;
content: "";
}
/* Pulses the footnote reference so you can quickly see where you left off reading.
This could use some improvement.
*/
@media not (prefers-reduced-motion) {
.footnote-reference:target {
animation: fn-highlight 0.8s;
border-radius: 2px;
}
@keyframes fn-highlight {
from {
background-color: var(--footnote-highlight);
}
}
}
.tooltiptext {
position: absolute;
visibility: hidden;
color: #fff;
background-color: #333;
transform: translateX(-50%); /* Center by moving tooltip 50% of its width left */
left: -8px; /* Half of the width of the icon */
top: -35px;
font-size: 0.8em;
text-align: center;
border-radius: 6px;
padding: 5px 8px;
margin: 5px;
z-index: 1000;
}
.tooltipped .tooltiptext {
visibility: visible;
}
.chapter li.part-title {
color: var(--sidebar-fg);
margin: 5px 0px;
font-weight: bold;
}
.result-no-output {
font-style: italic;
}
.fa-svg svg {
width: 1em;
height: 1em;
fill: currentColor;
margin-bottom: -0.1em;
}
dt {
font-weight: bold;
margin-top: 0.5em;
margin-bottom: 0.1em;
}
/* This uses a CSS counter to add numbers to definitions, but only if there is
more than one definition. */
dl, dt {
counter-reset: dd-counter;
}
/* When there is more than one definition, increment the counter. The first
selector selects the first definition, and the second one selects definitions
2 and beyond.*/
dd:has(+ dd), dd + dd {
counter-increment: dd-counter;
/* Use flex display to help with positioning the numbers when there is a p
tag inside the definition. */
display: flex;
align-items: flex-start;
}
/* Shows the counter for definitions. The first selector selects the first
definition, and the second one selections definitions 2 and beyond.*/
dd:has(+ dd)::before, dd + dd::before {
content: counter(dd-counter) ". ";
font-weight: 600;
display: inline-block;
margin-right: 0.5em;
}
dd > p {
/* For loose definitions that have a p tag inside, don't add a bunch of
space before the definition. */
margin-top: 0;
}
/* Remove some excess space from the bottom. */
.blockquote-tag p:last-child {
margin-bottom: 2px;
}
.blockquote-tag {
/* Add some padding to make the vertical bar a little taller than the text.*/
padding: 2px 0px 2px 20px;
/* Add a solid color bar on the left side. */
border-inline-start-style: solid;
border-inline-start-width: 4px;
/* Disable the background color from normal blockquotes . */
background-color: inherit;
/* Disable border blocks from blockquotes. */
border-block-start: none;
border-block-end: none;
}
.blockquote-tag-title svg {
fill: currentColor;
/* Add space between the icon and the title. */
margin-right: 8px;
}
.blockquote-tag-note {
border-inline-start-color: var(--blockquote-note-color);
}
.blockquote-tag-tip {
border-inline-start-color: var(--blockquote-tip-color);
}
.blockquote-tag-important {
border-inline-start-color: var(--blockquote-important-color);
}
.blockquote-tag-warning {
border-inline-start-color: var(--blockquote-warning-color);
}
.blockquote-tag-caution {
border-inline-start-color: var(--blockquote-caution-color);
}
.blockquote-tag-note .blockquote-tag-title {
color: var(--blockquote-note-color);
}
.blockquote-tag-tip .blockquote-tag-title {
color: var(--blockquote-tip-color);
}
.blockquote-tag-important .blockquote-tag-title {
color: var(--blockquote-important-color);
}
.blockquote-tag-warning .blockquote-tag-title {
color: var(--blockquote-warning-color);
}
.blockquote-tag-caution .blockquote-tag-title {
color: var(--blockquote-caution-color);
}
.blockquote-tag-title {
/* Slightly increase the weight for more emphasis. */
font-weight: 600;
/* Vertically center the icon with the text. */
display: flex;
align-items: center;
/* Remove default large margins for a more compact display. */
margin: 2px 0 8px 0;
}
.blockquote-tag-title .fa-svg {
fill: currentColor;
/* Add some space between the icon and the text. */
margin-right: 8px;
}

50
theme/css/print.css Normal file
View File

@@ -0,0 +1,50 @@
#mdbook-sidebar,
#mdbook-menu-bar,
.nav-chapters,
.mobile-nav-chapters {
display: none;
}
#mdbook-page-wrapper.page-wrapper {
transform: none !important;
margin-inline-start: 0px;
overflow-y: initial;
}
#mdbook-content {
max-width: none;
margin: 0;
padding: 0;
}
.page {
overflow-y: initial;
}
code {
direction: ltr !important;
}
pre > .buttons {
z-index: 2;
}
a, a:visited, a:active, a:hover {
color: #4183c4;
text-decoration: none;
}
h1, h2, h3, h4, h5, h6 {
page-break-inside: avoid;
page-break-after: avoid;
}
pre, code {
page-break-inside: avoid;
white-space: pre-wrap;
}
.fa {
display: none !important;
}

445
theme/css/variables.css Normal file
View File

@@ -0,0 +1,445 @@
/* Globals */
:root {
--sidebar-target-width: 300px;
--sidebar-width: min(var(--sidebar-target-width), 80vw);
--sidebar-resize-indicator-width: 8px;
--sidebar-resize-indicator-space: 2px;
--page-padding: 15px;
--content-max-width: 750px;
--menu-bar-height: 50px;
--mono-font: "JetBrains Mono", Consolas, "Ubuntu Mono", Menlo, "DejaVu Sans Mono", monospace, monospace;
--code-font-size: 0.875em; /* please adjust the ace font size accordingly in editor.js */
--searchbar-margin-block-start: 5px;
}
/* Themes */
.ayu {
--bg: hsl(210, 25%, 8%);
--fg: #c5c5c5;
--sidebar-bg: #14191f;
--sidebar-fg: #c8c9db;
--sidebar-non-existant: #5c6773;
--sidebar-active: #ffb454;
--sidebar-spacer: #2d334f;
--scrollbar: var(--sidebar-fg);
--icons: #737480;
--icons-hover: #b7b9cc;
--links: #0096cf;
--inline-code-color: #ffb454;
--theme-popup-bg: #14191f;
--theme-popup-border: #5c6773;
--theme-hover: #191f26;
--quote-bg: hsl(226, 15%, 17%);
--quote-border: hsl(226, 15%, 22%);
--warning-border: #ff8e00;
--table-border-color: hsl(210, 25%, 13%);
--table-header-bg: hsl(210, 25%, 28%);
--table-alternate-bg: hsl(210, 25%, 11%);
--searchbar-border-color: #848484;
--searchbar-bg: #424242;
--searchbar-fg: #fff;
--searchbar-shadow-color: #d4c89f;
--searchresults-header-fg: #666;
--searchresults-border-color: #888;
--searchresults-li-bg: #252932;
--search-mark-bg: #e3b171;
--color-scheme: dark;
/* Same as `--icons` */
--copy-button-filter: invert(45%) sepia(6%) saturate(621%) hue-rotate(198deg) brightness(99%) contrast(85%);
/* Same as `--sidebar-active` */
--copy-button-filter-hover: invert(68%) sepia(55%) saturate(531%) hue-rotate(341deg) brightness(104%) contrast(101%);
--footnote-highlight: #2668a6;
--overlay-bg: rgba(33, 40, 48, 0.4);
--blockquote-note-color: #74b9ff;
--blockquote-tip-color: #09ca09;
--blockquote-important-color: #d3abff;
--blockquote-warning-color: #f0b72f;
--blockquote-caution-color: #f21424;
--sidebar-header-border-color: #c18639;
}
.coal {
--bg: hsl(200, 7%, 8%);
--fg: #98a3ad;
--sidebar-bg: #292c2f;
--sidebar-fg: #a1adb8;
--sidebar-non-existant: #505254;
--sidebar-active: #3473ad;
--sidebar-spacer: #393939;
--scrollbar: var(--sidebar-fg);
--icons: #43484d;
--icons-hover: #b3c0cc;
--links: #2b79a2;
--inline-code-color: #c5c8c6;
--theme-popup-bg: #141617;
--theme-popup-border: #43484d;
--theme-hover: #1f2124;
--quote-bg: hsl(234, 21%, 18%);
--quote-border: hsl(234, 21%, 23%);
--warning-border: #ff8e00;
--table-border-color: hsl(200, 7%, 13%);
--table-header-bg: hsl(200, 7%, 28%);
--table-alternate-bg: hsl(200, 7%, 11%);
--searchbar-border-color: #aaa;
--searchbar-bg: #b7b7b7;
--searchbar-fg: #000;
--searchbar-shadow-color: #aaa;
--searchresults-header-fg: #666;
--searchresults-border-color: #98a3ad;
--searchresults-li-bg: #2b2b2f;
--search-mark-bg: #355c7d;
--color-scheme: dark;
/* Same as `--icons` */
--copy-button-filter: invert(26%) sepia(8%) saturate(575%) hue-rotate(169deg) brightness(87%) contrast(82%);
/* Same as `--sidebar-active` */
--copy-button-filter-hover: invert(36%) sepia(70%) saturate(503%) hue-rotate(167deg) brightness(98%) contrast(89%);
--footnote-highlight: #4079ae;
--overlay-bg: rgba(33, 40, 48, 0.4);
--blockquote-note-color: #4493f8;
--blockquote-tip-color: #08ae08;
--blockquote-important-color: #ab7df8;
--blockquote-warning-color: #d29922;
--blockquote-caution-color: #d91b29;
--sidebar-header-border-color: #3473ad;
}
.light, html:not(.js) {
--bg: hsl(0, 0%, 100%);
--fg: hsl(0, 0%, 0%);
--sidebar-bg: #fafafa;
--sidebar-fg: hsl(0, 0%, 0%);
--sidebar-non-existant: #aaaaaa;
--sidebar-active: #1f1fff;
--sidebar-spacer: #f4f4f4;
--scrollbar: #8F8F8F;
--icons: #747474;
--icons-hover: #000000;
--links: #20609f;
--inline-code-color: #301900;
--theme-popup-bg: #fafafa;
--theme-popup-border: #cccccc;
--theme-hover: #e6e6e6;
--quote-bg: hsl(197, 37%, 96%);
--quote-border: hsl(197, 37%, 91%);
--warning-border: #ff8e00;
--table-border-color: hsl(0, 0%, 95%);
--table-header-bg: hsl(0, 0%, 80%);
--table-alternate-bg: hsl(0, 0%, 97%);
--searchbar-border-color: #aaa;
--searchbar-bg: #fafafa;
--searchbar-fg: #000;
--searchbar-shadow-color: #aaa;
--searchresults-header-fg: #666;
--searchresults-border-color: #888;
--searchresults-li-bg: #e4f2fe;
--search-mark-bg: #a2cff5;
--color-scheme: light;
/* Same as `--icons` */
--copy-button-filter: invert(45.49%);
/* Same as `--sidebar-active` */
--copy-button-filter-hover: invert(14%) sepia(93%) saturate(4250%) hue-rotate(243deg) brightness(99%) contrast(130%);
--footnote-highlight: #7e7eff;
--overlay-bg: rgba(200, 200, 205, 0.4);
--blockquote-note-color: #0969da;
--blockquote-tip-color: #008000;
--blockquote-important-color: #8250df;
--blockquote-warning-color: #9a6700;
--blockquote-caution-color: #b52731;
--sidebar-header-border-color: #6e6edb;
}
.nnavy {
--bg: hsl(226, 23%, 11%);
--fg: #bcbdd0;
--sidebar-bg: #282d3f;
--sidebar-fg: #c8c9db;
--sidebar-non-existant: #505274;
--sidebar-active: #2b79a2;
--sidebar-spacer: #2d334f;
--scrollbar: var(--sidebar-fg);
--icons: #737480;
--icons-hover: #b7b9cc;
--links: #2b79a2;
--inline-code-color: #c5c8c6;
--theme-popup-bg: #161923;
--theme-popup-border: #737480;
--theme-hover: #282e40;
--quote-bg: hsl(226, 15%, 17%);
--quote-border: hsl(226, 15%, 22%);
--warning-border: #ff8e00;
--table-border-color: hsl(226, 23%, 16%);
--table-header-bg: hsl(226, 23%, 31%);
--table-alternate-bg: hsl(226, 23%, 14%);
--searchbar-border-color: #aaa;
--searchbar-bg: #aeaec6;
--searchbar-fg: #000;
--searchbar-shadow-color: #aaa;
--searchresults-header-fg: #5f5f71;
--searchresults-border-color: #5c5c68;
--searchresults-li-bg: #242430;
--search-mark-bg: #a2cff5;
--color-scheme: dark;
/* Same as `--icons` */
--copy-button-filter: invert(51%) sepia(10%) saturate(393%) hue-rotate(198deg) brightness(86%) contrast(87%);
/* Same as `--sidebar-active` */
--copy-button-filter-hover: invert(46%) sepia(20%) saturate(1537%) hue-rotate(156deg) brightness(85%) contrast(90%);
--footnote-highlight: #4079ae;
--overlay-bg: rgba(33, 40, 48, 0.4);
--blockquote-note-color: #4493f8;
--blockquote-tip-color: #09ca09;
--blockquote-important-color: #ab7df8;
--blockquote-warning-color: #d29922;
--blockquote-caution-color: #f21424;
--sidebar-header-border-color: #2f6ab5;
}
.rust {
--bg: hsl(60, 9%, 87%);
--fg: #262625;
--sidebar-bg: #3b2e2a;
--sidebar-fg: #c8c9db;
--sidebar-non-existant: #505254;
--sidebar-active: #e69f67;
--sidebar-spacer: #45373a;
--scrollbar: var(--sidebar-fg);
--icons: #737480;
--icons-hover: #262625;
--links: #2b79a2;
--inline-code-color: #6e6b5e;
--theme-popup-bg: #e1e1db;
--theme-popup-border: #b38f6b;
--theme-hover: #99908a;
--quote-bg: hsl(60, 5%, 75%);
--quote-border: hsl(60, 5%, 70%);
--warning-border: #ff8e00;
--table-border-color: hsl(60, 9%, 82%);
--table-header-bg: #b3a497;
--table-alternate-bg: hsl(60, 9%, 84%);
--searchbar-border-color: #aaa;
--searchbar-bg: #fafafa;
--searchbar-fg: #000;
--searchbar-shadow-color: #aaa;
--searchresults-header-fg: #666;
--searchresults-border-color: #888;
--searchresults-li-bg: #dec2a2;
--search-mark-bg: #e69f67;
/* Same as `--icons` */
--copy-button-filter: invert(51%) sepia(10%) saturate(393%) hue-rotate(198deg) brightness(86%) contrast(87%);
/* Same as `--sidebar-active` */
--copy-button-filter-hover: invert(77%) sepia(16%) saturate(1798%) hue-rotate(328deg) brightness(98%) contrast(83%);
--footnote-highlight: #d3a17a;
--overlay-bg: rgba(150, 150, 150, 0.25);
--blockquote-note-color: #023b95;
--blockquote-tip-color: #007700;
--blockquote-important-color: #8250df;
--blockquote-warning-color: #603700;
--blockquote-caution-color: #aa1721;
--sidebar-header-border-color: #8c391f;
}
.navy {
--bg: #161031;
--fg: #ffffff;
--sidebar-bg: #080511;
--sidebar-fg: #bebebf;
--sidebar-non-existant: #505274;
--sidebar-active: #a594f9;
--sidebar-spacer: #2d334f;
--scrollbar: var(--sidebar-fg);
--icons: #737480;
--icons-hover: #b7b9cc;
--links: #a594f9;
--inline-code-color: #c5c8c6;
--theme-popup-bg: #161923;
--theme-popup-border: #737480;
--theme-hover: #282e40;
--quote-bg: hsl(226, 15%, 17%);
--quote-border: hsl(226, 15%, 22%);
--warning-border: #ff8e00;
--table-border-color: hsl(226, 23%, 16%);
--table-header-bg: hsl(226, 23%, 31%);
--table-alternate-bg: hsl(226, 23%, 14%);
--searchbar-border-color: #aaa;
--searchbar-bg: #aeaec6;
--searchbar-fg: #000;
--searchbar-shadow-color: #aaa;
--searchresults-header-fg: #5f5f71;
--searchresults-border-color: #5c5c68;
--searchresults-li-bg: #242430;
--search-mark-bg: #a2cff5;
--color-scheme: dark;
/* Same as `--icons` */
--copy-button-filter: invert(51%) sepia(10%) saturate(393%) hue-rotate(198deg) brightness(86%) contrast(87%);
/* Same as `--sidebar-active` */
--copy-button-filter-hover: invert(46%) sepia(20%) saturate(1537%) hue-rotate(156deg) brightness(85%) contrast(90%);
--footnote-highlight: #4079ae;
--overlay-bg: rgba(33, 40, 48, 0.4);
--blockquote-note-color: #4493f8;
--blockquote-tip-color: #09ca09;
--blockquote-important-color: #ab7df8;
--blockquote-warning-color: #d29922;
--blockquote-caution-color: #f21424;
--sidebar-header-border-color: #000000;
}
@media (prefers-color-scheme: dark) {
html:not(.js) {
--bg: hsl(200, 7%, 8%);
--fg: #98a3ad;
--sidebar-bg: #292c2f;
--sidebar-fg: #a1adb8;
--sidebar-non-existant: #505254;
--sidebar-active: #3473ad;
--sidebar-spacer: #393939;
--scrollbar: var(--sidebar-fg);
--icons: #43484d;
--icons-hover: #b3c0cc;
--links: #2b79a2;
--inline-code-color: #c5c8c6;
--theme-popup-bg: #141617;
--theme-popup-border: #43484d;
--theme-hover: #1f2124;
--quote-bg: hsl(234, 21%, 18%);
--quote-border: hsl(234, 21%, 23%);
--warning-border: #ff8e00;
--table-border-color: hsl(200, 7%, 13%);
--table-header-bg: hsl(200, 7%, 28%);
--table-alternate-bg: hsl(200, 7%, 11%);
--searchbar-border-color: #aaa;
--searchbar-bg: #b7b7b7;
--searchbar-fg: #000;
--searchbar-shadow-color: #aaa;
--searchresults-header-fg: #666;
--searchresults-border-color: #98a3ad;
--searchresults-li-bg: #2b2b2f;
--search-mark-bg: #355c7d;
--color-scheme: dark;
/* Same as `--icons` */
--copy-button-filter: invert(26%) sepia(8%) saturate(575%) hue-rotate(169deg) brightness(87%) contrast(82%);
/* Same as `--sidebar-active` */
--copy-button-filter-hover: invert(36%) sepia(70%) saturate(503%) hue-rotate(167deg) brightness(98%) contrast(89%);
--footnote-highlight: #4079ae;
--overlay-bg: rgba(33, 40, 48, 0.4);
--blockquote-note-color: #4493f8;
--blockquote-tip-color: #08ae08;
--blockquote-important-color: #ab7df8;
--blockquote-warning-color: #d29922;
--blockquote-caution-color: #d91b29;
--sidebar-header-border-color: #3473ad;
}
}

BIN
theme/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

52
theme/favicon.svg Normal file
View File

@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="100.00389mm"
height="100.00055mm"
viewBox="0 0 100.00389 100.00055"
version="1.1"
id="svg1"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs1">
<linearGradient
id="linearGradient8">
<stop
style="stop-color:#64ffe1;stop-opacity:1;"
offset="0"
id="stop8" />
<stop
style="stop-color:#a3b9f5;stop-opacity:1;"
offset="0.5"
id="stop10" />
<stop
style="stop-color:#d1b8fb;stop-opacity:1;"
offset="0.75"
id="stop11" />
<stop
style="stop-color:#f3cdff;stop-opacity:1;"
offset="1"
id="stop9" />
</linearGradient>
<linearGradient
xlink:href="#linearGradient8"
id="linearGradient9"
x1="-42.253399"
y1="135.74071"
x2="-41.225731"
y2="239.96782"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.73239966,-0.77274564,0.76516532,0.73965537,-4.0932457,-8.6853091)" />
</defs>
<g
id="layer1"
transform="translate(-69.164575,-124.62841)">
<path
id="path1"
style="fill:url(#linearGradient9);fill-opacity:1;stroke:#ffffff;stroke-width:0.281629;stroke-opacity:0"
d="m 100.38267,124.7767 a 31.775753,32.090549 0 0 0 -22.257004,9.893 31.775753,32.090549 0 0 0 0.979215,45.36846 l -0.0038,0.004 45.917939,44.38672 43.95132,-46.37229 -45.91795,-44.38673 -0.004,0.004 a 31.775753,32.090549 0 0 0 -22.66587,-8.8969 z" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

1
theme/fonts/fonts.css Normal file
View File

@@ -0,0 +1 @@
@import url('https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&family=JetBrains+Mono:ital,wght@0,100..800;1,100..800&display=swap');

83
theme/highlight.css Normal file
View File

@@ -0,0 +1,83 @@
/*
* An increased contrast highlighting scheme loosely based on the
* "Base16 Atelier Dune Light" theme by Bram de Haan
* (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/dune)
* Original Base16 color scheme by Chris Kempson
* (https://github.com/chriskempson/base16)
*/
/* Comment */
.hljs-comment,
.hljs-quote {
color: #575757;
}
/* Red */
.hljs-variable,
.hljs-template-variable,
.hljs-attribute,
.hljs-attr,
.hljs-tag,
.hljs-name,
.hljs-regexp,
.hljs-link,
.hljs-name,
.hljs-selector-id,
.hljs-selector-class {
color: #d70025;
}
/* Orange */
.hljs-number,
.hljs-meta,
.hljs-built_in,
.hljs-builtin-name,
.hljs-literal,
.hljs-type,
.hljs-params {
color: #b21e00;
}
/* Green */
.hljs-string,
.hljs-symbol,
.hljs-bullet {
color: #008200;
}
/* Blue */
.hljs-title,
.hljs-section {
color: #0030f2;
}
/* Purple */
.hljs-keyword,
.hljs-selector-tag {
color: #9d00ec;
}
.hljs {
display: block;
overflow-x: auto;
background: #f6f7f6;
color: #000;
}
.hljs-emphasis {
font-style: italic;
}
.hljs-strong {
font-weight: bold;
}
.hljs-addition {
color: #22863a;
background-color: #f0fff4;
}
.hljs-deletion {
color: #b31d28;
background-color: #ffeef0;
}

2630
theme/highlight.js Normal file

File diff suppressed because it is too large Load Diff

367
theme/index.hbs Normal file
View File

@@ -0,0 +1,367 @@
<!DOCTYPE HTML>
<html lang="{{ language }}" class="{{ default_theme }} sidebar-visible" dir="{{ text_direction }}">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>{{ title }}</title>
{{#if is_print }}
<meta name="robots" content="noindex">
{{/if}}
{{#if base_url}}
<base href="{{ base_url }}">
{{/if}}
<!-- Custom HTML head -->
{{> head}}
<meta name="description" content="{{ description }}">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff">
{{#if favicon_svg}}
<link rel="icon" href="{{ resource "favicon.svg" }}">
{{/if}}
{{#if favicon_png}}
<link rel="shortcut icon" href="{{ resource "favicon.png" }}">
{{/if}}
<link rel="stylesheet" href="{{ resource "css/variables.css" }}">
<link rel="stylesheet" href="{{ resource "css/general.css" }}">
<link rel="stylesheet" href="{{ resource "css/chrome.css" }}">
{{#if print_enable}}
<link rel="stylesheet" href="{{ resource "css/print.css" }}" media="print">
{{/if}}
<!-- Fonts -->
<link rel="stylesheet" href="{{ resource "fonts/fonts.css" }}">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" id="mdbook-highlight-css" href="{{ resource "highlight.css" }}">
<link rel="stylesheet" id="mdbook-tomorrow-night-css" href="{{ resource "tomorrow-night.css" }}">
<link rel="stylesheet" id="mdbook-ayu-highlight-css" href="{{ resource "ayu-highlight.css" }}">
<!-- Custom theme stylesheets -->
{{#each additional_css}}
<link rel="stylesheet" href="{{ resource this }}">
{{/each}}
{{#if mathjax_support}}
<!-- MathJax -->
<script async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
{{/if}}
<!-- Provide site root and default themes to javascript -->
<script>
const path_to_root = "{{ path_to_root }}";
const default_light_theme = "{{ default_theme }}";
const default_dark_theme = "{{ preferred_dark_theme }}";
{{#if search_js}}
window.path_to_searchindex_js = "{{ resource "searchindex.js" }}";
{{/if}}
</script>
<!-- Start loading toc.js asap -->
<script src="{{ resource "toc.js" }}"></script>
</head>
<body>
<div id="mdbook-help-container">
<div id="mdbook-help-popup">
<h2 class="mdbook-help-title">Keyboard shortcuts</h2>
<div>
<p>Press <kbd>←</kbd> or <kbd>→</kbd> to navigate between chapters</p>
{{#if search_enabled}}
<p>Press <kbd>S</kbd> or <kbd>/</kbd> to search in the book</p>
{{/if}}
<p>Press <kbd>?</kbd> to show this help</p>
<p>Press <kbd>Esc</kbd> to hide this help</p>
</div>
</div>
</div>
<div id="mdbook-body-container">
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script>
try {
let theme = localStorage.getItem('mdbook-theme');
let sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
</script>
<!-- Set the theme before any content is loaded, prevents flash -->
<script>
const default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? default_dark_theme : default_light_theme;
let theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
const html = document.documentElement;
html.classList.remove('{{ default_theme }}')
html.classList.add(theme);
html.classList.add("js");
</script>
<input type="checkbox" id="mdbook-sidebar-toggle-anchor" class="hidden">
<!-- Hide / unhide sidebar before it is displayed -->
<script>
let sidebar = null;
const sidebar_toggle = document.getElementById("mdbook-sidebar-toggle-anchor");
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
} else {
sidebar = 'hidden';
sidebar_toggle.checked = false;
}
if (sidebar === 'visible') {
sidebar_toggle.checked = true;
} else {
html.classList.remove('sidebar-visible');
}
</script>
<nav id="mdbook-sidebar" class="sidebar" aria-label="Table of contents">
<!-- populated by js -->
<mdbook-sidebar-scrollbox class="sidebar-scrollbox"></mdbook-sidebar-scrollbox>
<noscript>
<iframe class="sidebar-iframe-outer" src="{{ path_to_root }}toc.html"></iframe>
</noscript>
<div id="mdbook-sidebar-resize-handle" class="sidebar-resize-handle">
<div class="sidebar-resize-indicator"></div>
</div>
</nav>
<div id="mdbook-page-wrapper" class="page-wrapper">
<div class="page">
{{> header}}
<div id="mdbook-menu-bar-hover-placeholder"></div>
<div id="mdbook-menu-bar" class="menu-bar sticky">
<div class="left-buttons">
<label id="mdbook-sidebar-toggle" class="icon-button" for="mdbook-sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="mdbook-sidebar">
{{fa "solid" "bars"}}
</label>
<button id="mdbook-theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="mdbook-theme-list">
{{fa "solid" "paintbrush"}}
</button>
<ul id="mdbook-theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="mdbook-theme-default_theme">Auto</button></li>
<li role="none"><button role="menuitem" class="theme" id="mdbook-theme-light">Light</button></li>
<li role="none"><button role="menuitem" class="theme" id="mdbook-theme-rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="mdbook-theme-coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="mdbook-theme-navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="mdbook-theme-ayu">Ayu</button></li>
</ul>
{{#if search_enabled}}
<button id="mdbook-search-toggle" class="icon-button" type="button" title="Search (`/`)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="/ s" aria-controls="mdbook-searchbar">
{{fa "solid" "magnifying-glass"}}
</button>
{{/if}}
</div>
<h1 class="menu-title">{{ book_title }}</h1>
<div class="right-buttons">
{{#if print_enable}}
<a href="{{ path_to_root }}print.html" title="Print this book" aria-label="Print this book">
{{fa "solid" "print" "print-button"}}
</a>
{{/if}}
{{#if git_repository_url}}
<a href="{{git_repository_url}}" title="Git repository" aria-label="Git repository">
{{fa git_repository_icon_class git_repository_icon}}
</a>
{{/if}}
{{#if git_repository_edit_url}}
<a href="{{git_repository_edit_url}}" title="Suggest an edit" aria-label="Suggest an edit" rel="edit">
{{fa "solid" "pencil" "git-edit-button"}}
</a>
{{/if}}
</div>
</div>
{{#if search_enabled}}
<div id="mdbook-search-wrapper" class="hidden">
<form id="mdbook-searchbar-outer" class="searchbar-outer">
<div class="search-wrapper">
<input type="search" id="mdbook-searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="mdbook-searchresults-outer" aria-describedby="searchresults-header">
<div class="spinner-wrapper">
{{fa "solid" "spinner" "fa-spin"}}
</div>
</div>
</form>
<div id="mdbook-searchresults-outer" class="searchresults-outer hidden">
<div id="mdbook-searchresults-header" class="searchresults-header"></div>
<ul id="mdbook-searchresults">
</ul>
</div>
</div>
{{/if}}
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script>
document.getElementById('mdbook-sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('mdbook-sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#mdbook-sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="mdbook-content" class="content">
<main>
{{{ content }}}
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
{{#if previous}}
<a rel="prev" href="{{ path_to_root }}{{previous.link}}" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
{{#if (eq ../text_direction "rtl")}}
{{fa "solid" "angle-right"}}
{{else}}
{{fa "solid" "angle-left"}}
{{/if}}
</a>
{{/if}}
{{#if next}}
<a rel="next prefetch" href="{{ path_to_root }}{{next.link}}" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
{{#if (eq ../text_direction "rtl")}}
{{fa "solid" "angle-left"}}
{{else}}
{{fa "solid" "angle-right"}}
{{/if}}
</a>
{{/if}}
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
{{#if previous}}
<a rel="prev" href="{{ path_to_root }}{{previous.link}}" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
{{#if (eq ../text_direction "rtl")}}
{{fa "solid" "angle-right"}}
{{else}}
{{fa "solid" "angle-left"}}
{{/if}}
</a>
{{/if}}
{{#if next}}
<a rel="next prefetch" href="{{ path_to_root }}{{next.link}}" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
{{#if (eq text_direction "rtl")}}
{{fa "solid" "angle-left"}}
{{else}}
{{fa "solid" "angle-right"}}
{{/if}}
</a>
{{/if}}
</nav>
</div>
<template id=fa-eye>{{fa "solid" "eye"}}</template>
<template id=fa-eye-slash>{{fa "solid" "eye-slash"}}</template>
<template id=fa-copy>{{fa "regular" "copy"}}</template>
<template id=fa-play>{{fa "solid" "play"}}</template>
<template id=fa-clock-rotate-left>{{fa "solid" "clock-rotate-left"}}</template>
{{#if live_reload_endpoint}}
<!-- Livereload script (if served using the cli tool) -->
<script>
const wsProtocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
const wsAddress = wsProtocol + "//" + location.host + "/" + "{{{live_reload_endpoint}}}";
const socket = new WebSocket(wsAddress);
socket.onmessage = function (event) {
if (event.data === "reload") {
socket.close();
location.reload();
}
};
window.onbeforeunload = function() {
socket.close();
}
</script>
{{/if}}
{{#if playground_line_numbers}}
<script>
window.playground_line_numbers = true;
</script>
{{/if}}
{{#if playground_copyable}}
<script>
window.playground_copyable = true;
</script>
{{/if}}
{{#if playground_js}}
<script src="{{ resource "ace.js" }}"></script>
<script src="{{ resource "mode-rust.js" }}"></script>
<script src="{{ resource "editor.js" }}"></script>
<script src="{{ resource "theme-dawn.js" }}"></script>
<script src="{{ resource "theme-tomorrow_night.js" }}"></script>
{{/if}}
{{#if search_js}}
<script src="{{ resource "elasticlunr.min.js" }}"></script>
<script src="{{ resource "mark.min.js" }}"></script>
<script src="{{ resource "searcher.js" }}"></script>
{{/if}}
<script src="{{ resource "clipboard.min.js" }}"></script>
<script src="{{ resource "highlight.js" }}"></script>
<script src="{{ resource "book.js" }}"></script>
<!-- Custom JS scripts -->
{{#each additional_js}}
<script src="{{ resource this}}"></script>
{{/each}}
{{#if is_print}}
{{#if mathjax_support}}
<script>
window.addEventListener('load', function() {
MathJax.Hub.Register.StartupHook('End', function() {
window.setTimeout(window.print, 100);
});
});
</script>
{{else}}
<script>
window.addEventListener('load', function() {
window.setTimeout(window.print, 100);
});
</script>
{{/if}}
{{/if}}
{{#if fragment_map}}
<script>
document.addEventListener('DOMContentLoaded', function() {
const fragmentMap =
{{{fragment_map}}}
;
const target = fragmentMap[window.location.hash];
if (target) {
let url = new URL(target, window.location.href);
window.location.replace(url.href);
}
});
</script>
{{/if}}
</div>
</body>
</html>