]>
git.proxmox.com Git - rustc.git/blob - src/vendor/mdbook/src/theme/book.js
3 // Fix back button cache problem
4 window
.onunload = function () { };
6 // Global variable, shared between modules
7 function playpen_text(playpen
) {
8 let code_block
= playpen
.querySelector("code");
10 if (window
.ace
&& code_block
.classList
.contains("editable")) {
11 let editor
= window
.ace
.edit(code_block
);
12 return editor
.getValue();
14 return code_block
.textContent
;
18 (function codeSnippets() {
19 // Hide Rust code lines prepended with a specific character
20 var hiding_character
= "#";
21 var request
= fetch("https://play.rust-lang.org/meta/crates", {
23 'Content-Type': "application/json",
29 function handle_crate_list_update(playpen_block
, playground_crates
) {
30 // update the play buttons after receiving the response
31 update_play_button(playpen_block
, playground_crates
);
33 // and install on change listener to dynamically update ACE editors
35 let code_block
= playpen_block
.querySelector("code");
36 if (code_block
.classList
.contains("editable")) {
37 let editor
= window
.ace
.edit(code_block
);
38 editor
.addEventListener("change", function (e
) {
39 update_play_button(playpen_block
, playground_crates
);
45 // updates the visibility of play button based on `no_run` class and
46 // used crates vs ones available on http://play.rust-lang.org
47 function update_play_button(pre_block
, playground_crates
) {
48 var play_button
= pre_block
.querySelector(".play-button");
50 // skip if code is `no_run`
51 if (pre_block
.querySelector('code').classList
.contains("no_run")) {
52 play_button
.classList
.add("hidden");
56 // get list of `extern crate`'s from snippet
57 var txt
= playpen_text(pre_block
);
58 var re
= /extern\s+crate\s+([a-zA-Z_0-9]+)\s*;/g;
59 var snippet_crates
= [];
61 while (item
= re
.exec(txt
)) {
62 snippet_crates
.push(item
[1]);
65 // check if all used crates are available on play.rust-lang.org
66 var all_available
= snippet_crates
.every(function (elem
) {
67 return playground_crates
.indexOf(elem
) > -1;
71 play_button
.classList
.remove("hidden");
73 play_button
.classList
.add("hidden");
77 function run_rust_code(code_block
) {
78 var result_block
= code_block
.querySelector(".result");
80 result_block
= document
.createElement('code');
81 result_block
.className
= 'result hljs language-bash';
83 code_block
.append(result_block
);
86 let text
= playpen_text(code_block
);
96 if (text
.indexOf("#![feature") !== -1) {
97 params
.channel
= "nightly";
100 result_block
.innerText
= "Running...";
102 var request
= fetch("https://play.rust-lang.org/execute", {
104 'Content-Type': "application/json",
108 body
: JSON
.stringify(params
)
112 .then(function (response
) { return response
.json(); })
113 .then(function (response
) { result_block
.innerText
= response
.success
? response
.stdout
: response
.stderr
; })
114 .catch(function (error
) { result_block
.innerText
= "Playground communication" + error
.message
; });
117 // Syntax highlighting Configuration
119 tabReplace
: ' ', // 4 spaces
120 languages
: [], // Languages used for auto-detection
124 // language-rust class needs to be removed for editable
125 // blocks or highlightjs will capture events
127 .from(document
.querySelectorAll('code.editable'))
128 .forEach(function (block
) { block
.classList
.remove('language-rust'); });
131 .from(document
.querySelectorAll('code:not(.editable)'))
132 .forEach(function (block
) { hljs
.highlightBlock(block
); });
135 .from(document
.querySelectorAll('code'))
136 .forEach(function (block
) { hljs
.highlightBlock(block
); });
139 // Adding the hljs class gives code blocks the color css
140 // even if highlighting doesn't apply
142 .from(document
.querySelectorAll('code'))
143 .forEach(function (block
) { block
.classList
.add('hljs'); });
145 Array
.from(document
.querySelectorAll("code.language-rust")).forEach(function (block
) {
147 var code_block
= block
;
148 var pre_block
= block
.parentNode
;
150 var lines
= code_block
.innerHTML
.split("\n");
151 var first_non_hidden_line
= false;
152 var lines_hidden
= false;
154 for (var n
= 0; n
< lines
.length
; n
++) {
155 if (lines
[n
].trim()[0] == hiding_character
) {
156 if (first_non_hidden_line
) {
157 lines
[n
] = "<span class=\"hidden\">" + "\n" + lines
[n
].replace(/(\s*)# ?/, "$1") + "</span>";
160 lines
[n
] = "<span class=\"hidden\">" + lines
[n
].replace(/(\s*)# ?/, "$1") + "\n" + "</span>";
164 else if (first_non_hidden_line
) {
165 lines
[n
] = "\n" + lines
[n
];
168 first_non_hidden_line
= true;
171 code_block
.innerHTML
= lines
.join("");
173 // If no lines were hidden, return
174 if (!lines_hidden
) { return; }
176 var buttons
= document
.createElement('div');
177 buttons
.className
= 'buttons';
178 buttons
.innerHTML
= "<button class=\"fa fa-expand\" title=\"Show hidden lines\" aria-label=\"Show hidden lines\"></button>";
181 pre_block
.insertBefore(buttons
, pre_block
.firstChild
);
183 pre_block
.querySelector('.buttons').addEventListener('click', function (e
) {
184 if (e
.target
.classList
.contains('fa-expand')) {
185 var lines
= pre_block
.querySelectorAll('span.hidden');
187 e
.target
.classList
.remove('fa-expand');
188 e
.target
.classList
.add('fa-compress');
189 e
.target
.title
= 'Hide lines';
190 e
.target
.setAttribute('aria-label', e
.target
.title
);
192 Array
.from(lines
).forEach(function (line
) {
193 line
.classList
.remove('hidden');
194 line
.classList
.add('unhidden');
196 } else if (e
.target
.classList
.contains('fa-compress')) {
197 var lines
= pre_block
.querySelectorAll('span.unhidden');
199 e
.target
.classList
.remove('fa-compress');
200 e
.target
.classList
.add('fa-expand');
201 e
.target
.title
= 'Show hidden lines';
202 e
.target
.setAttribute('aria-label', e
.target
.title
);
204 Array
.from(lines
).forEach(function (line
) {
205 line
.classList
.remove('unhidden');
206 line
.classList
.add('hidden');
212 Array
.from(document
.querySelectorAll('pre code')).forEach(function (block
) {
213 var pre_block
= block
.parentNode
;
214 if (!pre_block
.classList
.contains('playpen')) {
215 var buttons
= pre_block
.querySelector(".buttons");
217 buttons
= document
.createElement('div');
218 buttons
.className
= 'buttons';
219 pre_block
.insertBefore(buttons
, pre_block
.firstChild
);
222 var clipButton
= document
.createElement('button');
223 clipButton
.className
= 'fa fa-copy clip-button';
224 clipButton
.title
= 'Copy to clipboard';
225 clipButton
.setAttribute('aria-label', clipButton
.title
);
226 clipButton
.innerHTML
= '<i class=\"tooltiptext\"></i>';
228 buttons
.insertBefore(clipButton
, buttons
.firstChild
);
232 // Process playpen code blocks
233 Array
.from(document
.querySelectorAll(".playpen")).forEach(function (pre_block
) {
235 var buttons
= pre_block
.querySelector(".buttons");
237 buttons
= document
.createElement('div');
238 buttons
.className
= 'buttons';
239 pre_block
.insertBefore(buttons
, pre_block
.firstChild
);
242 var runCodeButton
= document
.createElement('button');
243 runCodeButton
.className
= 'fa fa-play play-button';
244 runCodeButton
.hidden
= true;
245 runCodeButton
.title
= 'Run this code';
246 runCodeButton
.setAttribute('aria-label', runCodeButton
.title
);
248 var copyCodeClipboardButton
= document
.createElement('button');
249 copyCodeClipboardButton
.className
= 'fa fa-copy clip-button';
250 copyCodeClipboardButton
.innerHTML
= '<i class="tooltiptext"></i>';
251 copyCodeClipboardButton
.title
= 'Copy to clipboard';
252 copyCodeClipboardButton
.setAttribute('aria-label', copyCodeClipboardButton
.title
);
254 buttons
.insertBefore(runCodeButton
, buttons
.firstChild
);
255 buttons
.insertBefore(copyCodeClipboardButton
, buttons
.firstChild
);
257 runCodeButton
.addEventListener('click', function (e
) {
258 run_rust_code(pre_block
);
261 let code_block
= pre_block
.querySelector("code");
262 if (window
.ace
&& code_block
.classList
.contains("editable")) {
263 var undoChangesButton
= document
.createElement('button');
264 undoChangesButton
.className
= 'fa fa-history reset-button';
265 undoChangesButton
.title
= 'Undo changes';
266 undoChangesButton
.setAttribute('aria-label', undoChangesButton
.title
);
268 buttons
.insertBefore(undoChangesButton
, buttons
.firstChild
);
270 undoChangesButton
.addEventListener('click', function () {
271 let editor
= window
.ace
.edit(code_block
);
272 editor
.setValue(editor
.originalCode
);
273 editor
.clearSelection();
279 .then(function (response
) { return response
.json(); })
280 .then(function (response
) {
281 // get list of crates available in the rust playground
282 let playground_crates
= response
.crates
.map(function (item
) { return item
["id"]; });
283 Array
.from(document
.querySelectorAll(".playpen")).forEach(function (block
) {
284 handle_crate_list_update(block
, playground_crates
);
291 var html
= document
.querySelector('html');
292 var themeToggleButton
= document
.getElementById('theme-toggle');
293 var themePopup
= document
.getElementById('theme-list');
294 var themeColorMetaTag
= document
.querySelector('meta[name="theme-color"]');
296 ayuHighlight
: document
.querySelector("[href='ayu-highlight.css']"),
297 tomorrowNight
: document
.querySelector("[href='tomorrow-night.css']"),
298 highlight
: document
.querySelector("[href='highlight.css']"),
301 function showThemes() {
302 themePopup
.style
.display
= 'block';
303 themeToggleButton
.setAttribute('aria-expanded', true);
304 themePopup
.querySelector("button#" + document
.body
.className
).focus();
307 function hideThemes() {
308 themePopup
.style
.display
= 'none';
309 themeToggleButton
.setAttribute('aria-expanded', false);
310 themeToggleButton
.focus();
313 function set_theme(theme
) {
316 if (theme
== 'coal' || theme
== 'navy') {
317 stylesheets
.ayuHighlight
.disabled
= true;
318 stylesheets
.tomorrowNight
.disabled
= false;
319 stylesheets
.highlight
.disabled
= true;
321 ace_theme
= "ace/theme/tomorrow_night";
322 } else if (theme
== 'ayu') {
323 stylesheets
.ayuHighlight
.disabled
= false;
324 stylesheets
.tomorrowNight
.disabled
= true;
325 stylesheets
.highlight
.disabled
= true;
327 ace_theme
= "ace/theme/tomorrow_night";
329 stylesheets
.ayuHighlight
.disabled
= true;
330 stylesheets
.tomorrowNight
.disabled
= true;
331 stylesheets
.highlight
.disabled
= false;
333 ace_theme
= "ace/theme/dawn";
336 setTimeout(function () {
337 themeColorMetaTag
.content
= getComputedStyle(document
.body
).backgroundColor
;
340 if (window
.ace
&& window
.editors
) {
341 window
.editors
.forEach(function (editor
) {
342 editor
.setTheme(ace_theme
);
347 try { previousTheme
= localStorage
.getItem('mdbook-theme'); } catch (e
) { }
348 if (previousTheme
=== null || previousTheme
=== undefined) { previousTheme
= 'light'; }
350 try { localStorage
.setItem('mdbook-theme', theme
); } catch (e
) { }
352 document
.body
.className
= theme
;
353 html
.classList
.remove(previousTheme
);
354 html
.classList
.add(theme
);
359 try { theme
= localStorage
.getItem('mdbook-theme'); } catch(e
) { }
360 if (theme
=== null || theme
=== undefined) { theme
= 'light'; }
364 themeToggleButton
.addEventListener('click', function () {
365 if (themePopup
.style
.display
=== 'block') {
372 themePopup
.addEventListener('click', function (e
) {
373 var theme
= e
.target
.id
|| e
.target
.parentElement
.id
;
377 themePopup
.addEventListener('focusout', function(e
) {
378 // e.relatedTarget is null in Safari and Firefox on macOS (see workaround below)
379 if (!!e
.relatedTarget
&& !themePopup
.contains(e
.relatedTarget
)) {
384 // Should not be needed, but it works around an issue on macOS & iOS: https://github.com/rust-lang-nursery/mdBook/issues/628
385 document
.addEventListener('click', function(e
) {
386 if (themePopup
.style
.display
=== 'block' && !themeToggleButton
.contains(e
.target
) && !themePopup
.contains(e
.target
)) {
391 document
.addEventListener('keydown', function (e
) {
392 if (e
.altKey
|| e
.ctrlKey
|| e
.metaKey
|| e
.shiftKey
) { return; }
393 if (!themePopup
.contains(e
.target
)) { return; }
402 var li
= document
.activeElement
.parentElement
;
403 if (li
&& li
.previousElementSibling
) {
404 li
.previousElementSibling
.querySelector('button').focus();
409 var li
= document
.activeElement
.parentElement
;
410 if (li
&& li
.nextElementSibling
) {
411 li
.nextElementSibling
.querySelector('button').focus();
416 themePopup
.querySelector('li:first-child button').focus();
420 themePopup
.querySelector('li:last-child button').focus();
426 (function sidebar() {
427 var html
= document
.querySelector("html");
428 var sidebar
= document
.getElementById("sidebar");
429 var sidebarLinks
= document
.querySelectorAll('#sidebar a');
430 var sidebarToggleButton
= document
.getElementById("sidebar-toggle");
431 var firstContact
= null;
433 function showSidebar() {
434 html
.classList
.remove('sidebar-hidden')
435 html
.classList
.add('sidebar-visible');
436 Array
.from(sidebarLinks
).forEach(function (link
) {
437 link
.setAttribute('tabIndex', 0);
439 sidebarToggleButton
.setAttribute('aria-expanded', true);
440 sidebar
.setAttribute('aria-hidden', false);
441 try { localStorage
.setItem('mdbook-sidebar', 'visible'); } catch (e
) { }
444 function hideSidebar() {
445 html
.classList
.remove('sidebar-visible')
446 html
.classList
.add('sidebar-hidden');
447 Array
.from(sidebarLinks
).forEach(function (link
) {
448 link
.setAttribute('tabIndex', -1);
450 sidebarToggleButton
.setAttribute('aria-expanded', false);
451 sidebar
.setAttribute('aria-hidden', true);
452 try { localStorage
.setItem('mdbook-sidebar', 'hidden'); } catch (e
) { }
456 sidebarToggleButton
.addEventListener('click', function sidebarToggle() {
457 if (html
.classList
.contains("sidebar-hidden")) {
459 } else if (html
.classList
.contains("sidebar-visible")) {
462 if (getComputedStyle(sidebar
)['transform'] === 'none') {
470 document
.addEventListener('touchstart', function (e
) {
472 x
: e
.touches
[0].clientX
,
475 }, { passive
: true });
477 document
.addEventListener('touchmove', function (e
) {
481 var curX
= e
.touches
[0].clientX
;
482 var xDiff
= curX
- firstContact
.x
,
483 tDiff
= Date
.now() - firstContact
.time
;
485 if (tDiff
< 250 && Math
.abs(xDiff
) >= 150) {
486 if (xDiff
>= 0 && firstContact
.x
< Math
.min(document
.body
.clientWidth
* 0.25, 300))
488 else if (xDiff
< 0 && curX
< 300)
493 }, { passive
: true });
495 // Scroll sidebar to current active section
496 var activeSection
= sidebar
.querySelector(".active");
498 sidebar
.scrollTop
= activeSection
.offsetTop
;
502 (function chapterNavigation() {
503 document
.addEventListener('keydown', function (e
) {
504 if (e
.altKey
|| e
.ctrlKey
|| e
.metaKey
|| e
.shiftKey
) { return; }
505 if (window
.search
&& window
.search
.hasFocus()) { return; }
510 var nextButton
= document
.querySelector('.nav-chapters.next');
512 window
.location
.href
= nextButton
.href
;
517 var previousButton
= document
.querySelector('.nav-chapters.previous');
518 if (previousButton
) {
519 window
.location
.href
= previousButton
.href
;
526 (function clipboard() {
527 var clipButtons
= document
.querySelectorAll('.clip-button');
529 function hideTooltip(elem
) {
530 elem
.firstChild
.innerText
= "";
531 elem
.className
= 'fa fa-copy clip-button';
534 function showTooltip(elem
, msg
) {
535 elem
.firstChild
.innerText
= msg
;
536 elem
.className
= 'fa fa-copy tooltipped';
539 var clipboardSnippets
= new Clipboard('.clip-button', {
540 text: function (trigger
) {
541 hideTooltip(trigger
);
542 let playpen
= trigger
.closest("pre");
543 return playpen_text(playpen
);
547 Array
.from(clipButtons
).forEach(function (clipButton
) {
548 clipButton
.addEventListener('mouseout', function (e
) {
549 hideTooltip(e
.currentTarget
);
553 clipboardSnippets
.on('success', function (e
) {
555 showTooltip(e
.trigger
, "Copied!");
558 clipboardSnippets
.on('error', function (e
) {
559 showTooltip(e
.trigger
, "Clipboard error!");
563 (function scrollToTop () {
564 var menuTitle
= document
.querySelector('.menu-title');
566 menuTitle
.addEventListener('click', function () {
567 document
.scrollingElement
.scrollTo({ top
: 0, behavior
: 'smooth' });
571 (function autoHideMenu() {
572 var menu
= document
.getElementById('menu-bar');
574 var previousScrollTop
= document
.scrollingElement
.scrollTop
;
576 document
.addEventListener('scroll', function () {
577 if (menu
.classList
.contains('folded') && document
.scrollingElement
.scrollTop
< previousScrollTop
) {
578 menu
.classList
.remove('folded');
579 } else if (!menu
.classList
.contains('folded') && document
.scrollingElement
.scrollTop
> previousScrollTop
) {
580 menu
.classList
.add('folded');
583 if (!menu
.classList
.contains('bordered') && document
.scrollingElement
.scrollTop
> 0) {
584 menu
.classList
.add('bordered');
587 if (menu
.classList
.contains('bordered') && document
.scrollingElement
.scrollTop
=== 0) {
588 menu
.classList
.remove('bordered');
591 previousScrollTop
= document
.scrollingElement
.scrollTop
;
592 }, { passive
: true });