summaryrefslogtreecommitdiffstats
path: root/vendor/mdbook/src/theme
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
commit698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch)
tree173a775858bd501c378080a10dca74132f05bc50 /vendor/mdbook/src/theme
parentInitial commit. (diff)
downloadrustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz
rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/mdbook/src/theme')
-rw-r--r--vendor/mdbook/src/theme/ayu-highlight.css78
-rw-r--r--vendor/mdbook/src/theme/book.js679
-rw-r--r--vendor/mdbook/src/theme/css/chrome.css534
-rw-r--r--vendor/mdbook/src/theme/css/general.css191
-rw-r--r--vendor/mdbook/src/theme/css/print.css54
-rw-r--r--vendor/mdbook/src/theme/css/variables.css253
-rw-r--r--vendor/mdbook/src/theme/favicon.pngbin0 -> 5679 bytes
-rwxr-xr-xvendor/mdbook/src/theme/favicon.svg22
-rw-r--r--vendor/mdbook/src/theme/head.hbs1
-rw-r--r--vendor/mdbook/src/theme/header.hbs1
-rw-r--r--vendor/mdbook/src/theme/index.hbs314
-rw-r--r--vendor/mdbook/src/theme/mod.rs270
-rw-r--r--vendor/mdbook/src/theme/redirect.hbs12
-rw-r--r--vendor/mdbook/src/theme/searcher/mod.rs6
-rw-r--r--vendor/mdbook/src/theme/searcher/searcher.js483
-rw-r--r--vendor/mdbook/src/theme/tomorrow-night.css102
16 files changed, 3000 insertions, 0 deletions
diff --git a/vendor/mdbook/src/theme/ayu-highlight.css b/vendor/mdbook/src/theme/ayu-highlight.css
new file mode 100644
index 000000000..32c943222
--- /dev/null
+++ b/vendor/mdbook/src/theme/ayu-highlight.css
@@ -0,0 +1,78 @@
+/*
+Based off of the Ayu theme
+Original by Dempfi (https://github.com/dempfi/ayu)
+*/
+
+.hljs {
+ display: block;
+ overflow-x: auto;
+ background: #191f26;
+ color: #e6e1cf;
+}
+
+.hljs-comment,
+.hljs-quote {
+ color: #5c6773;
+ font-style: italic;
+}
+
+.hljs-variable,
+.hljs-template-variable,
+.hljs-attribute,
+.hljs-attr,
+.hljs-regexp,
+.hljs-link,
+.hljs-selector-id,
+.hljs-selector-class {
+ color: #ff7733;
+}
+
+.hljs-number,
+.hljs-meta,
+.hljs-builtin-name,
+.hljs-literal,
+.hljs-type,
+.hljs-params {
+ color: #ffee99;
+}
+
+.hljs-string,
+.hljs-bullet {
+ color: #b8cc52;
+}
+
+.hljs-title,
+.hljs-built_in,
+.hljs-section {
+ color: #ffb454;
+}
+
+.hljs-keyword,
+.hljs-selector-tag,
+.hljs-symbol {
+ color: #ff7733;
+}
+
+.hljs-name {
+ color: #36a3d9;
+}
+
+.hljs-tag {
+ color: #00568d;
+}
+
+.hljs-emphasis {
+ font-style: italic;
+}
+
+.hljs-strong {
+ font-weight: bold;
+}
+
+.hljs-addition {
+ color: #91b362;
+}
+
+.hljs-deletion {
+ color: #d96c75;
+}
diff --git a/vendor/mdbook/src/theme/book.js b/vendor/mdbook/src/theme/book.js
new file mode 100644
index 000000000..d40440c72
--- /dev/null
+++ b/vendor/mdbook/src/theme/book.js
@@ -0,0 +1,679 @@
+"use strict";
+
+// Fix back button cache problem
+window.onunload = function () { };
+
+// Global variable, shared between modules
+function playground_text(playground) {
+ let code_block = playground.querySelector("code");
+
+ if (window.ace && code_block.classList.contains("editable")) {
+ let editor = window.ace.edit(code_block);
+ return editor.getValue();
+ } else {
+ return code_block.textContent;
+ }
+}
+
+(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))
+ ]);
+ }
+
+ var 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
+ let 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) {
+ let code_block = playground_block.querySelector("code");
+ if (code_block.classList.contains("editable")) {
+ let editor = window.ace.edit(code_block);
+ editor.addEventListener("change", function (e) {
+ 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 http://play.rust-lang.org
+ function update_play_button(pre_block, playground_crates) {
+ var 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
+ var txt = playground_text(pre_block);
+ var re = /extern\s+crate\s+([a-zA-Z_0-9]+)\s*;/g;
+ var snippet_crates = [];
+ var item;
+ while (item = re.exec(txt)) {
+ snippet_crates.push(item[1]);
+ }
+
+ // check if all used crates are available on play.rust-lang.org
+ var all_available = snippet_crates.every(function (elem) {
+ return playground_crates.indexOf(elem) > -1;
+ });
+
+ if (all_available) {
+ play_button.classList.remove("hidden");
+ } else {
+ play_button.classList.add("hidden");
+ }
+ }
+
+ function run_rust_code(code_block) {
+ var 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);
+ }
+
+ let text = playground_text(code_block);
+ let classes = code_block.querySelector('code').classList;
+ let edition = "2015";
+ if(classes.contains("edition2018")) {
+ edition = "2018";
+ } else if(classes.contains("edition2021")) {
+ edition = "2021";
+ }
+ var 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
+ });
+
+ let 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'); });
+
+ Array
+ 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.language-rust")).forEach(function (block) {
+
+ var lines = Array.from(block.querySelectorAll('.boring'));
+ // If no lines were hidden, return
+ if (!lines.length) { return; }
+ block.classList.add("hide-boring");
+
+ var buttons = document.createElement('div');
+ buttons.className = 'buttons';
+ buttons.innerHTML = "<button class=\"fa fa-eye\" title=\"Show hidden lines\" aria-label=\"Show hidden lines\"></button>";
+
+ // add expand button
+ var pre_block = block.parentNode;
+ pre_block.insertBefore(buttons, pre_block.firstChild);
+
+ pre_block.querySelector('.buttons').addEventListener('click', function (e) {
+ if (e.target.classList.contains('fa-eye')) {
+ e.target.classList.remove('fa-eye');
+ e.target.classList.add('fa-eye-slash');
+ e.target.title = 'Hide lines';
+ e.target.setAttribute('aria-label', e.target.title);
+
+ block.classList.remove('hide-boring');
+ } else if (e.target.classList.contains('fa-eye-slash')) {
+ e.target.classList.remove('fa-eye-slash');
+ e.target.classList.add('fa-eye');
+ e.target.title = 'Show hidden lines';
+ e.target.setAttribute('aria-label', e.target.title);
+
+ block.classList.add('hide-boring');
+ }
+ });
+ });
+
+ if (window.playground_copyable) {
+ Array.from(document.querySelectorAll('pre code')).forEach(function (block) {
+ var pre_block = block.parentNode;
+ if (!pre_block.classList.contains('playground')) {
+ var buttons = pre_block.querySelector(".buttons");
+ if (!buttons) {
+ buttons = document.createElement('div');
+ buttons.className = 'buttons';
+ pre_block.insertBefore(buttons, pre_block.firstChild);
+ }
+
+ var clipButton = document.createElement('button');
+ clipButton.className = 'fa fa-copy 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
+ var buttons = pre_block.querySelector(".buttons");
+ if (!buttons) {
+ buttons = document.createElement('div');
+ buttons.className = 'buttons';
+ pre_block.insertBefore(buttons, pre_block.firstChild);
+ }
+
+ var runCodeButton = document.createElement('button');
+ runCodeButton.className = 'fa fa-play play-button';
+ runCodeButton.hidden = true;
+ runCodeButton.title = 'Run this code';
+ runCodeButton.setAttribute('aria-label', runCodeButton.title);
+
+ buttons.insertBefore(runCodeButton, buttons.firstChild);
+ runCodeButton.addEventListener('click', function (e) {
+ run_rust_code(pre_block);
+ });
+
+ if (window.playground_copyable) {
+ var copyCodeClipboardButton = document.createElement('button');
+ copyCodeClipboardButton.className = 'fa fa-copy clip-button';
+ copyCodeClipboardButton.innerHTML = '<i class="tooltiptext"></i>';
+ copyCodeClipboardButton.title = 'Copy to clipboard';
+ copyCodeClipboardButton.setAttribute('aria-label', copyCodeClipboardButton.title);
+
+ buttons.insertBefore(copyCodeClipboardButton, buttons.firstChild);
+ }
+
+ let code_block = pre_block.querySelector("code");
+ if (window.ace && code_block.classList.contains("editable")) {
+ var undoChangesButton = document.createElement('button');
+ undoChangesButton.className = 'fa fa-history reset-button';
+ undoChangesButton.title = 'Undo changes';
+ undoChangesButton.setAttribute('aria-label', undoChangesButton.title);
+
+ buttons.insertBefore(undoChangesButton, buttons.firstChild);
+
+ undoChangesButton.addEventListener('click', function () {
+ let editor = window.ace.edit(code_block);
+ editor.setValue(editor.originalCode);
+ editor.clearSelection();
+ });
+ }
+ });
+})();
+
+(function themes() {
+ var html = document.querySelector('html');
+ var themeToggleButton = document.getElementById('theme-toggle');
+ var themePopup = document.getElementById('theme-list');
+ var themeColorMetaTag = document.querySelector('meta[name="theme-color"]');
+ var stylesheets = {
+ ayuHighlight: document.querySelector("[href$='ayu-highlight.css']"),
+ tomorrowNight: document.querySelector("[href$='tomorrow-night.css']"),
+ highlight: document.querySelector("[href$='highlight.css']"),
+ };
+
+ function showThemes() {
+ themePopup.style.display = 'block';
+ themeToggleButton.setAttribute('aria-expanded', true);
+ themePopup.querySelector("button#" + get_theme()).focus();
+ }
+
+ function hideThemes() {
+ themePopup.style.display = 'none';
+ themeToggleButton.setAttribute('aria-expanded', false);
+ themeToggleButton.focus();
+ }
+
+ function get_theme() {
+ var theme;
+ try { theme = localStorage.getItem('mdbook-theme'); } catch (e) { }
+ if (theme === null || theme === undefined) {
+ return default_theme;
+ } else {
+ return 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.body).backgroundColor;
+ }, 1);
+
+ if (window.ace && window.editors) {
+ window.editors.forEach(function (editor) {
+ editor.setTheme(ace_theme);
+ });
+ }
+
+ var previousTheme = get_theme();
+
+ if (store) {
+ try { localStorage.setItem('mdbook-theme', theme); } catch (e) { }
+ }
+
+ html.classList.remove(previousTheme);
+ html.classList.add(theme);
+ }
+
+ // Set theme
+ var theme = get_theme();
+
+ set_theme(theme, false);
+
+ themeToggleButton.addEventListener('click', function () {
+ if (themePopup.style.display === 'block') {
+ hideThemes();
+ } else {
+ showThemes();
+ }
+ });
+
+ themePopup.addEventListener('click', function (e) {
+ var theme;
+ if (e.target.className === "theme") {
+ theme = e.target.id;
+ } else if (e.target.parentElement.className === "theme") {
+ theme = e.target.parentElement.id;
+ } else {
+ return;
+ }
+ 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; }
+
+ switch (e.key) {
+ case 'Escape':
+ e.preventDefault();
+ hideThemes();
+ break;
+ case 'ArrowUp':
+ e.preventDefault();
+ var li = document.activeElement.parentElement;
+ if (li && li.previousElementSibling) {
+ li.previousElementSibling.querySelector('button').focus();
+ }
+ break;
+ case 'ArrowDown':
+ e.preventDefault();
+ var 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() {
+ var html = document.querySelector("html");
+ var sidebar = document.getElementById("sidebar");
+ var sidebarLinks = document.querySelectorAll('#sidebar a');
+ var sidebarToggleButton = document.getElementById("sidebar-toggle");
+ var sidebarResizeHandle = document.getElementById("sidebar-resize-handle");
+ var firstContact = null;
+
+ function showSidebar() {
+ html.classList.remove('sidebar-hidden')
+ html.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 (e) { }
+ }
+
+
+ var sidebarAnchorToggles = document.querySelectorAll('#sidebar a.toggle');
+
+ function toggleSection(ev) {
+ ev.currentTarget.parentElement.classList.toggle('expanded');
+ }
+
+ Array.from(sidebarAnchorToggles).forEach(function (el) {
+ el.addEventListener('click', toggleSection);
+ });
+
+ function hideSidebar() {
+ html.classList.remove('sidebar-visible')
+ html.classList.add('sidebar-hidden');
+ 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 (e) { }
+ }
+
+ // Toggle sidebar
+ sidebarToggleButton.addEventListener('click', function sidebarToggle() {
+ if (html.classList.contains("sidebar-hidden")) {
+ var current_width = parseInt(
+ document.documentElement.style.getPropertyValue('--sidebar-width'), 10);
+ if (current_width < 150) {
+ document.documentElement.style.setProperty('--sidebar-width', '150px');
+ }
+ showSidebar();
+ } else if (html.classList.contains("sidebar-visible")) {
+ hideSidebar();
+ } else {
+ if (getComputedStyle(sidebar)['transform'] === 'none') {
+ hideSidebar();
+ } else {
+ showSidebar();
+ }
+ }
+ });
+
+ sidebarResizeHandle.addEventListener('mousedown', initResize, false);
+
+ function initResize(e) {
+ window.addEventListener('mousemove', resize, false);
+ window.addEventListener('mouseup', stopResize, false);
+ html.classList.add('sidebar-resizing');
+ }
+ function resize(e) {
+ var pos = (e.clientX - sidebar.offsetLeft);
+ if (pos < 20) {
+ hideSidebar();
+ } else {
+ if (html.classList.contains("sidebar-hidden")) {
+ showSidebar();
+ }
+ pos = Math.min(pos, window.innerWidth - 100);
+ document.documentElement.style.setProperty('--sidebar-width', pos + 'px');
+ }
+ }
+ //on mouseup remove windows functions mousemove & mouseup
+ function stopResize(e) {
+ html.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;
+
+ var curX = e.touches[0].clientX;
+ var 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 });
+
+ // Scroll sidebar to current active section
+ var activeSection = document.getElementById("sidebar").querySelector(".active");
+ if (activeSection) {
+ // https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
+ activeSection.scrollIntoView({ block: 'center' });
+ }
+})();
+
+(function chapterNavigation() {
+ document.addEventListener('keydown', function (e) {
+ if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) { return; }
+ if (window.search && window.search.hasFocus()) { return; }
+
+ switch (e.key) {
+ case 'ArrowRight':
+ e.preventDefault();
+ var nextButton = document.querySelector('.nav-chapters.next');
+ if (nextButton) {
+ window.location.href = nextButton.href;
+ }
+ break;
+ case 'ArrowLeft':
+ e.preventDefault();
+ var previousButton = document.querySelector('.nav-chapters.previous');
+ if (previousButton) {
+ window.location.href = previousButton.href;
+ }
+ break;
+ }
+ });
+})();
+
+(function clipboard() {
+ var clipButtons = document.querySelectorAll('.clip-button');
+
+ function hideTooltip(elem) {
+ elem.firstChild.innerText = "";
+ elem.className = 'fa fa-copy clip-button';
+ }
+
+ function showTooltip(elem, msg) {
+ elem.firstChild.innerText = msg;
+ elem.className = 'fa fa-copy tooltipped';
+ }
+
+ var clipboardSnippets = new ClipboardJS('.clip-button', {
+ text: function (trigger) {
+ hideTooltip(trigger);
+ let playground = trigger.closest("pre");
+ return playground_text(playground);
+ }
+ });
+
+ 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 () {
+ var menuTitle = document.querySelector('.menu-title');
+
+ menuTitle.addEventListener('click', function () {
+ document.scrollingElement.scrollTo({ top: 0, behavior: 'smooth' });
+ });
+})();
+
+(function controllMenu() {
+ var menu = document.getElementById('menu-bar');
+
+ (function controllPosition() {
+ var scrollTop = document.scrollingElement.scrollTop;
+ var prevScrollTop = scrollTop;
+ var minMenuY = -menu.clientHeight - 50;
+ // When the script loads, the page can be at any scroll (e.g. if you reforesh it).
+ menu.style.top = scrollTop + 'px';
+ // Same as parseInt(menu.style.top.slice(0, -2), but faster
+ var topCache = menu.style.top.slice(0, -2);
+ menu.classList.remove('sticky');
+ var 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
+ var nextSticky = null;
+ var nextTop = null;
+ var scrollDown = scrollTop > prevScrollTop;
+ var 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() {
+ menu.classList.remove('bordered');
+ document.addEventListener('scroll', function () {
+ if (menu.offsetTop === 0) {
+ menu.classList.remove('bordered');
+ } else {
+ menu.classList.add('bordered');
+ }
+ }, { passive: true });
+ })();
+})();
diff --git a/vendor/mdbook/src/theme/css/chrome.css b/vendor/mdbook/src/theme/css/chrome.css
new file mode 100644
index 000000000..10fa4b365
--- /dev/null
+++ b/vendor/mdbook/src/theme/css/chrome.css
@@ -0,0 +1,534 @@
+/* CSS for UI elements (a.k.a. chrome) */
+
+@import 'variables.css';
+
+::-webkit-scrollbar {
+ background: var(--bg);
+}
+::-webkit-scrollbar-thumb {
+ background: var(--scrollbar);
+}
+html {
+ scrollbar-color: var(--scrollbar) var(--bg);
+}
+#searchresults a,
+.content a:link,
+a:visited,
+a > .hljs {
+ color: var(--links);
+}
+
+/* Menu Bar */
+
+#menu-bar,
+#menu-bar-hover-placeholder {
+ z-index: 101;
+ margin: auto calc(0px - var(--page-padding));
+}
+#menu-bar {
+ position: relative;
+ display: flex;
+ flex-wrap: wrap;
+ background-color: var(--bg);
+ border-bottom-color: var(--bg);
+ border-bottom-width: 1px;
+ border-bottom-style: solid;
+}
+#menu-bar.sticky,
+.js #menu-bar-hover-placeholder:hover + #menu-bar,
+.js #menu-bar:hover,
+.js.sidebar-visible #menu-bar {
+ position: -webkit-sticky;
+ position: sticky;
+ top: 0 !important;
+}
+#menu-bar-hover-placeholder {
+ position: sticky;
+ position: -webkit-sticky;
+ top: 0;
+ height: var(--menu-bar-height);
+}
+#menu-bar.bordered {
+ border-bottom-color: var(--table-border-color);
+}
+#menu-bar i, #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) {
+ #menu-bar i, #menu-bar .icon-button {
+ padding: 0 5px;
+ }
+}
+
+.icon-button {
+ border: none;
+ background: none;
+ padding: 0;
+ color: inherit;
+}
+.icon-button i {
+ margin: 0;
+}
+
+.right-buttons {
+ margin: 0 15px;
+}
+.right-buttons a {
+ text-decoration: none;
+}
+
+.left-buttons {
+ display: flex;
+ margin: 0 5px;
+}
+.no-js .left-buttons {
+ 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;
+}
+.js .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 i {
+ color: var(--icons);
+}
+
+.menu-bar i:hover,
+.menu-bar .icon-button:hover,
+.nav-chapters:hover,
+.mobile-nav-chapters i: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-top: 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);
+}
+
+.previous {
+ float: left;
+}
+
+.next {
+ float: right;
+ right: var(--page-padding);
+}
+
+@media only screen and (max-width: 1080px) {
+ .nav-wide-wrapper { display: none; }
+ .nav-wrapper { display: block; }
+}
+
+@media only screen and (max-width: 1380px) {
+ .sidebar-visible .nav-wide-wrapper { display: none; }
+ .sidebar-visible .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 i {
+ margin-left: 8px;
+}
+pre > .buttons button {
+ cursor: inherit;
+ margin: 0px 5px;
+ padding: 3px 5px;
+ font-size: 14px;
+
+ 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);
+}
+@media (pointer: coarse) {
+ pre > .buttons button {
+ /* On mobile, make it easier to tap buttons. */
+ padding: 0.3rem 1rem;
+ }
+}
+pre > code {
+ 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-top: 10px;
+}
+
+/* Search */
+
+#searchresults a {
+ text-decoration: none;
+}
+
+mark {
+ border-radius: 2px;
+ padding: 0 3px 1px 3px;
+ margin: 0 -3px -1px -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-left: auto;
+ margin-right: auto;
+ max-width: var(--content-max-width);
+}
+
+#searchbar {
+ width: 100%;
+ margin: 5px auto 0px 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);
+}
+#searchbar:focus,
+#searchbar.active {
+ box-shadow: 0 0 3px var(--searchbar-shadow-color);
+}
+
+.searchresults-header {
+ font-weight: bold;
+ font-size: 1em;
+ padding: 18px 0 0 5px;
+ color: var(--searchresults-header-fg);
+}
+
+.searchresults-outer {
+ margin-left: auto;
+ margin-right: auto;
+ max-width: var(--content-max-width);
+ border-bottom: 1px dashed var(--searchresults-border-color);
+}
+
+ul#searchresults {
+ list-style: none;
+ padding-left: 20px;
+}
+ul#searchresults li {
+ margin: 10px 0px;
+ padding: 2px;
+ border-radius: 2px;
+}
+ul#searchresults li.focus {
+ background-color: var(--searchresults-li-bg);
+}
+ul#searchresults span.teaser {
+ display: block;
+ clear: both;
+ margin: 5px 0 0 20px;
+ font-size: 0.8em;
+}
+ul#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-resizing {
+ -moz-user-select: none;
+ -webkit-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+.js: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: 0;
+ top: 0;
+ bottom: 0;
+}
+.js .sidebar .sidebar-resize-handle {
+ cursor: col-resize;
+ width: 5px;
+}
+.sidebar-hidden .sidebar {
+ transform: translateX(calc(0px - var(--sidebar-width)));
+}
+.sidebar::-webkit-scrollbar {
+ background: var(--sidebar-bg);
+}
+.sidebar::-webkit-scrollbar-thumb {
+ background: var(--scrollbar);
+}
+
+.sidebar-visible .page-wrapper {
+ transform: translateX(var(--sidebar-width));
+}
+@media only screen and (min-width: 620px) {
+ .sidebar-visible .page-wrapper {
+ transform: none;
+ margin-left: var(--sidebar-width);
+ }
+}
+
+.chapter {
+ list-style: none outside none;
+ padding-left: 0;
+ line-height: 2.2em;
+}
+
+.chapter ol {
+ width: 100%;
+}
+
+.chapter li {
+ display: flex;
+ color: var(--sidebar-non-existant);
+}
+.chapter li a {
+ display: block;
+ padding: 0;
+ text-decoration: none;
+ color: var(--sidebar-fg);
+}
+
+.chapter li a:hover {
+ color: var(--sidebar-active);
+}
+
+.chapter li a.active {
+ color: var(--sidebar-active);
+}
+
+.chapter li > a.toggle {
+ cursor: pointer;
+ display: block;
+ margin-left: auto;
+ padding: 0 10px;
+ user-select: none;
+ opacity: 0.68;
+}
+
+.chapter li > a.toggle div {
+ transition: transform 0.5s;
+}
+
+/* collapse the section */
+.chapter li:not(.expanded) + li > ol {
+ display: none;
+}
+
+.chapter li.chapter-item {
+ line-height: 1.5em;
+ margin-top: 0.6em;
+}
+
+.chapter li.expanded > a.toggle div {
+ transform: rotate(90deg);
+}
+
+.spacer {
+ width: 100%;
+ height: 3px;
+ margin: 5px 0px;
+}
+.chapter .spacer {
+ background-color: var(--sidebar-spacer);
+}
+
+@media (-moz-touch-enabled: 1), (pointer: coarse) {
+ .chapter li a { padding: 5px 0; }
+ .spacer { margin: 10px 0; }
+}
+
+.section {
+ list-style: none outside none;
+ padding-left: 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;
+}
+.theme-popup .default {
+ color: var(--icons);
+}
+.theme-popup .theme {
+ width: 100%;
+ border: 0;
+ margin: 0;
+ padding: 2px 10px;
+ line-height: 25px;
+ white-space: nowrap;
+ text-align: left;
+ cursor: pointer;
+ color: inherit;
+ background: inherit;
+ font-size: inherit;
+}
+.theme-popup .theme:hover {
+ background-color: var(--theme-hover);
+}
+.theme-popup .theme:hover:first-child,
+.theme-popup .theme:hover:last-child {
+ border-top-left-radius: inherit;
+ border-top-right-radius: inherit;
+}
diff --git a/vendor/mdbook/src/theme/css/general.css b/vendor/mdbook/src/theme/css/general.css
new file mode 100644
index 000000000..0e4f07a50
--- /dev/null
+++ b/vendor/mdbook/src/theme/css/general.css
@@ -0,0 +1,191 @@
+/* Base styles and content styles */
+
+@import 'variables.css';
+
+:root {
+ /* Browser default font-size is 16px, this way 1 rem = 10px */
+ font-size: 62.5%;
+}
+
+html {
+ font-family: "Open Sans", 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: "Source Code Pro", Consolas, "Ubuntu Mono", Menlo, "DejaVu Sans Mono", monospace, monospace !important;
+ font-size: 0.875em; /* please adjust the ace font size accordingly in editor.js */
+}
+
+/* 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-top: 2.5em; }
+h4, h5 { margin-top: 2em; }
+
+.header + .header h3,
+.header + .header h4,
+.header + .header h5 {
+ margin-top: 1em;
+}
+
+h1:target::before,
+h2:target::before,
+h3:target::before,
+h4:target::before,
+h5:target::before,
+h6:target::before {
+ display: inline-block;
+ content: "»";
+ margin-left: -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 {
+ scroll-margin-top: calc(var(--menu-bar-height) + 0.5em);
+}
+
+.page {
+ outline: 0;
+ padding: 0 var(--page-padding);
+ margin-top: calc(0px - var(--menu-bar-height)); /* Compensate for the #menu-bar-hover-placeholder */
+}
+.page-wrapper {
+ box-sizing: border-box;
+}
+.js:not(.sidebar-resizing) .page-wrapper {
+ transition: margin-left 0.3s ease, transform 0.3s ease; /* Animation: slide away */
+}
+
+.content {
+ overflow-y: auto;
+ padding: 0 5px 50px 5px;
+}
+.content main {
+ margin-left: auto;
+ margin-right: 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-top: .1em solid var(--quote-border);
+ border-bottom: .1em solid var(--quote-border);
+}
+
+
+:not(.footnote-definition) + .footnote-definition,
+.footnote-definition + :not(.footnote-definition) {
+ margin-top: 2em;
+}
+.footnote-definition {
+ font-size: 0.9em;
+ margin: 0.5em 0;
+}
+.footnote-definition p {
+ display: inline;
+}
+
+.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;
+}
diff --git a/vendor/mdbook/src/theme/css/print.css b/vendor/mdbook/src/theme/css/print.css
new file mode 100644
index 000000000..5e690f755
--- /dev/null
+++ b/vendor/mdbook/src/theme/css/print.css
@@ -0,0 +1,54 @@
+
+#sidebar,
+#menu-bar,
+.nav-chapters,
+.mobile-nav-chapters {
+ display: none;
+}
+
+#page-wrapper.page-wrapper {
+ transform: none;
+ margin-left: 0px;
+ overflow-y: initial;
+}
+
+#content {
+ max-width: none;
+ margin: 0;
+ padding: 0;
+}
+
+.page {
+ overflow-y: initial;
+}
+
+code {
+ background-color: #666666;
+ border-radius: 5px;
+
+ /* Force background to be printed in Chrome */
+ -webkit-print-color-adjust: exact;
+}
+
+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;
+}
diff --git a/vendor/mdbook/src/theme/css/variables.css b/vendor/mdbook/src/theme/css/variables.css
new file mode 100644
index 000000000..56b634bc3
--- /dev/null
+++ b/vendor/mdbook/src/theme/css/variables.css
@@ -0,0 +1,253 @@
+
+/* Globals */
+
+:root {
+ --sidebar-width: 300px;
+ --page-padding: 15px;
+ --content-max-width: 750px;
+ --menu-bar-height: 50px;
+}
+
+/* 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%);
+
+ --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;
+}
+
+.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%);
+
+ --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;
+}
+
+.light {
+ --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%);
+
+ --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;
+}
+
+.navy {
+ --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%);
+
+ --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;
+}
+
+.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%);
+
+ --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;
+}
+
+@media (prefers-color-scheme: dark) {
+ .light.no-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%);
+
+ --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;
+ }
+}
diff --git a/vendor/mdbook/src/theme/favicon.png b/vendor/mdbook/src/theme/favicon.png
new file mode 100644
index 000000000..a5b1aa16c
--- /dev/null
+++ b/vendor/mdbook/src/theme/favicon.png
Binary files differ
diff --git a/vendor/mdbook/src/theme/favicon.svg b/vendor/mdbook/src/theme/favicon.svg
new file mode 100755
index 000000000..90e0ea58b
--- /dev/null
+++ b/vendor/mdbook/src/theme/favicon.svg
@@ -0,0 +1,22 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 199.7 184.2">
+ <style>
+ @media (prefers-color-scheme: dark) {
+ svg { fill: white; }
+ }
+ </style>
+<path d="M189.5,36.8c0.2,2.8,0,5.1-0.6,6.8L153,162c-0.6,2.1-2,3.7-4.2,5c-2.2,1.2-4.4,1.9-6.7,1.9H31.4c-9.6,0-15.3-2.8-17.3-8.4
+ c-0.8-2.2-0.8-3.9,0.1-5.2c0.9-1.2,2.4-1.8,4.6-1.8H123c7.4,0,12.6-1.4,15.4-4.1s5.7-8.9,8.6-18.4l32.9-108.6
+ c1.8-5.9,1-11.1-2.2-15.6S169.9,0,164,0H72.7c-1,0-3.1,0.4-6.1,1.1l0.1-0.4C64.5,0.2,62.6,0,61,0.1s-3,0.5-4.3,1.4
+ c-1.3,0.9-2.4,1.8-3.2,2.8S52,6.5,51.2,8.1c-0.8,1.6-1.4,3-1.9,4.3s-1.1,2.7-1.8,4.2c-0.7,1.5-1.3,2.7-2,3.7c-0.5,0.6-1.2,1.5-2,2.5
+ s-1.6,2-2.2,2.8s-0.9,1.5-1.1,2.2c-0.2,0.7-0.1,1.8,0.2,3.2c0.3,1.4,0.4,2.4,0.4,3.1c-0.3,3-1.4,6.9-3.3,11.6
+ c-1.9,4.7-3.6,8.1-5.1,10.1c-0.3,0.4-1.2,1.3-2.6,2.7c-1.4,1.4-2.3,2.6-2.6,3.7c-0.3,0.4-0.3,1.5-0.1,3.4c0.3,1.8,0.4,3.1,0.3,3.8
+ c-0.3,2.7-1.3,6.3-3,10.8c-1.7,4.5-3.4,8.2-5,11c-0.2,0.5-0.9,1.4-2,2.8c-1.1,1.4-1.8,2.5-2,3.4c-0.2,0.6-0.1,1.8,0.1,3.4
+ c0.2,1.6,0.2,2.8-0.1,3.6c-0.6,3-1.8,6.7-3.6,11c-1.8,4.3-3.6,7.9-5.4,11c-0.5,0.8-1.1,1.7-2,2.8c-0.8,1.1-1.5,2-2,2.8
+ s-0.8,1.6-1,2.5c-0.1,0.5,0,1.3,0.4,2.3c0.3,1.1,0.4,1.9,0.4,2.6c-0.1,1.1-0.2,2.6-0.5,4.4c-0.2,1.8-0.4,2.9-0.4,3.2
+ c-1.8,4.8-1.7,9.9,0.2,15.2c2.2,6.2,6.2,11.5,11.9,15.8c5.7,4.3,11.7,6.4,17.8,6.4h110.7c5.2,0,10.1-1.7,14.7-5.2s7.7-7.8,9.2-12.9
+ l33-108.6c1.8-5.8,1-10.9-2.2-15.5C194.9,39.7,192.6,38,189.5,36.8z M59.6,122.8L73.8,80c0,0,7,0,10.8,0s28.8-1.7,25.4,17.5
+ c-3.4,19.2-18.8,25.2-36.8,25.4S59.6,122.8,59.6,122.8z M78.6,116.8c4.7-0.1,18.9-2.9,22.1-17.1S89.2,86.3,89.2,86.3l-8.9,0
+ l-10.2,30.5C70.2,116.9,74,116.9,78.6,116.8z M75.3,68.7L89,26.2h9.8l0.8,34l23.6-34h9.9l-13.6,42.5h-7.1l12.5-35.4l-24.5,35.4h-6.8
+ l-0.8-35L82,68.7H75.3z"/>
+</svg>
+<!-- Original image Copyright Dave Gandy — CC BY 4.0 License -->
diff --git a/vendor/mdbook/src/theme/head.hbs b/vendor/mdbook/src/theme/head.hbs
new file mode 100644
index 000000000..cb1be1876
--- /dev/null
+++ b/vendor/mdbook/src/theme/head.hbs
@@ -0,0 +1 @@
+{{!-- Put your head HTML text here --}}
diff --git a/vendor/mdbook/src/theme/header.hbs b/vendor/mdbook/src/theme/header.hbs
new file mode 100644
index 000000000..26fa2d2ef
--- /dev/null
+++ b/vendor/mdbook/src/theme/header.hbs
@@ -0,0 +1 @@
+{{!-- Put your header HTML text here --}} \ No newline at end of file
diff --git a/vendor/mdbook/src/theme/index.hbs b/vendor/mdbook/src/theme/index.hbs
new file mode 100644
index 000000000..18d984a2b
--- /dev/null
+++ b/vendor/mdbook/src/theme/index.hbs
@@ -0,0 +1,314 @@
+<!DOCTYPE HTML>
+<html lang="{{ language }}" class="sidebar-visible no-js {{ default_theme }}">
+ <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 content="text/html; charset=utf-8" http-equiv="Content-Type">
+ <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="{{ path_to_root }}favicon.svg">
+ {{/if}}
+ {{#if favicon_png}}
+ <link rel="shortcut icon" href="{{ path_to_root }}favicon.png">
+ {{/if}}
+ <link rel="stylesheet" href="{{ path_to_root }}css/variables.css">
+ <link rel="stylesheet" href="{{ path_to_root }}css/general.css">
+ <link rel="stylesheet" href="{{ path_to_root }}css/chrome.css">
+ {{#if print_enable}}
+ <link rel="stylesheet" href="{{ path_to_root }}css/print.css" media="print">
+ {{/if}}
+
+ <!-- Fonts -->
+ <link rel="stylesheet" href="{{ path_to_root }}FontAwesome/css/font-awesome.css">
+ {{#if copy_fonts}}
+ <link rel="stylesheet" href="{{ path_to_root }}fonts/fonts.css">
+ {{/if}}
+
+ <!-- Highlight.js Stylesheets -->
+ <link rel="stylesheet" href="{{ path_to_root }}highlight.css">
+ <link rel="stylesheet" href="{{ path_to_root }}tomorrow-night.css">
+ <link rel="stylesheet" href="{{ path_to_root }}ayu-highlight.css">
+
+ <!-- Custom theme stylesheets -->
+ {{#each additional_css}}
+ <link rel="stylesheet" href="{{ ../path_to_root }}{{ this }}">
+ {{/each}}
+
+ {{#if mathjax_support}}
+ <!-- MathJax -->
+ <script async type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
+ {{/if}}
+ </head>
+ <body>
+ <!-- Provide site root to javascript -->
+ <script type="text/javascript">
+ var path_to_root = "{{ path_to_root }}";
+ var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "{{ preferred_dark_theme }}" : "{{ default_theme }}";
+ </script>
+
+ <!-- Work around some values being stored in localStorage wrapped in quotes -->
+ <script type="text/javascript">
+ try {
+ var theme = localStorage.getItem('mdbook-theme');
+ var 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 type="text/javascript">
+ var theme;
+ try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
+ if (theme === null || theme === undefined) { theme = default_theme; }
+ var html = document.querySelector('html');
+ html.classList.remove('no-js')
+ html.classList.remove('{{ default_theme }}')
+ html.classList.add(theme);
+ html.classList.add('js');
+ </script>
+
+ <!-- Hide / unhide sidebar before it is displayed -->
+ <script type="text/javascript">
+ var html = document.querySelector('html');
+ var sidebar = 'hidden';
+ if (document.body.clientWidth >= 1080) {
+ try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
+ sidebar = sidebar || 'visible';
+ }
+ html.classList.remove('sidebar-visible');
+ html.classList.add("sidebar-" + sidebar);
+ </script>
+
+ <nav id="sidebar" class="sidebar" aria-label="Table of contents">
+ <div class="sidebar-scrollbox">
+ {{#toc}}{{/toc}}
+ </div>
+ <div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
+ </nav>
+
+ <div id="page-wrapper" class="page-wrapper">
+
+ <div class="page">
+ {{> header}}
+ <div id="menu-bar-hover-placeholder"></div>
+ <div id="menu-bar" class="menu-bar sticky bordered">
+ <div class="left-buttons">
+ <button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
+ <i class="fa fa-bars"></i>
+ </button>
+ <button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
+ <i class="fa fa-paint-brush"></i>
+ </button>
+ <ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
+ <li role="none"><button role="menuitem" class="theme" id="light">{{ theme_option "Light" }}</button></li>
+ <li role="none"><button role="menuitem" class="theme" id="rust">{{ theme_option "Rust" }}</button></li>
+ <li role="none"><button role="menuitem" class="theme" id="coal">{{ theme_option "Coal" }}</button></li>
+ <li role="none"><button role="menuitem" class="theme" id="navy">{{ theme_option "Navy" }}</button></li>
+ <li role="none"><button role="menuitem" class="theme" id="ayu">{{ theme_option "Ayu" }}</button></li>
+ </ul>
+ {{#if search_enabled}}
+ <button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
+ <i class="fa fa-search"></i>
+ </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">
+ <i id="print-button" class="fa fa-print"></i>
+ </a>
+ {{/if}}
+ {{#if git_repository_url}}
+ <a href="{{git_repository_url}}" title="Git repository" aria-label="Git repository">
+ <i id="git-repository-button" class="fa {{git_repository_icon}}"></i>
+ </a>
+ {{/if}}
+ {{#if git_repository_edit_url}}
+ <a href="{{git_repository_edit_url}}" title="Suggest an edit" aria-label="Suggest an edit">
+ <i id="git-edit-button" class="fa fa-edit"></i>
+ </a>
+ {{/if}}
+
+ </div>
+ </div>
+
+ {{#if search_enabled}}
+ <div id="search-wrapper" class="hidden">
+ <form id="searchbar-outer" class="searchbar-outer">
+ <input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
+ </form>
+ <div id="searchresults-outer" class="searchresults-outer hidden">
+ <div id="searchresults-header" class="searchresults-header"></div>
+ <ul id="searchresults">
+ </ul>
+ </div>
+ </div>
+ {{/if}}
+
+ <!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
+ <script type="text/javascript">
+ document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
+ document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
+ Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
+ link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
+ });
+ </script>
+
+ <div id="content" class="content">
+ <main>
+ {{{ content }}}
+ </main>
+
+ <nav class="nav-wrapper" aria-label="Page navigation">
+ <!-- Mobile navigation buttons -->
+ {{#previous}}
+ <a rel="prev" href="{{ path_to_root }}{{link}}" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
+ <i class="fa fa-angle-left"></i>
+ </a>
+ {{/previous}}
+
+ {{#next}}
+ <a rel="next" href="{{ path_to_root }}{{link}}" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
+ <i class="fa fa-angle-right"></i>
+ </a>
+ {{/next}}
+
+ <div style="clear: both"></div>
+ </nav>
+ </div>
+ </div>
+
+ <nav class="nav-wide-wrapper" aria-label="Page navigation">
+ {{#previous}}
+ <a rel="prev" href="{{ path_to_root }}{{link}}" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
+ <i class="fa fa-angle-left"></i>
+ </a>
+ {{/previous}}
+
+ {{#next}}
+ <a rel="next" href="{{ path_to_root }}{{link}}" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
+ <i class="fa fa-angle-right"></i>
+ </a>
+ {{/next}}
+ </nav>
+
+ </div>
+
+ {{#if live_reload_endpoint}}
+ <!-- Livereload script (if served using the cli tool) -->
+ <script type="text/javascript">
+ 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 google_analytics}}
+ <!-- Google Analytics Tag -->
+ <script type="text/javascript">
+ var localAddrs = ["localhost", "127.0.0.1", ""];
+
+ // make sure we don't activate google analytics if the developer is
+ // inspecting the book locally...
+ if (localAddrs.indexOf(document.location.hostname) === -1) {
+ (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
+ m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+ })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
+
+ ga('create', '{{google_analytics}}', 'auto');
+ ga('send', 'pageview');
+ }
+ </script>
+ {{/if}}
+
+ {{#if playground_line_numbers}}
+ <script type="text/javascript">
+ window.playground_line_numbers = true;
+ </script>
+ {{/if}}
+
+ {{#if playground_copyable}}
+ <script type="text/javascript">
+ window.playground_copyable = true;
+ </script>
+ {{/if}}
+
+ {{#if playground_js}}
+ <script src="{{ path_to_root }}ace.js" type="text/javascript" charset="utf-8"></script>
+ <script src="{{ path_to_root }}editor.js" type="text/javascript" charset="utf-8"></script>
+ <script src="{{ path_to_root }}mode-rust.js" type="text/javascript" charset="utf-8"></script>
+ <script src="{{ path_to_root }}theme-dawn.js" type="text/javascript" charset="utf-8"></script>
+ <script src="{{ path_to_root }}theme-tomorrow_night.js" type="text/javascript" charset="utf-8"></script>
+ {{/if}}
+
+ {{#if search_js}}
+ <script src="{{ path_to_root }}elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
+ <script src="{{ path_to_root }}mark.min.js" type="text/javascript" charset="utf-8"></script>
+ <script src="{{ path_to_root }}searcher.js" type="text/javascript" charset="utf-8"></script>
+ {{/if}}
+
+ <script src="{{ path_to_root }}clipboard.min.js" type="text/javascript" charset="utf-8"></script>
+ <script src="{{ path_to_root }}highlight.js" type="text/javascript" charset="utf-8"></script>
+ <script src="{{ path_to_root }}book.js" type="text/javascript" charset="utf-8"></script>
+
+ <!-- Custom JS scripts -->
+ {{#each additional_js}}
+ <script type="text/javascript" src="{{ ../path_to_root }}{{this}}"></script>
+ {{/each}}
+
+ {{#if is_print}}
+ {{#if mathjax_support}}
+ <script type="text/javascript">
+ window.addEventListener('load', function() {
+ MathJax.Hub.Register.StartupHook('End', function() {
+ window.setTimeout(window.print, 100);
+ });
+ });
+ </script>
+ {{else}}
+ <script type="text/javascript">
+ window.addEventListener('load', function() {
+ window.setTimeout(window.print, 100);
+ });
+ </script>
+ {{/if}}
+ {{/if}}
+
+ </body>
+</html>
diff --git a/vendor/mdbook/src/theme/mod.rs b/vendor/mdbook/src/theme/mod.rs
new file mode 100644
index 000000000..a1ee18aff
--- /dev/null
+++ b/vendor/mdbook/src/theme/mod.rs
@@ -0,0 +1,270 @@
+#![allow(missing_docs)]
+
+pub mod playground_editor;
+
+pub mod fonts;
+
+#[cfg(feature = "search")]
+pub mod searcher;
+
+use std::fs::File;
+use std::io::Read;
+use std::path::Path;
+
+use crate::errors::*;
+
+pub static INDEX: &[u8] = include_bytes!("index.hbs");
+pub static HEAD: &[u8] = include_bytes!("head.hbs");
+pub static REDIRECT: &[u8] = include_bytes!("redirect.hbs");
+pub static HEADER: &[u8] = include_bytes!("header.hbs");
+pub static CHROME_CSS: &[u8] = include_bytes!("css/chrome.css");
+pub static GENERAL_CSS: &[u8] = include_bytes!("css/general.css");
+pub static PRINT_CSS: &[u8] = include_bytes!("css/print.css");
+pub static VARIABLES_CSS: &[u8] = include_bytes!("css/variables.css");
+pub static FAVICON_PNG: &[u8] = include_bytes!("favicon.png");
+pub static FAVICON_SVG: &[u8] = include_bytes!("favicon.svg");
+pub static JS: &[u8] = include_bytes!("book.js");
+pub static HIGHLIGHT_JS: &[u8] = include_bytes!("highlight.js");
+pub static TOMORROW_NIGHT_CSS: &[u8] = include_bytes!("tomorrow-night.css");
+pub static HIGHLIGHT_CSS: &[u8] = include_bytes!("highlight.css");
+pub static AYU_HIGHLIGHT_CSS: &[u8] = include_bytes!("ayu-highlight.css");
+pub static CLIPBOARD_JS: &[u8] = include_bytes!("clipboard.min.js");
+pub static FONT_AWESOME: &[u8] = include_bytes!("FontAwesome/css/font-awesome.min.css");
+pub static FONT_AWESOME_EOT: &[u8] = include_bytes!("FontAwesome/fonts/fontawesome-webfont.eot");
+pub static FONT_AWESOME_SVG: &[u8] = include_bytes!("FontAwesome/fonts/fontawesome-webfont.svg");
+pub static FONT_AWESOME_TTF: &[u8] = include_bytes!("FontAwesome/fonts/fontawesome-webfont.ttf");
+pub static FONT_AWESOME_WOFF: &[u8] = include_bytes!("FontAwesome/fonts/fontawesome-webfont.woff");
+pub static FONT_AWESOME_WOFF2: &[u8] =
+ include_bytes!("FontAwesome/fonts/fontawesome-webfont.woff2");
+pub static FONT_AWESOME_OTF: &[u8] = include_bytes!("FontAwesome/fonts/FontAwesome.otf");
+
+/// The `Theme` struct should be used instead of the static variables because
+/// the `new()` method will look if the user has a theme directory in their
+/// source folder and use the users theme instead of the default.
+///
+/// You should only ever use the static variables directly if you want to
+/// override the user's theme with the defaults.
+#[derive(Debug, PartialEq)]
+pub struct Theme {
+ pub index: Vec<u8>,
+ pub head: Vec<u8>,
+ pub redirect: Vec<u8>,
+ pub header: Vec<u8>,
+ pub chrome_css: Vec<u8>,
+ pub general_css: Vec<u8>,
+ pub print_css: Vec<u8>,
+ pub variables_css: Vec<u8>,
+ pub favicon_png: Option<Vec<u8>>,
+ pub favicon_svg: Option<Vec<u8>>,
+ pub js: Vec<u8>,
+ pub highlight_css: Vec<u8>,
+ pub tomorrow_night_css: Vec<u8>,
+ pub ayu_highlight_css: Vec<u8>,
+ pub highlight_js: Vec<u8>,
+ pub clipboard_js: Vec<u8>,
+}
+
+impl Theme {
+ /// Creates a `Theme` from the given `theme_dir`.
+ /// If a file is found in the theme dir, it will override the default version.
+ pub fn new<P: AsRef<Path>>(theme_dir: P) -> Self {
+ let theme_dir = theme_dir.as_ref();
+ let mut theme = Theme::default();
+
+ // If the theme directory doesn't exist there's no point continuing...
+ if !theme_dir.exists() || !theme_dir.is_dir() {
+ return theme;
+ }
+
+ // Check for individual files, if they exist copy them across
+ {
+ let files = vec![
+ (theme_dir.join("index.hbs"), &mut theme.index),
+ (theme_dir.join("head.hbs"), &mut theme.head),
+ (theme_dir.join("redirect.hbs"), &mut theme.redirect),
+ (theme_dir.join("header.hbs"), &mut theme.header),
+ (theme_dir.join("book.js"), &mut theme.js),
+ (theme_dir.join("css/chrome.css"), &mut theme.chrome_css),
+ (theme_dir.join("css/general.css"), &mut theme.general_css),
+ (theme_dir.join("css/print.css"), &mut theme.print_css),
+ (
+ theme_dir.join("css/variables.css"),
+ &mut theme.variables_css,
+ ),
+ (theme_dir.join("highlight.js"), &mut theme.highlight_js),
+ (theme_dir.join("clipboard.min.js"), &mut theme.clipboard_js),
+ (theme_dir.join("highlight.css"), &mut theme.highlight_css),
+ (
+ theme_dir.join("tomorrow-night.css"),
+ &mut theme.tomorrow_night_css,
+ ),
+ (
+ theme_dir.join("ayu-highlight.css"),
+ &mut theme.ayu_highlight_css,
+ ),
+ ];
+
+ let load_with_warn = |filename: &Path, dest| {
+ if !filename.exists() {
+ // Don't warn if the file doesn't exist.
+ return false;
+ }
+ if let Err(e) = load_file_contents(filename, dest) {
+ warn!("Couldn't load custom file, {}: {}", filename.display(), e);
+ false
+ } else {
+ true
+ }
+ };
+
+ for (filename, dest) in files {
+ load_with_warn(&filename, dest);
+ }
+
+ // If the user overrides one favicon, but not the other, do not
+ // copy the default for the other.
+ let favicon_png = &mut theme.favicon_png.as_mut().unwrap();
+ let png = load_with_warn(&theme_dir.join("favicon.png"), favicon_png);
+ let favicon_svg = &mut theme.favicon_svg.as_mut().unwrap();
+ let svg = load_with_warn(&theme_dir.join("favicon.svg"), favicon_svg);
+ match (png, svg) {
+ (true, true) | (false, false) => {}
+ (true, false) => {
+ theme.favicon_svg = None;
+ }
+ (false, true) => {
+ theme.favicon_png = None;
+ }
+ }
+ }
+
+ theme
+ }
+}
+
+impl Default for Theme {
+ fn default() -> Theme {
+ Theme {
+ index: INDEX.to_owned(),
+ head: HEAD.to_owned(),
+ redirect: REDIRECT.to_owned(),
+ header: HEADER.to_owned(),
+ chrome_css: CHROME_CSS.to_owned(),
+ general_css: GENERAL_CSS.to_owned(),
+ print_css: PRINT_CSS.to_owned(),
+ variables_css: VARIABLES_CSS.to_owned(),
+ favicon_png: Some(FAVICON_PNG.to_owned()),
+ favicon_svg: Some(FAVICON_SVG.to_owned()),
+ js: JS.to_owned(),
+ highlight_css: HIGHLIGHT_CSS.to_owned(),
+ tomorrow_night_css: TOMORROW_NIGHT_CSS.to_owned(),
+ ayu_highlight_css: AYU_HIGHLIGHT_CSS.to_owned(),
+ highlight_js: HIGHLIGHT_JS.to_owned(),
+ clipboard_js: CLIPBOARD_JS.to_owned(),
+ }
+ }
+}
+
+/// Checks if a file exists, if so, the destination buffer will be filled with
+/// its contents.
+fn load_file_contents<P: AsRef<Path>>(filename: P, dest: &mut Vec<u8>) -> Result<()> {
+ let filename = filename.as_ref();
+
+ let mut buffer = Vec::new();
+ File::open(filename)?.read_to_end(&mut buffer)?;
+
+ // We needed the buffer so we'd only overwrite the existing content if we
+ // could successfully load the file into memory.
+ dest.clear();
+ dest.append(&mut buffer);
+
+ Ok(())
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use std::fs;
+ use std::path::PathBuf;
+ use tempfile::Builder as TempFileBuilder;
+
+ #[test]
+ fn theme_uses_defaults_with_nonexistent_src_dir() {
+ let non_existent = PathBuf::from("/non/existent/directory/");
+ assert!(!non_existent.exists());
+
+ let should_be = Theme::default();
+ let got = Theme::new(&non_existent);
+
+ assert_eq!(got, should_be);
+ }
+
+ #[test]
+ fn theme_dir_overrides_defaults() {
+ let files = [
+ "index.hbs",
+ "head.hbs",
+ "redirect.hbs",
+ "header.hbs",
+ "favicon.png",
+ "favicon.svg",
+ "css/chrome.css",
+ "css/fonts.css",
+ "css/general.css",
+ "css/print.css",
+ "css/variables.css",
+ "book.js",
+ "highlight.js",
+ "tomorrow-night.css",
+ "highlight.css",
+ "ayu-highlight.css",
+ "clipboard.min.js",
+ ];
+
+ let temp = TempFileBuilder::new().prefix("mdbook-").tempdir().unwrap();
+ fs::create_dir(temp.path().join("css")).unwrap();
+
+ // "touch" all of the special files so we have empty copies
+ for file in &files {
+ File::create(&temp.path().join(file)).unwrap();
+ }
+
+ let got = Theme::new(temp.path());
+
+ let empty = Theme {
+ index: Vec::new(),
+ head: Vec::new(),
+ redirect: Vec::new(),
+ header: Vec::new(),
+ chrome_css: Vec::new(),
+ general_css: Vec::new(),
+ print_css: Vec::new(),
+ variables_css: Vec::new(),
+ favicon_png: Some(Vec::new()),
+ favicon_svg: Some(Vec::new()),
+ js: Vec::new(),
+ highlight_css: Vec::new(),
+ tomorrow_night_css: Vec::new(),
+ ayu_highlight_css: Vec::new(),
+ highlight_js: Vec::new(),
+ clipboard_js: Vec::new(),
+ };
+
+ assert_eq!(got, empty);
+ }
+
+ #[test]
+ fn favicon_override() {
+ let temp = TempFileBuilder::new().prefix("mdbook-").tempdir().unwrap();
+ fs::write(temp.path().join("favicon.png"), "1234").unwrap();
+ let got = Theme::new(temp.path());
+ assert_eq!(got.favicon_png.as_ref().unwrap(), b"1234");
+ assert_eq!(got.favicon_svg, None);
+
+ let temp = TempFileBuilder::new().prefix("mdbook-").tempdir().unwrap();
+ fs::write(temp.path().join("favicon.svg"), "4567").unwrap();
+ let got = Theme::new(temp.path());
+ assert_eq!(got.favicon_png, None);
+ assert_eq!(got.favicon_svg.as_ref().unwrap(), b"4567");
+ }
+}
diff --git a/vendor/mdbook/src/theme/redirect.hbs b/vendor/mdbook/src/theme/redirect.hbs
new file mode 100644
index 000000000..9f49e6d09
--- /dev/null
+++ b/vendor/mdbook/src/theme/redirect.hbs
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <title>Redirecting...</title>
+ <meta http-equiv="refresh" content="0;URL='{{url}}'">
+ <meta rel="canonical" href="{{url}}">
+ </head>
+ <body>
+ <p>Redirecting to... <a href="{{url}}">{{url}}</a>.</p>
+ </body>
+</html>
diff --git a/vendor/mdbook/src/theme/searcher/mod.rs b/vendor/mdbook/src/theme/searcher/mod.rs
new file mode 100644
index 000000000..d5029db16
--- /dev/null
+++ b/vendor/mdbook/src/theme/searcher/mod.rs
@@ -0,0 +1,6 @@
+//! Theme dependencies for in-browser search. Not included in mdbook when
+//! the "search" cargo feature is disabled.
+
+pub static JS: &[u8] = include_bytes!("searcher.js");
+pub static MARK_JS: &[u8] = include_bytes!("mark.min.js");
+pub static ELASTICLUNR_JS: &[u8] = include_bytes!("elasticlunr.min.js");
diff --git a/vendor/mdbook/src/theme/searcher/searcher.js b/vendor/mdbook/src/theme/searcher/searcher.js
new file mode 100644
index 000000000..d2b0aeed3
--- /dev/null
+++ b/vendor/mdbook/src/theme/searcher/searcher.js
@@ -0,0 +1,483 @@
+"use strict";
+window.search = window.search || {};
+(function search(search) {
+ // Search functionality
+ //
+ // You can use !hasFocus() to prevent keyhandling in your key
+ // event handlers while the user is typing their search.
+
+ if (!Mark || !elasticlunr) {
+ return;
+ }
+
+ //IE 11 Compatibility from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith
+ if (!String.prototype.startsWith) {
+ String.prototype.startsWith = function(search, pos) {
+ return this.substr(!pos || pos < 0 ? 0 : +pos, search.length) === search;
+ };
+ }
+
+ var search_wrap = document.getElementById('search-wrapper'),
+ searchbar = document.getElementById('searchbar'),
+ searchbar_outer = document.getElementById('searchbar-outer'),
+ searchresults = document.getElementById('searchresults'),
+ searchresults_outer = document.getElementById('searchresults-outer'),
+ searchresults_header = document.getElementById('searchresults-header'),
+ searchicon = document.getElementById('search-toggle'),
+ content = document.getElementById('content'),
+
+ searchindex = null,
+ doc_urls = [],
+ results_options = {
+ teaser_word_count: 30,
+ limit_results: 30,
+ },
+ search_options = {
+ bool: "AND",
+ expand: true,
+ fields: {
+ title: {boost: 1},
+ body: {boost: 1},
+ breadcrumbs: {boost: 0}
+ }
+ },
+ mark_exclude = [],
+ marker = new Mark(content),
+ current_searchterm = "",
+ URL_SEARCH_PARAM = 'search',
+ URL_MARK_PARAM = 'highlight',
+ teaser_count = 0,
+
+ SEARCH_HOTKEY_KEYCODE = 83,
+ ESCAPE_KEYCODE = 27,
+ DOWN_KEYCODE = 40,
+ UP_KEYCODE = 38,
+ SELECT_KEYCODE = 13;
+
+ function hasFocus() {
+ return searchbar === document.activeElement;
+ }
+
+ function removeChildren(elem) {
+ while (elem.firstChild) {
+ elem.removeChild(elem.firstChild);
+ }
+ }
+
+ // Helper to parse a url into its building blocks.
+ function parseURL(url) {
+ var a = document.createElement('a');
+ a.href = url;
+ return {
+ source: url,
+ protocol: a.protocol.replace(':',''),
+ host: a.hostname,
+ port: a.port,
+ params: (function(){
+ var ret = {};
+ var seg = a.search.replace(/^\?/,'').split('&');
+ var len = seg.length, i = 0, s;
+ for (;i<len;i++) {
+ if (!seg[i]) { continue; }
+ s = seg[i].split('=');
+ ret[s[0]] = s[1];
+ }
+ return ret;
+ })(),
+ file: (a.pathname.match(/\/([^/?#]+)$/i) || [,''])[1],
+ hash: a.hash.replace('#',''),
+ path: a.pathname.replace(/^([^/])/,'/$1')
+ };
+ }
+
+ // Helper to recreate a url string from its building blocks.
+ function renderURL(urlobject) {
+ var url = urlobject.protocol + "://" + urlobject.host;
+ if (urlobject.port != "") {
+ url += ":" + urlobject.port;
+ }
+ url += urlobject.path;
+ var joiner = "?";
+ for(var prop in urlobject.params) {
+ if(urlobject.params.hasOwnProperty(prop)) {
+ url += joiner + prop + "=" + urlobject.params[prop];
+ joiner = "&";
+ }
+ }
+ if (urlobject.hash != "") {
+ url += "#" + urlobject.hash;
+ }
+ return url;
+ }
+
+ // Helper to escape html special chars for displaying the teasers
+ var escapeHTML = (function() {
+ var MAP = {
+ '&': '&amp;',
+ '<': '&lt;',
+ '>': '&gt;',
+ '"': '&#34;',
+ "'": '&#39;'
+ };
+ var repl = function(c) { return MAP[c]; };
+ return function(s) {
+ return s.replace(/[&<>'"]/g, repl);
+ };
+ })();
+
+ function formatSearchMetric(count, searchterm) {
+ if (count == 1) {
+ return count + " search result for '" + searchterm + "':";
+ } else if (count == 0) {
+ return "No search results for '" + searchterm + "'.";
+ } else {
+ return count + " search results for '" + searchterm + "':";
+ }
+ }
+
+ function formatSearchResult(result, searchterms) {
+ var teaser = makeTeaser(escapeHTML(result.doc.body), searchterms);
+ teaser_count++;
+
+ // The ?URL_MARK_PARAM= parameter belongs inbetween the page and the #heading-anchor
+ var url = doc_urls[result.ref].split("#");
+ if (url.length == 1) { // no anchor found
+ url.push("");
+ }
+
+ // encodeURIComponent escapes all chars that could allow an XSS except
+ // for '. Due to that we also manually replace ' with its url-encoded
+ // representation (%27).
+ var searchterms = encodeURIComponent(searchterms.join(" ")).replace(/\'/g, "%27");
+
+ return '<a href="' + path_to_root + url[0] + '?' + URL_MARK_PARAM + '=' + searchterms + '#' + url[1]
+ + '" aria-details="teaser_' + teaser_count + '">' + result.doc.breadcrumbs + '</a>'
+ + '<span class="teaser" id="teaser_' + teaser_count + '" aria-label="Search Result Teaser">'
+ + teaser + '</span>';
+ }
+
+ function makeTeaser(body, searchterms) {
+ // The strategy is as follows:
+ // First, assign a value to each word in the document:
+ // Words that correspond to search terms (stemmer aware): 40
+ // Normal words: 2
+ // First word in a sentence: 8
+ // Then use a sliding window with a constant number of words and count the
+ // sum of the values of the words within the window. Then use the window that got the
+ // maximum sum. If there are multiple maximas, then get the last one.
+ // Enclose the terms in <em>.
+ var stemmed_searchterms = searchterms.map(function(w) {
+ return elasticlunr.stemmer(w.toLowerCase());
+ });
+ var searchterm_weight = 40;
+ var weighted = []; // contains elements of ["word", weight, index_in_document]
+ // split in sentences, then words
+ var sentences = body.toLowerCase().split('. ');
+ var index = 0;
+ var value = 0;
+ var searchterm_found = false;
+ for (var sentenceindex in sentences) {
+ var words = sentences[sentenceindex].split(' ');
+ value = 8;
+ for (var wordindex in words) {
+ var word = words[wordindex];
+ if (word.length > 0) {
+ for (var searchtermindex in stemmed_searchterms) {
+ if (elasticlunr.stemmer(word).startsWith(stemmed_searchterms[searchtermindex])) {
+ value = searchterm_weight;
+ searchterm_found = true;
+ }
+ };
+ weighted.push([word, value, index]);
+ value = 2;
+ }
+ index += word.length;
+ index += 1; // ' ' or '.' if last word in sentence
+ };
+ index += 1; // because we split at a two-char boundary '. '
+ };
+
+ if (weighted.length == 0) {
+ return body;
+ }
+
+ var window_weight = [];
+ var window_size = Math.min(weighted.length, results_options.teaser_word_count);
+
+ var cur_sum = 0;
+ for (var wordindex = 0; wordindex < window_size; wordindex++) {
+ cur_sum += weighted[wordindex][1];
+ };
+ window_weight.push(cur_sum);
+ for (var wordindex = 0; wordindex < weighted.length - window_size; wordindex++) {
+ cur_sum -= weighted[wordindex][1];
+ cur_sum += weighted[wordindex + window_size][1];
+ window_weight.push(cur_sum);
+ };
+
+ if (searchterm_found) {
+ var max_sum = 0;
+ var max_sum_window_index = 0;
+ // backwards
+ for (var i = window_weight.length - 1; i >= 0; i--) {
+ if (window_weight[i] > max_sum) {
+ max_sum = window_weight[i];
+ max_sum_window_index = i;
+ }
+ };
+ } else {
+ max_sum_window_index = 0;
+ }
+
+ // add <em/> around searchterms
+ var teaser_split = [];
+ var index = weighted[max_sum_window_index][2];
+ for (var i = max_sum_window_index; i < max_sum_window_index+window_size; i++) {
+ var word = weighted[i];
+ if (index < word[2]) {
+ // missing text from index to start of `word`
+ teaser_split.push(body.substring(index, word[2]));
+ index = word[2];
+ }
+ if (word[1] == searchterm_weight) {
+ teaser_split.push("<em>")
+ }
+ index = word[2] + word[0].length;
+ teaser_split.push(body.substring(word[2], index));
+ if (word[1] == searchterm_weight) {
+ teaser_split.push("</em>")
+ }
+ };
+
+ return teaser_split.join('');
+ }
+
+ function init(config) {
+ results_options = config.results_options;
+ search_options = config.search_options;
+ searchbar_outer = config.searchbar_outer;
+ doc_urls = config.doc_urls;
+ searchindex = elasticlunr.Index.load(config.index);
+
+ // Set up events
+ searchicon.addEventListener('click', function(e) { searchIconClickHandler(); }, false);
+ searchbar.addEventListener('keyup', function(e) { searchbarKeyUpHandler(); }, false);
+ document.addEventListener('keydown', function(e) { globalKeyHandler(e); }, false);
+ // If the user uses the browser buttons, do the same as if a reload happened
+ window.onpopstate = function(e) { doSearchOrMarkFromUrl(); };
+ // Suppress "submit" events so the page doesn't reload when the user presses Enter
+ document.addEventListener('submit', function(e) { e.preventDefault(); }, false);
+
+ // If reloaded, do the search or mark again, depending on the current url parameters
+ doSearchOrMarkFromUrl();
+ }
+
+ function unfocusSearchbar() {
+ // hacky, but just focusing a div only works once
+ var tmp = document.createElement('input');
+ tmp.setAttribute('style', 'position: absolute; opacity: 0;');
+ searchicon.appendChild(tmp);
+ tmp.focus();
+ tmp.remove();
+ }
+
+ // On reload or browser history backwards/forwards events, parse the url and do search or mark
+ function doSearchOrMarkFromUrl() {
+ // Check current URL for search request
+ var url = parseURL(window.location.href);
+ if (url.params.hasOwnProperty(URL_SEARCH_PARAM)
+ && url.params[URL_SEARCH_PARAM] != "") {
+ showSearch(true);
+ searchbar.value = decodeURIComponent(
+ (url.params[URL_SEARCH_PARAM]+'').replace(/\+/g, '%20'));
+ searchbarKeyUpHandler(); // -> doSearch()
+ } else {
+ showSearch(false);
+ }
+
+ if (url.params.hasOwnProperty(URL_MARK_PARAM)) {
+ var words = decodeURIComponent(url.params[URL_MARK_PARAM]).split(' ');
+ marker.mark(words, {
+ exclude: mark_exclude
+ });
+
+ var markers = document.querySelectorAll("mark");
+ function hide() {
+ for (var i = 0; i < markers.length; i++) {
+ markers[i].classList.add("fade-out");
+ window.setTimeout(function(e) { marker.unmark(); }, 300);
+ }
+ }
+ for (var i = 0; i < markers.length; i++) {
+ markers[i].addEventListener('click', hide);
+ }
+ }
+ }
+
+ // Eventhandler for keyevents on `document`
+ function globalKeyHandler(e) {
+ if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey || e.target.type === 'textarea' || e.target.type === 'text') { return; }
+
+ if (e.keyCode === ESCAPE_KEYCODE) {
+ e.preventDefault();
+ searchbar.classList.remove("active");
+ setSearchUrlParameters("",
+ (searchbar.value.trim() !== "") ? "push" : "replace");
+ if (hasFocus()) {
+ unfocusSearchbar();
+ }
+ showSearch(false);
+ marker.unmark();
+ } else if (!hasFocus() && e.keyCode === SEARCH_HOTKEY_KEYCODE) {
+ e.preventDefault();
+ showSearch(true);
+ window.scrollTo(0, 0);
+ searchbar.select();
+ } else if (hasFocus() && e.keyCode === DOWN_KEYCODE) {
+ e.preventDefault();
+ unfocusSearchbar();
+ searchresults.firstElementChild.classList.add("focus");
+ } else if (!hasFocus() && (e.keyCode === DOWN_KEYCODE
+ || e.keyCode === UP_KEYCODE
+ || e.keyCode === SELECT_KEYCODE)) {
+ // not `:focus` because browser does annoying scrolling
+ var focused = searchresults.querySelector("li.focus");
+ if (!focused) return;
+ e.preventDefault();
+ if (e.keyCode === DOWN_KEYCODE) {
+ var next = focused.nextElementSibling;
+ if (next) {
+ focused.classList.remove("focus");
+ next.classList.add("focus");
+ }
+ } else if (e.keyCode === UP_KEYCODE) {
+ focused.classList.remove("focus");
+ var prev = focused.previousElementSibling;
+ if (prev) {
+ prev.classList.add("focus");
+ } else {
+ searchbar.select();
+ }
+ } else { // SELECT_KEYCODE
+ window.location.assign(focused.querySelector('a'));
+ }
+ }
+ }
+
+ function showSearch(yes) {
+ if (yes) {
+ search_wrap.classList.remove('hidden');
+ searchicon.setAttribute('aria-expanded', 'true');
+ } else {
+ search_wrap.classList.add('hidden');
+ searchicon.setAttribute('aria-expanded', 'false');
+ var results = searchresults.children;
+ for (var i = 0; i < results.length; i++) {
+ results[i].classList.remove("focus");
+ }
+ }
+ }
+
+ function showResults(yes) {
+ if (yes) {
+ searchresults_outer.classList.remove('hidden');
+ } else {
+ searchresults_outer.classList.add('hidden');
+ }
+ }
+
+ // Eventhandler for search icon
+ function searchIconClickHandler() {
+ if (search_wrap.classList.contains('hidden')) {
+ showSearch(true);
+ window.scrollTo(0, 0);
+ searchbar.select();
+ } else {
+ showSearch(false);
+ }
+ }
+
+ // Eventhandler for keyevents while the searchbar is focused
+ function searchbarKeyUpHandler() {
+ var searchterm = searchbar.value.trim();
+ if (searchterm != "") {
+ searchbar.classList.add("active");
+ doSearch(searchterm);
+ } else {
+ searchbar.classList.remove("active");
+ showResults(false);
+ removeChildren(searchresults);
+ }
+
+ setSearchUrlParameters(searchterm, "push_if_new_search_else_replace");
+
+ // Remove marks
+ marker.unmark();
+ }
+
+ // Update current url with ?URL_SEARCH_PARAM= parameter, remove ?URL_MARK_PARAM and #heading-anchor .
+ // `action` can be one of "push", "replace", "push_if_new_search_else_replace"
+ // and replaces or pushes a new browser history item.
+ // "push_if_new_search_else_replace" pushes if there is no `?URL_SEARCH_PARAM=abc` yet.
+ function setSearchUrlParameters(searchterm, action) {
+ var url = parseURL(window.location.href);
+ var first_search = ! url.params.hasOwnProperty(URL_SEARCH_PARAM);
+ if (searchterm != "" || action == "push_if_new_search_else_replace") {
+ url.params[URL_SEARCH_PARAM] = searchterm;
+ delete url.params[URL_MARK_PARAM];
+ url.hash = "";
+ } else {
+ delete url.params[URL_MARK_PARAM];
+ delete url.params[URL_SEARCH_PARAM];
+ }
+ // A new search will also add a new history item, so the user can go back
+ // to the page prior to searching. A updated search term will only replace
+ // the url.
+ if (action == "push" || (action == "push_if_new_search_else_replace" && first_search) ) {
+ history.pushState({}, document.title, renderURL(url));
+ } else if (action == "replace" || (action == "push_if_new_search_else_replace" && !first_search) ) {
+ history.replaceState({}, document.title, renderURL(url));
+ }
+ }
+
+ function doSearch(searchterm) {
+
+ // Don't search the same twice
+ if (current_searchterm == searchterm) { return; }
+ else { current_searchterm = searchterm; }
+
+ if (searchindex == null) { return; }
+
+ // Do the actual search
+ var results = searchindex.search(searchterm, search_options);
+ var resultcount = Math.min(results.length, results_options.limit_results);
+
+ // Display search metrics
+ searchresults_header.innerText = formatSearchMetric(resultcount, searchterm);
+
+ // Clear and insert results
+ var searchterms = searchterm.split(' ');
+ removeChildren(searchresults);
+ for(var i = 0; i < resultcount ; i++){
+ var resultElem = document.createElement('li');
+ resultElem.innerHTML = formatSearchResult(results[i], searchterms);
+ searchresults.appendChild(resultElem);
+ }
+
+ // Display results
+ showResults(true);
+ }
+
+ fetch(path_to_root + 'searchindex.json')
+ .then(response => response.json())
+ .then(json => init(json))
+ .catch(error => { // Try to load searchindex.js if fetch failed
+ var script = document.createElement('script');
+ script.src = path_to_root + 'searchindex.js';
+ script.onload = () => init(window.search);
+ document.head.appendChild(script);
+ });
+
+ // Exported functions
+ search.hasFocus = hasFocus;
+})(window.search);
diff --git a/vendor/mdbook/src/theme/tomorrow-night.css b/vendor/mdbook/src/theme/tomorrow-night.css
new file mode 100644
index 000000000..5b4aca77c
--- /dev/null
+++ b/vendor/mdbook/src/theme/tomorrow-night.css
@@ -0,0 +1,102 @@
+/* Tomorrow Night Theme */
+/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */
+/* Original theme - https://github.com/chriskempson/tomorrow-theme */
+/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */
+
+/* Tomorrow Comment */
+.hljs-comment {
+ color: #969896;
+}
+
+/* Tomorrow Red */
+.hljs-variable,
+.hljs-attribute,
+.hljs-tag,
+.hljs-regexp,
+.ruby .hljs-constant,
+.xml .hljs-tag .hljs-title,
+.xml .hljs-pi,
+.xml .hljs-doctype,
+.html .hljs-doctype,
+.css .hljs-id,
+.css .hljs-class,
+.css .hljs-pseudo {
+ color: #cc6666;
+}
+
+/* Tomorrow Orange */
+.hljs-number,
+.hljs-preprocessor,
+.hljs-pragma,
+.hljs-built_in,
+.hljs-literal,
+.hljs-params,
+.hljs-constant {
+ color: #de935f;
+}
+
+/* Tomorrow Yellow */
+.ruby .hljs-class .hljs-title,
+.css .hljs-rule .hljs-attribute {
+ color: #f0c674;
+}
+
+/* Tomorrow Green */
+.hljs-string,
+.hljs-value,
+.hljs-inheritance,
+.hljs-header,
+.hljs-name,
+.ruby .hljs-symbol,
+.xml .hljs-cdata {
+ color: #b5bd68;
+}
+
+/* Tomorrow Aqua */
+.hljs-title,
+.css .hljs-hexcolor {
+ color: #8abeb7;
+}
+
+/* Tomorrow Blue */
+.hljs-function,
+.python .hljs-decorator,
+.python .hljs-title,
+.ruby .hljs-function .hljs-title,
+.ruby .hljs-title .hljs-keyword,
+.perl .hljs-sub,
+.javascript .hljs-title,
+.coffeescript .hljs-title {
+ color: #81a2be;
+}
+
+/* Tomorrow Purple */
+.hljs-keyword,
+.javascript .hljs-function {
+ color: #b294bb;
+}
+
+.hljs {
+ display: block;
+ overflow-x: auto;
+ background: #1d1f21;
+ color: #c5c8c6;
+}
+
+.coffeescript .javascript,
+.javascript .xml,
+.tex .hljs-formula,
+.xml .javascript,
+.xml .vbscript,
+.xml .css,
+.xml .hljs-cdata {
+ opacity: 0.5;
+}
+
+.hljs-addition {
+ color: #718c00;
+}
+
+.hljs-deletion {
+ color: #c82829;
+}