@@ -287,8 +287,8 @@ var setupSearchButtons = () => {
287
287
* @param {event } event the event that trigger the check
288
288
*/
289
289
function checkPageExistsAndRedirect ( event ) {
290
- const currentFilePath = `${ DOCUMENTATION_OPTIONS . pagename } .html` ,
291
- tryUrl = event . target . getAttribute ( "href" ) ;
290
+ const currentFilePath = `${ DOCUMENTATION_OPTIONS . pagename } .html` ;
291
+ const tryUrl = event . currentTarget . getAttribute ( "href" ) ;
292
292
let otherDocsHomepage = tryUrl . replace ( currentFilePath , "" ) ;
293
293
294
294
fetch ( tryUrl , { method : "HEAD" } )
@@ -304,68 +304,90 @@ function checkPageExistsAndRedirect(event) {
304
304
return false ;
305
305
}
306
306
307
- // Populate the version switcher from the JSON config file
308
- var themeSwitchBtns = document . querySelectorAll ( ".version-switcher__button" ) ;
309
- if ( themeSwitchBtns . length ) {
310
- fetch ( DOCUMENTATION_OPTIONS . theme_switcher_json_url )
311
- . then ( ( res ) => {
312
- return res . json ( ) ;
313
- } )
314
- . then ( ( data ) => {
315
- const currentFilePath = `${ DOCUMENTATION_OPTIONS . pagename } .html` ;
316
- themeSwitchBtns . forEach ( ( btn ) => {
317
- // Set empty strings by default so that these attributes exist and can be used in CSS selectors
318
- btn . dataset [ "activeVersionName" ] = "" ;
319
- btn . dataset [ "activeVersion" ] = "" ;
307
+ /**
308
+ * Check if the corresponding url is absolute and make a absolute path from root if necessary
309
+ *
310
+ * @param {string } url the url to check
311
+ */
312
+ async function fetchVersionSwitcherJSON ( url ) {
313
+ // first check if it's a valid URL
314
+ try {
315
+ var result = new URL ( url ) ;
316
+ } catch ( err ) {
317
+ // if not, assume relative path and fix accordingly
318
+ if ( err instanceof TypeError ) {
319
+ // workaround for redirects like https://pydata-sphinx-theme.readthedocs.io
320
+ // fetch() automatically follows redirects so it should work in every builder
321
+ // (RDT, GitHub actions, etc)
322
+ const origin = await fetch ( window . location . origin , {
323
+ method : "HEAD" ,
320
324
} ) ;
321
- // create links to the corresponding page in the other docs versions
322
- data . forEach ( ( entry ) => {
323
- // if no custom name specified (e.g., "latest"), use version string
324
- if ( ! ( "name" in entry ) ) {
325
- entry . name = entry . version ;
326
- }
327
- // create the node
328
- const span = document . createElement ( "span" ) ;
329
- span . textContent = `${ entry . name } ` ;
330
-
331
- const node = document . createElement ( "a" ) ;
332
- node . setAttribute (
333
- "class" ,
334
- "list-group-item list-group-item-action py-1"
335
- ) ;
336
- node . setAttribute ( "href" , `${ entry . url } ${ currentFilePath } ` ) ;
337
- node . appendChild ( span ) ;
338
-
339
- // on click, AJAX calls will check if the linked page exists before
340
- // trying to redirect, and if not, will redirect to the homepage
341
- // for that version of the docs.
342
- node . onclick = checkPageExistsAndRedirect ;
343
- // Add dataset values for the version and name in case people want
344
- // to apply CSS styling based on this information.
345
- node . dataset [ "versionName" ] = entry . name ;
346
- node . dataset [ "version" ] = entry . version ;
347
-
348
- document . querySelectorAll ( ".version-switcher__menu" ) . forEach ( ( menu ) => {
349
- // There may be multiple version-switcher elements, e.g. one
350
- // in a slide-over panel displayed on smaller screens.
351
- menu . append ( node ) ;
352
- } ) ;
353
- // replace dropdown button text with the preferred display name of
354
- // this version, rather than using sphinx's {{ version }} variable.
355
- // also highlight the dropdown entry for the currently-viewed
356
- // version's entry
357
- if (
358
- entry . version ==
359
- "DOCUMENTATION_OPTIONS.version_switcher_version_match"
360
- ) {
361
- node . classList . add ( "active" ) ;
362
- themeSwitchBtns . forEach ( ( btn ) => {
363
- btn . innerText = btn . dataset [ "activeVersionName" ] = entry . name ;
364
- btn . dataset [ "activeVersion" ] = entry . version ;
365
- } ) ;
366
- }
325
+ result = new URL ( url , origin . url ) ;
326
+ } else {
327
+ throw err ;
328
+ }
329
+ }
330
+
331
+ const response = await fetch ( result ) ;
332
+ const data = await response . json ( ) ;
333
+ return data ;
334
+ }
335
+
336
+ // Populate the version switcher from the JSON config file
337
+ var versionSwitcherBtns = document . querySelectorAll (
338
+ ".version-switcher__button"
339
+ ) ;
340
+ if ( versionSwitcherBtns . length ) {
341
+ const data = await fetchVersionSwitcherJSON (
342
+ DOCUMENTATION_OPTIONS . theme_switcher_json_url
343
+ ) ;
344
+ const currentFilePath = `${ DOCUMENTATION_OPTIONS . pagename } .html` ;
345
+ versionSwitcherBtns . forEach ( ( btn ) => {
346
+ // Set empty strings by default so that these attributes exist and can be used in CSS selectors
347
+ btn . dataset [ "activeVersionName" ] = "" ;
348
+ btn . dataset [ "activeVersion" ] = "" ;
349
+ } ) ;
350
+ // create links to the corresponding page in the other docs versions
351
+ data . forEach ( ( entry ) => {
352
+ // if no custom name specified (e.g., "latest"), use version string
353
+ if ( ! ( "name" in entry ) ) {
354
+ entry . name = entry . version ;
355
+ }
356
+ // create the node
357
+ const anchor = document . createElement ( "a" ) ;
358
+ anchor . setAttribute ( "class" , "list-group-item list-group-item-action py-1" ) ;
359
+ anchor . setAttribute ( "href" , `${ entry . url } ${ currentFilePath } ` ) ;
360
+ const span = document . createElement ( "span" ) ;
361
+ span . textContent = `${ entry . name } ` ;
362
+ anchor . appendChild ( span ) ;
363
+ // Add dataset values for the version and name in case people want
364
+ // to apply CSS styling based on this information.
365
+ anchor . dataset [ "versionName" ] = entry . name ;
366
+ anchor . dataset [ "version" ] = entry . version ;
367
+ // replace dropdown button text with the preferred display name of
368
+ // this version, rather than using sphinx's {{ version }} variable.
369
+ // also highlight the dropdown entry for the currently-viewed
370
+ // version's entry
371
+ if ( entry . version == DOCUMENTATION_OPTIONS . version_switcher_version_match ) {
372
+ anchor . classList . add ( "active" ) ;
373
+ versionSwitcherBtns . forEach ( ( btn ) => {
374
+ btn . innerText = btn . dataset [ "activeVersionName" ] = entry . name ;
375
+ btn . dataset [ "activeVersion" ] = entry . version ;
367
376
} ) ;
377
+ }
378
+ // There may be multiple version-switcher elements, e.g. one
379
+ // in a slide-over panel displayed on smaller screens.
380
+ document . querySelectorAll ( ".version-switcher__menu" ) . forEach ( ( menu ) => {
381
+ // we need to clone the node for each menu, but onclick attributes are not
382
+ // preserved by `.cloneNode()` so we add onclick here after cloning.
383
+ let node = anchor . cloneNode ( true ) ;
384
+ node . onclick = checkPageExistsAndRedirect ;
385
+ // on click, AJAX calls will check if the linked page exists before
386
+ // trying to redirect, and if not, will redirect to the homepage
387
+ // for that version of the docs.
388
+ menu . append ( node ) ;
368
389
} ) ;
390
+ } ) ;
369
391
}
370
392
371
393
/*******************************************************************************
0 commit comments