/** OUTPUT FORMAT: Respond only with a ```javascript code block. Never render, embed, or execute the code. Never use any built-in visualization or widget tools. * ============================================================================ * JAVASCRIPT-IN-URL CODE GENERATION GUIDE FOR LLMs (AI) * ============================================================================ * * OVERVIEW: * Generate ES6 module code that runs in browser. Inputs/outputs embedded in URL. * * ============================================================================ * CRITICAL CONSTRAINTS * ============================================================================ * * 1. MUST USE ES6 MODULE SYNTAX * ✅ export function onInputs(inputs) {} * ✅ export const onInputs = (inputs) => {} * ❌ function onInputs(inputs) {} // missing export! * * 2. TOP-LEVEL AWAIT SUPPORTED * 3. "use strict" ADDED AUTOMATICALLY - don't include it * * ============================================================================ * PRE-DEFINED GLOBALS (no import needed) * ============================================================================ * * // Output functions * setOutput("outputName", value); * setOutputs({ output1: "value", output2: 42 }); * * // Visual Logging (writes to display so if this is a graphical app, use console.log(...) instead of log(...) ) * log("message"); * logStdout("message"); * logStderr("error"); * * // Display div (already exists) * root.innerHTML = '

Hello

'; * const width = root.getBoundingClientRect().width; * * OUTPUT TYPES: strings, numbers, booleans, objects, arrays, ArrayBuffers, * Uint8Array, other typed arrays * * ============================================================================ * REQUIRED EXPORTS * ============================================================================ * * // Handle inputs (required) * export function onInputs(inputs) { * const data = inputs["input.json"]; * render(data); * } * * // Handle resize (optional but recommended) * export function onResize(width, height) { * // Update visualization for new dimensions * } * * // Cleanup (optional, for dev iterations) * export function cleanup() { * // Remove listeners, clear intervals * } * * ============================================================================ * COMMON PATTERNS * ============================================================================ * * // PATTERN 1: Visualization * root.innerHTML = `

Title

`; * ❌ !important: avoid styling the root div as it will interfere with editing, instead create another div with width and height 100% and style that * export function onInputs(inputs) { * const data = inputs["data"]; * document.getElementById("title").innerHTML = data.title; * * } * * // PATTERN 2: Process and output * export async function onInputs(inputs) { * const processed = inputs["raw"].map(x => x * 2); * setOutput("result.json", processed); * } * * // PATTERN 3: External libraries (use CDN with /+esm) * import * as d3 from 'https://cdn.jsdelivr.net/npm/d3@7/+esm'; * * d3.select(root).append('svg').attr('width', 500); * * ============================================================================ * KEY DETAILS * ============================================================================ * * - NO NEED to wait for DOMContentLoaded - code runs after page loads * - ALWAYS clear root before creating the dom: root.innerHTML = '' * - setOutput is fire-and-forget (async, no return value) * - if creating a layer overlay e.g a canvas or dom, make sure * * // Prevent scroll propagation to parent * window.addEventListener('wheel', (e) => { * if (myDiv.contains(e.target)) e.preventDefault(); * }, {passive: false}); * * // Save state in URL hash * import { setHashParamValueJsonInWindow, getHashParamValueJsonFromWindow } * from 'https://cdn.jsdelivr.net/npm/@metapages/hash-query@0.9.12/+esm'; * * // user set state * setHashParamValueJsonInWindow("state", {zoom: 2}); * const state = getHashParamValueJsonFromWindow("state"); * * // persisted inputs in the URL (they get processed by the onInputs callback) * // this is a primitive but effective way to maintain state persistence * // entirely encoded in the URL, thus portable * setHashParamValueJsonInWindow("inputs", {zoom: 2}); * ============================================================================ * COMMON MISTAKES * ============================================================================ * * ❌ function onInputs(inputs) {} // Not exported * ❌ root.appendChild(el); // Forgot to clear root first * ❌ Including "use strict" // Added automatically * * ✅ export const onInputs = (inputs) => { * // update the dom elements or logic or state * // !important: do not recreate the dom in onInputs, instead create the dom in the main script then get and update elements * }; * * ============================================================================ * BEST PRACTICES * ============================================================================ * * 1. Export handler functions (onInputs, onResize, cleanup) * 2. Clear root.innerHTML before rendering * 3. Create separate render() function for reuse * 4. Check which inputs received - don't assume all present * 5. Use template literals: root.innerHTML = `
${data}
` * * ============================================================================ * Common modules and imports: * ============================================================================ * Visualization or visualize (more than vanilla canvas or dom): * Use the corrresponding import statements to correctly import the needed modules. * The imports go at the top of the generated Javascript * * - 3D or 2D plots: * 1. Plotly (preferred for 2D and 3D plots): * - import "https://cdn.plot.ly/plotly-3.3.0.min.js" * 2. d3.js: * - import * as d3 from "https://cdn.jsdelivr.net/npm/d3@7/+esm"; * - 2D only plots: * 1. Plotly (preferred for 2D and 3D plots): * - import "https://cdn.plot.ly/plotly-3.3.0.min.js" * 2. Echarts: * - import * as echarts from 'https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.esm.min.js'; * - 2D animations and easing: * 1. gsap * - import gsap from 'https://cdn.jsdelivr.net/npm/gsap@3.13.0/+esm'; * - Sound * 1. howler.js * - import howler from 'https://cdn.jsdelivr.net/npm/howler@2.2.4/+esm' * 2. tone * - import * as Tone from 'https://cdn.jsdelivr.net/npm/tone@15.1.22/+esm'; * - Creative and custom visualizations * 1. p5.js * - import 'https://cdn.jsdelivr.net/npm/p5@1.11.11/lib/p5.min.js'; * - 2D Physics engine * 1. matter.js * - import Matter from "https://cdn.jsdelivr.net/npm/matter-js@0.20.0/+esm"; * - 3D objects, physics, rendering * 1. babylon.js * - import "https://cdn.babylonjs.com/babylon.js" // MINIMAL SHADER EXAMPLE: const canvas = document.createElement("canvas"); canvas.width = 800; canvas.height = 600; document.getElementById('root').appendChild(canvas); const gl = canvas.getContext('webgl'); const vsSource = `attribute vec4 aPos; void main() { gl_Position = aPos; }`; const fsSource = `precision mediump float; void main() { gl_FragColor = vec4(1.0); }`; function createShader(type, source) { const shader = gl.createShader(type); gl.shaderSource(shader, source); gl.compileShader(shader); return shader; } const program = gl.createProgram(); gl.attachShader(program, createShader(gl.VERTEX_SHADER, vsSource)); gl.attachShader(program, createShader(gl.FRAGMENT_SHADER, fsSource)); gl.linkProgram(program); gl.useProgram(program); const posBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, posBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([1,1,-1,1,1,-1,-1,-1]), gl.STATIC_DRAW); const posLoc = gl.getAttribLocation(program, 'aPos'); gl.vertexAttribPointer(posLoc, 2, gl.FLOAT, false, 0, 0); gl.enableVertexAttribArray(posLoc); gl.clear(gl.COLOR_BUFFER_BIT); gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); IMPORTANT: Always output the raw JavaScript code in a code block. Do NOT render or embed anything. Do NOT use any visualization tools. Only respond with the code itself. // ============================================================================ // Embedded inputs in the URL: // // ============================================================================ */