Skip to content

Commit b037a75

Browse files
jbashjbash
jbash
andauthored
Serve static third-party code from local codeworld server (download at build time) (#1412)
* Untested first whack at removing use of static remote resources * Dynamically mirror code at install time to comply with Google third-party redistribution policies * Prevent Git from suggesting checking in mirrored third-party code * Eliminate some missed references to cdn.materialdesignicons.com * Pick up missing font file from materialdesignicons.com * Mirror more missing font stuff from materialdesignicons.com * Freeze checksums of mirrored code * Changes related to discussion in PR #1412 + Mirror static code into $BUILD/mirrored instead of $top/mirrored. + Do mirroring in build.sh instead of install.sh + Rename top-level directory from "mirrored" (primarily a place where mirrored material goes) to "mirror" (a place for mirroring code and control data). + Eliminate .gitignore from "mirror" directory (it was confusing and anyway it's obviated by the directory naming changes) + Make it easier/safer to run the mirroring script interactively; in particular, it should now work from any directory within the CodeWorld tree, and it runs base.sh to get $BUILD if it's not already in the environment. + Re-download mirrored files more than 30 days old to make it evident if the upstream source has changed or withdrawn a file. Co-authored-by: jbash aka John Bashinski <[email protected]>
1 parent fb5ffcb commit b037a75

File tree

11 files changed

+182
-27
lines changed

11 files changed

+182
-27
lines changed

.githooks/pre-commit

+11-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
11
#!/bin/bash
2-
set -euo pipefail
32

4-
FILES_PRETTIER=$(git diff --cached --name-only --diff-filter=ACMR "*.js" "*.css" "*.html" "*.json" | sed 's| |\\ |g')
5-
FILES_ESLINT=$(git diff --cached --name-only --diff-filter=ACMR "*.js" | sed 's| |\\ |g')
6-
FILES_ORMOLU=$(git diff --cached --name-only --diff-filter=ACMR "*.hs" | sed 's| |\\ |g')
3+
FILES_PRETTIER=$(git diff --cached --name-only --diff-filter=ACMR "*.js" "*.css" "*.html" "*.json" | \
4+
sed 's| |\\ |g' | \
5+
grep -v '^third_party/')
6+
FILES_ESLINT=$(git diff --cached --name-only --diff-filter=ACMR "*.js" | \
7+
sed 's| |\\ |g' | \
8+
grep -v '^third_party/')
9+
FILES_ORMOLU=$(git diff --cached --name-only --diff-filter=ACMR "*.hs" | \
10+
sed 's| |\\ |g' | \
11+
grep -v '^third_party/')
12+
13+
set -euo pipefail
714

815
if [ -n "$FILES_PRETTIER" ]
916
then

build.sh

+5
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ cwd=$(pwd)
1818

1919
source base.sh
2020

21+
# Locally mirror various third-party JavaScript, CSS, etc, so that we don't
22+
# have to have user's browsers retrieve code from random remote locations.
23+
24+
run . mirror/get_mirrored
25+
2126
# Install the codeworld-base and codeworld-api packages
2227
run . cabal_install --ghcjs ./codeworld-prediction \
2328
./codeworld-error-sanitizer \

mirror/get_mirrored

+130
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
#!/bin/bash
2+
# This script is normally invoked from build.sh, but can be run
3+
# interactively from anywhere in the CodeWorld source tree.
4+
#
5+
# It mirrors static content from various places on the Web and puts it
6+
# in subdirectories of "${BUILD}/mirrored", which is in turn linked
7+
# into the CodeWorld "web" hierarchy, where the mirrored files are
8+
# available to be loaded from our own Web server instead of having
9+
# pages retrieve a lot of static content from "remote" sources.
10+
#
11+
# The files are checksummed to make sure the content matches
12+
# what's expected.
13+
#
14+
15+
## Configuration variables
16+
17+
# These are the URLS to be copied in.
18+
TO_MIRROR=(
19+
'http://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css'
20+
'http://code.jquery.com/jquery-2.2.4.min.js'
21+
'http://code.jquery.com/jquery-1.12.4.min.js'
22+
'http://code.jquery.com/jquery-1.12.4.js'
23+
'http://code.jquery.com/ui/1.12.0/jquery-ui.min.js'
24+
'http://cdn.materialdesignicons.com/3.6.95/css/materialdesignicons.min.css'
25+
'http://cdn.materialdesignicons.com/3.6.95/fonts/materialdesignicons-webfont.ttf'
26+
'http://cdn.materialdesignicons.com/3.6.95/fonts/materialdesignicons-webfont.woff2'
27+
'http://casual-effects.com/markdeep/latest/markdeep.min.js'
28+
'http://cdnjs.cloudflare.com/ajax/libs/jquery-layout/1.4.3/jquery.layout_and_plugins.min.js'
29+
'http://cdnjs.cloudflare.com/ajax/libs/limonte-sweetalert2/7.19.2/sweetalert2.all.min.js'
30+
'http://cdnjs.cloudflare.com/ajax/libs/jqtree/1.4.10/tree.jquery.js'
31+
'http://cdn.jsdelivr.net/npm/[email protected]/dist/promise.min.js'
32+
)
33+
34+
# Files that are already in the build tree aren't normally
35+
# re-downloaded... except that files older than "MAX_DAYS" are
36+
# deleted and treated as if they hadn't existed. If the original
37+
# source has withdrawn or modifieda file, there'll be a download error
38+
# a checksum error, which may alert a maintainer or admin to a change
39+
# that needs to be dealt with.
40+
MAX_DAYS=30
41+
42+
# The "frozen" hash file may be checked into git to force the checksums expected
43+
# for mirrored files starting from the very first download of each file. If a file
44+
# isn't listed, any checksum will be accepted on the first download, but any subsequent
45+
# downloads must have the same checksum (until the file is removed from the list of
46+
# cached hashes).
47+
#
48+
FROZEN_HASHES="sums.txt.frozen" # In the script directory, if it exists
49+
CACHED_HASHES="sums.txt" # In the mirrorored directory (location computed below)
50+
51+
## Global shell behavior
52+
shopt -s extglob
53+
54+
## Prelimininaries, mostly to make it convenient to run this script
55+
## interactively for administrative or debugging purproses. Also
56+
## does a couple of minor sanity checks on the build tree.
57+
58+
# Where is this script?
59+
script_dir="${0%/*}"
60+
61+
# We may be run interactively from unpredictable places, so have a way
62+
# of guessing the root of the CodeWorld source tree if we need it
63+
cw_base() {
64+
if [ -z "${cw_base}" ]; then
65+
if [ -f "base.sh" ]; then
66+
cw_base="$(pwd)"
67+
elif cw_base="$(cd "$(git rev-parse --show-cdup)"; pwd)" && [ -f "${cw_base}/base.sh" ]; then
68+
:
69+
else
70+
echo "Can't find root of Codeworld source tree" 1>&2
71+
exit 1
72+
fi
73+
fi
74+
echo "${cw_base}"
75+
return
76+
}
77+
78+
# Find the build directory. Normally this will be passed to us from
79+
# build.sh.
80+
if [ -z "${BUILD}" ]; then
81+
pushd "$(cw_base)" > /dev/null
82+
. base.sh
83+
popd > /dev/null
84+
if [ -z "${BUILD}" ]; then
85+
BUILD="$(cw_base)/build"
86+
if [ ! -d "${BUILD}" ]; then
87+
echo "Won't create build directory in a guessed location (${BUILD})" 1>&2
88+
exit 1
89+
fi
90+
fi
91+
fi
92+
93+
## The meat of the script
94+
95+
mirror_dir="${BUILD}/mirrored"
96+
mkdir -p "${mirror_dir}" || exit 1
97+
98+
cached_hash_file="${mirror_dir}/${CACHED_HASHES}"
99+
frozen_hash_file="${script_dir}/${FROZEN_HASHES}"
100+
if [ ! -e "${cached_hash_file}" ]; then
101+
if [ -f "${frozen_hash_file}" ]; then
102+
cp "${frozen_hash_file}" "${cached_hash_file}" || exit 1
103+
else
104+
touch "${cached_hash_file}"
105+
fi
106+
fi
107+
108+
# Now do the actual work
109+
exitstat=0
110+
111+
for url in "${TO_MIRROR[@]}"; do
112+
file_relative=".${url#http?(s):/}"
113+
file="${mirror_dir}/${file_relative}"
114+
[ -e "${file}" ] && (find "${file}" -type f -mtime "+${MAX_DAYS}" -print0 | xargs -0 -r rm) || exitstat=1
115+
[ -f "${file}" ] || \
116+
wget --no-verbose --no-use-server-timestamps \
117+
--directory-prefix="${mirror_dir}" --force-directories "${url}" || \
118+
exitstat=1
119+
if ! (sed 's/[^ ]* *//' "${cached_hash_file}" | grep -F -x -q "${file_relative}"); then
120+
echo "Warning: First download of ${url}; adding hash to ${cached_hash_file}"
121+
(cd "${mirror_dir}"; sha256sum "${file_relative}") >> "${cached_hash_file}" || exitstat=1
122+
fi
123+
done
124+
125+
if ! (cd "${mirror_dir}"; sha256sum --quiet --check -) < "${cached_hash_file}"; then
126+
exitstat="$?"
127+
echo "DANGER: Validation failed for downloaded third-party code; tampered with?" 1>&2
128+
fi
129+
130+
exit "${exitstat}"

mirror/sums.txt.frozen

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
f9b751c1cd0d2b0f91862db987fed9dda48758b15e6f42ca67796b45f4b21702 ./ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css
2+
05b85d96f41fff14d8f608dad03ab71e2c1017c2da0914d7c59291bad7a54f8e ./code.jquery.com/jquery-2.2.4.min.js
3+
668b046d12db350ccba6728890476b3efee53b2f42dbb84743e5e9f1ae0cc404 ./code.jquery.com/jquery-1.12.4.min.js
4+
430f36f9b5f21aae8cc9dca6a81c4d3d84da5175eaedcf2fdc2c226302cb3575 ./code.jquery.com/jquery-1.12.4.js
5+
78613a6e5bab939b078feae691fb0661e2b2671dcce1b1be66517203b2a7b3b1 ./code.jquery.com/ui/1.12.0/jquery-ui.min.js
6+
a3f3c57f087b8635419218cc25ee2633b6e142e3d7f39c5ab7e0b19565bd74ca ./cdn.materialdesignicons.com/3.6.95/css/materialdesignicons.min.css
7+
e6f4238d686c77e6b6c7f4bd55aba73460d75a7c3ccd920ac96c4914daf82dcc ./casual-effects.com/markdeep/latest/markdeep.min.js
8+
5bde9a452e5284dc2b7e2b58eaeb84ac1dff3e4225804ca6fb20a93611eeed72 ./cdnjs.cloudflare.com/ajax/libs/jquery-layout/1.4.3/jquery.layout_and_plugins.min.js
9+
f47498ae0c01e6339476f5a719baf060e67fb7550281e3d6003e167eebb1ab8b ./cdnjs.cloudflare.com/ajax/libs/limonte-sweetalert2/7.19.2/sweetalert2.all.min.js
10+
31c462810097490230f49b879d7a568b5504b46ec46e37fd23deb4469fd705c3 ./cdnjs.cloudflare.com/ajax/libs/jqtree/1.4.10/tree.jquery.js
11+
ba13d5eaf44e07573d61242a1073f62f6b20aa6e0b6b8284cc7681d6941ad40f ./cdn.jsdelivr.net/npm/[email protected]/dist/promise.min.js
12+
7b0a4e3df95dc4b534adbeb68e19b0fb76b2de22586c9f9c76528f2c1c323642 ./cdn.materialdesignicons.com/3.6.95/fonts/materialdesignicons-webfont.ttf
13+
eab044658fa11dd5af66c4ec56766eb9162779692a9dd87fc33822dc67d2f29b ./cdn.materialdesignicons.com/3.6.95/fonts/materialdesignicons-webfont.woff2

web/blocks.html

+7-7
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
<link rel="stylesheet" href="css/directoryTree.css" />
2929
<link
3030
rel="stylesheet"
31-
href="//cdn.materialdesignicons.com/3.6.95/css/materialdesignicons.min.css"
31+
href="mirrored/cdn.materialdesignicons.com/3.6.95/css/materialdesignicons.min.css"
3232
/>
3333
</head>
3434

@@ -159,7 +159,7 @@
159159
<script language="javascript" src="js/blocks_rts.js"></script>
160160
<script language="javascript" src="js/blocks_lib.js"></script>
161161
<script language="javascript" src="js/blocks_out.js"></script>
162-
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
162+
<script src="mirrored/code.jquery.com/jquery-2.2.4.min.js"></script>
163163

164164
<script src="blockly/blockly_compressed.js"></script>
165165
<script src="blockly/blocks/lists.js"></script>
@@ -180,22 +180,22 @@
180180
<script src="blockly/msg/js/en.js"></script>
181181

182182
<script
183-
src="https://code.jquery.com/jquery-1.12.4.min.js"
183+
src="mirrored/code.jquery.com/jquery-1.12.4.min.js"
184184
integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ="
185185
crossorigin="anonymous"
186186
></script>
187187
<script
188-
src="https://code.jquery.com/ui/1.12.0/jquery-ui.min.js"
188+
src="mirrored/code.jquery.com/ui/1.12.0/jquery-ui.min.js"
189189
integrity="sha256-eGE6blurk5sHj+rmkfsGYeKyZx3M4bG+ZlFyA7Kns7E="
190190
crossorigin="anonymous"
191191
></script>
192192
<script
193193
type="text/javascript"
194-
src="https://cdnjs.cloudflare.com/ajax/libs/jquery-layout/1.4.3/jquery.layout_and_plugins.min.js"
194+
src="mirrored/cdnjs.cloudflare.com/ajax/libs/jquery-layout/1.4.3/jquery.layout_and_plugins.min.js"
195195
></script>
196196
<script
197197
type="text/javascript"
198-
src="https://cdnjs.cloudflare.com/ajax/libs/jqtree/1.4.10/tree.jquery.js"
198+
src="mirrored/cdnjs.cloudflare.com/ajax/libs/jqtree/1.4.10/tree.jquery.js"
199199
></script>
200200
<script type="text/javascript">
201201
window.mainLayout = $(".ui-layout-container").layout({
@@ -230,7 +230,7 @@
230230
<script type="text/javascript" src="js/codeworld-mode.js"></script>
231231
<script
232232
type="text/javascript"
233-
src="https://cdn.jsdelivr.net/npm/[email protected]/dist/promise.min.js"
233+
src="mirrored/cdn.jsdelivr.net/npm/[email protected]/dist/promise.min.js"
234234
></script>
235235

236236
<xml id="toolbox" style="display: none;">

web/css/blockly.css

+2-3
Original file line numberDiff line numberDiff line change
@@ -326,8 +326,7 @@
326326

327327
.blocklyWidgetDiv .goog-option-selected .goog-menuitem-checkbox,
328328
.blocklyWidgetDiv .goog-option-selected .goog-menuitem-icon {
329-
background: url(https://blockly-demo.appspot.com/static/media/sprites.png)
330-
no-repeat -48px -16px !important;
329+
background: url(../blockly/media/sprites.png) no-repeat -48px -16px !important;
331330
}
332331

333332
.blocklyToolboxDiv {
@@ -395,7 +394,7 @@
395394
}
396395

397396
.blocklyTreeIcon {
398-
background-image: url(https://blockly-demo.appspot.com/static/media/sprites.png);
397+
background-image: url(../blockly/media/sprites.png);
399398
height: 16px;
400399
vertical-align: middle;
401400
width: 16px;

web/doc.html

+4-4
Original file line numberDiff line numberDiff line change
@@ -25,23 +25,23 @@
2525
};
2626
</script>
2727
<script
28-
src="https://casual-effects.com/markdeep/latest/markdeep.min.js"
28+
src="mirrored/casual-effects.com/markdeep/latest/markdeep.min.js"
2929
charset="UTF-8"
3030
></script>
3131
<script
32-
src="https://code.jquery.com/jquery-1.12.4.min.js"
32+
src="mirrored/code.jquery.com/jquery-1.12.4.min.js"
3333
integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ="
3434
crossorigin="anonymous"
3535
></script>
3636
<script
37-
src="https://code.jquery.com/ui/1.12.0/jquery-ui.min.js"
37+
src="mirrored/code.jquery.com/ui/1.12.0/jquery-ui.min.js"
3838
integrity="sha256-eGE6blurk5sHj+rmkfsGYeKyZx3M4bG+ZlFyA7Kns7E="
3939
crossorigin="anonymous"
4040
></script>
4141
<title>CodeWorld</title>
4242
<link
4343
rel="stylesheet"
44-
href="//cdn.materialdesignicons.com/3.6.95/css/materialdesignicons.min.css"
44+
href="mirrored/cdn.materialdesignicons.com/3.6.95/css/materialdesignicons.min.css"
4545
/>
4646
<link
4747
rel="stylesheet"

web/env.html

+7-7
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,11 @@
3232
<link rel="stylesheet" href="css/directoryTree.css" />
3333
<link
3434
rel="stylesheet"
35-
href="//cdn.materialdesignicons.com/3.6.95/css/materialdesignicons.min.css"
35+
href="mirrored/cdn.materialdesignicons.com/3.6.95/css/materialdesignicons.min.css"
3636
/>
3737
<link
3838
rel="stylesheet"
39-
href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css"
39+
href="mirrored/ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css"
4040
/>
4141
</head>
4242

@@ -166,22 +166,22 @@
166166
</div>
167167

168168
<script
169-
src="https://code.jquery.com/jquery-1.12.4.min.js"
169+
src="mirrored/code.jquery.com/jquery-1.12.4.min.js"
170170
integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ="
171171
crossorigin="anonymous"
172172
></script>
173173
<script
174-
src="https://code.jquery.com/ui/1.12.0/jquery-ui.min.js"
174+
src="mirrored/code.jquery.com/ui/1.12.0/jquery-ui.min.js"
175175
integrity="sha256-eGE6blurk5sHj+rmkfsGYeKyZx3M4bG+ZlFyA7Kns7E="
176176
crossorigin="anonymous"
177177
></script>
178178
<script
179179
type="text/javascript"
180-
src="https://cdnjs.cloudflare.com/ajax/libs/jquery-layout/1.4.3/jquery.layout_and_plugins.min.js"
180+
src="mirrored/cdnjs.cloudflare.com/ajax/libs/jquery-layout/1.4.3/jquery.layout_and_plugins.min.js"
181181
></script>
182182
<script
183183
type="text/javascript"
184-
src="https://cdnjs.cloudflare.com/ajax/libs/jqtree/1.4.10/tree.jquery.js"
184+
src="mirrored/cdnjs.cloudflare.com/ajax/libs/jqtree/1.4.10/tree.jquery.js"
185185
></script>
186186
<script type="text/javascript">
187187
window.mainLayout = $(".ui-layout-container").layout({
@@ -243,7 +243,7 @@
243243
<script type="module" src="js/codeworld.js"></script>
244244
<script
245245
type="text/javascript"
246-
src="https://cdn.jsdelivr.net/npm/[email protected]/dist/promise.min.js"
246+
src="mirrored/cdn.jsdelivr.net/npm/[email protected]/dist/promise.min.js"
247247
></script>
248248
<script async src="js/diff.min.js"></script>
249249
</body>

web/gallery.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<head>
44
<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=default,Array.prototype.find,Number.isFinite,Number.isInteger,console,console.log,document.head,performance.now"></script>
55
<title>CodeWorld Gallery</title>
6-
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
6+
<script src="mirrored/code.jquery.com/jquery-1.12.4.js"></script>
77
<style type="text/css">
88
body {
99
background-color: #222222;

web/js/utils/alert.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import { encode } from './html.js';
1919
async function init() {
2020
return Promise.resolve(
2121
$.getScript(
22-
'https://cdnjs.cloudflare.com/ajax/libs/limonte-sweetalert2/7.19.2/sweetalert2.all.min.js'
22+
'../../mirrored/cdnjs.cloudflare.com/ajax/libs/limonte-sweetalert2/7.19.2/sweetalert2.all.min.js'
2323
)
2424
).catch((e) => console.log('Alert.init failed'));
2525
}

web/mirrored

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../build/mirrored

0 commit comments

Comments
 (0)