PageSourceSearch

https://zcash.github.io/orchard/book.js

js zcash.github.io collected 2026-10-03 10:14:29 UTC 25,437 bytes, 697 lines download raw bytes

1"use strict";
2
3// Fix back button cache problem
4window.onunload = function () { };
5
6// Global variable, shared between modules
7function playground_text(playground, hidden = true) {
8    let code_block = playground.querySelector("code");
9
10    if (window.ace && code_block.classList.contains("editable")) {
11        let editor = window.ace.edit(code_block);
12        return editor.getValue();
13    } else if (hidden) {
14        return code_block.textContent;
15    } else {
16        return code_block.innerText;
17    }
18}
19
20(function codeSnippets() {
21    function fetch_with_timeout(url, options, timeout = 6000) {
22        return Promise.race([
23            fetch(url, options),
24            new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), timeout))
25        ]);
26    }
27
28    var playgrounds = Array.from(document.querySelectorAll(".playground"));
29    if (playgrounds.length > 0) {
30        fetch_with_timeout("https://play.rust-lang.org/meta/crates", {
31            headers: {
32                'Content-Type': "application/json",
33            },
34            method: 'POST',
35            mode: 'cors',
36        })
37        .then(response => response.json())
38        .then(response => {
39            // get list of crates available in the rust playground
40            let playground_crates = response.crates.map(item => item["id"]);
41            playgrounds.forEach(block => handle_crate_list_update(block, playground_crates));
42        });
43    }
44
45    function handle_crate_list_update(playground_block, playground_crates) {
46        // update the play buttons after receiving the response
47        update_play_button(playground_block, playground_crates);
48
49        // and install on change listener to dynamically update ACE editors
50        if (window.ace) {
51            let code_block = playground_block.querySelector("code");
52            if (code_block.classList.contains("editable")) {
53                let editor = window.ace.edit(code_block);
54                editor.addEventListener("change", function (e) {
55                    update_play_button(playground_block, playground_crates);
56                });
57                // add Ctrl-Enter command to execute rust code
58                editor.commands.addCommand({
59                    name: "run",
60                    bindKey: {
61                        win: "Ctrl-Enter",
62                        mac: "Ctrl-Enter"
63                    },
64                    exec: _editor => run_rust_code(playground_block)
65                });
66            }
67        }
68    }
69
70    // updates the visibility of play button based on `no_run` class and
71    // used crates vs ones available on https://play.rust-lang.org
72    function update_play_button(pre_block, playground_crates) {
73        var play_button = pre_block.querySelector(".play-button");
74
75        // skip if code is `no_run`
76        if (pre_block.querySelector('code').classList.contains("no_run")) {
77            play_button.classList.add("hidden");
78            return;
79        }
80
81        // get list of `extern crate`'s from snippet
82        var txt = playground_text(pre_block);
83        var re = /extern\s+crate\s+([a-zA-Z_0-9]+)\s*;/g;
84        var snippet_crates = [];
85        var item;
86        while (item = re.exec(txt)) {
87            snippet_crates.push(item[1]);
88        }
89
90        // check if all used crates are available on play.rust-lang.org
91        var all_available = snippet_crates.every(function (elem) {
92            return playground_crates.indexOf(elem) > -1;
93        });
94
95        if (all_available) {
96            play_button.classList.remove("hidden");
97        } else {
98            play_button.classList.add("hidden");
99        }
100    }
101
102    function run_rust_code(code_block) {
103        var result_block = code_block.querySelector(".result");
104        if (!result_block) {
105            result_block = document.createElement('code');
106            result_block.className = 'result hljs language-bash';
107
108            code_block.append(result_block);
109        }
110
111        let text = playground_text(code_block);
112        let classes = code_block.querySelector('code').classList;
113        let edition = "2015";
114        if(classes.contains("edition2018")) {
115            edition = "2018";
116        } else if(classes.contains("edition2021")) {
117            edition = "2021";
118        }
119        var params = {
120            version: "stable",
121            optimize: "0",
122            code: text,
123            edition: edition
124        };
125
126        if (text.indexOf("#![feature") !== -1) {
127            params.version = "nightly";
128        }
129
130        result_block.innerText = "Running...";
131
132        fetch_with_timeout("https://play.rust-lang.org/evaluate.json", {
133            headers: {
134                'Content-Type': "application/json",
135            },
136            method: 'POST',
137            mode: 'cors',
138            body: JSON.stringify(params)
139        })
140        .then(response => response.json())
141        .then(response => {
142            if (response.result.trim() === '') {
143                result_block.innerText = "No output";
144                result_block.classList.add("result-no-output");
145            } else {
146                result_block.innerText = response.result;
147                result_block.classList.remove("result-no-output");
148            }
149        })
150        .catch(error => result_block.innerText = "Playground Communication: " + error.message);
151    }
152
153    // Syntax highlighting Configuration
154    hljs.configure({
155        tabReplace: '    ', // 4 spaces
156        languages: [],      // Languages used for auto-detection
157    });
158
159    let code_nodes = Array
160        .from(document.querySelectorAll('code'))
161        // Don't highlight `inline code` blocks in headers.
162        .filter(function (node) {return !node.parentElement.classList.contains("header"); });
163
164    if (window.ace) {
165        // language-rust class needs to be removed for editable
166        // blocks or highlightjs will capture events
167        code_nodes
168            .filter(function (node) {return node.classList.contains("editable"); })
169            .forEach(function (block) { block.classList.remove('language-rust'); });
170
171        code_nodes
172            .filter(function (node) {return !node.classList.contains("editable"); })
173            .forEach(function (block) { hljs.highlightBlock(block); });
174    } else {
175        code_nodes.forEach(function (block) { hljs.highlightBlock(block); });
176    }
177
178    // Adding the hljs class gives code blocks the color css
179    // even if highlighting doesn't apply
180    code_nodes.forEach(function (block) { block.classList.add('hljs'); });
181
182    Array.from(document.querySelectorAll("code.hljs")).forEach(function (block) {
183
184        var lines = Array.from(block.querySelectorAll('.boring'));
185        // If no lines were hidden, return
186        if (!lines.length) { return; }
187        block.classList.add("hide-boring");
188
189        var buttons = document.createElement('div');
190        buttons.className = 'buttons';
191        buttons.innerHTML = "<button class=\"fa fa-eye\" title=\"Show hidden lines\" aria-label=\"Show hidden lines\"></button>";
192
193        // add expand button
194        var pre_block = block.parentNode;
195        pre_block.insertBefore(buttons, pre_block.firstChild);
196
197        pre_block.querySelector('.buttons').addEventListener('click', function (e) {
198            if (e.target.classList.contains('fa-eye')) {
199                e.target.classList.remove('fa-eye');
200                e.target.classList.add('fa-eye-slash');
201                e.target.title = 'Hide lines';
202                e.target.setAttribute('aria-label', e.target.title);
203
204                block.classList.remove('hide-boring');
205            } else if (e.target.classList.contains('fa-eye-slash')) {
206                e.target.classList.remove('fa-eye-slash');
207                e.target.classList.add('fa-eye');
208                e.target.title = 'Show hidden lines';
209                e.target.setAttribute('aria-label', e.target.title);
210
211                block.classList.add('hide-boring');
212            }
213        });
214    });
215
216    if (window.playground_copyable) {
217        Array.from(document.querySelectorAll('pre code')).forEach(function (block) {
218            var pre_block = block.parentNode;
219            if (!pre_block.classList.contains('playground')) {
220                var buttons = pre_block.querySelector(".buttons");
221                if (!buttons) {
222                    buttons = document.createElement('div');
223                    buttons.className = 'buttons';
224                    pre_block.insertBefore(buttons, pre_block.firstChild);
225                }
226
227                var clipButton = document.createElement('button');
228                clipButton.className = 'fa fa-copy clip-button';
229                clipButton.title = 'Copy to clipboard';
230                clipButton.setAttribute('aria-label', clipButton.title);
231                clipButton.innerHTML = '<i class=\"tooltiptext\"></i>';
232
233                buttons.insertBefore(clipButton, buttons.firstChild);
234            }
235        });
236    }
237
238    // Process playground code blocks
239    Array.from(document.querySelectorAll(".playground")).forEach(function (pre_block) {
240        // Add play button
241        var buttons = pre_block.querySelector(".buttons");
242        if (!buttons) {
243            buttons = document.createElement('div');
244            buttons.className = 'buttons';
245            pre_block.insertBefore(buttons, pre_block.firstChild);
246        }
247
248        var runCodeButton = document.createElement('button');
249        runCodeButton.className = 'fa fa-play play-button';
250        runCodeButton.hidden = true;
251        runCodeButton.title = 'Run this code';
252        runCodeButton.setAttribute('aria-label', runCodeButton.title);
253
254        buttons.insertBefore(runCodeButton, buttons.firstChild);
255        runCodeButton.addEventListener('click', function (e) {
256            run_rust_code(pre_block);
257        });
258
259        if (window.playground_copyable) {
260            var copyCodeClipboardButton = document.createElement('button');
261            copyCodeClipboardButton.className = 'fa fa-copy clip-button';
262            copyCodeClipboardButton.innerHTML = '<i class="tooltiptext"></i>';
263            copyCodeClipboardButton.title = 'Copy to clipboard';
264            copyCodeClipboardButton.setAttribute('aria-label', copyCodeClipboardButton.title);
265
266            buttons.insertBefore(copyCodeClipboardButton, buttons.firstChild);
267        }
268
269        let code_block = pre_block.querySelector("code");
270        if (window.ace && code_block.classList.contains("editable")) {
271            var undoChangesButton = document.createElement('button');
272            undoChangesButton.className = 'fa fa-history reset-button';
273            undoChangesButton.title = 'Undo changes';
274            undoChangesButton.setAttribute('aria-label', undoChangesButton.title);
275
276            buttons.insertBefore(undoChangesButton, buttons.firstChild);
277
278            undoChangesButton.addEventListener('click', function () {
279                let editor = window.ace.edit(code_block);
280                editor.setValue(editor.originalCode);
281                editor.clearSelection();
282            });
283        }
284    });
285})();
286
287(function themes() {
288    var html = document.querySelector('html');
289    var themeToggleButton = document.getElementById('theme-toggle');
290    var themePopup = document.getElementById('theme-list');
291    var themeColorMetaTag = document.querySelector('meta[name="theme-color"]');
292    var stylesheets = {
293        ayuHighlight: document.querySelector("[href$='ayu-highlight.css']"),
294        tomorrowNight: document.querySelector("[href$='tomorrow-night.css']"),
295        highlight: document.querySelector("[href$='highlight.css']"),
296    };
297
298    function showThemes() {
299        themePopup.style.display = 'block';
300        themeToggleButton.setAttribute('aria-expanded', true);
301        themePopup.querySelector("button#" + get_theme()).focus();
302    }
303
304    function updateThemeSelected() {
305        themePopup.querySelectorAll('.theme-selected').forEach(function (el) {
306            el.classList.remove('theme-selected');
307        });
308        themePopup.querySelector("button#" + get_theme()).classList.add('theme-selected');
309    }
310
311    function hideThemes() {
312        themePopup.style.display = 'none';
313        themeToggleButton.setAttribute('aria-expanded', false);
314        themeToggleButton.focus();
315    }
316
317    function get_theme() {
318        var theme;
319        try { theme = localStorage.getItem('mdbook-theme'); } catch (e) { }
320        if (theme === null || theme === undefined) {
321            return default_theme;
322        } else {
323            return theme;
324        }
325    }
326
327    function set_theme(theme, store = true) {
328        let ace_theme;
329
330        if (theme == 'coal' || theme == 'navy') {
331            stylesheets.ayuHighlight.disabled = true;
332            stylesheets.tomorrowNight.disabled = false;
333            stylesheets.highlight.disabled = true;
334
335            ace_theme = "ace/theme/tomorrow_night";
336        } else if (theme == 'ayu') {
337            stylesheets.ayuHighlight.disabled = false;
338            stylesheets.tomorrowNight.disabled = true;
339            stylesheets.highlight.disabled = true;
340            ace_theme = "ace/theme/tomorrow_night";
341        } else {
342            stylesheets.ayuHighlight.disabled = true;
343            stylesheets.tomorrowNight.disabled = true;
344            stylesheets.highlight.disabled = false;
345            ace_theme = "ace/theme/dawn";
346        }
347
348        setTimeout(function () {
349            themeColorMetaTag.content = getComputedStyle(document.documentElement).backgroundColor;
350        }, 1);
351
352        if (window.ace && window.editors) {
353            window.editors.forEach(function (editor) {
354                editor.setTheme(ace_theme);
355            });
356        }
357
358        var previousTheme = get_theme();
359
360        if (store) {
361            try { localStorage.setItem('mdbook-theme', theme); } catch (e) { }
362        }
363
364        html.classList.remove(previousTheme);
365        html.classList.add(theme);
366        updateThemeSelected();
367    }
368
369    // Set theme
370    var theme = get_theme();
371
372    set_theme(theme, false);
373
374    themeToggleButton.addEventListener('click', function () {
375        if (themePopup.style.display === 'block') {
376            hideThemes();
377        } else {
378            showThemes();
379        }
380    });
381
382    themePopup.addEventListener('click', function (e) {
383        var theme;
384        if (e.target.className === "theme") {
385            theme = e.target.id;
386        } else if (e.target.parentElement.className === "theme") {
387            theme = e.target.parentElement.id;
388        } else {
389            return;
390        }
391        set_theme(theme);
392    });
393
394    themePopup.addEventListener('focusout', function(e) {
395        // e.relatedTarget is null in Safari and Firefox on macOS (see workaround below)
396        if (!!e.relatedTarget && !themeToggleButton.contains(e.relatedTarget) && !themePopup.contains(e.relatedTarget)) {
397            hideThemes();
398        }
399    });
400
401    // Should not be needed, but it works around an issue on macOS & iOS: https://github.com/rust-lang/mdBook/issues/628
402    document.addEventListener('click', function(e) {
403        if (themePopup.style.display === 'block' && !themeToggleButton.contains(e.target) && !themePopup.contains(e.target)) {
404            hideThemes();
405        }
406    });
407
408    document.addEventListener('keydown', function (e) {
409        if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) { return; }
410        if (!themePopup.contains(e.target)) { return; }
411
412        switch (e.key) {
413            case 'Escape':
414                e.preventDefault();
415                hideThemes();
416                break;
417            case 'ArrowUp':
418                e.preventDefault();
419                var li = document.activeElement.parentElement;
420                if (li && li.previousElementSibling) {
421                    li.previousElementSibling.querySelector('button').focus();
422                }
423                break;
424            case 'ArrowDown':
425                e.preventDefault();
426                var li = document.activeElement.parentElement;
427                if (li && li.nextElementSibling) {
428                    li.nextElementSibling.querySelector('button').focus();
429                }
430                break;
431            case 'Home':
432                e.preventDefault();
433                themePopup.querySelector('li:first-child button').focus();
434                break;
435            case 'End':
436                e.preventDefault();
437                themePopup.querySelector('li:last-child button').focus();
438                break;
439        }
440    });
441})();
442
443(function sidebar() {
444    var body = document.querySelector("body");
445    var sidebar = document.getElementById("sidebar");
446    var sidebarLinks = document.querySelectorAll('#sidebar a');
447    var sidebarToggleButton = document.getElementById("sidebar-toggle");
448    var sidebarResizeHandle = document.getElementById("sidebar-resize-handle");
449    var firstContact = null;
450
451    function showSidebar() {
452        body.classList.remove('sidebar-hidden')
453        body.classList.add('sidebar-visible');
454        Array.from(sidebarLinks).forEach(function (link) {
455            link.setAttribute('tabIndex', 0);
456        });
457        sidebarToggleButton.setAttribute('aria-expanded', true);
458        sidebar.setAttribute('aria-hidden', false);
459        try { localStorage.setItem('mdbook-sidebar', 'visible'); } catch (e) { }
460    }
461
462
463    var sidebarAnchorToggles = document.querySelectorAll('#sidebar a.toggle');
464
465    function toggleSection(ev) {
466        ev.currentTarget.parentElement.classList.toggle('expanded');
467    }
468
469    Array.from(sidebarAnchorToggles).forEach(function (el) {
470        el.addEventListener('click', toggleSection);
471    });
472
473    function hideSidebar() {
474        body.classList.remove('sidebar-visible')
475        body.classList.add('sidebar-hidden');
476        Array.from(sidebarLinks).forEach(function (link) {
477            link.setAttribute('tabIndex', -1);
478        });
479        sidebarToggleButton.setAttribute('aria-expanded', false);
480        sidebar.setAttribute('aria-hidden', true);
481        try { localStorage.setItem('mdbook-sidebar', 'hidden'); } catch (e) { }
482    }
483
484    // Toggle sidebar
485    sidebarToggleButton.addEventListener('click', function sidebarToggle() {
486        if (body.classList.contains("sidebar-hidden")) {
487            var current_width = parseInt(
488                document.documentElement.style.getPropertyValue('--sidebar-width'), 10);
489            if (current_width < 150) {
490                document.documentElement.style.setProperty('--sidebar-width', '150px');
491            }
492            showSidebar();
493        } else if (body.classList.contains("sidebar-visible")) {
494            hideSidebar();
495        } else {
496            if (getComputedStyle(sidebar)['transform'] === 'none') {
497                hideSidebar();
498            } else {
499                showSidebar();
500            }
501        }
502    });
503
504    sidebarResizeHandle.addEventListener('mousedown', initResize, false);
505
506    function initResize(e) {
507        window.addEventListener('mousemove', resize, false);
508        window.addEventListener('mouseup', stopResize, false);
509        body.classList.add('sidebar-resizing');
510    }
511    function resize(e) {
512        var pos = (e.clientX - sidebar.offsetLeft);
513        if (pos < 20) {
514            hideSidebar();
515        } else {
516            if (body.classList.contains("sidebar-hidden")) {
517                showSidebar();
518            }
519            pos = Math.min(pos, window.innerWidth - 100);
520            document.documentElement.style.setProperty('--sidebar-width', pos + 'px');
521        }
522    }
523    //on mouseup remove windows functions mousemove & mouseup
524    function stopResize(e) {
525        body.classList.remove('sidebar-resizing');
526        window.removeEventListener('mousemove', resize, false);
527        window.removeEventListener('mouseup', stopResize, false);
528    }
529
530    document.addEventListener('touchstart', function (e) {
531        firstContact = {
532            x: e.touches[0].clientX,
533            time: Date.now()
534        };
535    }, { passive: true });
536
537    document.addEventListener('touchmove', function (e) {
538        if (!firstContact)
539            return;
540
541        var curX = e.touches[0].clientX;
542        var xDiff = curX - firstContact.x,
543            tDiff = Date.now() - firstContact.time;
544
545        if (tDiff < 250 && Math.abs(xDiff) >= 150) {
546            if (xDiff >= 0 && firstContact.x < Math.min(document.body.clientWidth * 0.25, 300))
547                showSidebar();
548            else if (xDiff < 0 && curX < 300)
549                hideSidebar();
550
551            firstContact = null;
552        }
553    }, { passive: true });
554})();
555
556(function chapterNavigation() {
557    document.addEventListener('keydown', function (e) {
558        if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) { return; }
559        if (window.search && window.search.hasFocus()) { return; }
560        var html = document.querySelector('html');
561
562        function next() {
563            var nextButton = document.querySelector('.nav-chapters.next');
564            if (nextButton) {
565                window.location.href = nextButton.href;
566            }
567        }
568        function prev() {
569            var previousButton = document.querySelector('.nav-chapter
569s.previous');
570            if (previousButton) {
571                window.location.href = previousButton.href;
572            }
573        }
574        switch (e.key) {
575            case 'ArrowRight':
576                e.preventDefault();
577                if (html.dir == 'rtl') {
578                    prev();
579                } else {
580                    next();
581                }
582                break;
583            case 'ArrowLeft':
584                e.preventDefault();
585                if (html.dir == 'rtl') {
586                    next();
587                } else {
588                    prev();
589                }
590                break;
591        }
592    });
593})();
594
595(function clipboard() {
596    var clipButtons = document.querySelectorAll('.clip-button');
597
598    function hideTooltip(elem) {
599        elem.firstChild.innerText = "";
600        elem.className = 'fa fa-copy clip-button';
601    }
602
603    function showTooltip(elem, msg) {
604        elem.firstChild.innerText = msg;
605        elem.className = 'fa fa-copy tooltipped';
606    }
607
608    var clipboardSnippets = new ClipboardJS('.clip-button', {
609        text: function (trigger) {
610            hideTooltip(trigger);
611            let playground = trigger.closest("pre");
612            return playground_text(playground, false);
613        }
614    });
615
616    Array.from(clipButtons).forEach(function (clipButton) {
617        clipButton.addEventListener('mouseout', function (e) {
618            hideTooltip(e.currentTarget);
619        });
620    });
621
622    clipboardSnippets.on('success', function (e) {
623        e.clearSelection();
624        showTooltip(e.trigger, "Copied!");
625    });
626
627    clipboardSnippets.on('error', function (e) {
628        showTooltip(e.trigger, "Clipboard error!");
629    });
630})();
631
632(function scrollToTop () {
633    var menuTitle = document.querySelector('.menu-title');
634
635    menuTitle.addEventListener('click', function () {
636        document.scrollingElement.scrollTo({ top: 0, behavior: 'smooth' });
637    });
638})();
639
640(function controllMenu() {
641    var menu = document.getElementById('menu-bar');
642
643    (function controllPosition() {
644        var scrollTop = document.scrollingElement.scrollTop;
645        var prevScrollTop = scrollTop;
646        var minMenuY = -menu.clientHeight - 50;
647        // When the script loads, the page can be at any scroll (e.g. if you reforesh it).
648        menu.style.top = scrollTop + 'px';
649        // Same as parseInt(menu.style.top.slice(0, -2), but faster
650        var topCache = menu.style.top.slice(0, -2);
651        menu.classList.remove('sticky');
652        var stickyCache = false; // Same as menu.classList.contains('sticky'), but faster
653        document.addEventListener('scroll', function () {
654            scrollTop = Math.max(document.scrollingElement.scrollTop, 0);
655            // `null` means that it doesn't need to be updated
656            var nextSticky = null;
657            var nextTop = null;
658            var scrollDown = scrollTop > prevScrollTop;
659            var menuPosAbsoluteY = topCache - scrollTop;
660            if (scrollDown) {
661                nextSticky = false;
662                if (menuPosAbsoluteY > 0) {
663                    nextTop = prevScrollTop;
664                }
665            } else {
666                if (menuPosAbsoluteY > 0) {
667                    nextSticky = true;
668                } else if (menuPosAbsoluteY < minMenuY) {
669                    nextTop = prevScrollTop + minMenuY;
670                }
671            }
672            if (nextSticky === true && stickyCache === false) {
673                menu.classList.add('sticky');
674                stickyCache = true;
675            } else if (nextSticky === false && stickyCache === true) {
676                menu.classList.remove('sticky');
677                stickyCache = false;
678            }
679            if (nextTop !== null) {
680                menu.style.top = nextTop + 'px';
681                topCache = nextTop;
682            }
683            prevScrollTop = scrollTop;
684        }, { passive: true });
685    })();
686    (function controllBorder() {
687        function updateBorder() {
688            if (menu.offsetTop === 0) {
689                menu.classList.remove('bordered');
690            } else {
691                menu.classList.add('bordered');
692            }
693        }
694        updateBorder();
695        document.addEventListener('scroll', updateBorder, { passive: true });
696    })();
697})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.