diff --git a/README.md b/README.md index 8e39ad27..43c9682e 100644 --- a/README.md +++ b/README.md @@ -218,3 +218,14 @@ You can debug the extension from Visual Studio Code: * Open the main folder of the plugin with vscode. * Open the file `extension.ts`. * Choose "Run" from the menu, then "Start Debugging". + +## WebDev + +You can develop the design of the visualization using an example trace in your browser: + +* `npm install` +* `npm run build` +* `npm run watch:web` +* In console: `cd out/programflow-visualization/web` + `python3 -m http.server 5173` +* Then open http://localhost:5173/index.web.html +* Now you can edit files in `src/programflow-visualization/web`, watch:web will rebuild automatically and you can refresh your browser tab to see the changes \ No newline at end of file diff --git a/media/programflow-visualization/linkerline.js b/media/programflow-visualization/linkerline.js deleted file mode 100644 index 23781b77..00000000 --- a/media/programflow-visualization/linkerline.js +++ /dev/null @@ -1,2 +0,0 @@ -import LinkerLine from "linkerline"; -window.LinkerLine = LinkerLine; diff --git a/media/programflow-visualization/webview.js b/media/programflow-visualization/webview.js deleted file mode 100644 index 56f326f3..00000000 --- a/media/programflow-visualization/webview.js +++ /dev/null @@ -1,199 +0,0 @@ -const vscode = acquireVsCodeApi(); - -let refTags = []; - -/** - * Event Listener that listens to all incoming messages from the extension. - * Needs to be done so that Webview and js Script can communication with one another. - */ -window.addEventListener("message", (event) => { - // Data send from extension - const message = event.data; - - switch (message.command) { - case "updateButtons": - document.querySelector("#nextButton").disabled = !message.next; - document.querySelector("#prevButton").disabled = !message.prev; - document.querySelector("#firstButton").disabled = !message.first; - document.querySelector("#lastButton").disabled = !message.last; - break; - case "updateContent": - var traceMax = message.traceLen - 1; - if (traceMax < 0) { - traceMax = 0; - } - document.querySelector("#traceSlider").max = traceMax; - document.querySelector("#traceSlider").value = message.traceIndex; - document.querySelector("#traceMax").innerHTML = "/" + (message.traceComplete ? traceMax.toString() : "?"); - document.querySelector("#indexCounter").innerHTML = message.traceIndex; - updateVisualization(message.traceElem); - updateIntend(message.traceElem); - updateRefArrows(message.traceElem); - break; - } -}); - -/** - * Updates the Visualization in the Webview, with the given BackendTraceElem. - * - * @param traceElem A FrontendTraceElem - */ -function updateVisualization(traceElem) { - const data = ` -
-
-
- Frames -
-
-
-
-
- Objects -
-
-
-
-
-
- ${traceElem.stackHTML} -
-
- ${traceElem.heapHTML} -
-
- `; - const viz = document.getElementById("viz"); - viz.innerHTML = data; - - // Scroll to the end of the stack - const frames = document.getElementById("frames"); - if (frames.lastElementChild !== null) { - const framesHeight = frames.lastElementChild.offsetTop + frames.lastElementChild.offsetHeight; - var y = framesHeight - viz.clientHeight; - if (y < 0) { - y = 0; - } - viz.scrollTo(0, y); - } - - const stdoutLog = document.getElementById("stdout-log"); - stdoutLog.innerHTML = traceElem.outputState; - stdoutLog.scrollTo(0, stdoutLog.scrollHeight); -} - -/** - * Updates the indendation for heap elements, if a other heap element references it. - * - * @param traceElem A FrontendTraceElem - */ -function updateIntend(traceElem) { - const heapTags = traceElem.heapHTML.match(/(?<=startPointer)[0-9]+/g); - if (heapTags) { - heapTags.forEach((tag) => { - const element = document.getElementById("objectItem" + tag); - if (element) { element.classList.add("object-intendation"); } - }); - } -} - -/** - * Updates the Reference Arrows from frame items to heap & heap items to heap items. - * - * @param traceElem A BackendTraceElem with 3 fields (line, stack, heap) - */ -function updateRefArrows(traceElem) { - const tags = getCurrentTags(traceElem); - refTags.forEach((tag) => tag.remove()); - refTags = []; - - if (!tags) { - return; - } - - refTags = tags - .filter((tag) => tag.elem1 && tag.elem2) - .map((tag) => { - return new LinkerLine({ - parent: document.getElementById("viz"), - start: tag.elem1, - end: tag.elem2, - size: 2, - path: "magnet", - startSocket: "right", - endSocket: "left", - startPlug: "square", - startSocketGravity: [50, -10], - endSocketGravity: [-5, -5], - endPlug: "arrow1", - color: getColor(tag), - }); - }); -} - -/** - * Retrieves all id's on the frame side and heap side, that have a potential start or end pointer in there id. - * Is later used to create Reference Arrows. - * - * @param traceElem A BackendTraceElem with 3 fields (line, stack, heap) - * @returns A list with all ids that have either a start or end pointer id in the html - */ -function getCurrentTags(traceElem) { - const stackTags = traceElem.stackHTML.match(/(?<=id=")(.+)Pointer[0-9]+/g); - const heapTags = traceElem.heapHTML.match(/(?<=startPointer)[0-9]+/g); - const uniqueId = traceElem.heapHTML.match(/(?<=)\d+(?=startPointer)/g); - - if (!stackTags) { - return; - } - - const stackRefs = stackTags.map((tag) => { - const id = tag.match(/(?<=.*Pointer)[\d]+/g); - return { - tag: id, - elem1: document.getElementById(tag), - elem2: document.getElementById("heapEndPointer" + id), - }; - }); - - let heapRefs = []; - if (heapTags) { - heapRefs = heapTags.map((reference, index) => { - return { - tag: reference, - elem1: document.getElementById( - uniqueId[index] + "startPointer" + reference - ), - elem2: document.getElementById("heapEndPointer" + reference), - }; - }); - } - - return [...heapRefs, ...stackRefs]; -} - -/** - * Creates a color based on the tag number (variable reference). - * - * @param tag The tag number (variable reference) is used to create a color. - * @returns - */ -function getColor(tag) { - const hue = ((0.618033988749895 + tag.tag / 10) % 1) * 100; - return `hsl(${hue}, 60%, 45%)`; -} - -function onLoad() { - document.querySelector("#nextButton").disabled = false; - document.querySelector("#lastButton").disabled = false; - document.querySelector("#prevButton").disabled = true; - document.querySelector("#firstButton").disabled = true; -} - -async function onClick(type) { - await vscode.postMessage({ command: "onClick", type: type }); -} - -async function onSlide(sliderValue) { - await vscode.postMessage({ command: "onSlide", sliderValue: sliderValue }); -} diff --git a/package-lock.json b/package-lock.json index 9e3958a8..75e0e67b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,14 @@ { "name": "write-your-python-program", - "version": "1.2.1", + "version": "2.1.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "write-your-python-program", - "version": "1.2.1", + "version": "2.1.2", "license": "See license in LICENSE", "dependencies": { - "@types/node": "^18.11.13", "linkerline": "^1.5.0", "stringify-json": "^2.0.0", "tmp": "^0.2.3", @@ -17,31 +16,436 @@ }, "devDependencies": { "@types/mocha": "^8.2.3", - "@types/node": "^18.11.13", + "@types/node": "^18.19.130", "@types/tmp": "^0.2.6", "@types/vscode": "^1.85.0", "@typescript-eslint/eslint-plugin": "^5.30.0", "@typescript-eslint/parser": "^5.30.0", "@vscode/test-electron": "^1.6.1", + "esbuild": "^0.27.3", "eslint": "^8.18.0", "glob": "^11.0.0", "mocha": "^10.7.3", - "typescript": "^5.4.2", - "webpack": "^5.96.1", - "webpack-cli": "^5.1.4" + "typescript": "^5.4.2" }, "engines": { - "vscode": "^1.85.0" + "vscode": "^1.94.2" } }, - "node_modules/@discoveryjs/json-ext": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", - "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", + "integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==", + "cpu": [ + "ppc64" + ], "dev": true, - "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz", + "integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz", + "integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz", + "integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz", + "integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz", + "integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz", + "integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz", + "integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz", + "integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz", + "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz", + "integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz", + "integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz", + "integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz", + "integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz", + "integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz", + "integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz", + "integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz", + "integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz", + "integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz", + "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz", + "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz", + "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz", + "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz", + "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz", + "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz", + "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=10.0.0" + "node": ">=18" } }, "node_modules/@eslint-community/eslint-utils": { @@ -264,70 +668,6 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", - "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -375,35 +715,6 @@ "node": ">= 6" } }, - "node_modules/@types/eslint": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", - "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -418,11 +729,10 @@ "dev": true }, "node_modules/@types/node": { - "version": "18.19.51", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.51.tgz", - "integrity": "sha512-IIMkWEIVQDlBpi6pPeGqTqOx7KbzGC3EgIyH8NrxplXOwWw0uVl9vthJUMFrxD7kcEfcRp7jIkgpB28M6JnfWA==", + "version": "18.19.130", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.130.tgz", + "integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==", "dev": true, - "license": "MIT", "dependencies": { "undici-types": "~5.26.4" } @@ -613,280 +923,58 @@ "@typescript-eslint/types": "5.62.0", "@typescript-eslint/typescript-estree": "5.62.0", "eslint-scope": "^5.1.1", - "semver": "^7.3.7" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", - "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/@vscode/test-electron": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-1.6.2.tgz", - "integrity": "sha512-W01ajJEMx6223Y7J5yaajGjVs1QfW3YGkkOJHVKfAMEqNB1ZHN9wCcViehv5ZwVSSJnjhu6lYEYgwBdHtCxqhQ==", - "dev": true, - "dependencies": { - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "rimraf": "^3.0.2", - "unzipper": "^0.10.11" - }, - "engines": { - "node": ">=8.9.3" - } - }, - "node_modules/@webassemblyjs/ast": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", - "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/helper-numbers": "1.13.2", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2" - } - }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", - "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", - "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", - "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", - "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.13.2", - "@webassemblyjs/helper-api-error": "1.13.2", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", - "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", - "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/wasm-gen": "1.14.1" - } - }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", - "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", - "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", - "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", - "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/helper-wasm-section": "1.14.1", - "@webassemblyjs/wasm-gen": "1.14.1", - "@webassemblyjs/wasm-opt": "1.14.1", - "@webassemblyjs/wasm-parser": "1.14.1", - "@webassemblyjs/wast-printer": "1.14.1" - } - }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", - "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/ieee754": "1.13.2", - "@webassemblyjs/leb128": "1.13.2", - "@webassemblyjs/utf8": "1.13.2" - } - }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", - "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/wasm-gen": "1.14.1", - "@webassemblyjs/wasm-parser": "1.14.1" - } - }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", - "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-api-error": "1.13.2", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/ieee754": "1.13.2", - "@webassemblyjs/leb128": "1.13.2", - "@webassemblyjs/utf8": "1.13.2" - } - }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", - "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webpack-cli/configtest": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", - "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.15.0" + "semver": "^7.3.7" }, - "peerDependencies": { - "webpack": "5.x.x", - "webpack-cli": "5.x.x" - } - }, - "node_modules/@webpack-cli/info": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", - "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", - "dev": true, - "license": "MIT", "engines": { - "node": ">=14.15.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "webpack": "5.x.x", - "webpack-cli": "5.x.x" + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/@webpack-cli/serve": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", - "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", "dev": true, "license": "MIT", - "engines": { - "node": ">=14.15.0" + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" }, - "peerDependencies": { - "webpack": "5.x.x", - "webpack-cli": "5.x.x" + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, - "peerDependenciesMeta": { - "webpack-dev-server": { - "optional": true - } + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@xtuc/ieee754": { + "node_modules/@ungap/structured-clone": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", "dev": true, - "license": "BSD-3-Clause" + "license": "ISC" }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "node_modules/@vscode/test-electron": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-1.6.2.tgz", + "integrity": "sha512-W01ajJEMx6223Y7J5yaajGjVs1QfW3YGkkOJHVKfAMEqNB1ZHN9wCcViehv5ZwVSSJnjhu6lYEYgwBdHtCxqhQ==", "dev": true, - "license": "Apache-2.0" + "dependencies": { + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "rimraf": "^3.0.2", + "unzipper": "^0.10.11" + }, + "engines": { + "node": ">=8.9.3" + } }, "node_modules/acorn": { "version": "8.14.0", @@ -940,16 +1028,6 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "ajv": "^6.9.1" - } - }, "node_modules/ansi-colors": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", @@ -1088,46 +1166,6 @@ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, - "node_modules/browserslist": { - "version": "4.24.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", - "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "caniuse-lite": "^1.0.30001669", - "electron-to-chromium": "^1.5.41", - "node-releases": "^2.0.18", - "update-browserslist-db": "^1.1.1" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true, - "license": "MIT" - }, "node_modules/buffer-indexof-polyfill": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", @@ -1168,27 +1206,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/caniuse-lite": { - "version": "1.0.30001680", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001680.tgz", - "integrity": "sha512-rPQy70G6AGUMnbwS1z6Xg+RkHYPAi18ihs47GH0jcxIG7wArmPgY3XbS2sRdBbxJljp3thdT8BIqv9ccCypiPA==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" - }, "node_modules/chainsaw": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", @@ -1253,16 +1270,6 @@ "fsevents": "~2.3.2" } }, - "node_modules/chrome-trace-event": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", - "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0" - } - }, "node_modules/cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", @@ -1274,21 +1281,6 @@ "wrap-ansi": "^7.0.0" } }, - "node_modules/clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -1307,20 +1299,6 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true, - "license": "MIT" - }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true, - "license": "MIT" - }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1435,53 +1413,53 @@ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true }, - "node_modules/electron-to-chromium": { - "version": "1.5.63", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.63.tgz", - "integrity": "sha512-ddeXKuY9BHo/mw145axlyWjlJ1UBt4WK3AlvkT7W2AbqfRQoacVoRUCF6wL3uIx/8wT9oLKXzI+rFqHHscByaA==", - "dev": true, - "license": "ISC" - }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, - "node_modules/enhanced-resolve": { - "version": "5.17.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", - "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", + "node_modules/esbuild": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz", + "integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==", "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/envinfo": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.14.0.tgz", - "integrity": "sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg==", - "dev": true, - "license": "MIT", + "hasInstallScript": true, "bin": { - "envinfo": "dist/cli.js" + "esbuild": "bin/esbuild" }, "engines": { - "node": ">=4" + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.3", + "@esbuild/android-arm": "0.27.3", + "@esbuild/android-arm64": "0.27.3", + "@esbuild/android-x64": "0.27.3", + "@esbuild/darwin-arm64": "0.27.3", + "@esbuild/darwin-x64": "0.27.3", + "@esbuild/freebsd-arm64": "0.27.3", + "@esbuild/freebsd-x64": "0.27.3", + "@esbuild/linux-arm": "0.27.3", + "@esbuild/linux-arm64": "0.27.3", + "@esbuild/linux-ia32": "0.27.3", + "@esbuild/linux-loong64": "0.27.3", + "@esbuild/linux-mips64el": "0.27.3", + "@esbuild/linux-ppc64": "0.27.3", + "@esbuild/linux-riscv64": "0.27.3", + "@esbuild/linux-s390x": "0.27.3", + "@esbuild/linux-x64": "0.27.3", + "@esbuild/netbsd-arm64": "0.27.3", + "@esbuild/netbsd-x64": "0.27.3", + "@esbuild/openbsd-arm64": "0.27.3", + "@esbuild/openbsd-x64": "0.27.3", + "@esbuild/openharmony-arm64": "0.27.3", + "@esbuild/sunos-x64": "0.27.3", + "@esbuild/win32-arm64": "0.27.3", + "@esbuild/win32-ia32": "0.27.3", + "@esbuild/win32-x64": "0.27.3" } }, - "node_modules/es-module-lexer": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", - "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", - "dev": true, - "license": "MIT" - }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -1724,16 +1702,6 @@ "node": ">=0.10.0" } }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.x" - } - }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -1772,16 +1740,6 @@ "dev": true, "license": "MIT" }, - "node_modules/fastest-levenshtein": { - "version": "1.0.16", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", - "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4.9.1" - } - }, "node_modules/fastq": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", @@ -1963,16 +1921,6 @@ "rimraf": "bin.js" } }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -2017,13 +1965,6 @@ "node": ">= 6" } }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true, - "license": "BSD-2-Clause" - }, "node_modules/glob/node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -2109,19 +2050,6 @@ "node": ">=8" } }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -2185,26 +2113,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/import-local": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", - "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", - "dev": true, - "license": "MIT", - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -2232,16 +2140,6 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, - "node_modules/interpret": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", - "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -2254,22 +2152,6 @@ "node": ">=8" } }, - "node_modules/is-core-module": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", - "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -2330,19 +2212,6 @@ "node": ">=8" } }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "license": "MIT", - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-unicode-supported": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", @@ -2367,16 +2236,6 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/jackspeak": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.2.tgz", @@ -2392,21 +2251,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -2427,13 +2271,6 @@ "dev": true, "license": "MIT" }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true, - "license": "MIT" - }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -2458,16 +2295,6 @@ "json-buffer": "3.0.1" } }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -2494,16 +2321,6 @@ "integrity": "sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc=", "dev": true }, - "node_modules/loader-runner": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.11.5" - } - }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -2557,13 +2374,6 @@ "integrity": "sha512-JpaZKIuEcjxjcyLSykhirzd706MIVa6agPbidZbNCifl+6MHdFZ7U0Bg8cno3PN0Z9a1A690OsvxMSjc/gc9gg==", "license": "MIT" }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true, - "license": "MIT" - }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -2588,29 +2398,6 @@ "node": ">=8.6" } }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/minimatch": { "version": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", @@ -2738,20 +2525,6 @@ "dev": true, "license": "MIT" }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true, - "license": "MIT" - }, - "node_modules/node-releases": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", - "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", - "dev": true, - "license": "MIT" - }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -2815,17 +2588,7 @@ "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/package-json-from-dist": { @@ -2875,13 +2638,6 @@ "node": ">=8" } }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true, - "license": "MIT" - }, "node_modules/path-scurry": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", @@ -2908,13 +2664,6 @@ "node": ">=8" } }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "license": "ISC" - }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -2928,75 +2677,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-dir/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -3086,19 +2766,6 @@ "node": ">=8.10.0" } }, - "node_modules/rechoir": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", - "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "resolve": "^1.20.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -3108,47 +2775,6 @@ "node": ">=0.10.0" } }, - "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-cwd/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -3263,25 +2889,6 @@ } ] }, - "node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, "node_modules/semver": { "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", @@ -3310,19 +2917,6 @@ "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", "dev": true }, - "node_modules/shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "license": "MIT", - "dependencies": { - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -3368,27 +2962,6 @@ "node": ">=8" } }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, "node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -3498,83 +3071,6 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/terser": { - "version": "5.36.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.36.0.tgz", - "integrity": "sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.10", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", - "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.20", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.26.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } - } - }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -3709,37 +3205,6 @@ "setimmediate": "~1.0.4" } }, - "node_modules/update-browserslist-db": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", - "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.0" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -3756,148 +3221,6 @@ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, - "node_modules/watchpack": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", - "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", - "dev": true, - "license": "MIT", - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/webpack": { - "version": "5.96.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.96.1.tgz", - "integrity": "sha512-l2LlBSvVZGhL4ZrPwyr8+37AunkcYj5qh8o6u2/2rzoPc8gxFJkLj1WxNgooi9pnoc06jh0BjuXnamM4qlujZA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/eslint-scope": "^3.7.7", - "@types/estree": "^1.0.6", - "@webassemblyjs/ast": "^1.12.1", - "@webassemblyjs/wasm-edit": "^1.12.1", - "@webassemblyjs/wasm-parser": "^1.12.1", - "acorn": "^8.14.0", - "browserslist": "^4.24.0", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.1", - "es-module-lexer": "^1.2.1", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.11", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.2.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.10", - "watchpack": "^2.4.1", - "webpack-sources": "^3.2.3" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-cli": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", - "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@discoveryjs/json-ext": "^0.5.0", - "@webpack-cli/configtest": "^2.1.1", - "@webpack-cli/info": "^2.0.2", - "@webpack-cli/serve": "^2.0.5", - "colorette": "^2.0.14", - "commander": "^10.0.1", - "cross-spawn": "^7.0.3", - "envinfo": "^7.7.3", - "fastest-levenshtein": "^1.0.12", - "import-local": "^3.0.2", - "interpret": "^3.1.1", - "rechoir": "^0.8.0", - "webpack-merge": "^5.7.3" - }, - "bin": { - "webpack-cli": "bin/cli.js" - }, - "engines": { - "node": ">=14.15.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "5.x.x" - }, - "peerDependenciesMeta": { - "@webpack-cli/generators": { - "optional": true - }, - "webpack-bundle-analyzer": { - "optional": true - }, - "webpack-dev-server": { - "optional": true - } - } - }, - "node_modules/webpack-cli/node_modules/commander": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", - "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14" - } - }, - "node_modules/webpack-merge": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", - "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", - "dev": true, - "license": "MIT", - "dependencies": { - "clone-deep": "^4.0.1", - "flat": "^5.0.2", - "wildcard": "^2.0.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -3913,13 +3236,6 @@ "node": ">= 8" } }, - "node_modules/wildcard": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", - "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", - "dev": true, - "license": "MIT" - }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", diff --git a/package.json b/package.json index b4a543cf..565a2607 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,11 @@ }, "write-your-python-program.language": { "type": "string", - "enum": ["german", "english", "system default"], + "enum": [ + "german", + "english", + "system default" + ], "default": "system default", "description": "Choose the language for error messages." } @@ -84,11 +88,11 @@ "lint": "eslint src --ext ts", "watch": "tsc -watch -p ./", "test": "npm run compile && npm run lint", - "bundle": "webpack", - "build": "npm run compile && npm run bundle" + "build:web": "node scripts/build-web.mjs", + "watch:web": "node scripts/build-web.mjs --watch", + "build": "npm run compile && npm run build:web" }, "dependencies": { - "@types/node": "^18.11.13", "linkerline": "^1.5.0", "stringify-json": "^2.0.0", "tmp": "^0.2.3", @@ -96,17 +100,16 @@ }, "devDependencies": { "@types/mocha": "^8.2.3", - "@types/node": "^18.11.13", + "@types/node": "^18.19.130", "@types/tmp": "^0.2.6", "@types/vscode": "^1.85.0", "@typescript-eslint/eslint-plugin": "^5.30.0", "@typescript-eslint/parser": "^5.30.0", "@vscode/test-electron": "^1.6.1", + "esbuild": "^0.27.3", "eslint": "^8.18.0", "glob": "^11.0.0", "mocha": "^10.7.3", - "typescript": "^5.4.2", - "webpack": "^5.96.1", - "webpack-cli": "^5.1.4" + "typescript": "^5.4.2" } } diff --git a/scripts/build-web.mjs b/scripts/build-web.mjs new file mode 100644 index 00000000..2a173c3d --- /dev/null +++ b/scripts/build-web.mjs @@ -0,0 +1,79 @@ +import * as esbuild from "esbuild"; +import fs from "fs"; +import path from "path"; +import { fileURLToPath } from "url"; + +const _dirname = path.dirname(fileURLToPath(import.meta.url)); +const root = path.resolve(_dirname, ".."); + +const webSrc = path.join(root, "src/programflow-visualization/web"); +const webOut = path.join(root, "out/programflow-visualization/web"); +const watch = process.argv.includes("--watch"); + +fs.mkdirSync(webOut, { recursive: true }); + +// Bundle webview.ts -> out/.../webview.js +const webviewCtx = await esbuild.context({ + entryPoints: [path.join(webSrc, "webview.ts")], + bundle: true, + platform: "browser", + format: "iife", // classic - - Code Visualization - - -
-
-
- Frames -
-
-
- Objects -
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-

Step 

-

0

-

/?

-
-
- - - - -
-
-
-

-          
-        
- - - `; + public dispose() { + this._panel?.dispose(); } - private async updateLineHighlight(remove: boolean = false) { - try { - if (this._trace.length === 0) { - this._outChannel.appendLine("updateLineHighlight: no trace available, aborting"); - return; - } - const traceFile = this._trace[this._traceIndex].filename; - this._outChannel.appendLine( - `updateLineHighlight: traceFile=${traceFile}, traceIndex=${this._traceIndex}, remove=${remove}`); + // HTML loader: reads web/index.html and replaces placeholders + private getWebviewHtml(webview: vscode.Webview): string { + const webDir = path.join(this._context.extensionPath, VisualizationPanel.webComponentDir); + const indexPath = path.join(webDir, "index.html"); + let html = fs.readFileSync(indexPath, "utf8"); - // Use vscode.Uri.file() for proper file path to URI conversion - const openPath = vscode.Uri.file(traceFile); + const cssUri = webview.asWebviewUri(vscode.Uri.file(path.join(webDir, "webview.css"))); + const jsUri = webview.asWebviewUri(vscode.Uri.file(path.join(webDir, "webview.js"))); + const adapterUri = webview.asWebviewUri(vscode.Uri.file(path.join(webDir, "vscode-host-adapter.js"))); + const nonce = getNonce(); - // Find editor by full normalized path, not just basename - let editor: vscode.TextEditor | undefined = vscode.window.visibleTextEditors.find( - editor => editor.document.uri.fsPath === openPath.fsPath - ); + html = replaceAll(html, "{{WEBVIEW_CSS}}", String(cssUri)); + html = replaceAll(html, "{{VSCODE_HOST_ADAPTER_JS}}", String(adapterUri)); + html = replaceAll(html, "{{WEBVIEW_JS}}", String(jsUri)); + html = replaceAll(html, "{{NONCE}}", nonce); + html = replaceAll(html, "{{CSP_SOURCE}}", webview.cspSource); - if (!editor && remove) { - return; - } else if (!editor){ - this._outChannel.appendLine(`updateLineHighlight: editor not found, opening document: ${openPath.fsPath}`); - await vscode.commands.executeCommand('workbench.action.focusFirstEditorGroup'); - const document = await vscode.workspace.openTextDocument(openPath); - editor = await vscode.window.showTextDocument(document, { preserveFocus: false }); - // Give the editor time to fully initialize - await new Promise(resolve => setTimeout(resolve, 100)); - if (!editor) { - this._outChannel.appendLine(`updateLineHighlight: failed to get editor after opening document`); - return; - } - } + return html; + } - const traceLine = this._trace[this._traceIndex].lineNumber; - const lineNo = traceLine - 1; // zero-based indexing in vscode - if (remove) { - this._outChannel.appendLine( - "updateLineHighlight: removing highlighting in " + editor.document.fileName); - editor.setDecorations(nextLineExecuteHighlightType, []); - } else if (lineNo < 0 || lineNo >= editor.document.lineCount) { - this._outChannel.appendLine( - "updateLineHighlight: traceLine " + traceLine + " out of range (doc has " + - editor.document.lineCount + " lines) in " + editor.document.fileName); - editor.setDecorations(nextLineExecuteHighlightType, []); - } else { - this._outChannel.appendLine( - "updateLineHighlight: highlighting line " + traceLine + " in " + editor.document.fileName); - this.setEditorDecorations(editor, nextLineExecuteHighlightType, lineNo); - } - } catch (error) { - this._outChannel.appendLine(`updateLineHighlight: ERROR - ${error}`); - if (error instanceof Error) { - this._outChannel.appendLine(`Stack: ${error.stack}`); - } - } + // Posting data into the web component + private async postReset() { + if (!this._panel) {return;} + + await this._panel.webview.postMessage({ + command: "reset", + trace: this._backendTrace.trace, + complete: this._backendTrace.complete, + index: this._traceIndex, + }); } - private setEditorDecorations(editor: vscode.TextEditor, highlightType: vscode.TextEditorDecorationType, line: number) { - editor.setDecorations( - highlightType, - this.createDecorationOptions( - new vscode.Range(new vscode.Position(line, 0), new vscode.Position(line, 999)) - ) - ); + private async postAppend(elem: BackendTraceElem) { + if (!this._panel) {return;} + + await this._panel.webview.postMessage({ + command: "append", + elem, + complete: this._backendTrace.complete, + index: this._traceIndex, + len: this._backendTrace.trace.length, + }); } + // Compatibility navigation handlers private async onClick(type: string) { this.updateTraceIndex(type); - await this.postMessagesToWebview('updateButtons', 'updateContent'); + await this.postReset(); this.updateLineHighlight(); } private async onSlide(sliderValue: number) { this._traceIndex = Number(sliderValue); - await this.postMessagesToWebview('updateButtons', 'updateContent'); + await this.postReset(); this.updateLineHighlight(); } private updateTraceIndex(actionType: string) { + const max = Math.max(0, this._backendTrace.trace.length - 1); switch (actionType) { - case 'next': ++this._traceIndex; - break; - case 'prev': --this._traceIndex; + case "next": + this._traceIndex = Math.min(max, this._traceIndex + 1); break; - case 'first': this._traceIndex = 0; + case "prev": + this._traceIndex = Math.max(0, this._traceIndex - 1); break; - case 'last': this._traceIndex = this._trace.length - 1; + case "first": + this._traceIndex = 0; break; - default: + case "last": + this._traceIndex = max; break; } } - private async postMessagesToWebview(...args: string[]) { - for (const message of args) { - switch (message) { - case 'updateButtons': - const nextActive = this._traceIndex < this._trace.length - 1; - const prevActive = this._traceIndex > 0; - const firstActive = this._traceIndex > 0; - const lastActive = this._traceIndex !== this._trace.length - 1; - await this._panel!.webview.postMessage({ - command: 'updateButtons', - next: nextActive, - prev: prevActive, - first: firstActive, - last: lastActive, - }); - break; - case 'updateContent': - await this._panel!.webview.postMessage({ - command: 'updateContent', - traceComplete: this._backendTrace.complete, - traceElem: this._trace[this._traceIndex], - traceIndex: this._traceIndex, - traceLen: this._trace.length, - }); - break; + // Editor highlighting + private async updateLineHighlight(remove: boolean = false, overrideFile?: string, overrideLine?: number) { + try { + if (this._backendTrace.trace.length === 0) { + return; } - }; - } - private createDecorationOptions(range: vscode.Range): vscode.DecorationOptions[] { - return [ - { - range: range, - }, - ]; + const current = this._backendTrace.trace[this._traceIndex]; + const traceFile = overrideFile ?? current.filePath; + const traceLine = overrideLine ?? current.line; + + const openPath = vscode.Uri.file(traceFile); + + let editor: vscode.TextEditor | undefined = vscode.window.visibleTextEditors.find( + (ed) => ed.document.uri.fsPath === openPath.fsPath + ); + + if (!editor && !remove) { + await vscode.commands.executeCommand("workbench.action.focusFirstEditorGroup"); + const doc = await vscode.workspace.openTextDocument(openPath); + editor = await vscode.window.showTextDocument(doc, { preserveFocus: false }); + await new Promise((r) => setTimeout(r, 50)); + } + + if (!editor) {return;} + + if (remove) { + editor.setDecorations(nextLineExecuteHighlightType, []); + return; + } + + const lineNo = traceLine - 1; + if (lineNo < 0 || lineNo >= editor.document.lineCount) { + editor.setDecorations(nextLineExecuteHighlightType, []); + return; + } + + const range = new vscode.Range(new vscode.Position(lineNo, 0), new vscode.Position(lineNo, 999)); + editor.revealRange(range, vscode.TextEditorRevealType.InCenterIfOutsideViewport); + editor.setDecorations(nextLineExecuteHighlightType, [{ range }]); + } catch (e: any) { + this._outChannel.appendLine(`updateLineHighlight failed: ${e?.message ?? String(e)}`); + } } } + +function getNonce(): string { + const possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + let text = ""; + for (let i = 0; i < 32; i++) {text += possible.charAt(Math.floor(Math.random() * possible.length));} + return text; +} + +function replaceAll(str: string, search: string, replacement: string): string { + return str.split(search).join(replacement); +} diff --git a/src/programflow-visualization/main.ts b/src/programflow-visualization/main.ts index a56e0ab8..60c138d3 100644 --- a/src/programflow-visualization/main.ts +++ b/src/programflow-visualization/main.ts @@ -2,7 +2,7 @@ import * as vscode from 'vscode'; import { startBackend } from './backend/backend'; import * as FileHandler from './FileHandler'; import { Md5 } from 'ts-md5'; -import { startFrontend } from './frontend/frontend'; +import { VisualizationPanel } from './frontend/visualization_panel'; import { traceAlreadyExists } from './trace_cache'; export function getProgFlowVizCallback(context: vscode.ExtensionContext, outChannel: vscode.OutputChannel): () => Promise { @@ -29,11 +29,8 @@ export function getProgFlowVizCallback(context: vscode.ExtensionContext, outChan tracePort = startBackend(context, file, outChannel); } - const result = await startFrontend(context, outChannel, file.fsPath, fileHash, tracePort); - if (result) { - await vscode.window.showErrorMessage("Error ProgramFlow-Visualization: " + result.errorMessage); - return; - } + await VisualizationPanel.start(context, outChannel, file.fsPath, fileHash, tracePort); + } catch (e: any) { if (e instanceof Error) { outChannel.appendLine(e.stack?.toString() ?? "Error: "); diff --git a/src/programflow-visualization/trace_cache.ts b/src/programflow-visualization/trace_cache.ts index 0cc049d8..49d72871 100644 --- a/src/programflow-visualization/trace_cache.ts +++ b/src/programflow-visualization/trace_cache.ts @@ -5,6 +5,7 @@ import path = require('path'); import stringify from 'stringify-json'; import util = require('util'); import * as FileHandler from './FileHandler'; +import type { BackendTrace } from "./types"; export async function initTraceCache(context: vscode.ExtensionContext): Promise { tmp.setGracefulCleanup(); diff --git a/src/programflow-visualization/types.ts b/src/programflow-visualization/types.ts index e2528ac4..0a65ba49 100644 --- a/src/programflow-visualization/types.ts +++ b/src/programflow-visualization/types.ts @@ -1,14 +1,14 @@ /** * For better readable code */ -type Try = Success | Failure; -type Success = { result: any }; -type Failure = { errorMessage: string }; +export type Try = Success | Failure; +export type Success = { result: any }; +export type Failure = { errorMessage: string }; // State Types for the Frontend -type FrontendTrace = Array; +export type FrontendTrace = Array; -type FrontendTraceElem = { +export type FrontendTraceElem = { lineNumber: number, // 1-based stackHTML: string, heapHTML: string, @@ -18,12 +18,12 @@ type FrontendTraceElem = { // ############################################################################################ // State Types for the Backend -type PartialBackendTrace = { +export type PartialBackendTrace = { trace: BackendTrace; complete: boolean; }; -type BackendTrace = Array; -type BackendTraceElem = { +export type BackendTrace = Array; +export type BackendTraceElem = { line: number; filePath: string, stack: Array; @@ -32,9 +32,9 @@ type BackendTraceElem = { traceback: string | undefined; }; -type Address = number; +export type Address = number; -type Value = +export type Value = | { type: 'int'; value: number } | { type: 'float'; value: number } | { type: 'str'; value: string } @@ -44,17 +44,17 @@ type Value = | { type: 'function'; value: string } | { type: 'ref'; value: Address }; -type NamedValue = Value & { +export type NamedValue = Value & { name: string; }; -type StackElem = { +export type StackElem = { frameName: string; locals: Array; }; -type HeapValue = +export type HeapValue = | { type: 'list'; value: Array } | { type: 'tuple'; value: Array } | { type: 'set'; value: Array } diff --git a/src/programflow-visualization/web/example-trace-content.js b/src/programflow-visualization/web/example-trace-content.js new file mode 100644 index 00000000..0213b1cf --- /dev/null +++ b/src/programflow-visualization/web/example-trace-content.js @@ -0,0 +1,426 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +// placeholder trace for design development +window.__PROGRAMFLOW_TRACE__ = { + complete: true, + trace: [ + { + "line": 1, + "filePath": "wyppSimple.py", + "stack": [ + { + "frameName": "", + "locals": [] + } + ], + "heap": {}, + "stdout": "" + }, + { + "line": 2, + "filePath": "wyppSimple.py", + "stack": [ + { + "frameName": "", + "locals": [] + } + ], + "heap": {}, + "stdout": "" + }, + { + "line": 5, + "filePath": "wyppSimple.py", + "stack": [ + { + "frameName": "", + "locals": [] + } + ], + "heap": {}, + "stdout": "" + }, + { + "line": 8, + "filePath": "wyppSimple.py", + "stack": [ + { + "frameName": "", + "locals": [ + { + "type": "type", + "value": "", + "name": "Bar" + } + ] + } + ], + "heap": {}, + "stdout": "" + }, + { + "line": 11, + "filePath": "wyppSimple.py", + "stack": [ + { + "frameName": "", + "locals": [ + { + "type": "type", + "value": "", + "name": "Bar" + }, + { + "type": "function", + "value": "", + "name": "generate_bar" + } + ] + } + ], + "heap": {}, + "stdout": "" + }, + { + "line": 12, + "filePath": "wyppSimple.py", + "stack": [ + { + "frameName": "", + "locals": [ + { + "type": "type", + "value": "", + "name": "Bar" + }, + { + "type": "function", + "value": "", + "name": "generate_bar" + }, + { + "type": "ref", + "value": 0, + "name": "obj1" + } + ] + } + ], + "heap": { + "0": { + "type": "instance", + "value": { + "baz": { + "type": "str", + "value": "baz value" + } + }, + "name": "Bar" + } + }, + "stdout": "" + }, + { + "line": 13, + "filePath": "wyppSimple.py", + "stack": [ + { + "frameName": "", + "locals": [ + { + "type": "type", + "value": "", + "name": "Bar" + }, + { + "type": "function", + "value": "", + "name": "generate_bar" + }, + { + "type": "ref", + "value": 0, + "name": "obj1" + } + ] + } + ], + "heap": { + "0": { + "type": "instance", + "value": { + "baz": { + "type": "str", + "value": "baz value" + } + }, + "name": "Bar" + } + }, + "stdout": "baz value\n" + }, + { + "line": 9, + "filePath": "wyppSimple.py", + "stack": [ + { + "frameName": "", + "locals": [ + { + "type": "type", + "value": "", + "name": "Bar" + }, + { + "type": "function", + "value": "", + "name": "generate_bar" + }, + { + "type": "ref", + "value": 0, + "name": "obj1" + } + ] + }, + { + "frameName": "generate_bar", + "locals": [] + } + ], + "heap": { + "0": { + "type": "instance", + "value": { + "baz": { + "type": "str", + "value": "baz value" + } + }, + "name": "Bar" + } + }, + "stdout": "baz value\n" + }, + { + "line": 9, + "filePath": "wyppSimple.py", + "stack": [ + { + "frameName": "", + "locals": [ + { + "type": "type", + "value": "", + "name": "Bar" + }, + { + "type": "function", + "value": "", + "name": "generate_bar" + }, + { + "type": "ref", + "value": 0, + "name": "obj1" + } + ] + }, + { + "frameName": "generate_bar", + "locals": [ + { + "type": "ref", + "value": 1, + "name": "return" + } + ] + } + ], + "heap": { + "0": { + "type": "instance", + "value": { + "baz": { + "type": "str", + "value": "baz value" + } + }, + "name": "Bar" + }, + "1": { + "type": "instance", + "value": { + "baz": { + "type": "str", + "value": "baz value" + } + }, + "name": "Bar" + } + }, + "stdout": "baz value\n" + }, + { + "line": 14, + "filePath": "wyppSimple.py", + "stack": [ + { + "frameName": "", + "locals": [ + { + "type": "type", + "value": "", + "name": "Bar" + }, + { + "type": "function", + "value": "", + "name": "generate_bar" + }, + { + "type": "ref", + "value": 0, + "name": "obj1" + }, + { + "type": "ref", + "value": 1, + "name": "obj2" + } + ] + } + ], + "heap": { + "0": { + "type": "instance", + "value": { + "baz": { + "type": "str", + "value": "baz value" + } + }, + "name": "Bar" + }, + "1": { + "type": "instance", + "value": { + "baz": { + "type": "str", + "value": "baz value" + } + }, + "name": "Bar" + } + }, + "stdout": "baz value\n" + }, + { + "line": 16, + "filePath": "wyppSimple.py", + "stack": [ + { + "frameName": "", + "locals": [ + { + "type": "type", + "value": "", + "name": "Bar" + }, + { + "type": "function", + "value": "", + "name": "generate_bar" + }, + { + "type": "ref", + "value": 0, + "name": "obj1" + }, + { + "type": "ref", + "value": 1, + "name": "obj2" + } + ] + } + ], + "heap": { + "0": { + "type": "instance", + "value": { + "baz": { + "type": "str", + "value": "baz value" + } + }, + "name": "Bar" + }, + "1": { + "type": "instance", + "value": { + "baz": { + "type": "str", + "value": "baz value" + } + }, + "name": "Bar" + } + }, + "stdout": "baz value\nbaz value\n" + }, + { + "line": 18, + "filePath": "wyppSimple.py", + "stack": [ + { + "frameName": "", + "locals": [ + { + "type": "type", + "value": "", + "name": "Bar" + }, + { + "type": "function", + "value": "", + "name": "generate_bar" + }, + { + "type": "ref", + "value": 0, + "name": "obj1" + }, + { + "type": "ref", + "value": 1, + "name": "obj2" + } + ] + } + ], + "heap": { + "0": { + "type": "instance", + "value": { + "baz": { + "type": "str", + "value": "baz value" + } + }, + "name": "Bar" + }, + "1": { + "type": "instance", + "value": { + "baz": { + "type": "str", + "value": "baz value" + } + }, + "name": "Bar" + } + }, + "stdout": "baz value\nbaz value\n" + } +] +}; diff --git a/src/programflow-visualization/frontend/HTMLGenerator.ts b/src/programflow-visualization/web/html-generator.ts similarity index 98% rename from src/programflow-visualization/frontend/HTMLGenerator.ts rename to src/programflow-visualization/web/html-generator.ts index bab8730f..3700f3fb 100644 --- a/src/programflow-visualization/frontend/HTMLGenerator.ts +++ b/src/programflow-visualization/web/html-generator.ts @@ -1,3 +1,12 @@ +import type { + BackendTraceElem, + FrontendTraceElem, + HeapValue, + NamedValue, + StackElem, + Value +} from "../types"; + function escapeHTML(s: any) { if (s !== undefined && s !== null) { return s.toString().replace(/[^0-9A-Za-z ]/g, (c: string) => "&#" + c.charCodeAt(0) + ";"); diff --git a/src/programflow-visualization/web/index.html b/src/programflow-visualization/web/index.html new file mode 100644 index 00000000..fd1f1102 --- /dev/null +++ b/src/programflow-visualization/web/index.html @@ -0,0 +1,79 @@ + + + + + + + + + + Code Visualization + + + +
+
+
+
Frames
+
+
+
+
Objects
+
+
+
+ +
+
+
+
+
+ +
+
+
+ +
+ +
+

Step 

+

0

+

/?

+
+ +
+ + + + +
+
+ +
+

+    
+
+ + + + + + + + + + + diff --git a/src/programflow-visualization/web/tsconfig.json b/src/programflow-visualization/web/tsconfig.json new file mode 100644 index 00000000..722cd406 --- /dev/null +++ b/src/programflow-visualization/web/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "lib": ["es2017", "dom"], + "types": [] + }, + "include": ["**/*.ts"], + "exclude": ["../../../node_modules", "../../../.vscode-test"] +} \ No newline at end of file diff --git a/src/programflow-visualization/web/vscode-host-adapter.ts b/src/programflow-visualization/web/vscode-host-adapter.ts new file mode 100644 index 00000000..9ac5092e --- /dev/null +++ b/src/programflow-visualization/web/vscode-host-adapter.ts @@ -0,0 +1,41 @@ +declare const acquireVsCodeApi: undefined | (() => { postMessage: (msg: any) => void }); + +const vscode = typeof acquireVsCodeApi === "function" + ? acquireVsCodeApi() + : { postMessage: (_: any) => {} }; + +window.addEventListener("message", (event: MessageEvent) => { + const msg = event.data; + if (!msg?.command) {return;} + + switch (msg.command) { + case "reset": + window.dispatchEvent(new CustomEvent("programflow:reset", { detail: msg })); + break; + case "append": + window.dispatchEvent(new CustomEvent("programflow:append", { detail: msg })); + break; + + case "updateButtons": + window.dispatchEvent(new CustomEvent("programflow:updateButtons", { detail: msg })); + break; + case "updateContent": + window.dispatchEvent(new CustomEvent("programflow:updateContent", { detail: msg })); + break; + } +}); + +window.addEventListener("programflow:select", (e: Event) => { + const ce = e as CustomEvent; + vscode.postMessage({ command: "select", ...ce.detail }); +}); + +window.addEventListener("programflow:onClick", (e: Event) => { + const ce = e as CustomEvent<{ type: string }>; + vscode.postMessage({ command: "onClick", type: ce.detail.type }); +}); + +window.addEventListener("programflow:onSlide", (e: Event) => { + const ce = e as CustomEvent<{ value: string }>; + vscode.postMessage({ command: "onSlide", sliderValue: ce.detail.value }); +}); \ No newline at end of file diff --git a/media/programflow-visualization/webview.css b/src/programflow-visualization/web/webview.css similarity index 100% rename from media/programflow-visualization/webview.css rename to src/programflow-visualization/web/webview.css diff --git a/src/programflow-visualization/web/webview.ts b/src/programflow-visualization/web/webview.ts new file mode 100644 index 00000000..1c00b80b --- /dev/null +++ b/src/programflow-visualization/web/webview.ts @@ -0,0 +1,316 @@ +import { HTMLGenerator } from "./html-generator"; +import LinkerLine from "linkerline"; +import type { BackendTraceElem, FrontendTraceElem } from "../types"; + +// only used to add seperate Browser navigation if not in vscode +const isVscode = typeof (window as any).acquireVsCodeApi === "function"; + +type ResetMsg = { + command: "reset"; + trace: BackendTraceElem[]; + complete: boolean; + index: number; +}; + +type AppendMsg = { + command: "append"; + elem: BackendTraceElem; + complete: boolean; + index: number; + len: number; +}; + +// Optional example trace format (designer mode) +type StaticTrace = { complete: boolean; trace: BackendTraceElem[] }; + +let refLines: any[] = []; +let trace: BackendTraceElem[] = []; +let traceComplete = false; +let traceIndex = 0; + +const gen = new HTMLGenerator(); + +//DOM helpers +function $(sel: string): HTMLElement { + const el = document.querySelector(sel); + if (!el) {throw new Error(`Missing element: ${sel}`);} + return el as HTMLElement; +} + +function setDisabled(id: string, disabled: boolean) { + (document.querySelector(id) as HTMLButtonElement).disabled = disabled; +} + +function clamp(n: number, min: number, max: number) { + return Math.max(min, Math.min(max, n)); +} + +//Rendering +function renderCurrent() { + const max = Math.max(0, trace.length - 1); + traceIndex = clamp(traceIndex, 0, max); + + // Update slider + counters + const slider = $("#traceSlider") as HTMLInputElement; + slider.max = String(max); + slider.value = String(traceIndex); + + $("#traceMax").innerHTML = "/" + (traceComplete ? String(max) : "?"); + $("#indexCounter").innerHTML = String(traceIndex); + + // Update button enable/disable + setDisabled("#firstButton", traceIndex <= 0); + setDisabled("#prevButton", traceIndex <= 0); + setDisabled("#nextButton", traceIndex >= max); + setDisabled("#lastButton", traceIndex >= max); + + // Nothing to show yet + if (trace.length === 0) { + $("#stdout-log").innerHTML = ""; + clearArrows(); + return; + } + + const backendElem = trace[traceIndex]; + const frontendElem = gen.generateHTML(backendElem); + + updateVisualization(frontendElem); + updateIndent(frontendElem); + updateRefArrows(frontendElem); +} + +function updateVisualization(traceElem: any /* FrontendTraceElem */) { + clearArrows(); + + const frames = document.getElementById("frames"); + const objects = document.getElementById("objects"); + const stdoutLog = document.getElementById("stdout-log"); + + if (!frames || !objects || !stdoutLog) { + throw new Error("Missing required visualization containers"); + } + + frames.innerHTML = traceElem.stackHTML; + objects.innerHTML = traceElem.heapHTML; + stdoutLog.innerHTML = traceElem.outputState; + stdoutLog.scrollTo(0, stdoutLog.scrollHeight); +} + +function updateIndent(traceElem: any /* FrontendTraceElem */) { + const heapTags = traceElem.heapHTML.match(/(?<=startPointer)[0-9]+/g); + if (heapTags) { + heapTags.forEach((tag: string) => { + const element = document.getElementById("objectItem" + tag); + if (element) {element.classList.add("object-intendation");} + }); + } +} + +//Arrows +function clearArrows() { + refLines.forEach((l) => { + try { + l.remove(); + } catch {} + }); + refLines = []; +} + +function updateRefArrows(traceElem: any /* FrontendTraceElem */) { + const tags = getCurrentTags(traceElem); + if (!tags) { return; } + + requestAnimationFrame(() => { + const parent = document.getElementById("viz"); + if (!parent) { return; } + + const usable = tags.filter((t: any) => { + const a = t.elem1 as HTMLElement | null | undefined; + const b = t.elem2 as HTMLElement | null | undefined; + return !!a && !!b && a.isConnected && b.isConnected; + }); + + const lines: any[] = []; + for (const t of usable) { + try { + lines.push( + new (LinkerLine as any)({ + parent, + start: t.elem1, + end: t.elem2, + size: 2, + path: "magnet", + startSocket: "right", + endSocket: "left", + startPlug: "square", + startSocketGravity: [50, -10], + endSocketGravity: [-5, -5], + endPlug: "arrow1", + color: getColor(t), + }) + ); + } catch (err) { + // Keep going if one arrow fails (prevents breaking the whole render) + console.warn("LinkerLine failed for one tag:", t, err); + } + } + + refLines = lines; + }); +} + +function getCurrentTags(traceElem: FrontendTraceElem) { + const stackTags = traceElem.stackHTML.match(/(?<=id=")(.+)Pointer[0-9]+/g); + const heapTags = traceElem.heapHTML.match(/(?<=startPointer)[0-9]+/g); + const uniqueId = traceElem.heapHTML.match(/\d+(?=startPointer)/g); + + if (!stackTags) {return;} + + const stackRefs = stackTags.map((tag: string) => { + const id = tag.match(/(?<=.*Pointer)[\d]+/g); + return { + tag: id, + elem1: document.getElementById(tag), + elem2: document.getElementById("heapEndPointer" + id), + }; + }); + + let heapRefs: any[] = []; + if (heapTags && uniqueId) { + heapRefs = heapTags.map((reference: string, index: number) => { + return { + tag: reference, + elem1: document.getElementById(uniqueId[index] + "startPointer" + reference), + elem2: document.getElementById("heapEndPointer" + reference), + }; + }); + } + + return [...heapRefs, ...stackRefs]; +} + +function getColor(tag: any) { + const hue = ((0.618033988749895 + Number(tag.tag) / 10) % 1) * 100; + return `hsl(${hue}, 60%, 45%)`; +} + +//Incoming events (from vscode-host-adapter.ts) +window.addEventListener("programflow:reset", (e: Event) => { + const msg = (e as CustomEvent).detail; + trace = msg.trace ?? []; + traceComplete = !!msg.complete; + traceIndex = Number(msg.index ?? 0); + renderCurrent(); +}); + +window.addEventListener("programflow:append", (e: Event) => { + const msg = (e as CustomEvent).detail; + trace.push(msg.elem); + traceComplete = !!msg.complete; + traceIndex = Number(msg.index ?? traceIndex); + renderCurrent(); +}); + +window.addEventListener("programflow:updateButtons", (e: Event) => { + const msg = (e as CustomEvent).detail; + setDisabled("#nextButton", !msg.next); + setDisabled("#prevButton", !msg.prev); + setDisabled("#firstButton", !msg.first); + setDisabled("#lastButton", !msg.last); +}); + +window.addEventListener("programflow:updateContent", (e: Event) => { + const msg = (e as CustomEvent).detail; + + const max = Math.max(0, (msg.traceLen ?? 0) - 1); + const slider = $("#traceSlider") as HTMLInputElement; + slider.max = String(max); + slider.value = String(msg.traceIndex ?? 0); + + $("#traceMax").innerHTML = "/" + (msg.traceComplete ? String(max) : "?"); + $("#indexCounter").innerHTML = String(msg.traceIndex ?? 0); + + updateVisualization(msg.traceElem); + updateIndent(msg.traceElem); + updateRefArrows(msg.traceElem); +}); + +// Browser-only navigation handling +if (!isVscode) { + + window.addEventListener("programflow:onClick", (e: Event) => { + const ce = e as CustomEvent<{ type: "first" | "prev" | "next" | "last" }>; + const max = Math.max(0, trace.length - 1); + + switch (ce.detail.type) { + case "first": + traceIndex = 0; + break; + + case "prev": + traceIndex = Math.max(0, traceIndex - 1); + break; + + case "next": + traceIndex = Math.min(max, traceIndex + 1); + break; + + case "last": + traceIndex = max; + break; + } + + renderCurrent(); + }); + + window.addEventListener("programflow:onSlide", (e: Event) => { + const ce = e as CustomEvent<{ value: string }>; + traceIndex = Number(ce.detail.value) || 0; + renderCurrent(); + }); + +} + + +function setupUi() { + // Disable until first reset arrives + setDisabled("#nextButton", true); + setDisabled("#lastButton", true); + setDisabled("#prevButton", true); + setDisabled("#firstButton", true); + + // Button clicks -> dispatch events (adapter forwards to VS Code) + $("#firstButton").addEventListener("click", () => { + window.dispatchEvent(new CustomEvent("programflow:onClick", { detail: { type: "first" } })); + }); + $("#prevButton").addEventListener("click", () => { + window.dispatchEvent(new CustomEvent("programflow:onClick", { detail: { type: "prev" } })); + }); + $("#nextButton").addEventListener("click", () => { + window.dispatchEvent(new CustomEvent("programflow:onClick", { detail: { type: "next" } })); + }); + $("#lastButton").addEventListener("click", () => { + window.dispatchEvent(new CustomEvent("programflow:onClick", { detail: { type: "last" } })); + }); + + // Slider input -> dispatch event + ($("#traceSlider") as HTMLInputElement).addEventListener("input", (e: Event) => { + const value = (e.target as HTMLInputElement).value; + window.dispatchEvent(new CustomEvent("programflow:onSlide", { detail: { value } })); + }); + + // Optional: example trace mode + const anyWin = window as any; + const staticTrace: StaticTrace | undefined = anyWin.__PROGRAMFLOW_TRACE__; + + console.log("static trace mode:", !!staticTrace?.trace, staticTrace?.trace?.length); + + if (staticTrace?.trace) { + trace = staticTrace.trace; + traceComplete = !!staticTrace.complete; + traceIndex = 0; + renderCurrent(); + } +} + +document.addEventListener("DOMContentLoaded", setupUi); \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index b65c7451..342b7493 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,6 +6,7 @@ "lib": [ "es6" ], + "types": ["node"], "sourceMap": true, "rootDir": "src", "strict": true /* enable all strict type-checking options */ @@ -16,6 +17,7 @@ }, "exclude": [ "node_modules", - ".vscode-test" + ".vscode-test", + "src/programflow-visualization/web/**" ] } diff --git a/webpack.config.js b/webpack.config.js deleted file mode 100644 index 136b385b..00000000 --- a/webpack.config.js +++ /dev/null @@ -1,12 +0,0 @@ -const path = require('path'); - -module.exports = { - entry: { - linkerline: './media/programflow-visualization/linkerline.js', - }, - output: { - path: path.resolve(__dirname, 'out'), - filename: '[name].bundle.js', - }, - mode: "production" -};