@ -31,7 +31,9 @@ function playground_text(playground, hidden = true) {
function fetch _with _timeout ( url , options , timeout = 15000 ) {
function fetch _with _timeout ( url , options , timeout = 15000 ) {
return Promise . race ( [
return Promise . race ( [
fetch ( url , options ) ,
fetch ( url , options ) ,
new Promise ( ( _ , reject ) => setTimeout ( ( ) => reject ( new Error ( 'timeout' ) ) , timeout ) )
new Promise ( ( _ , reject ) =>
setTimeout ( ( ) => reject ( new Error ( "timeout" ) ) , timeout )
) ,
] ) ;
] ) ;
}
}
@ -39,16 +41,18 @@ function playground_text(playground, hidden = true) {
if ( playgrounds . length > 0 ) {
if ( playgrounds . length > 0 ) {
fetch _with _timeout ( "https://play.rust-lang.org/meta/crates" , {
fetch _with _timeout ( "https://play.rust-lang.org/meta/crates" , {
headers : {
headers : {
'Content-Type' : "application/json" ,
"Content-Type" : "application/json" ,
} ,
} ,
method : 'POST' ,
method : "POST" ,
mode : 'cors' ,
mode : "cors" ,
} )
} )
. then ( response => response . json ( ) )
. then ( ( response ) => response . json ( ) )
. then ( response => {
. then ( ( response ) => {
// get list of crates available in the rust playground
// get list of crates available in the rust playground
let playground _crates = response . crates . map ( item => item [ "id" ] ) ;
let playground _crates = response . crates . map ( ( item ) => item [ "id" ] ) ;
playgrounds . forEach ( block => handle _crate _list _update ( block , playground _crates ) ) ;
playgrounds . forEach ( ( block ) =>
handle _crate _list _update ( block , playground _crates )
) ;
} ) ;
} ) ;
}
}
@ -69,21 +73,21 @@ function playground_text(playground, hidden = true) {
name : "run" ,
name : "run" ,
bindKey : {
bindKey : {
win : "Ctrl-Enter" ,
win : "Ctrl-Enter" ,
mac : "Ctrl-Enter"
mac : "Ctrl-Enter" ,
} ,
} ,
exec : _editor => run _rust _code ( playground _block )
exec : ( _editor ) => run _rust _code ( playground _block ) ,
} ) ;
} ) ;
}
}
}
}
}
}
// updates the visibility of play button based on `no_run` class and
// updates the visibility of play button based on `no_run` class and
// used crates vs ones available on http ://play.rust-lang.org
// used crates vs ones available on http s ://play.rust-lang.org
function update _play _button ( pre _block , playground _crates ) {
function update _play _button ( pre _block , playground _crates ) {
var play _button = pre _block . querySelector ( ".play-button" ) ;
var play _button = pre _block . querySelector ( ".play-button" ) ;
// skip if code is `no_run`
// skip if code is `no_run`
if ( pre _block . querySelector ( 'code' ) . classList . contains ( "no_run" ) ) {
if ( pre _block . querySelector ( "code" ) . classList . contains ( "no_run" ) ) {
play _button . classList . add ( "hidden" ) ;
play _button . classList . add ( "hidden" ) ;
return ;
return ;
}
}
@ -93,7 +97,7 @@ function playground_text(playground, hidden = true) {
var re = /extern\s+crate\s+([a-zA-Z_0-9]+)\s*;/g ;
var re = /extern\s+crate\s+([a-zA-Z_0-9]+)\s*;/g ;
var snippet _crates = [ ] ;
var snippet _crates = [ ] ;
var item ;
var item ;
while ( item = re . exec ( txt ) ) {
while ( ( item = re . exec ( txt ) ) ) {
snippet _crates . push ( item [ 1 ] ) ;
snippet _crates . push ( item [ 1 ] ) ;
}
}
@ -112,14 +116,14 @@ function playground_text(playground, hidden = true) {
function run _rust _code ( code _block ) {
function run _rust _code ( code _block ) {
var result _block = code _block . querySelector ( ".result" ) ;
var result _block = code _block . querySelector ( ".result" ) ;
if ( ! result _block ) {
if ( ! result _block ) {
result _block = document . createElement ( 'code' ) ;
result _block = document . createElement ( "code" ) ;
result _block . className = 'result hljs language-bash' ;
result _block . className = "result hljs language-bash" ;
code _block . append ( result _block ) ;
code _block . append ( result _block ) ;
}
}
let text = playground _text ( code _block ) ;
let text = playground _text ( code _block ) ;
let classes = code _block . querySelector ( 'code' ) . classList ;
let classes = code _block . querySelector ( "code" ) . classList ;
let edition = "2015" ;
let edition = "2015" ;
if ( classes . contains ( "edition2018" ) ) {
if ( classes . contains ( "edition2018" ) ) {
edition = "2018" ;
edition = "2018" ;
@ -130,7 +134,7 @@ function playground_text(playground, hidden = true) {
version : "stable" ,
version : "stable" ,
optimize : "0" ,
optimize : "0" ,
code : text ,
code : text ,
edition : edition
edition : edition ,
} ;
} ;
if ( text . indexOf ( "#![feature" ) !== - 1 ) {
if ( text . indexOf ( "#![feature" ) !== - 1 ) {
@ -143,22 +147,22 @@ function playground_text(playground, hidden = true) {
const startTime = window . performance . now ( ) ;
const startTime = window . performance . now ( ) ;
fetch _with _timeout ( "https://play.rust-lang.org/evaluate.json" , {
fetch _with _timeout ( "https://play.rust-lang.org/evaluate.json" , {
headers : {
headers : {
'Content-Type' : "application/json" ,
"Content-Type" : "application/json" ,
} ,
} ,
method : 'POST' ,
method : "POST" ,
mode : 'cors' ,
mode : "cors" ,
body : JSON . stringify ( params )
body : JSON . stringify ( params ) ,
} )
} )
. then ( response => response . json ( ) )
. then ( ( response ) => response . json ( ) )
. then ( response => {
. then ( ( response ) => {
const endTime = window . performance . now ( ) ;
const endTime = window . performance . now ( ) ;
gtag ( "event" , "playground" , {
gtag ( "event" , "playground" , {
"modified" : playgroundModified ,
modified : playgroundModified ,
"error" : ( response . error == null ) ? null : 'compilation_error' ,
error : response . error == null ? null : "compilation_error" ,
"latency" : ( endTime - startTime ) / 1000 ,
latency : ( endTime - startTime ) / 1000 ,
} ) ;
} ) ;
if ( response . result . trim ( ) === '' ) {
if ( response . result . trim ( ) === "" ) {
result _block . innerText = "No output" ;
result _block . innerText = "No output" ;
result _block . classList . add ( "result-no-output" ) ;
result _block . classList . add ( "result-no-output" ) ;
} else {
} else {
@ -166,96 +170,111 @@ function playground_text(playground, hidden = true) {
result _block . classList . remove ( "result-no-output" ) ;
result _block . classList . remove ( "result-no-output" ) ;
}
}
} )
} )
. catch ( error => {
. catch ( ( error ) => {
const endTime = window . performance . now ( ) ;
const endTime = window . performance . now ( ) ;
gtag ( "event" , "playground" , {
gtag ( "event" , "playground" , {
"modified" : playgroundModified ,
modified : playgroundModified ,
"error" : error . message ,
error : error . message ,
"latency" : ( endTime - startTime ) / 1000 ,
latency : ( endTime - startTime ) / 1000 ,
} ) ;
} ) ;
result _block . innerText = "Playground Communication: " + error . message
result _block . innerText = "Playground Communication: " + error . message ;
} ) ;
} ) ;
}
}
// Syntax highlighting Configuration
// Syntax highlighting Configuration
hljs . configure ( {
hljs . configure ( {
tabReplace : ' ' , // 4 spaces
tabReplace : " " , // 4 spaces
languages : [ ] , // Languages used for auto-detection
languages : [ ] , // Languages used for auto-detection
} ) ;
} ) ;
let code _nodes = Array
let code _nodes = Array . from ( document . querySelectorAll ( "code" ) )
. from ( document . querySelectorAll ( 'code' ) )
// Don't highlight `inline code` blocks in headers.
// Don't highlight `inline code` blocks in headers.
. filter ( function ( node ) { return ! node . parentElement . classList . contains ( "header" ) ; } ) ;
. filter ( function ( node ) {
return ! node . parentElement . classList . contains ( "header" ) ;
} ) ;
if ( window . ace ) {
if ( window . ace ) {
// language-rust class needs to be removed for editable
// language-rust class needs to be removed for editable
// blocks or highlightjs will capture events
// blocks or highlightjs will capture events
code _nodes
code _nodes
. filter ( function ( node ) { return node . classList . contains ( "editable" ) ; } )
. filter ( function ( node ) {
. forEach ( function ( block ) { block . classList . remove ( 'language-rust' ) ; } ) ;
return node . classList . contains ( "editable" ) ;
} )
. forEach ( function ( block ) {
block . classList . remove ( "language-rust" ) ;
} ) ;
code _nodes
code _nodes
. filter ( function ( node ) { return ! node . classList . contains ( "editable" ) ; } )
. filter ( function ( node ) {
. forEach ( function ( block ) { hljs . highlightBlock ( block ) ; } ) ;
return ! node . classList . contains ( "editable" ) ;
} )
. forEach ( function ( block ) {
hljs . highlightBlock ( block ) ;
} ) ;
} else {
} else {
code _nodes . forEach ( function ( block ) { hljs . highlightBlock ( block ) ; } ) ;
code _nodes . forEach ( function ( block ) {
hljs . highlightBlock ( block ) ;
} ) ;
}
}
// Adding the hljs class gives code blocks the color css
// Adding the hljs class gives code blocks the color css
// even if highlighting doesn't apply
// even if highlighting doesn't apply
code _nodes . forEach ( function ( block ) { block . classList . add ( 'hljs' ) ; } ) ;
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' ) ) ;
Array . from ( document . querySelectorAll ( "code.hljs" ) ) . forEach ( function ( block ) {
var lines = Array . from ( block . querySelectorAll ( ".boring" ) ) ;
// If no lines were hidden, return
// If no lines were hidden, return
if ( ! lines . length ) { return ; }
if ( ! lines . length ) {
return ;
}
block . classList . add ( "hide-boring" ) ;
block . classList . add ( "hide-boring" ) ;
var buttons = document . createElement ( 'div' ) ;
var buttons = document . createElement ( "div" ) ;
buttons . className = 'buttons' ;
buttons . className = "buttons" ;
buttons . innerHTML = "<button class=\"fa fa-eye\" title=\"Show hidden lines\" aria-label=\"Show hidden lines\"></button>" ;
buttons . innerHTML =
'<button class="fa fa-eye" title="Show hidden lines" aria-label="Show hidden lines"></button>' ;
// add expand button
// add expand button
var pre _block = block . parentNode ;
var pre _block = block . parentNode ;
pre _block . insertBefore ( buttons , pre _block . firstChild ) ;
pre _block . insertBefore ( buttons , pre _block . firstChild ) ;
pre _block . querySelector ( '.buttons' ) . addEventListener ( 'click' , function ( e ) {
pre _block . querySelector ( ".buttons" ) . addEventListener ( "click" , function ( e ) {
if ( e . target . classList . contains ( 'fa-eye' ) ) {
if ( e . target . classList . contains ( "fa-eye" ) ) {
e . target . classList . remove ( 'fa-eye' ) ;
e . target . classList . remove ( "fa-eye" ) ;
e . target . classList . add ( 'fa-eye-slash' ) ;
e . target . classList . add ( "fa-eye-slash" ) ;
e . target . title = 'Hide lines' ;
e . target . title = "Hide lines" ;
e . target . setAttribute ( 'aria-label' , e . target . title ) ;
e . target . setAttribute ( "aria-label" , e . target . title ) ;
block . classList . remove ( 'hide-boring' ) ;
block . classList . remove ( "hide-boring" ) ;
} else if ( e . target . classList . contains ( 'fa-eye-slash' ) ) {
} else if ( e . target . classList . contains ( "fa-eye-slash" ) ) {
e . target . classList . remove ( 'fa-eye-slash' ) ;
e . target . classList . remove ( "fa-eye-slash" ) ;
e . target . classList . add ( 'fa-eye' ) ;
e . target . classList . add ( "fa-eye" ) ;
e . target . title = 'Show hidden lines' ;
e . target . title = "Show hidden lines" ;
e . target . setAttribute ( 'aria-label' , e . target . title ) ;
e . target . setAttribute ( "aria-label" , e . target . title ) ;
block . classList . add ( 'hide-boring' ) ;
block . classList . add ( "hide-boring" ) ;
}
}
} ) ;
} ) ;
} ) ;
} ) ;
if ( window . playground _copyable ) {
if ( window . playground _copyable ) {
Array . from ( document . querySelectorAll ( 'pre code' ) ) . forEach ( function ( block ) {
Array . from ( document . querySelectorAll ( "pre code" ) ) . forEach ( function ( block ) {
var pre _block = block . parentNode ;
var pre _block = block . parentNode ;
if ( ! pre _block . classList . contains ( 'playground' ) ) {
if ( ! pre _block . classList . contains ( "playground" ) ) {
var buttons = pre _block . querySelector ( ".buttons" ) ;
var buttons = pre _block . querySelector ( ".buttons" ) ;
if ( ! buttons ) {
if ( ! buttons ) {
buttons = document . createElement ( 'div' ) ;
buttons = document . createElement ( "div" ) ;
buttons . className = 'buttons' ;
buttons . className = "buttons" ;
pre _block . insertBefore ( buttons , pre _block . firstChild ) ;
pre _block . insertBefore ( buttons , pre _block . firstChild ) ;
}
}
var clipButton = document . createElement ( 'button' ) ;
var clipButton = document . createElement ( "button" ) ;
clipButton . className = 'fa fa-copy clip-button' ;
clipButton . className = "fa fa-copy clip-button" ;
clipButton . title = 'Copy to clipboard' ;
clipButton . title = "Copy to clipboard" ;
clipButton . setAttribute ( 'aria-label' , clipButton . title ) ;
clipButton . setAttribute ( "aria-label" , clipButton . title ) ;
clipButton . innerHTML = '<i class= \ "tooltiptext\ "></i>';
clipButton . innerHTML = '<i class= "tooltiptext"></i>';
buttons . insertBefore ( clipButton , buttons . firstChild ) ;
buttons . insertBefore ( clipButton , buttons . firstChild ) ;
}
}
@ -263,46 +282,51 @@ function playground_text(playground, hidden = true) {
}
}
// Process playground code blocks
// Process playground code blocks
Array . from ( document . querySelectorAll ( ".playground" ) ) . forEach ( function ( pre _block ) {
Array . from ( document . querySelectorAll ( ".playground" ) ) . forEach ( function (
pre _block
) {
// Add play button
// Add play button
var buttons = pre _block . querySelector ( ".buttons" ) ;
var buttons = pre _block . querySelector ( ".buttons" ) ;
if ( ! buttons ) {
if ( ! buttons ) {
buttons = document . createElement ( 'div' ) ;
buttons = document . createElement ( "div" ) ;
buttons . className = 'buttons' ;
buttons . className = "buttons" ;
pre _block . insertBefore ( buttons , pre _block . firstChild ) ;
pre _block . insertBefore ( buttons , pre _block . firstChild ) ;
}
}
var runCodeButton = document . createElement ( 'button' ) ;
var runCodeButton = document . createElement ( "button" ) ;
runCodeButton . className = 'fa fa-play play-button' ;
runCodeButton . className = "fa fa-play play-button" ;
runCodeButton . hidden = true ;
runCodeButton . hidden = true ;
runCodeButton . title = 'Run this code' ;
runCodeButton . title = "Run this code" ;
runCodeButton . setAttribute ( 'aria-label' , runCodeButton . title ) ;
runCodeButton . setAttribute ( "aria-label" , runCodeButton . title ) ;
buttons . insertBefore ( runCodeButton , buttons . firstChild ) ;
buttons . insertBefore ( runCodeButton , buttons . firstChild ) ;
runCodeButton . addEventListener ( 'click' , function ( e ) {
runCodeButton . addEventListener ( "click" , function ( e ) {
run _rust _code ( pre _block ) ;
run _rust _code ( pre _block ) ;
} ) ;
} ) ;
if ( window . playground _copyable ) {
if ( window . playground _copyable ) {
var copyCodeClipboardButton = document . createElement ( 'button' ) ;
var copyCodeClipboardButton = document . createElement ( "button" ) ;
copyCodeClipboardButton . className = 'fa fa-copy clip-button' ;
copyCodeClipboardButton . className = "fa fa-copy clip-button" ;
copyCodeClipboardButton . innerHTML = '<i class="tooltiptext"></i>' ;
copyCodeClipboardButton . innerHTML = '<i class="tooltiptext"></i>' ;
copyCodeClipboardButton . title = 'Copy to clipboard' ;
copyCodeClipboardButton . title = "Copy to clipboard" ;
copyCodeClipboardButton . setAttribute ( 'aria-label' , copyCodeClipboardButton . title ) ;
copyCodeClipboardButton . setAttribute (
"aria-label" ,
copyCodeClipboardButton . title
) ;
buttons . insertBefore ( copyCodeClipboardButton , buttons . firstChild ) ;
buttons . insertBefore ( copyCodeClipboardButton , buttons . firstChild ) ;
}
}
let code _block = pre _block . querySelector ( "code" ) ;
let code _block = pre _block . querySelector ( "code" ) ;
if ( window . ace && code _block . classList . contains ( "editable" ) ) {
if ( window . ace && code _block . classList . contains ( "editable" ) ) {
var undoChangesButton = document . createElement ( 'button' ) ;
var undoChangesButton = document . createElement ( "button" ) ;
undoChangesButton . className = 'fa fa-history reset-button' ;
undoChangesButton . className = "fa fa-history reset-button" ;
undoChangesButton . title = 'Undo changes' ;
undoChangesButton . title = "Undo changes" ;
undoChangesButton . setAttribute ( 'aria-label' , undoChangesButton . title ) ;
undoChangesButton . setAttribute ( "aria-label" , undoChangesButton . title ) ;
buttons . insertBefore ( undoChangesButton , buttons . firstChild ) ;
buttons . insertBefore ( undoChangesButton , buttons . firstChild ) ;
undoChangesButton . addEventListener ( 'click' , function ( ) {
undoChangesButton . addEventListener ( "click" , function ( ) {
let editor = window . ace . edit ( code _block ) ;
let editor = window . ace . edit ( code _block ) ;
editor . setValue ( editor . originalCode ) ;
editor . setValue ( editor . originalCode ) ;
editor . clearSelection ( ) ;
editor . clearSelection ( ) ;
@ -312,9 +336,9 @@ function playground_text(playground, hidden = true) {
} ) ( ) ;
} ) ( ) ;
( function themes ( ) {
( function themes ( ) {
var html = document . querySelector ( 'html' ) ;
var html = document . querySelector ( "html" ) ;
var themeToggleButton = document . getElementById ( 'theme-toggle' ) ;
var themeToggleButton = document . getElementById ( "theme-toggle" ) ;
var themePopup = document . getElementById ( 'theme-list' ) ;
var themePopup = document . getElementById ( "theme-list" ) ;
var themeColorMetaTag = document . querySelector ( 'meta[name="theme-color"]' ) ;
var themeColorMetaTag = document . querySelector ( 'meta[name="theme-color"]' ) ;
var stylesheets = {
var stylesheets = {
ayuHighlight : document . querySelector ( "[href$='ayu-highlight.css']" ) ,
ayuHighlight : document . querySelector ( "[href$='ayu-highlight.css']" ) ,
@ -323,27 +347,31 @@ function playground_text(playground, hidden = true) {
} ;
} ;
function showThemes ( ) {
function showThemes ( ) {
themePopup . style . display = 'block' ;
themePopup . style . display = "block" ;
themeToggleButton . setAttribute ( 'aria-expanded' , true ) ;
themeToggleButton . setAttribute ( "aria-expanded" , true ) ;
themePopup . querySelector ( "button#" + get _theme ( ) ) . focus ( ) ;
themePopup . querySelector ( "button#" + get _theme ( ) ) . focus ( ) ;
}
}
function updateThemeSelected ( ) {
function updateThemeSelected ( ) {
themePopup . querySelectorAll ( '.theme-selected' ) . forEach ( function ( el ) {
themePopup . querySelectorAll ( ".theme-selected" ) . forEach ( function ( el ) {
el . classList . remove ( 'theme-selected' ) ;
el . classList . remove ( "theme-selected" ) ;
} ) ;
} ) ;
themePopup . querySelector ( "button#" + get _theme ( ) ) . classList . add ( 'theme-selected' ) ;
themePopup
. querySelector ( "button#" + get _theme ( ) )
. classList . add ( "theme-selected" ) ;
}
}
function hideThemes ( ) {
function hideThemes ( ) {
themePopup . style . display = 'none' ;
themePopup . style . display = "none" ;
themeToggleButton . setAttribute ( 'aria-expanded' , false ) ;
themeToggleButton . setAttribute ( "aria-expanded" , false ) ;
themeToggleButton . focus ( ) ;
themeToggleButton . focus ( ) ;
}
}
function get _theme ( ) {
function get _theme ( ) {
var theme ;
var theme ;
try { theme = localStorage . getItem ( 'mdbook-theme' ) ; } catch ( e ) { }
try {
theme = localStorage . getItem ( "mdbook-theme" ) ;
} catch ( e ) { }
if ( theme === null || theme === undefined ) {
if ( theme === null || theme === undefined ) {
return default _theme ;
return default _theme ;
} else {
} else {
@ -354,13 +382,13 @@ function playground_text(playground, hidden = true) {
function set _theme ( theme , store = true ) {
function set _theme ( theme , store = true ) {
let ace _theme ;
let ace _theme ;
if ( theme == 'coal' || theme == 'navy' ) {
if ( theme == "coal" || theme == "navy" ) {
stylesheets . ayuHighlight . disabled = true ;
stylesheets . ayuHighlight . disabled = true ;
stylesheets . tomorrowNight . disabled = false ;
stylesheets . tomorrowNight . disabled = false ;
stylesheets . highlight . disabled = true ;
stylesheets . highlight . disabled = true ;
ace _theme = "ace/theme/tomorrow_night" ;
ace _theme = "ace/theme/tomorrow_night" ;
} else if ( theme == 'ayu' ) {
} else if ( theme == "ayu" ) {
stylesheets . ayuHighlight . disabled = false ;
stylesheets . ayuHighlight . disabled = false ;
stylesheets . tomorrowNight . disabled = true ;
stylesheets . tomorrowNight . disabled = true ;
stylesheets . highlight . disabled = true ;
stylesheets . highlight . disabled = true ;
@ -373,7 +401,9 @@ function playground_text(playground, hidden = true) {
}
}
setTimeout ( function ( ) {
setTimeout ( function ( ) {
themeColorMetaTag . content = getComputedStyle ( document . body ) . backgroundColor ;
themeColorMetaTag . content = getComputedStyle (
document . documentElement
) . backgroundColor ;
} , 1 ) ;
} , 1 ) ;
if ( window . ace && window . editors ) {
if ( window . ace && window . editors ) {
@ -385,7 +415,9 @@ function playground_text(playground, hidden = true) {
var previousTheme = get _theme ( ) ;
var previousTheme = get _theme ( ) ;
if ( store ) {
if ( store ) {
try { localStorage . setItem ( 'mdbook-theme' , theme ) ; } catch ( e ) { }
try {
localStorage . setItem ( "mdbook-theme" , theme ) ;
} catch ( e ) { }
}
}
html . classList . remove ( previousTheme ) ;
html . classList . remove ( previousTheme ) ;
@ -398,15 +430,15 @@ function playground_text(playground, hidden = true) {
set _theme ( theme , false ) ;
set _theme ( theme , false ) ;
themeToggleButton . addEventListener ( 'click' , function ( ) {
themeToggleButton . addEventListener ( "click" , function ( ) {
if ( themePopup . style . display === 'block' ) {
if ( themePopup . style . display === "block" ) {
hideThemes ( ) ;
hideThemes ( ) ;
} else {
} else {
showThemes ( ) ;
showThemes ( ) ;
}
}
} ) ;
} ) ;
themePopup . addEventListener ( 'click' , function ( e ) {
themePopup . addEventListener ( "click" , function ( e ) {
var theme ;
var theme ;
if ( e . target . className === "theme" ) {
if ( e . target . className === "theme" ) {
theme = e . target . id ;
theme = e . target . id ;
@ -418,50 +450,62 @@ function playground_text(playground, hidden = true) {
set _theme ( theme ) ;
set _theme ( theme ) ;
} ) ;
} ) ;
themePopup . addEventListener ( 'focusout' , function ( e ) {
themePopup . addEventListener ( "focusout" , function ( e ) {
// e.relatedTarget is null in Safari and Firefox on macOS (see workaround below)
// e.relatedTarget is null in Safari and Firefox on macOS (see workaround below)
if ( ! ! e . relatedTarget && ! themeToggleButton . contains ( e . relatedTarget ) && ! themePopup . contains ( e . relatedTarget ) ) {
if (
! ! e . relatedTarget &&
! themeToggleButton . contains ( e . relatedTarget ) &&
! themePopup . contains ( e . relatedTarget )
) {
hideThemes ( ) ;
hideThemes ( ) ;
}
}
} ) ;
} ) ;
// Should not be needed, but it works around an issue on macOS & iOS: https://github.com/rust-lang/mdBook/issues/628
// 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 ) {
document . addEventListener ( "click" , function ( e ) {
if ( themePopup . style . display === 'block' && ! themeToggleButton . contains ( e . target ) && ! themePopup . contains ( e . target ) ) {
if (
themePopup . style . display === "block" &&
! themeToggleButton . contains ( e . target ) &&
! themePopup . contains ( e . target )
) {
hideThemes ( ) ;
hideThemes ( ) ;
}
}
} ) ;
} ) ;
document . addEventListener ( 'keydown' , function ( e ) {
document . addEventListener ( "keydown" , function ( e ) {
if ( e . altKey || e . ctrlKey || e . metaKey || e . shiftKey ) { return ; }
if ( e . altKey || e . ctrlKey || e . metaKey || e . shiftKey ) {
if ( ! themePopup . contains ( e . target ) ) { return ; }
return ;
}
if ( ! themePopup . contains ( e . target ) ) {
return ;
}
switch ( e . key ) {
switch ( e . key ) {
case 'Escape' :
case "Escape" :
e . preventDefault ( ) ;
e . preventDefault ( ) ;
hideThemes ( ) ;
hideThemes ( ) ;
break ;
break ;
case 'ArrowUp' :
case "ArrowUp" :
e . preventDefault ( ) ;
e . preventDefault ( ) ;
var li = document . activeElement . parentElement ;
var li = document . activeElement . parentElement ;
if ( li && li . previousElementSibling ) {
if ( li && li . previousElementSibling ) {
li . previousElementSibling . querySelector ( 'button' ) . focus ( ) ;
li . previousElementSibling . querySelector ( "button" ) . focus ( ) ;
}
}
break ;
break ;
case 'ArrowDown' :
case "ArrowDown" :
e . preventDefault ( ) ;
e . preventDefault ( ) ;
var li = document . activeElement . parentElement ;
var li = document . activeElement . parentElement ;
if ( li && li . nextElementSibling ) {
if ( li && li . nextElementSibling ) {
li . nextElementSibling . querySelector ( 'button' ) . focus ( ) ;
li . nextElementSibling . querySelector ( "button" ) . focus ( ) ;
}
}
break ;
break ;
case 'Home' :
case "Home" :
e . preventDefault ( ) ;
e . preventDefault ( ) ;
themePopup . querySelector ( 'li:first-child button' ) . focus ( ) ;
themePopup . querySelector ( "li:first-child button" ) . focus ( ) ;
break ;
break ;
case 'End' :
case "End" :
e . preventDefault ( ) ;
e . preventDefault ( ) ;
themePopup . querySelector ( 'li:last-child button' ) . focus ( ) ;
themePopup . querySelector ( "li:last-child button" ) . focus ( ) ;
break ;
break ;
}
}
} ) ;
} ) ;
@ -470,57 +514,62 @@ function playground_text(playground, hidden = true) {
( function sidebar ( ) {
( function sidebar ( ) {
var html = document . querySelector ( "html" ) ;
var html = document . querySelector ( "html" ) ;
var sidebar = document . getElementById ( "sidebar" ) ;
var sidebar = document . getElementById ( "sidebar" ) ;
var sidebarLinks = document . querySelectorAll ( '#sidebar a' ) ;
var sidebarLinks = document . querySelectorAll ( "#sidebar a" ) ;
var sidebarToggleButton = document . getElementById ( "sidebar-toggle" ) ;
var sidebarToggleButton = document . getElementById ( "sidebar-toggle" ) ;
var sidebarResizeHandle = document . getElementById ( "sidebar-resize-handle" ) ;
var sidebarResizeHandle = document . getElementById ( "sidebar-resize-handle" ) ;
var firstContact = null ;
var firstContact = null ;
function showSidebar ( ) {
function showSidebar ( ) {
html . classList . remove ( 'sidebar-hidden' )
html . classList . remove ( "sidebar-hidden" ) ;
html . classList . add ( 'sidebar-visible' ) ;
html . classList . add ( "sidebar-visible" ) ;
Array . from ( sidebarLinks ) . forEach ( function ( link ) {
Array . from ( sidebarLinks ) . forEach ( function ( link ) {
link . setAttribute ( 'tabIndex' , 0 ) ;
link . setAttribute ( "tabIndex" , 0 ) ;
} ) ;
} ) ;
sidebarToggleButton . setAttribute ( 'aria-expanded' , true ) ;
sidebarToggleButton . setAttribute ( "aria-expanded" , true ) ;
sidebar . setAttribute ( 'aria-hidden' , false ) ;
sidebar . setAttribute ( "aria-hidden" , false ) ;
try { localStorage . setItem ( 'mdbook-sidebar' , 'visible' ) ; } catch ( e ) { }
try {
localStorage . setItem ( "mdbook-sidebar" , "visible" ) ;
} catch ( e ) { }
}
}
var sidebarAnchorToggles = document . querySelectorAll ( "#sidebar a.toggle" ) ;
var sidebarAnchorToggles = document . querySelectorAll ( '#sidebar a.toggle' ) ;
function toggleSection ( ev ) {
function toggleSection ( ev ) {
ev . currentTarget . parentElement . classList . toggle ( 'expanded' ) ;
ev . currentTarget . parentElement . classList . toggle ( "expanded" ) ;
}
}
Array . from ( sidebarAnchorToggles ) . forEach ( function ( el ) {
Array . from ( sidebarAnchorToggles ) . forEach ( function ( el ) {
el . addEventListener ( 'click' , toggleSection ) ;
el . addEventListener ( "click" , toggleSection ) ;
} ) ;
} ) ;
function hideSidebar ( ) {
function hideSidebar ( ) {
html . classList . remove ( 'sidebar-visible' )
html . classList . remove ( "sidebar-visible" ) ;
html . classList . add ( 'sidebar-hidden' ) ;
html . classList . add ( "sidebar-hidden" ) ;
Array . from ( sidebarLinks ) . forEach ( function ( link ) {
Array . from ( sidebarLinks ) . forEach ( function ( link ) {
link . setAttribute ( 'tabIndex' , - 1 ) ;
link . setAttribute ( "tabIndex" , - 1 ) ;
} ) ;
} ) ;
sidebarToggleButton . setAttribute ( 'aria-expanded' , false ) ;
sidebarToggleButton . setAttribute ( "aria-expanded" , false ) ;
sidebar . setAttribute ( 'aria-hidden' , true ) ;
sidebar . setAttribute ( "aria-hidden" , true ) ;
try { localStorage . setItem ( 'mdbook-sidebar' , 'hidden' ) ; } catch ( e ) { }
try {
localStorage . setItem ( "mdbook-sidebar" , "hidden" ) ;
} catch ( e ) { }
}
}
// Toggle sidebar
// Toggle sidebar
sidebarToggleButton . addEventListener ( 'click' , function sidebarToggle ( ) {
sidebarToggleButton . addEventListener ( "click" , function sidebarToggle ( ) {
if ( html . classList . contains ( "sidebar-hidden" ) ) {
if ( html . classList . contains ( "sidebar-hidden" ) ) {
var current _width = parseInt (
var current _width = parseInt (
document . documentElement . style . getPropertyValue ( '--sidebar-width' ) , 10 ) ;
document . documentElement . style . getPropertyValue ( "--sidebar-width" ) ,
10
) ;
if ( current _width < 150 ) {
if ( current _width < 150 ) {
document . documentElement . style . setProperty ( '--sidebar-width' , '150px' ) ;
document . documentElement . style . setProperty ( "--sidebar-width" , "150px" ) ;
}
}
showSidebar ( ) ;
showSidebar ( ) ;
} else if ( html . classList . contains ( "sidebar-visible" ) ) {
} else if ( html . classList . contains ( "sidebar-visible" ) ) {
hideSidebar ( ) ;
hideSidebar ( ) ;
} else {
} else {
if ( getComputedStyle ( sidebar ) [ 'transform' ] === 'none' ) {
if ( getComputedStyle ( sidebar ) [ "transform" ] === "none" ) {
hideSidebar ( ) ;
hideSidebar ( ) ;
} else {
} else {
showSidebar ( ) ;
showSidebar ( ) ;
@ -528,15 +577,15 @@ function playground_text(playground, hidden = true) {
}
}
} ) ;
} ) ;
sidebarResizeHandle . addEventListener ( 'mousedown' , initResize , false ) ;
sidebarResizeHandle . addEventListener ( "mousedown" , initResize , false ) ;
function initResize ( e ) {
function initResize ( e ) {
window . addEventListener ( 'mousemove' , resize , false ) ;
window . addEventListener ( "mousemove" , resize , false ) ;
window . addEventListener ( 'mouseup' , stopResize , false ) ;
window . addEventListener ( "mouseup" , stopResize , false ) ;
html . classList . add ( 'sidebar-resizing' ) ;
html . classList . add ( "sidebar-resizing" ) ;
}
}
function resize ( e ) {
function resize ( e ) {
var pos = ( e . clientX - sidebar . offsetLeft ) ;
var pos = e . clientX - sidebar . offsetLeft ;
if ( pos < 20 ) {
if ( pos < 20 ) {
hideSidebar ( ) ;
hideSidebar ( ) ;
} else {
} else {
@ -544,65 +593,71 @@ function playground_text(playground, hidden = true) {
showSidebar ( ) ;
showSidebar ( ) ;
}
}
pos = Math . min ( pos , window . innerWidth - 100 ) ;
pos = Math . min ( pos , window . innerWidth - 100 ) ;
document . documentElement . style . setProperty ( '--sidebar-width' , pos + 'px' ) ;
document . documentElement . style . setProperty ( "--sidebar-width" , pos + "px" ) ;
}
}
}
}
//on mouseup remove windows functions mousemove & mouseup
//on mouseup remove windows functions mousemove & mouseup
function stopResize ( e ) {
function stopResize ( e ) {
html . classList . remove ( 'sidebar-resizing' ) ;
html . classList . remove ( "sidebar-resizing" ) ;
window . removeEventListener ( 'mousemove' , resize , false ) ;
window . removeEventListener ( "mousemove" , resize , false ) ;
window . removeEventListener ( 'mouseup' , stopResize , false ) ;
window . removeEventListener ( "mouseup" , stopResize , false ) ;
}
}
document . addEventListener ( 'touchstart' , function ( e ) {
document . addEventListener (
"touchstart" ,
function ( e ) {
firstContact = {
firstContact = {
x : e . touches [ 0 ] . clientX ,
x : e . touches [ 0 ] . clientX ,
time : Date . now ( )
time : Date . now ( ) ,
} ;
} ;
} , { passive : true } ) ;
} ,
{ passive : true }
) ;
document . addEventListener ( 'touchmove' , function ( e ) {
document . addEventListener (
if ( ! firstContact )
"touchmove" ,
return ;
function ( e ) {
if ( ! firstContact ) return ;
var curX = e . touches [ 0 ] . clientX ;
var curX = e . touches [ 0 ] . clientX ;
var xDiff = curX - firstContact . x ,
var xDiff = curX - firstContact . x ,
tDiff = Date . now ( ) - firstContact . time ;
tDiff = Date . now ( ) - firstContact . time ;
if ( tDiff < 250 && Math . abs ( xDiff ) >= 150 ) {
if ( tDiff < 250 && Math . abs ( xDiff ) >= 150 ) {
if ( xDiff >= 0 && firstContact . x < Math . min ( document . body . clientWidth * 0.25 , 300 ) )
if (
xDiff >= 0 &&
firstContact . x < Math . min ( document . body . clientWidth * 0.25 , 300 )
)
showSidebar ( ) ;
showSidebar ( ) ;
else if ( xDiff < 0 && curX < 300 )
else if ( xDiff < 0 && curX < 300 ) hideSidebar ( ) ;
hideSidebar ( ) ;
firstContact = null ;
firstContact = null ;
}
}
} , { passive : true } ) ;
} ,
{ 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 ( ) {
( function chapterNavigation ( ) {
document . addEventListener ( 'keydown' , function ( e ) {
document . addEventListener ( "keydown" , function ( e ) {
if ( e . altKey || e . ctrlKey || e . metaKey || e . shiftKey ) { return ; }
if ( e . altKey || e . ctrlKey || e . metaKey || e . shiftKey ) {
if ( window . search && window . search . hasFocus ( ) ) { return ; }
return ;
}
if ( window . search && window . search . hasFocus ( ) ) {
return ;
}
switch ( e . key ) {
switch ( e . key ) {
case 'ArrowRight' :
case "ArrowRight" :
e . preventDefault ( ) ;
e . preventDefault ( ) ;
var nextButton = document . querySelector ( '.nav-chapters.next' ) ;
var nextButton = document . querySelector ( ".nav-chapters.next" ) ;
if ( nextButton ) {
if ( nextButton ) {
window . location . href = nextButton . href ;
window . location . href = nextButton . href ;
}
}
break ;
break ;
case 'ArrowLeft' :
case "ArrowLeft" :
e . preventDefault ( ) ;
e . preventDefault ( ) ;
var previousButton = document . querySelector ( '.nav-chapters.previous' ) ;
var previousButton = document . querySelector ( ".nav-chapters.previous" ) ;
if ( previousButton ) {
if ( previousButton ) {
window . location . href = previousButton . href ;
window . location . href = previousButton . href ;
}
}
@ -612,64 +667,66 @@ function playground_text(playground, hidden = true) {
} ) ( ) ;
} ) ( ) ;
( function clipboard ( ) {
( function clipboard ( ) {
var clipButtons = document . querySelectorAll ( '.clip-button' ) ;
var clipButtons = document . querySelectorAll ( ".clip-button" ) ;
function hideTooltip ( elem ) {
function hideTooltip ( elem ) {
elem . firstChild . innerText = "" ;
elem . firstChild . innerText = "" ;
elem . className = 'fa fa-copy clip-button' ;
elem . className = "fa fa-copy clip-button" ;
}
}
function showTooltip ( elem , msg ) {
function showTooltip ( elem , msg ) {
elem . firstChild . innerText = msg ;
elem . firstChild . innerText = msg ;
elem . className = 'fa fa-copy tooltipped' ;
elem . className = "fa fa-copy tooltipped" ;
}
}
var clipboardSnippets = new ClipboardJS ( '.clip-button' , {
var clipboardSnippets = new ClipboardJS ( ".clip-button" , {
text : function ( trigger ) {
text : function ( trigger ) {
hideTooltip ( trigger ) ;
hideTooltip ( trigger ) ;
let playground = trigger . closest ( "pre" ) ;
let playground = trigger . closest ( "pre" ) ;
return playground _text ( playground , false ) ;
return playground _text ( playground , false ) ;
}
} ,
} ) ;
} ) ;
Array . from ( clipButtons ) . forEach ( function ( clipButton ) {
Array . from ( clipButtons ) . forEach ( function ( clipButton ) {
clipButton . addEventListener ( 'mouseout' , function ( e ) {
clipButton . addEventListener ( "mouseout" , function ( e ) {
hideTooltip ( e . currentTarget ) ;
hideTooltip ( e . currentTarget ) ;
} ) ;
} ) ;
} ) ;
} ) ;
clipboardSnippets . on ( 'success' , function ( e ) {
clipboardSnippets . on ( "success" , function ( e ) {
e . clearSelection ( ) ;
e . clearSelection ( ) ;
showTooltip ( e . trigger , "Copied!" ) ;
showTooltip ( e . trigger , "Copied!" ) ;
} ) ;
} ) ;
clipboardSnippets . on ( 'error' , function ( e ) {
clipboardSnippets . on ( "error" , function ( e ) {
showTooltip ( e . trigger , "Clipboard error!" ) ;
showTooltip ( e . trigger , "Clipboard error!" ) ;
} ) ;
} ) ;
} ) ( ) ;
} ) ( ) ;
( function scrollToTop ( ) {
( function scrollToTop ( ) {
var menuTitle = document . querySelector ( '.menu-title' ) ;
var menuTitle = document . querySelector ( ".menu-title" ) ;
menuTitle . addEventListener ( 'click' , function ( ) {
menuTitle . addEventListener ( "click" , function ( ) {
document . scrollingElement . scrollTo ( { top : 0 , behavior : 'smooth' } ) ;
document . scrollingElement . scrollTo ( { top : 0 , behavior : "smooth" } ) ;
} ) ;
} ) ;
} ) ( ) ;
} ) ( ) ;
( function controllMenu ( ) {
( function controllMenu ( ) {
var menu = document . getElementById ( 'menu-bar' ) ;
var menu = document . getElementById ( "menu-bar" ) ;
( function controllPosition ( ) {
( function controllPosition ( ) {
var scrollTop = document . scrollingElement . scrollTop ;
var scrollTop = document . scrollingElement . scrollTop ;
var prevScrollTop = scrollTop ;
var prevScrollTop = scrollTop ;
var minMenuY = - menu . clientHeight - 50 ;
var minMenuY = - menu . clientHeight - 50 ;
// When the script loads, the page can be at any scroll (e.g. if you reforesh it).
// When the script loads, the page can be at any scroll (e.g. if you reforesh it).
menu . style . top = scrollTop + 'px' ;
menu . style . top = scrollTop + "px" ;
// Same as parseInt(menu.style.top.slice(0, -2), but faster
// Same as parseInt(menu.style.top.slice(0, -2), but faster
var topCache = menu . style . top . slice ( 0 , - 2 ) ;
var topCache = menu . style . top . slice ( 0 , - 2 ) ;
menu . classList . remove ( 'sticky' ) ;
menu . classList . remove ( "sticky" ) ;
var stickyCache = false ; // Same as menu.classList.contains('sticky'), but faster
var stickyCache = false ; // Same as menu.classList.contains('sticky'), but faster
document . addEventListener ( 'scroll' , function ( ) {
document . addEventListener (
"scroll" ,
function ( ) {
scrollTop = Math . max ( document . scrollingElement . scrollTop , 0 ) ;
scrollTop = Math . max ( document . scrollingElement . scrollTop , 0 ) ;
// `null` means that it doesn't need to be updated
// `null` means that it doesn't need to be updated
var nextSticky = null ;
var nextSticky = null ;
@ -689,27 +746,30 @@ function playground_text(playground, hidden = true) {
}
}
}
}
if ( nextSticky === true && stickyCache === false ) {
if ( nextSticky === true && stickyCache === false ) {
menu . classList . add ( 'sticky' ) ;
menu . classList . add ( "sticky" ) ;
stickyCache = true ;
stickyCache = true ;
} else if ( nextSticky === false && stickyCache === true ) {
} else if ( nextSticky === false && stickyCache === true ) {
menu . classList . remove ( 'sticky' ) ;
menu . classList . remove ( "sticky" ) ;
stickyCache = false ;
stickyCache = false ;
}
}
if ( nextTop !== null ) {
if ( nextTop !== null ) {
menu . style . top = nextTop + 'px' ;
menu . style . top = nextTop + "px" ;
topCache = nextTop ;
topCache = nextTop ;
}
}
prevScrollTop = scrollTop ;
prevScrollTop = scrollTop ;
} , { passive : true } ) ;
} ,
{ passive : true }
) ;
} ) ( ) ;
} ) ( ) ;
( function controllBorder ( ) {
( function controllBorder ( ) {
menu . classList . remove ( 'bordered' ) ;
function updateBorder ( ) {
document . addEventListener ( 'scroll' , function ( ) {
if ( menu . offsetTop === 0 ) {
if ( menu . offsetTop === 0 ) {
menu . classList . remove ( 'bordered' ) ;
menu . classList . remove ( "bordered" ) ;
} else {
} else {
menu . classList . add ( 'bordered' ) ;
menu . classList . add ( "bordered" ) ;
}
}
}
} , { passive : true } ) ;
updateBorder ( ) ;
document . addEventListener ( "scroll" , updateBorder , { passive : true } ) ;
} ) ( ) ;
} ) ( ) ;
} ) ( ) ;
} ) ( ) ;