Add a fast language switcher button in preliminary mode. (#3464)

Also, when switching languages, the site now stays at the same page if possible.
This should help with translation work.
This commit is contained in:
Martin Taillefer 2019-03-02 17:39:32 -08:00 committed by GitHub
parent 18ce618eda
commit 5a9f78e843
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 110 additions and 25 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 92 KiB

After

Width:  |  Height:  |  Size: 92 KiB

View File

@ -1,6 +1,6 @@
const click="click",mouseenter="mouseenter",mouseleave="mouseleave",active="active";
"use strict";const escapeChars={"¢":"cent","£":"pound","¥":"yen","€":"euro","©":"copy","®":"reg","<":"lt",">":"gt",'"':"quot","&":"amp","'":"#39"},regex=/[¢£¥€©®<>"&']/g;function escapeHTML(a){return a.replace(regex,function(a){return"&"+escapeChars[a]+";"})}function copyToClipboard(a){const b=document.createElement("textarea");b.value=a,b.setAttribute("readonly",""),b.style.position="absolute",b.style.left="-9999px",document.body.appendChild(b);const c=!!(0<document.getSelection().rangeCount)&&document.getSelection().getRangeAt(0);b.select(),document.execCommand("copy"),document.body.removeChild(b),c&&(document.getSelection().removeAllRanges(),document.getSelection().addRange(c))}function saveFile(a,b){const c=document.createElement("a");c.setAttribute("href","data:text/text;charset=utf-8,"+encodeURI(b)),c.setAttribute("download",a),c.click()}function printText(a){const b=window.open("","","left=0,top=0,width=100,height=100,toolbar=0,scrollbars=0,status=0,location=0,menubar=0",!1);b.document.write("<html><body><pre><code>"+a+"</code></pre></html>"),b.document.close(),b.focus(),b.print(),b.close()}function navigateToUrlOrRoot(a){const b=new XMLHttpRequest;b.open("GET",a,!0),b.onreadystatechange=()=>{if(4===b.readyState&&404===b.status){const b=new URL(a);b.pathname="",a=b.toString()}window.location.href=a},b.send()}function getById(a){return document.getElementById(a)}function query(a,b){return a.querySelector(b)}function queryAll(a,b){return a.querySelectorAll(b)}function listen(a,b,c){a.addEventListener(b,c)}
"use strict";function handleThemes(){function a(a,b,c){let d="";if(c){const a=new Date;a.setTime(a.getTime()+1e3*(60*(60*(24*c)))),d="; expires="+a.toGMTString()}document.cookie=a+"="+b+d+"; path=/"}applyStyleSheet(cookieValue),listen(getById(lightThemeItem),click,()=>(applyStyleSheet(lightTheme),a(styleCookie,lightTheme),!1)),listen(getById(darkThemeItem),click,()=>(applyStyleSheet(darkTheme),a(styleCookie,darkTheme),!1))}handleThemes();
"use strict";const escapeChars={"¢":"cent","£":"pound","¥":"yen","€":"euro","©":"copy","®":"reg","<":"lt",">":"gt",'"':"quot","&":"amp","'":"#39"},regex=/[¢£¥€©®<>"&']/g;function escapeHTML(a){return a.replace(regex,function(a){return"&"+escapeChars[a]+";"})}function copyToClipboard(a){const b=document.createElement("textarea");b.value=a,b.setAttribute("readonly",""),b.style.position="absolute",b.style.left="-9999px",document.body.appendChild(b);const c=!!(0<document.getSelection().rangeCount)&&document.getSelection().getRangeAt(0);b.select(),document.execCommand("copy"),document.body.removeChild(b),c&&(document.getSelection().removeAllRanges(),document.getSelection().addRange(c))}function saveFile(a,b){const c=document.createElement("a");c.setAttribute("href","data:text/text;charset=utf-8,"+encodeURI(b)),c.setAttribute("download",a),c.click()}function printText(a){const b=window.open("","","left=0,top=0,width=100,height=100,toolbar=0,scrollbars=0,status=0,location=0,menubar=0",!1);b.document.write("<html><body><pre><code>"+a+"</code></pre></html>"),b.document.close(),b.focus(),b.print(),b.close()}function navigateToUrlOrRoot(a){const b=new XMLHttpRequest;b.open("GET",a,!0),b.onreadystatechange=()=>{if(4===b.readyState&&404===b.status){const b=new URL(a);b.pathname="",a=b.toString()}window.location.href=a},b.send()}function createCookie(a,b,c){let d="";if(c){const a=new Date;a.setTime(a.getTime()+1e3*(60*(60*(24*c)))),d="; expires="+a.toGMTString()}document.cookie=a+"="+b+d+"; path=/"}function getById(a){return document.getElementById(a)}function query(a,b){return a.querySelector(b)}function queryAll(a,b){return a.querySelectorAll(b)}function listen(a,b,c){a.addEventListener(b,c)}
"use strict";function handleThemes(){applyStyleSheet(cookieValue),listen(getById(lightThemeItem),click,()=>(applyStyleSheet(lightTheme),createCookie(styleCookie,lightTheme),!1)),listen(getById(darkThemeItem),click,()=>(applyStyleSheet(darkTheme),createCookie(styleCookie,darkTheme),!1))}handleThemes();
"use strict";function handleMenu(){queryAll(document,".menu").forEach(a=>{listen(query(a,".menu-trigger"),click,b=>{b.cancelBubble=!0,toggleOverlay(a)})})}handleMenu();
"use strict";function handleHeader(){function a(){getById(c).classList.remove(g),getById(d).classList.remove(g),getById(f).value=""}function b(){getById(c).classList.add(g),getById(d).classList.add(g),getById(f).focus()}const c="search-form",d="header-links",f="search-textbox",g="show-search",h="open-hamburger";listen(document.body,"keyup",b=>{27===b.which&&a()}),listen(getById("search-show"),click,a=>{a.preventDefault(),b()}),listen(getById("search-close"),click,b=>{b.preventDefault(),a()}),listen(getById("search-form"),"submit",b=>{b.preventDefault();const c=getById(f),d=getById("search-page-url"),e=d.value+"?q="+c.value;a(),window.location.assign(e)}),listen(getById("hamburger"),click,()=>{getById("brand").classList.toggle(h),getById(d).classList.toggle(h),getById(c).classList.toggle(h),getById(f).focus()}),listen(window,"resize",()=>{getById("brand").classList.remove(h),getById(d).classList.remove(h),getById(c).classList.remove(h)})}handleHeader();
"use strict";function handleSidebar(){const a=getById("sidebar");if(null!=a){queryAll(a,"button").forEach(a=>{listen(a,click,a=>{let b=a.currentTarget;b.classList.toggle("show"),b.nextElementSibling.nextElementSibling.classList.toggle("show");do b=b.parentElement;while(!b.classList.contains("body"));b.style.maxHeight=b.scrollHeight+"px"})}),queryAll(a,".header").forEach(a=>{listen(a,click,()=>{const b=a.nextElementSibling;b.classList.toggle("show"),b.style.maxHeight=b.classList.contains("show")?b.scrollHeight+"px":null})}),queryAll(a,".body").forEach(a=>{a.classList.contains("default")&&(a.style.maxHeight=a.scrollHeight+"px",a.classList.toggle("default"),a.classList.toggle("show"))});const b=getById("sidebar-toggler");b&&listen(b,click,a=>{getById("sidebar-container").classList.toggle(active),query(a.currentTarget,"svg.icon").classList.toggle("flipped")})}}handleSidebar();
@ -10,5 +10,6 @@ var _self="undefined"==typeof window?"undefined"!=typeof WorkerGlobalScope&&self
"use strict";function handleLinks(){function a(a){const b=document.createElement("a");b.className="header-link",b.href="#"+a.id,b.setAttribute("aria-hidden","true"),b.innerHTML="<svg class='icon'><use xlink:href='"+iconFile+"#links'/></svg>",a.appendChild(b)}(function(){for(let b=2;6>=b;b++)queryAll(document,"h"+b.toString()).forEach(b=>{""!==b.id&&a(b)})})(),function(){queryAll(document,"dt").forEach(b=>{""!==b.id&&a(b)})}(),function(){queryAll(document,"a").forEach(a=>{a.hostname&&a.hostname!==location.hostname&&(a.setAttribute("target","_blank"),a.setAttribute("rel","noopener"))})}(),function(){const a=getById("endnotes");if(null===a)return;const b=document.getElementsByTagName("main")[0],c=new Map(null);let d=0;queryAll(b,"a").forEach(b=>{if(b.pathname===location.pathname)return;if(b.pathname.endsWith("/")&&""!==b.hash)return;if(b.classList.contains("btn"))return;if(b.classList.contains("not-for-endnotes"))return;let e=c.get(b.href);if(e===void 0){e=c.size+1,c.set(b.href,e);const d=document.createElement("li");d.innerText=b.href,a.appendChild(d)}b.insertAdjacentHTML("afterend","<sup class='endnote-ref' aria-hidden='true'>"+e+"</sup>"),d++}),0<d&&getById("endnotes-container").classList.add("show")}()}handleLinks();
"use strict";let scrollToTopButton,tocLinks,tocHeadings;function handleScroll(){function a(){function a(){scrollToTopButton&&(300<document.body.scrollTop||300<document.documentElement.scrollTop?scrollToTopButton.classList.add("show"):scrollToTopButton.classList.remove("show"))}function b(){if(tocLinks){let a=-1,b=1e6,c=-1,d=-1e6;for(let e=0;e<tocLinks.length;e++){const f=tocHeadings[e];if(null===f)continue;const g=f.getBoundingClientRect();(g.width||g.height)&&(0<=g.top&&g.top<window.innerHeight?g.top<b&&(a=e,b=g.top):0>g.top&&g.top>d&&(c=e,d=g.top)),tocLinks[e].classList.remove("current")}0<=a?tocLinks[a].classList.add("current"):0<=c&&tocLinks[c].classList.add("current")}}a(),b();const c=query(document,":target");c&&"TR"===c.tagName&&!c.dataset.scrolled&&(document.documentElement.scrollTop-=55,c.dataset.scrolled="true")}scrollToTopButton=getById("scroll-to-top"),listen(scrollToTopButton,click,()=>{document.body.scrollTop=0,document.documentElement.scrollTop=0});const b=getById("toc");if(b){tocLinks=b.getElementsByTagName("a"),tocHeadings=Array(tocLinks.length);for(let a=0;a<tocLinks.length;a++)tocHeadings[a]=getById(tocLinks[a].hash.substring(1))}a(),listen(window,"scroll",a)}handleScroll();
"use strict";let overlay=null,popper=null;function toggleOverlay(a){overlay===a?closeActiveOverlay():(null!=overlay&&closeActiveOverlay(),a.classList.add("show"),overlay=a)}function closeActiveOverlay(){null!=overlay&&(overlay.classList.remove("show"),overlay=null,null!==popper&&(popper.destroy(),popper=null))}function handleOverlays(){function a(a,b){null!==popper&&popper.destroy(),popper=new Popper(a,b,{placement:"auto-start",modifiers:{preventOverflow:{enabled:!0},shift:{enabled:!0},flip:{enabled:!0}}})}queryAll(document,".term").forEach(b=>{const c=document.createElement("i");c.innerHTML="<svg class='icon'><use xlink:href='"+iconFile+"#glossary'/></svg>";const d=document.createElement("span");d.innerText=" "+b.dataset.title;const e=document.createElement("div");e.className="title",e.appendChild(c),e.appendChild(d);const f=document.createElement("div");f.className="body",f.innerHTML=b.dataset.body;const g=document.createElement("div");g.className="arrow",g.setAttribute("x-arrow","");const h=document.createElement("div");h.className="popover",h.appendChild(e),h.appendChild(f),h.appendChild(g),h.setAttribute("aria-hidden","true"),listen(h,click,a=>{a.cancelBubble=!0}),b.parentNode.insertBefore(h,b.nextSibling),b.removeAttribute("data-title"),b.removeAttribute("data-body"),listen(b,click,c=>{c.cancelBubble=!0,toggleOverlay(h),a(b,h)})}),listen(window,click,closeActiveOverlay),listen(window,"resize",closeActiveOverlay)}handleOverlays();
"use strict";function handleLanguageSwitch(){listen(getById("switch-lang"),click,()=>{const a=new URL(window.location.href);let b=a.pathname;return b=b.startsWith("/zh")?b.substr(3):"/zh"+b,a.pathname=b,navigateToUrlOrRoot(a.toString()),!0}),listen(getById("switch-lang-en"),click,()=>{const a=new URL(window.location.href);let b=a.pathname;b.startsWith("/zh")&&(b=b.substr(3)),a.pathname=b,createCookie("nf_lang","en"),navigateToUrlOrRoot(a.toString())}),listen(getById("switch-lang-zh"),click,()=>{const a=new URL(window.location.href);let b=a.pathname;b.startsWith("/zh")||(b="/zh"+b),a.pathname=b,createCookie("nf_lang","zh"),navigateToUrlOrRoot(a.toString())})}handleLanguageSwitch();
//# sourceMappingURL=all.min.js.map

File diff suppressed because one or more lines are too long

View File

@ -171,3 +171,6 @@ other = "Links"
[generated_file]
other = "This is an auto-generated file, please edit the source in the %s repo."
[switch_lang]
other = "Switch to Chinese"

View File

@ -171,3 +171,6 @@ other = "Links"
[generated_file]
other = "This is an auto-generated file, please edit the source in the %s repo."
[switch_lang]
other = "Switch to English"

View File

@ -148,6 +148,13 @@
</div>
{{ if .Site.Data.args.preliminary }}
<div id="switch-lang-container">
{{ $home := .Site.GetPage "home" }}
<a id="switch-lang" class="not-for-endnotes" aria-hidden="true" title='{{ i18n "switch_lang"}}'>
{{ partial "icon.html" "switch-lang" }}
</a>
</div>
{{ if .Page.Params.source_repo }}
<div id="edit-this-page-container">
{{ $msg := i18n "generated_file" }}

View File

@ -42,8 +42,8 @@
</a>
<div class="menu-content" aria-labelledby="gearDropdown">
<a lang="en" href="/" {{ if eq $home.Lang "en" }}class="active"{{ end }} onclick="createCookie('nf_lang', 'en'); return true;">English</a>
<a lang="zh" href="/zh" {{ if eq $home.Lang "zh" }}class="active"{{ end }} onclick="createCookie('nf_lang', 'zh'); return true;">中文</a>
<a lang="en" id="switch-lang-en" {{ if eq $home.Lang "en" }}class="active"{{ end }}>English</a>
<a lang="zh" id="switch-lang-zh" {{ if eq $home.Lang "zh" }}class="active"{{ end }}>中文</a>
<div></div>

View File

@ -5,6 +5,6 @@ mkdir -p generated/css generated/js generated/img
npx sass src/sass/_all.scss all.css -s compressed
mv all.css* generated/css
npx babel src/js/constants.js src/js/utils.js src/js/themes.js src/js/menu.js src/js/header.js src/js/sidebar.js src/js/tabs.js src/js/prism.js src/js/codeBlocks.js src/js/links.js src/js/scroll.js src/js/overlays.js --out-file generated/js/all.min.js --source-maps --minified --no-comments --presets minify
npx babel src/js/constants.js src/js/utils.js src/js/themes.js src/js/menu.js src/js/header.js src/js/sidebar.js src/js/tabs.js src/js/prism.js src/js/codeBlocks.js src/js/links.js src/js/scroll.js src/js/overlays.js src/js/lang.js --out-file generated/js/all.min.js --source-maps --minified --no-comments --presets minify
npx babel src/js/themes_init.js --out-file generated/js/themes_init.min.js --source-maps --minified --no-comments --presets minify
npx svgstore -o generated/img/icons.svg src/icons/**/*.svg

View File

@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 469.333 469.333">
<path d="M253.227,300.267L253.227,300.267L199.04,246.72l0.64-0.64c37.12-41.387,63.573-88.96,79.147-139.307h62.507V64H192
V21.333h-42.667V64H0v42.453h238.293c-14.4,41.173-36.907,80.213-67.627,114.347c-19.84-22.08-36.267-46.08-49.28-71.467H78.72
c15.573,34.773,36.907,67.627,63.573,97.28l-108.48,107.2L64,384l106.667-106.667l66.347,66.347L253.227,300.267z"/>
<path d="M373.333,192h-42.667l-96,256h42.667l24-64h101.333l24,64h42.667L373.333,192z M317.333,341.333L352,248.853
l34.667,92.48H317.333z"/>
</svg>

After

Width:  |  Height:  |  Size: 582 B

45
src/js/lang.js Normal file
View File

@ -0,0 +1,45 @@
"use strict";
function handleLanguageSwitch() {
listen(getById("switch-lang"), click, () => {
const url = new URL(window.location.href);
let path = url.pathname;
if (path.startsWith("/zh")) {
path = path.substr(3);
// createCookie("nf_lang", "en");
} else {
path = '/zh' + path;
// createCookie("nf_lang", "zh");
}
url.pathname = path;
navigateToUrlOrRoot(url.toString());
return true;
});
listen(getById("switch-lang-en"), click, () => {
const url = new URL(window.location.href);
let path = url.pathname;
if (path.startsWith("/zh")) {
path = path.substr(3);
}
url.pathname = path;
createCookie("nf_lang", "en");
navigateToUrlOrRoot(url.toString());
});
listen(getById("switch-lang-zh"), click, () => {
const url = new URL(window.location.href);
let path = url.pathname;
if (!path.startsWith("/zh")) {
path = '/zh' + path;
}
url.pathname = path;
createCookie("nf_lang", "zh");
navigateToUrlOrRoot(url.toString());
});
}
handleLanguageSwitch();

View File

@ -1 +1 @@
"use strict"; function handleThemes() { function createCookie(name, value, days) { let expires = ""; if (days) { const date = new Date(); date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); expires = "; expires=" + date.toGMTString(); } document.cookie = name + "=" + value + expires + "; path=/"; } // reapply this in case the first call didn't 'stick' due to timing applyStyleSheet(cookieValue); listen(getById(lightThemeItem), click, () => { applyStyleSheet(lightTheme); createCookie(styleCookie, lightTheme); return false; }); listen(getById(darkThemeItem), click, () => { applyStyleSheet(darkTheme); createCookie(styleCookie, darkTheme); return false; }); } handleThemes();
"use strict"; function handleThemes() { // reapply this in case the first call didn't 'stick' due to timing applyStyleSheet(cookieValue); listen(getById(lightThemeItem), click, () => { applyStyleSheet(lightTheme); createCookie(styleCookie, lightTheme); return false; }); listen(getById(darkThemeItem), click, () => { applyStyleSheet(darkTheme); createCookie(styleCookie, darkTheme); return false; }); } handleThemes();

View File

@ -83,6 +83,16 @@ function navigateToUrlOrRoot(url) {
request.send();
}
function createCookie(name, value, days) {
let expires = "";
if (days) {
const date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
expires = "; expires=" + date.toGMTString();
}
document.cookie = name + "=" + value + expires + "; path=/";
}
function getById(id) {
return document.getElementById(id);
}

View File

@ -1,4 +1,4 @@
#sidebar-toggler, #scroll-to-top, #edit-this-page, #report-site-bugs {
#sidebar-toggler, #scroll-to-top, #switch-lang, #edit-this-page, #report-site-bugs {
z-index: $floating-button-z;
outline: none;
background-color: rgba($backgroundColor, .7);
@ -57,15 +57,14 @@
}
}
#edit-this-page-container {
#switch-lang-container, #edit-this-page-container, #report-site-bugs-container {
@media print {
display: none;
}
#edit-this-page {
#switch-lang, #edit-this-page, #report-site-bugs {
display: block;
position: fixed;
bottom: calc(4rem + #{$footerHeight});
right: 1rem;
background-color: bisque;
@ -80,16 +79,20 @@
}
}
#report-site-bugs-container {
@media print {
display: none;
#switch-lang-container {
#switch-lang {
bottom: calc(6rem + #{$footerHeight});
}
}
#edit-this-page-container {
#edit-this-page {
bottom: calc(3.5rem + #{$footerHeight});
}
}
#report-site-bugs-container {
#report-site-bugs {
display: block;
position: fixed;
bottom: calc(1rem + #{$footerHeight});
right: 1rem;
background-color: bisque;
}
}