content/static: rearrange loading order of scripts plus cleanup

+ Load all JavaScript files at the end of the page so that DOM
  parsing won’t be blocked by script execution.
+ Extract out Google Tag Manager script tag and place init logic in
  a separate file instead of using an inscrutable, minified inline
  script.
+ Add the JavaScript compilation script.
+ Update license headers to have a range so that multiple licenses
  are not included in the minified source when only the date is
  different.
+ Update the prettier config to avoid arrow parentheses unless they
  are needed to match existing style.

Change-Id: I7331ee7fab04eb2ff45b5f59928b3e5817d35813
Reviewed-on: https://team-review.git.corp.google.com/c/golang/discovery/+/752822
CI-Result: Cloud Build <devtools-proctor-result-processor@system.gserviceaccount.com>
Reviewed-by: Julie Qiu <julieqiu@google.com>
Reviewed-by: Alexander Rakoczy <rakoczy@google.com>
This commit is contained in:
Andrew Bonventre 2020-05-21 16:43:46 -04:00 коммит произвёл Andrew Bonventre
Родитель 9a1fb33cac
Коммит dec9db9ed0
10 изменённых файлов: 143 добавлений и 86 удалений

Просмотреть файл

@ -1 +1,2 @@
arrowParens: avoid
singleQuote: true

Просмотреть файл

@ -13,25 +13,7 @@
<link href="/static/css/stylesheet.css?version={{.AppVersionLabel}}" rel="stylesheet">
<link href="/third_party/dialog-polyfill/dialog-polyfill.css?version={{.AppVersionLabel}}" rel="stylesheet">
<title>{{if .HTMLTitle}}{{.HTMLTitle}} · {{end}}go.dev</title>
{{if not .DevMode}}
<!-- Google Tag Manager -->
<script nonce="{{.Nonce}}">
(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','{{.GoogleTagManagerContainerID}}');
</script>
<!-- End Google Tag Manager -->
{{end}}
<script nonce="{{.Nonce}}" src="/static/js/base.min.js?version={{.AppVersionLabel}}"></script>
<body class="Site">
{{if not .DevMode}}
<!-- Google Tag Manager (noscript) -->
<noscript><iframe nonce="{{.Nonce}}" src="https://www.googletagmanager.com/ns.html?id={{.GoogleTagManagerContainerID}}"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->
{{end}}
<header class="Site-header Site-header--dark">
<div class="Header">
<nav class="Header-nav">
@ -185,6 +167,12 @@
</div>
</footer>
{{block "post_content" .}}{{end}}
{{if not .DevMode}}
<script nonce="{{.Nonce}}" async src="https://www.googletagmanager.com/gtm.js?id={{.GoogleTagManagerContainerID}}"></script>
<noscript><iframe nonce="{{.Nonce}}" src="https://www.googletagmanager.com/ns.html?id={{.GoogleTagManagerContainerID}}"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
{{end}}
<script nonce="{{.Nonce}}" src="/static/js/base.min.js?version={{.AppVersionLabel}}"></script>
{{if (.Experiments.IsActive "autocomplete")}}
<script nonce="{{.Nonce}}" src="/third_party/autoComplete.js/autoComplete.min.js?version={{.AppVersionLabel}}"></script>
<script nonce="{{.Nonce}}" src="/static/js/completion.min.js?version={{.AppVersionLabel}}"></script>

Просмотреть файл

@ -0,0 +1,14 @@
/**
* @license
* Copyright 2019-2020 The Go Authors. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
(function setupGoogleTagManager() {
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
'gtm.start': new Date().getTime(),
event: 'gtm.js',
});
})();

10
content/static/js/base.min.js поставляемый
Просмотреть файл

@ -1,8 +1,8 @@
/*
Copyright 2019 The Go Authors. All rights reserved.
Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file.
Copyright 2019-2020 The Go Authors. All rights reserved.
Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file.
*/
(function(){(function(){var b=document.querySelector(".js-header"),a=document.querySelectorAll(".js-headerMenuButton");a.forEach(function(a){a.addEventListener("click",function(c){c.preventDefault();b.classList.toggle("is-active");a.setAttribute("aria-expanded",b.classList.contains("is-active"))})});var c=document.querySelector(".js-scrim");c&&c.hasOwnProperty("addEventListener")&&c.addEventListener("click",function(c){c.preventDefault();b.classList.remove("is-active");a.forEach(function(a){a.setAttribute("aria-expanded",
b.classList.contains("is-active"))})})})()})();window.addEventListener("load",function(){for(var b=document.getElementsByClassName("js-feedbackButton"),a=0;a<b.length;a++)b[a].addEventListener("click",sendFeedback)});function sendFeedback(){userfeedback.api.startFeedback({productId:"5131929",bucket:"Default"})};
(function(){var b=document.querySelector(".js-header"),c=document.querySelectorAll(".js-headerMenuButton");c.forEach(function(d){d.addEventListener("click",function(a){a.preventDefault();b.classList.toggle("is-active");d.setAttribute("aria-expanded",b.classList.contains("is-active"))})});var a=document.querySelector(".js-scrim");a&&a.hasOwnProperty("addEventListener")&&a.addEventListener("click",function(a){a.preventDefault();b.classList.remove("is-active");c.forEach(function(a){a.setAttribute("aria-expanded",
b.classList.contains("is-active"))})})})();(function(){window.dataLayer=window.dataLayer||[];window.dataLayer.push({"gtm.start":(new Date).getTime(),event:"gtm.js"})})();

Просмотреть файл

@ -1,10 +1,11 @@
/** @license
Copyright 2019 The Go Authors. All rights reserved.
Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file.
*/
/**
* @license
* Copyright 2019-2020 The Go Authors. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
document.addEventListener('DOMContentLoaded', function() {
document.addEventListener('DOMContentLoaded', () => {
// To implement autocomplete we use autoComplete.js, but override the
// navigation controller to be more accessible.
//
@ -78,7 +79,7 @@ document.addEventListener('DOMContentLoaded', function() {
results: resultsValues.list.map(record => record.value),
selection: resultsValues.list.find(
value => value.index === Number(elem.getAttribute('data-id'))
)
),
});
hideCompletion();
};
@ -87,7 +88,7 @@ document.addEventListener('DOMContentLoaded', function() {
ENTER: 13,
ESCAPE: 27,
ARROW_UP: 38,
ARROW_DOWN: 40
ARROW_DOWN: 40,
};
let next = undefined; // the next item to highlight
if (lis.length > 0) {
@ -158,7 +159,7 @@ document.addEventListener('DOMContentLoaded', function() {
// The string we're completing is stored in the 'PackagePath' field of
// the returned JSON array elements.
key: ['PackagePath'],
cache: false
cache: false,
},
threshold: 1, // minimum number of characters before rendering results
debounce: 100, // in milliseconds
@ -172,7 +173,7 @@ document.addEventListener('DOMContentLoaded', function() {
destination: document.querySelector('#AutoComplete-parent'),
position: 'beforeend',
element: 'ul',
navigation: navigation
navigation: navigation,
},
highlight: true,
selector: '#AutoComplete',
@ -180,8 +181,8 @@ document.addEventListener('DOMContentLoaded', function() {
if (feedback.selection.value.PackagePath) {
// Navigate directly to the package.
// TODO (b/149016238): update ARIA attributes to reflect this.
window.location.href = "/" + feedback.selection.value.PackagePath;
window.location.href = '/' + feedback.selection.value.PackagePath;
}
}
},
});
});

6
content/static/js/completion.min.js поставляемый
Просмотреть файл

@ -1,8 +1,8 @@
/*
Copyright 2019 The Go Authors. All rights reserved.
Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file.
Copyright 2019-2020 The Go Authors. All rights reserved.
Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file.
*/
var $jscomp=$jscomp||{};$jscomp.scope={};$jscomp.arrayIteratorImpl=function(a){var b=0;return function(){return b<a.length?{done:!1,value:a[b++]}:{done:!0}}};$jscomp.arrayIterator=function(a){return{next:$jscomp.arrayIteratorImpl(a)}};$jscomp.makeIterator=function(a){var b="undefined"!=typeof Symbol&&Symbol.iterator&&a[Symbol.iterator];return b?b.call(a):$jscomp.arrayIterator(a)};
$jscomp.getGlobal=function(a){a=["object"==typeof window&&window,"object"==typeof self&&self,"object"==typeof global&&global,a];for(var b=0;b<a.length;++b){var d=a[b];if(d&&d.Math==Math)return d}return globalThis};$jscomp.global=$jscomp.getGlobal(this);$jscomp.ASSUME_ES5=!1;$jscomp.ASSUME_NO_NATIVE_MAP=!1;$jscomp.ASSUME_NO_NATIVE_SET=!1;$jscomp.SIMPLE_FROUND_POLYFILL=!1;

Просмотреть файл

@ -1,8 +1,9 @@
/** @license
Copyright 2019 The Go Authors. All rights reserved.
Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file.
*/
/**
* @license
* Copyright 2019-2020 The Go Authors. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
// This file implements the behavior of the "jump to identifer" dialog for Go
// package documentation, as well as the simple dialog that displays keyboard
@ -51,10 +52,14 @@ function collectJumpListItems() {
}
// Clicking on any of the links closes the dialog.
for (const item of items) {
item.link.addEventListener('click', function() { jumpDialog.close(); });
item.link.addEventListener('click', function () {
jumpDialog.close();
});
}
// Sort case-insensitively by identifier name.
items.sort(function (a, b) { return a.lower.localeCompare(b.lower); });
items.sort(function (a, b) {
return a.lower.localeCompare(b.lower);
});
return items;
}
@ -77,7 +82,6 @@ function collectJumpListItemsFallback(doc) {
return items;
}
// newJumpListItem creates a new item for the DOM element el.
// An item is an object with:
// - name: the element's id (which is the identifer name)
@ -127,8 +131,8 @@ function guessKind(el) {
}
}
let lastFilterValue; // The last contents of the filter text box.
let activeJumpItem = -1; // The index of the currently active item in the list.
let lastFilterValue; // The last contents of the filter text box.
let activeJumpItem = -1; // The index of the currently active item in the list.
// updateJumpList sets the elements of the dialog list to
// everything whose name contains filter.
@ -146,12 +150,17 @@ function updateJumpList(filter) {
// Make a regexp corresponding to filter. The result will match any string
// containing filter, case-insensitively. Escape the regexp metacharacters in
// filter.
const re = new RegExp(filter.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, '\\$1'), 'gi');
const re = new RegExp(
filter.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, '\\$1'),
'gi'
);
for (const item of jumpListItems) {
var name = item.name;
if (filter) {
// Boldify the substring of name matching the filter.
name = name.replace(re, function (s) { return '<b>' + s + '</b>'; });
name = name.replace(re, function (s) {
return '<b>' + s + '</b>';
});
if (name == item.name) {
// We didn't change name, so it didn't match the filter.
continue;
@ -211,7 +220,7 @@ function incActiveJumpItem(delta) {
}
// Pressing a key in the filter updates the list (if the filter actually changed).
jumpFilter.addEventListener('keyup', function(event) {
jumpFilter.addEventListener('keyup', function (event) {
if (jumpFilter.value.toUpperCase() != lastFilterValue.toUpperCase()) {
updateJumpList(jumpFilter.value);
}
@ -219,7 +228,7 @@ jumpFilter.addEventListener('keyup', function(event) {
// Pressing enter in the filter selects the first element in the list.
// TODO(b/143454398) add arrow keys and track the active list element.
jumpFilter.addEventListener('keydown', function(event) {
jumpFilter.addEventListener('keydown', function (event) {
const upArrow = 38;
const downArrow = 40;
const enterKey = 13;
@ -245,7 +254,6 @@ if (!shortcutsDialog.showModal) {
dialogPolyfill.registerDialog(shortcutsDialog);
}
// Keyboard shortcuts:
// - Pressing 'f' or 'F' opens the jump-to-identifier dialog.
// - Pressing '?' opens up the shortcut dialog.
@ -254,7 +262,7 @@ if (!shortcutsDialog.showModal) {
document.addEventListener('keypress', function (e) {
if (jumpDialog.open || shortcutsDialog.open) return;
const t = e.target.tagName;
if (t == 'INPUT' || t == 'SELECT' || t == 'TEXTAREA' ) return;
if (t == 'INPUT' || t == 'SELECT' || t == 'TEXTAREA') return;
if (e.target.contentEditable && e.target.contentEditable == 'true') return;
if (e.metaKey || e.ctrlKey) return;
const ch = String.fromCharCode(e.which);

6
content/static/js/jump.min.js поставляемый
Просмотреть файл

@ -1,8 +1,8 @@
/*
Copyright 2019 The Go Authors. All rights reserved.
Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file.
Copyright 2019-2020 The Go Authors. All rights reserved.
Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file.
*/
var $jscomp=$jscomp||{};$jscomp.scope={};$jscomp.arrayIteratorImpl=function(b){var c=0;return function(){return c<b.length?{done:!1,value:b[c++]}:{done:!0}}};$jscomp.arrayIterator=function(b){return{next:$jscomp.arrayIteratorImpl(b)}};$jscomp.makeIterator=function(b){var c="undefined"!=typeof Symbol&&Symbol.iterator&&b[Symbol.iterator];return c?c.call(b):$jscomp.arrayIterator(b)};
(function(b,c){"object"===typeof exports&&"undefined"!==typeof module?module.exports=c():"function"===typeof define&&define.amd?define(c):(b=b||self,b.dialogPolyfill=c())})(this,function(){function b(a){for(;a&&a!==document.body;){var h=window.getComputedStyle(a),b=function(a,b){return!(void 0===h[a]||h[a]===b)};if(1>h.opacity||b("zIndex","auto")||b("transform","none")||b("mixBlendMode","normal")||b("filter","none")||b("perspective","none")||"isolate"===h.isolation||"fixed"===h.position||"touch"===

Просмотреть файл

@ -1,43 +1,40 @@
/** @license
Copyright 2019 The Go Authors. All rights reserved.
Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file.
*/
/**
* @license
* Copyright 2019-2020 The Go Authors. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
/**
* A bit of navigation related code for handling dismissible elements.
*/
(function() {
(function registerHeaderListeners() {
'use strict';
function registerHeaderListeners() {
const header = document.querySelector('.js-header');
const menuButtons = document.querySelectorAll('.js-headerMenuButton');
menuButtons.forEach(button => {
button.addEventListener('click', e => {
e.preventDefault();
header.classList.toggle('is-active');
const header = document.querySelector('.js-header');
const menuButtons = document.querySelectorAll('.js-headerMenuButton');
menuButtons.forEach(button => {
button.addEventListener('click', e => {
e.preventDefault();
header.classList.toggle('is-active');
button.setAttribute(
'aria-expanded',
header.classList.contains('is-active')
);
});
});
const scrim = document.querySelector('.js-scrim');
if (scrim && scrim.hasOwnProperty('addEventListener')) {
scrim.addEventListener('click', e => {
e.preventDefault();
header.classList.remove('is-active');
menuButtons.forEach(button => {
button.setAttribute(
'aria-expanded',
header.classList.contains('is-active')
);
});
});
const scrim = document.querySelector('.js-scrim');
if (scrim && scrim.hasOwnProperty('addEventListener')) {
scrim.addEventListener('click', e => {
e.preventDefault();
header.classList.remove('is-active');
menuButtons.forEach(button => {
button.setAttribute(
'aria-expanded',
header.classList.contains('is-active')
);
});
});
}
}
registerHeaderListeners();
})();

48
devtools/compile_js.sh Executable file
Просмотреть файл

@ -0,0 +1,48 @@
#!/usr/bin/env -S bash -e
# Copyright 2019 The Go Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# Use the Google Closure Compiler to minimize and concatenate
# our JavasScript.
# With -check, it checks that the source files are not newer
# than the compiled ones instead.
source scripts/lib.sh || { echo "Are you at repo root?"; exit 1; }
JSDIR=content/static/js
# compile OUTFILE INFILE1 INFILE2 ...
compile() {
local outfile=$1
shift
rm -f $outfile
docker run --rm -i femtopixel/google-closure-compiler-app:v20200112 < <(cat $@) > $outfile
echo "wrote $outfile"
}
check() {
local outfile=$1
shift
for infile in $@; do
if [[ $infile -nt $outfile ]]; then
echo "$infile is newer than $outfile; run scripts/compile_js.sh"
exit 1
fi
done
echo "checked $outfile"
}
main() {
local cmd=compile
if [[ $1 = "-check" ]]; then
cmd=check
fi
$cmd $JSDIR/base.min.js $JSDIR/{site,analytics}.js
# TODO: once this is not an experiment, add it to the line above.
$cmd $JSDIR/completion.min.js $JSDIR/completion.js
$cmd $JSDIR/jump.min.js third_party/dialog-polyfill/dialog-polyfill.js $JSDIR/jump.js
}
main $@