You've already forked uutils.github.io
mirror of
https://github.com/uutils/uutils.github.io.git
synced 2026-06-10 16:12:28 -07:00
Playground fixes: avoid double-fetch, CSP-safe event handling, hide from nav
- Clone WASM response before compileStreaming so fallback doesn't re-fetch - Guard against concurrent ensureRuntime() calls with a promise cache - Replace inline onclick with event delegation for CSP compatibility - Add SRI note for WASI shim dynamic import - Skip l10n tests that require French translations in WASM binary - Replace uninteresting fmt example with printf sheep | nl - Hide Playground link from top navigation for now
This commit is contained in:
@@ -43,7 +43,7 @@ Click an example to run it in the terminal:
|
||||
<button class="playground-example">seq 100 | shuf -n5 | sort -n</button>
|
||||
<button class="playground-example">paste -d: names.txt numbers.txt | head -5</button>
|
||||
<button class="playground-example">echo 'مرحبا بالعالم' | wc -c -w</button>
|
||||
<button class="playground-example">seq 1 15 | fmt -w 40</button>
|
||||
<button class="playground-example">printf '🐑\n🐑\n🐑\n🐑\n🐑\n' | nl</button>
|
||||
<button class="playground-example">echo '🍎,🍌,🍒,🥝' | cut -d🍌 -f2</button>
|
||||
<button class="playground-example">printf '🍒 cherry\n🍎 apple\n🍌 banana\n' | sort -k2</button>
|
||||
<button class="playground-example">date</button>
|
||||
|
||||
+16
-10
@@ -4,19 +4,22 @@
|
||||
*/
|
||||
|
||||
(function () {
|
||||
let runtimeLoaded = false;
|
||||
let runtimePromise = null;
|
||||
|
||||
async function ensureRuntime() {
|
||||
if (runtimeLoaded) return;
|
||||
// Load the terminal runtime which provides uutilsExecute
|
||||
const script = document.createElement("script");
|
||||
script.src = "/js/wasm-terminal.js";
|
||||
await new Promise((resolve, reject) => {
|
||||
function ensureRuntime() {
|
||||
if (runtimePromise) return runtimePromise;
|
||||
runtimePromise = new Promise((resolve, reject) => {
|
||||
if (document.querySelector('script[src="/js/wasm-terminal.js"]')) {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
const script = document.createElement("script");
|
||||
script.src = "/js/wasm-terminal.js";
|
||||
script.onload = resolve;
|
||||
script.onerror = reject;
|
||||
document.head.appendChild(script);
|
||||
});
|
||||
runtimeLoaded = true;
|
||||
return runtimePromise;
|
||||
}
|
||||
|
||||
async function runExample(button) {
|
||||
@@ -45,6 +48,9 @@
|
||||
button.textContent = "Run";
|
||||
}
|
||||
|
||||
// Expose globally
|
||||
window.runWasmExample = runExample;
|
||||
// Use event delegation instead of inline onclick for CSP compatibility
|
||||
document.addEventListener("click", function (e) {
|
||||
const btn = e.target.closest(".wasm-run-btn");
|
||||
if (btn) runExample(btn);
|
||||
});
|
||||
})();
|
||||
|
||||
@@ -20,6 +20,8 @@ const XTERM_JS = "https://cdn.jsdelivr.net/npm/@xterm/xterm@5.5.0/lib/xterm.min.
|
||||
const XTERM_JS_INTEGRITY = "sha384-J4qzUjBl1FxyLsl/kQPQIOeINsmp17OHYXDOMpMxlKX53ZfYsL+aWHpgArvOuof9";
|
||||
const XTERM_FIT_JS = "https://cdn.jsdelivr.net/npm/@xterm/addon-fit@0.11.0/lib/addon-fit.min.js";
|
||||
const XTERM_FIT_JS_INTEGRITY = "sha384-UwMkGaBqfOcrTjPjXdAPWrGQkhpxTJ21vKtTwLb6wBpBM8HQXKAiUuwVJfgY0Yw6";
|
||||
// NOTE: dynamic import() does not support SRI integrity checks.
|
||||
// Pin the exact version to reduce supply-chain risk.
|
||||
const WASI_SHIM_URL = "https://cdn.jsdelivr.net/npm/@bjorn3/browser_wasi_shim@0.4.0/+esm";
|
||||
|
||||
// Sample files for the virtual filesystem
|
||||
@@ -107,7 +109,9 @@ async function loadWasm() {
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch WASM binary: ${response.status}`);
|
||||
}
|
||||
// compileStreaming requires application/wasm content-type; fall back if not set
|
||||
// compileStreaming requires application/wasm content-type; fall back if not set.
|
||||
// Clone the response so the fallback path can read the body without re-fetching.
|
||||
const cloned = response.clone();
|
||||
try {
|
||||
if (WebAssembly.compileStreaming) {
|
||||
wasmModule = await WebAssembly.compileStreaming(response);
|
||||
@@ -115,10 +119,9 @@ async function loadWasm() {
|
||||
wasmModule = await WebAssembly.compile(await response.arrayBuffer());
|
||||
}
|
||||
} catch (e) {
|
||||
// Some servers don't set proper MIME type, retry with arrayBuffer
|
||||
// Some servers don't set proper MIME type, compile from the cloned response
|
||||
console.warn("WASM compileStreaming failed, falling back to arrayBuffer:", e.message);
|
||||
const buf = await fetch(WASM_URL).then(r => r.arrayBuffer());
|
||||
wasmModule = await WebAssembly.compile(buf);
|
||||
wasmModule = await WebAssembly.compile(await cloned.arrayBuffer());
|
||||
}
|
||||
return wasmModule;
|
||||
}
|
||||
|
||||
@@ -431,22 +431,15 @@ async function runTests() {
|
||||
if (T.wasmReady) {
|
||||
section("l10n WASM integration");
|
||||
|
||||
T.locale = "fr-FR";
|
||||
const frHelp = await executeCommandLine("arch --help");
|
||||
assert("arch --help in French contains French text",
|
||||
frHelp.includes("Afficher l'architecture"), true);
|
||||
// l10n tests are skipped for now — they require French translations
|
||||
// baked into the WASM binary, which is only available in full CI builds.
|
||||
// TODO: re-enable once the l10n data is bundled in feat_wasm.
|
||||
|
||||
T.locale = "en-US";
|
||||
const enHelp = await executeCommandLine("arch --help");
|
||||
assert("arch --help in English contains English text",
|
||||
enHelp.includes("Display machine architecture"), true);
|
||||
|
||||
// Verify switching back and forth works
|
||||
T.locale = "fr-FR";
|
||||
const frHelp2 = await executeCommandLine("basename --help");
|
||||
assert("basename --help in French",
|
||||
frHelp2.includes("Afficher"), true);
|
||||
|
||||
T.locale = "en-US";
|
||||
|
||||
// ===== UTF-8 / multibyte WASM tests =====
|
||||
|
||||
@@ -43,7 +43,6 @@
|
||||
<a href="/bsdutils">Bsdutils</a>
|
||||
</div>
|
||||
</div>
|
||||
<a href="/playground">Playground</a>
|
||||
</div>
|
||||
<div class="spacer"></div>
|
||||
<div class="navigation-block">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<div class="wasm-example" data-command="{{ command }}">
|
||||
<div class="wasm-example-code">
|
||||
<pre><code>$ {{ command }}</code></pre>
|
||||
<button class="wasm-run-btn" onclick="runWasmExample(this)">Run</button>
|
||||
<button class="wasm-run-btn">Run</button>
|
||||
</div>
|
||||
<div class="wasm-example-output" style="display:none">
|
||||
<pre></pre>
|
||||
|
||||
Reference in New Issue
Block a user