forked from pydata/pydata-sphinx-theme
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
b5351c5
commit acd3084
Showing
3 changed files
with
218 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,206 @@ | ||
<script type="text/javascript"> | ||
(function () { | ||
const version_json_url = "{{theme_version_switch_json_url}}"; | ||
const enable_locale = "{{theme_version_switch_enable_locale}}" === 'True'; | ||
|
||
// TODO check how to pass an array instead of raw string | ||
// const all_locales = "{{theme_version_switch_locales}}"; | ||
all_locales = [ | ||
{ | ||
"locale": "zh", | ||
"display": "中文" | ||
}, | ||
{ | ||
"locale": "en", | ||
"display": "EN" | ||
} | ||
] | ||
|
||
|
||
// Remote version should like this. | ||
// .name and .alias must be unique in each locale. | ||
// It's not necessary to have same versions in all locales. | ||
// When locale is enabled, there must be only one .default=true item in each locale to indicate which one should be redirect if target version doesn't exist in target locale. | ||
|
||
/* | ||
let all_versions = { | ||
"en": [ | ||
{ | ||
"name": "v1.2.0", | ||
"url": "v1.2.0", | ||
"alias": ["latest"], | ||
"default": true | ||
}, | ||
{ | ||
"name": "v1.1.0", | ||
"url": "v1.1.0", | ||
"alias": [] | ||
}, | ||
], | ||
"zh":[ | ||
{ | ||
"name": "v1.0.0", | ||
"url": "v1.0.0", | ||
"alias": [] | ||
"default": true | ||
}, | ||
], | ||
}; | ||
*/ | ||
|
||
function parse_current_url() { | ||
// sphinx will fill here. | ||
let page_name = "{{pagename}}.html"; | ||
|
||
if (window.location.pathname.slice(-page_name.length) !== page_name) { | ||
// Sphinx generated pages should have exactly same suffix | ||
throw 'page suffix do not match requirements'; | ||
} | ||
// Get base URL by Removing '/' and page_name | ||
let base_url = window.location.pathname.slice(0, -(page_name.length + 1)); | ||
let parts = base_url.split('/'); | ||
|
||
let current_version = ''; | ||
let current_locale = ''; | ||
|
||
if (enable_locale) { | ||
if (parts.length < 1) { | ||
throw 'page base URL do not have any locale information'; | ||
} | ||
current_locale = parts.pop(); | ||
} | ||
if (parts.length < 1) { | ||
throw 'page base URL do not have any locale information'; | ||
} | ||
current_version = parts.pop(); | ||
// This is base URL without any version or locate. | ||
let global_base_url = parts.join('/') | ||
|
||
return {page_name, base_url, current_version, current_locale, global_base_url}; | ||
} | ||
|
||
// validate Check current_locale and current_version is valid. | ||
// Return canonical_version: indicate current version's real name | ||
function validate(all_versions, info) { | ||
let locale = "default"; // Use default as key when locale feature is disabled | ||
if (enable_locale) { | ||
locale = info.current_locale; | ||
} | ||
let version_list = all_versions[locale]; | ||
|
||
if (version_list === undefined) { | ||
throw `locale '${locale}'doesn't exist in remote version mapping`; | ||
} | ||
|
||
let canonical_version = function() { // Match current_version in version_list, try to find canonical version name by matching name and alias | ||
for (const v of version_list) { | ||
if (info.current_version === v.name) { | ||
return v.name; | ||
} | ||
for (const alias_name of v.alias) { | ||
if (info.current_version === alias_name) { | ||
return v.name; | ||
} | ||
} | ||
} | ||
throw `version '${info.current_version}' doesn't exist in remove version maaping` | ||
}() | ||
|
||
return canonical_version; | ||
} | ||
|
||
// Set locale or version to null to indicate unchanged property. | ||
function construct_url(info, target_locale, target_version) { | ||
let segments = [info.global_base_url]; | ||
|
||
if (target_locale == null) { | ||
target_locale = info.current_locale; | ||
} | ||
if (target_version == null) { | ||
target_version = info.current_version; | ||
} | ||
segments.push(target_version); | ||
if (enable_locale) { | ||
segments.push(target_locale); | ||
} | ||
segments.push(info.page_name); | ||
return segments.join('/') + window.location.hash; | ||
} | ||
|
||
function render(all_versions, info) { | ||
function on_switch(evt) { | ||
evt.preventDefault() | ||
let selected = evt.currentTarget.getAttribute('key'); | ||
|
||
// process with alias problem, e.g. do not jump if target is just an alias of current one. | ||
if (selected == info.canonical_version) { | ||
// Current page is already the target version, ignore | ||
return; | ||
} | ||
|
||
let new_url = construct_url(info, null, selected); | ||
window.location.assign(new_url); | ||
} | ||
// Fill the current version in the dropdown, always show real name instead of alias | ||
document.getElementById("version-dropdown").innerText = info.canonical_version; | ||
|
||
const menu_html = (function() { | ||
return all_versions[info.current_locale].map((version) => { | ||
let text = version.name; | ||
if (version.alias.length > 0) { | ||
text = `${version.name} (${version.alias.join(' ')})` | ||
} | ||
|
||
return `<button class="dropdown-item" key="${version.name}">${text}</button>` | ||
}) | ||
})().join('') | ||
// fill the version menu | ||
document.getElementById("version-menu").innerHTML = menu_html; | ||
|
||
// bind the changes to this menu to trigger the switching function | ||
$('#version-menu button').on('click', on_switch) | ||
|
||
// Adding locale switcher | ||
const locale_html = (function() { | ||
return all_locales.map((l) => { | ||
return `<span><a key="${l.locale}">${l.display}</a></span>` | ||
}) | ||
})().join('/') | ||
document.getElementById("locale-switcher").innerHTML = locale_html; | ||
} | ||
|
||
|
||
// Trigger fetch as earlier as possible to speedup page loading. | ||
let p = fetch(version_json_url).then((resp) => { | ||
return resp.json() | ||
}); | ||
|
||
$(document).ready(function () { | ||
let info = parse_current_url(); | ||
|
||
p.then((all_versions) => { | ||
let canonical_version = validate(all_versions, info); | ||
info.canonical_version = canonical_version; | ||
|
||
render(all_versions, info); | ||
}) | ||
}); | ||
})(); | ||
|
||
</script> | ||
|
||
<ul class="navbar-nav"> | ||
<li class="nav-item dropdown"> | ||
<button id="version-dropdown" class="btn btn-secondary btn-sm dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> | ||
<!-- placeholder for javascript filling above --> | ||
</button> | ||
<div id="version-menu" class="dropdown-menu" style="min-width: 6rem;"> | ||
<!-- placeholder for javascript filling above --> | ||
</div> | ||
</li> | ||
<li class="nav-item"> | ||
<span id="locale-switcher"> | ||
<!-- placeholder for locale switcher --> | ||
</span> | ||
</li> | ||
</ul> |