1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
#!/usr/bin/env bash
: <<'COMMENT'
Download the front-end libraries the web UI embeds, into web/vendor/.
Usage:
./vendor.sh download the versions pinned below into web/vendor/
./vendor.sh --outdated compare the pinned versions with the published ones
(changes nothing)
To update a library: run --outdated, change its version below, run
./vendor.sh, check the UI (go run ./cmd/server …), then commit web/vendor/.
web/vendor/ is committed: go:embed needs it at build time, and a checkout
(or a CI job) must build without network access to npm. The page loads
nothing from the network: everything it uses is in the binary.
web/vendor/monaco/vs/ the Monaco editor (AMD build), without its UI
translations and source maps
web/vendor/xterm/ xterm.js and its fit addon, for the terminal
web/vendor/material-icons/ the file and folder icons of the explorer
(VS Code's Material Icon Theme) and their manifest
web/vendor/tailwind/ Tailwind CSS 3, the "Play CDN" build: it generates
the CSS of the classes the page uses, in the browser
web/vendor/marked/ Markdown -> HTML, for the chat
web/vendor/highlight/ code highlighting in the chat, and its two themes
web/vendor/dompurify/ HTML sanitizer: what the agent writes is Markdown,
but the HTML marked makes of it is filtered
before it enters the page
COMMENT
set -euo pipefail
# Each version is pinned; the comment says why a newer one may not simply be
# dropped in (what --outdated reminds too).
MONACO_VERSION="0.52.2" # the last release with the AMD build and workerMain.js
XTERM_VERSION="5.5.0" # 6.x: API changes, and needs addon-fit 0.11
XTERM_FIT_VERSION="0.10.0" # the last one for xterm 5
MATERIAL_ICONS_VERSION="5.38.1"
TAILWIND_VERSION="3.4.17" # v4 has no Play CDN build; its classes differ
MARKED_VERSION="9.1.2" # later majors: check renderMarkdown in app.js
HIGHLIGHT_VERSION="11.8.0"
DOMPURIFY_VERSION="3.4.16" # a security filter: keep it current
cd "$(dirname "${BASH_SOURCE[0]}")"
VENDOR="web/vendor"
# --outdated: the npm registry's "latest" (for Tailwind, the v3 line) next to
# the pinned version. Only a report: an update is a decision, see above.
if [ "${1:-}" = "--outdated" ]; then
latest() { # package [dist-tag]
curl -fsSL "https://registry.npmjs.org/$1" -H "Accept: application/vnd.npm.install-v1+json" |
grep -o "\"${2:-latest}\":\"[^\"]*\"" | head -1 | cut -d'"' -f4
}
printf '%-24s %-10s %-10s\n' "package" "pinned" "published"
while read -r pkg pinned tag; do
published="$(latest "${pkg}" "${tag}" || echo '?')"
mark=""
[ "${published}" != "${pinned}" ] && mark=" ⬆"
printf '%-24s %-10s %-10s%s\n' "${pkg}" "${pinned}" "${published}" "${mark}"
done <<EOF
monaco-editor ${MONACO_VERSION} latest
@xterm/xterm ${XTERM_VERSION} latest
@xterm/addon-fit ${XTERM_FIT_VERSION} latest
material-icon-theme ${MATERIAL_ICONS_VERSION} latest
tailwindcss ${TAILWIND_VERSION} v3-lts
marked ${MARKED_VERSION} latest
@highlightjs/cdn-assets ${HIGHLIGHT_VERSION} latest
dompurify ${DOMPURIFY_VERSION} latest
EOF
echo ""
echo "The comments next to the versions in $0 say which updates need more than a version bump."
exit 0
fi
TMP="$(mktemp -d)"
trap 'rm -rf "${TMP}"' EXIT
# fetch downloads an npm package tarball and unpacks it into $TMP/<name>.
fetch() {
local pkg=$1 version=$2 name=$3
local base="${pkg##*/}"
echo "📥 ${pkg}@${version}"
mkdir -p "${TMP}/${name}"
curl -fsSL "https://registry.npmjs.org/${pkg}/-/${base}-${version}.tgz" |
tar xz -C "${TMP}/${name}" --strip-components=1
}
fetch monaco-editor "${MONACO_VERSION}" monaco
fetch @xterm/xterm "${XTERM_VERSION}" xterm
fetch @xterm/addon-fit "${XTERM_FIT_VERSION}" xterm-fit
fetch material-icon-theme "${MATERIAL_ICONS_VERSION}" material-icons
fetch tailwindcss "${TAILWIND_VERSION}" tailwind # for its LICENSE only
fetch marked "${MARKED_VERSION}" marked
fetch @highlightjs/cdn-assets "${HIGHLIGHT_VERSION}" highlight
fetch dompurify "${DOMPURIFY_VERSION}" dompurify
# The Play CDN build of Tailwind is not in the npm package: it is only
# published on cdn.tailwindcss.com, one URL per version.
echo "📥 cdn.tailwindcss.com/${TAILWIND_VERSION}"
curl -fsSL "https://cdn.tailwindcss.com/${TAILWIND_VERSION}" -o "${TMP}/tailwind.js"
rm -rf "${VENDOR}"
mkdir -p "${VENDOR}"/{monaco,xterm,material-icons,tailwind,marked,highlight,dompurify}
cp -R "${TMP}/monaco/min/vs" "${VENDOR}/monaco/vs"
# English only: the other UI languages weigh 2 MB and are never loaded.
rm -f "${VENDOR}"/monaco/vs/nls.messages.*.js
find "${VENDOR}" -name '*.map' -delete
cp "${TMP}/monaco/LICENSE" "${VENDOR}/monaco/LICENSE"
cp "${TMP}/xterm/lib/xterm.js" "${TMP}/xterm/css/xterm.css" "${TMP}/xterm/LICENSE" "${VENDOR}/xterm/"
cp "${TMP}/xterm-fit/lib/addon-fit.js" "${VENDOR}/xterm/"
# The manifest maps extensions, file and folder names to icons, as VS Code
# reads it; the explorer applies the same rules (see iconFor in app.js).
cp -R "${TMP}/material-icons/icons" "${VENDOR}/material-icons/icons"
cp "${TMP}/material-icons/dist/material-icons.json" "${TMP}/material-icons/LICENSE" "${VENDOR}/material-icons/"
cp "${TMP}/tailwind.js" "${TMP}/tailwind/LICENSE" "${VENDOR}/tailwind/"
cp "${TMP}/marked/marked.min.js" "${TMP}/marked/LICENSE.md" "${VENDOR}/marked/"
cp "${TMP}/highlight/highlight.min.js" "${TMP}/highlight/LICENSE" \
"${TMP}/highlight/styles/github.min.css" "${TMP}/highlight/styles/github-dark.min.css" \
"${VENDOR}/highlight/"
cp "${TMP}/dompurify/dist/purify.min.js" "${TMP}/dompurify/LICENSE" "${VENDOR}/dompurify/"
cat >"${VENDOR}/VERSIONS" <<EOF
monaco-editor ${MONACO_VERSION}
@xterm/xterm ${XTERM_VERSION}
@xterm/addon-fit ${XTERM_FIT_VERSION}
material-icon-theme ${MATERIAL_ICONS_VERSION}
tailwindcss ${TAILWIND_VERSION} (Play CDN build)
marked ${MARKED_VERSION}
@highlightjs/cdn-assets ${HIGHLIGHT_VERSION}
dompurify ${DOMPURIFY_VERSION}
EOF
echo "✅ ${VENDOR}: $(du -sh "${VENDOR}" | cut -f1)"
|