diff --git a/README.md b/README.md
index 06c1220c7..a5f036ef9 100644
--- a/README.md
+++ b/README.md
@@ -11,10 +11,10 @@ Front-end of [ComfyUI](https://github.com/comfyanonymous/ComfyUI) modernized. Th
- Added a shim layer to be backward compatible with the existing extension system. https://github.com/huchenlei/ComfyUI_frontend/pull/15
- Front-end dev server.
- Zod schema for input validation on ComfyUI workflow.
+- Make litegraph a npm dependency.
### What to be done
-- Make litegraph a npm dependency.
- Replace the existing ComfyUI front-end impl.
- Turn on `strict` on `tsconfig.json`.
- Introduce react to start managing part of the UI.
diff --git a/browser_tests/ComfyPage.ts b/browser_tests/ComfyPage.ts
index 742e9aedc..97d21afc1 100644
--- a/browser_tests/ComfyPage.ts
+++ b/browser_tests/ComfyPage.ts
@@ -38,6 +38,8 @@ export class ComfyPage {
async resetView() {
await this.resetViewButton.click();
+ // Avoid "Reset View" button highlight.
+ await this.page.mouse.move(10, 10);
await this.nextFrame();
}
diff --git a/browser_tests/interaction.spec.ts-snapshots/adjusted-widget-value-chromium-linux.png b/browser_tests/interaction.spec.ts-snapshots/adjusted-widget-value-chromium-linux.png
index a8cb5d004..ca6ede7f4 100644
Binary files a/browser_tests/interaction.spec.ts-snapshots/adjusted-widget-value-chromium-linux.png and b/browser_tests/interaction.spec.ts-snapshots/adjusted-widget-value-chromium-linux.png differ
diff --git a/browser_tests/interaction.spec.ts-snapshots/adjusted-widget-value-chromium-win32.png b/browser_tests/interaction.spec.ts-snapshots/adjusted-widget-value-chromium-win32.png
index 097e16ebd..d5594d4ca 100644
Binary files a/browser_tests/interaction.spec.ts-snapshots/adjusted-widget-value-chromium-win32.png and b/browser_tests/interaction.spec.ts-snapshots/adjusted-widget-value-chromium-win32.png differ
diff --git a/browser_tests/interaction.spec.ts-snapshots/default-chromium-linux.png b/browser_tests/interaction.spec.ts-snapshots/default-chromium-linux.png
index 1b8629a5e..e364f03a9 100644
Binary files a/browser_tests/interaction.spec.ts-snapshots/default-chromium-linux.png and b/browser_tests/interaction.spec.ts-snapshots/default-chromium-linux.png differ
diff --git a/browser_tests/interaction.spec.ts-snapshots/default-chromium-win32.png b/browser_tests/interaction.spec.ts-snapshots/default-chromium-win32.png
index 36964c27b..967a7b4fa 100644
Binary files a/browser_tests/interaction.spec.ts-snapshots/default-chromium-win32.png and b/browser_tests/interaction.spec.ts-snapshots/default-chromium-win32.png differ
diff --git a/browser_tests/interaction.spec.ts-snapshots/disconnected-edge-with-menu-chromium-linux.png b/browser_tests/interaction.spec.ts-snapshots/disconnected-edge-with-menu-chromium-linux.png
index 450939e70..2786ddee9 100644
Binary files a/browser_tests/interaction.spec.ts-snapshots/disconnected-edge-with-menu-chromium-linux.png and b/browser_tests/interaction.spec.ts-snapshots/disconnected-edge-with-menu-chromium-linux.png differ
diff --git a/browser_tests/interaction.spec.ts-snapshots/disconnected-edge-with-menu-chromium-win32.png b/browser_tests/interaction.spec.ts-snapshots/disconnected-edge-with-menu-chromium-win32.png
index 6ef707045..20ee5b816 100644
Binary files a/browser_tests/interaction.spec.ts-snapshots/disconnected-edge-with-menu-chromium-win32.png and b/browser_tests/interaction.spec.ts-snapshots/disconnected-edge-with-menu-chromium-win32.png differ
diff --git a/browser_tests/interaction.spec.ts-snapshots/panned-chromium-linux.png b/browser_tests/interaction.spec.ts-snapshots/panned-chromium-linux.png
index 0f7c30613..da1dd83d9 100644
Binary files a/browser_tests/interaction.spec.ts-snapshots/panned-chromium-linux.png and b/browser_tests/interaction.spec.ts-snapshots/panned-chromium-linux.png differ
diff --git a/browser_tests/interaction.spec.ts-snapshots/panned-chromium-win32.png b/browser_tests/interaction.spec.ts-snapshots/panned-chromium-win32.png
index 069848b02..28d787386 100644
Binary files a/browser_tests/interaction.spec.ts-snapshots/panned-chromium-win32.png and b/browser_tests/interaction.spec.ts-snapshots/panned-chromium-win32.png differ
diff --git a/browser_tests/interaction.spec.ts-snapshots/selected-node1-chromium-linux.png b/browser_tests/interaction.spec.ts-snapshots/selected-node1-chromium-linux.png
index 32de7e50b..bbe682f83 100644
Binary files a/browser_tests/interaction.spec.ts-snapshots/selected-node1-chromium-linux.png and b/browser_tests/interaction.spec.ts-snapshots/selected-node1-chromium-linux.png differ
diff --git a/browser_tests/interaction.spec.ts-snapshots/selected-node1-chromium-win32.png b/browser_tests/interaction.spec.ts-snapshots/selected-node1-chromium-win32.png
index 4aeb32f98..c12e91382 100644
Binary files a/browser_tests/interaction.spec.ts-snapshots/selected-node1-chromium-win32.png and b/browser_tests/interaction.spec.ts-snapshots/selected-node1-chromium-win32.png differ
diff --git a/browser_tests/interaction.spec.ts-snapshots/selected-node2-chromium-linux.png b/browser_tests/interaction.spec.ts-snapshots/selected-node2-chromium-linux.png
index 0060e9330..17e635f2a 100644
Binary files a/browser_tests/interaction.spec.ts-snapshots/selected-node2-chromium-linux.png and b/browser_tests/interaction.spec.ts-snapshots/selected-node2-chromium-linux.png differ
diff --git a/browser_tests/interaction.spec.ts-snapshots/selected-node2-chromium-win32.png b/browser_tests/interaction.spec.ts-snapshots/selected-node2-chromium-win32.png
index 24457766c..a4a367c0d 100644
Binary files a/browser_tests/interaction.spec.ts-snapshots/selected-node2-chromium-win32.png and b/browser_tests/interaction.spec.ts-snapshots/selected-node2-chromium-win32.png differ
diff --git a/browser_tests/interaction.spec.ts-snapshots/zoomed-in-chromium-linux.png b/browser_tests/interaction.spec.ts-snapshots/zoomed-in-chromium-linux.png
index e32881a78..791c74151 100644
Binary files a/browser_tests/interaction.spec.ts-snapshots/zoomed-in-chromium-linux.png and b/browser_tests/interaction.spec.ts-snapshots/zoomed-in-chromium-linux.png differ
diff --git a/browser_tests/interaction.spec.ts-snapshots/zoomed-in-chromium-win32.png b/browser_tests/interaction.spec.ts-snapshots/zoomed-in-chromium-win32.png
index 1c5cb815a..c94ece8ce 100644
Binary files a/browser_tests/interaction.spec.ts-snapshots/zoomed-in-chromium-win32.png and b/browser_tests/interaction.spec.ts-snapshots/zoomed-in-chromium-win32.png differ
diff --git a/browser_tests/interaction.spec.ts-snapshots/zoomed-out-chromium-linux.png b/browser_tests/interaction.spec.ts-snapshots/zoomed-out-chromium-linux.png
index d52586f3b..0ac44001a 100644
Binary files a/browser_tests/interaction.spec.ts-snapshots/zoomed-out-chromium-linux.png and b/browser_tests/interaction.spec.ts-snapshots/zoomed-out-chromium-linux.png differ
diff --git a/browser_tests/interaction.spec.ts-snapshots/zoomed-out-chromium-win32.png b/browser_tests/interaction.spec.ts-snapshots/zoomed-out-chromium-win32.png
index 9060879f6..967a7b4fa 100644
Binary files a/browser_tests/interaction.spec.ts-snapshots/zoomed-out-chromium-win32.png and b/browser_tests/interaction.spec.ts-snapshots/zoomed-out-chromium-win32.png differ
diff --git a/browser_tests/rightClickMenu.spec.ts-snapshots/right-click-node-chromium-linux.png b/browser_tests/rightClickMenu.spec.ts-snapshots/right-click-node-chromium-linux.png
index c540d0c27..e24037e18 100644
Binary files a/browser_tests/rightClickMenu.spec.ts-snapshots/right-click-node-chromium-linux.png and b/browser_tests/rightClickMenu.spec.ts-snapshots/right-click-node-chromium-linux.png differ
diff --git a/browser_tests/rightClickMenu.spec.ts-snapshots/right-click-node-chromium-win32.png b/browser_tests/rightClickMenu.spec.ts-snapshots/right-click-node-chromium-win32.png
index 603ae8846..a1460ffb2 100644
Binary files a/browser_tests/rightClickMenu.spec.ts-snapshots/right-click-node-chromium-win32.png and b/browser_tests/rightClickMenu.spec.ts-snapshots/right-click-node-chromium-win32.png differ
diff --git a/browser_tests/rightClickMenu.spec.ts-snapshots/right-click-node-collapsed-chromium-linux.png b/browser_tests/rightClickMenu.spec.ts-snapshots/right-click-node-collapsed-chromium-linux.png
index 22c2b8658..3eec3f233 100644
Binary files a/browser_tests/rightClickMenu.spec.ts-snapshots/right-click-node-collapsed-chromium-linux.png and b/browser_tests/rightClickMenu.spec.ts-snapshots/right-click-node-collapsed-chromium-linux.png differ
diff --git a/browser_tests/rightClickMenu.spec.ts-snapshots/right-click-node-collapsed-chromium-win32.png b/browser_tests/rightClickMenu.spec.ts-snapshots/right-click-node-collapsed-chromium-win32.png
index 294716652..b11730051 100644
Binary files a/browser_tests/rightClickMenu.spec.ts-snapshots/right-click-node-collapsed-chromium-win32.png and b/browser_tests/rightClickMenu.spec.ts-snapshots/right-click-node-collapsed-chromium-win32.png differ
diff --git a/browser_tests/rightClickMenu.spec.ts-snapshots/right-click-node-group-node-chromium-linux.png b/browser_tests/rightClickMenu.spec.ts-snapshots/right-click-node-group-node-chromium-linux.png
index ebab40000..45ab0746f 100644
Binary files a/browser_tests/rightClickMenu.spec.ts-snapshots/right-click-node-group-node-chromium-linux.png and b/browser_tests/rightClickMenu.spec.ts-snapshots/right-click-node-group-node-chromium-linux.png differ
diff --git a/browser_tests/rightClickMenu.spec.ts-snapshots/right-click-node-group-node-chromium-win32.png b/browser_tests/rightClickMenu.spec.ts-snapshots/right-click-node-group-node-chromium-win32.png
index da2043bd7..0f350f11a 100644
Binary files a/browser_tests/rightClickMenu.spec.ts-snapshots/right-click-node-group-node-chromium-win32.png and b/browser_tests/rightClickMenu.spec.ts-snapshots/right-click-node-group-node-chromium-win32.png differ
diff --git a/browser_tests/rightClickMenu.spec.ts-snapshots/right-click-node-properties-panel-chromium-linux.png b/browser_tests/rightClickMenu.spec.ts-snapshots/right-click-node-properties-panel-chromium-linux.png
index 477efc00e..f898378e2 100644
Binary files a/browser_tests/rightClickMenu.spec.ts-snapshots/right-click-node-properties-panel-chromium-linux.png and b/browser_tests/rightClickMenu.spec.ts-snapshots/right-click-node-properties-panel-chromium-linux.png differ
diff --git a/browser_tests/rightClickMenu.spec.ts-snapshots/right-click-node-properties-panel-chromium-win32.png b/browser_tests/rightClickMenu.spec.ts-snapshots/right-click-node-properties-panel-chromium-win32.png
index 49427089d..4b21608ae 100644
Binary files a/browser_tests/rightClickMenu.spec.ts-snapshots/right-click-node-properties-panel-chromium-win32.png and b/browser_tests/rightClickMenu.spec.ts-snapshots/right-click-node-properties-panel-chromium-win32.png differ
diff --git a/browser_tests/rightClickMenu.spec.ts-snapshots/right-click-node-widget-converted-chromium-linux.png b/browser_tests/rightClickMenu.spec.ts-snapshots/right-click-node-widget-converted-chromium-linux.png
index 967e80d90..d40e0a585 100644
Binary files a/browser_tests/rightClickMenu.spec.ts-snapshots/right-click-node-widget-converted-chromium-linux.png and b/browser_tests/rightClickMenu.spec.ts-snapshots/right-click-node-widget-converted-chromium-linux.png differ
diff --git a/browser_tests/rightClickMenu.spec.ts-snapshots/right-click-node-widget-converted-chromium-win32.png b/browser_tests/rightClickMenu.spec.ts-snapshots/right-click-node-widget-converted-chromium-win32.png
index 7de0f30a0..11c30d344 100644
Binary files a/browser_tests/rightClickMenu.spec.ts-snapshots/right-click-node-widget-converted-chromium-win32.png and b/browser_tests/rightClickMenu.spec.ts-snapshots/right-click-node-widget-converted-chromium-win32.png differ
diff --git a/browser_tests/rightClickMenu.spec.ts-snapshots/selected-2-nodes-chromium-linux.png b/browser_tests/rightClickMenu.spec.ts-snapshots/selected-2-nodes-chromium-linux.png
index 817495702..3ed7d43d2 100644
Binary files a/browser_tests/rightClickMenu.spec.ts-snapshots/selected-2-nodes-chromium-linux.png and b/browser_tests/rightClickMenu.spec.ts-snapshots/selected-2-nodes-chromium-linux.png differ
diff --git a/browser_tests/rightClickMenu.spec.ts-snapshots/selected-2-nodes-chromium-win32.png b/browser_tests/rightClickMenu.spec.ts-snapshots/selected-2-nodes-chromium-win32.png
index 69de4cd73..b7eefd87c 100644
Binary files a/browser_tests/rightClickMenu.spec.ts-snapshots/selected-2-nodes-chromium-win32.png and b/browser_tests/rightClickMenu.spec.ts-snapshots/selected-2-nodes-chromium-win32.png differ
diff --git a/index.html b/index.html
index cb641816b..a43969556 100644
--- a/index.html
+++ b/index.html
@@ -12,12 +12,6 @@
font-family: 'Roboto Mono', 'Noto Color Emoji';
}
-->
-
-
-
-
-
-
+
+
diff --git a/package-lock.json b/package-lock.json
index 97768d3c4..20a8f857f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,13 +1,14 @@
{
"name": "comfyui-frontend",
- "version": "1.0.0",
+ "version": "1.0.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "comfyui-frontend",
- "version": "1.0.0",
+ "version": "1.0.1",
"dependencies": {
+ "@comfyorg/litegraph": "^0.7.20",
"dotenv": "^16.4.5",
"zod": "^3.23.8",
"zod-validation-error": "^3.3.0"
@@ -1775,6 +1776,11 @@
"integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
"dev": true
},
+ "node_modules/@comfyorg/litegraph": {
+ "version": "0.7.20",
+ "resolved": "https://registry.npmjs.org/@comfyorg/litegraph/-/litegraph-0.7.20.tgz",
+ "integrity": "sha512-MOXObIlBhfPWHCT5/mQeYQhU1fh1Qtfmq6fzEBCiJHRvxTSFPMtaLe+h3GDrE1ZUlbJJ9Q/22UJnpHrPyWYeqg=="
+ },
"node_modules/@cspotcode/source-map-support": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
@@ -1798,9 +1804,9 @@
}
},
"node_modules/@esbuild/aix-ppc64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz",
- "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
+ "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==",
"cpu": [
"ppc64"
],
@@ -1814,9 +1820,9 @@
}
},
"node_modules/@esbuild/android-arm": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz",
- "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz",
+ "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==",
"cpu": [
"arm"
],
@@ -1830,9 +1836,9 @@
}
},
"node_modules/@esbuild/android-arm64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz",
- "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz",
+ "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==",
"cpu": [
"arm64"
],
@@ -1846,9 +1852,9 @@
}
},
"node_modules/@esbuild/android-x64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz",
- "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz",
+ "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==",
"cpu": [
"x64"
],
@@ -1862,9 +1868,9 @@
}
},
"node_modules/@esbuild/darwin-arm64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz",
- "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz",
+ "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==",
"cpu": [
"arm64"
],
@@ -1878,9 +1884,9 @@
}
},
"node_modules/@esbuild/darwin-x64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz",
- "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz",
+ "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==",
"cpu": [
"x64"
],
@@ -1894,9 +1900,9 @@
}
},
"node_modules/@esbuild/freebsd-arm64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz",
- "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz",
+ "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==",
"cpu": [
"arm64"
],
@@ -1910,9 +1916,9 @@
}
},
"node_modules/@esbuild/freebsd-x64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz",
- "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz",
+ "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==",
"cpu": [
"x64"
],
@@ -1926,9 +1932,9 @@
}
},
"node_modules/@esbuild/linux-arm": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz",
- "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz",
+ "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==",
"cpu": [
"arm"
],
@@ -1942,9 +1948,9 @@
}
},
"node_modules/@esbuild/linux-arm64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz",
- "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz",
+ "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==",
"cpu": [
"arm64"
],
@@ -1958,9 +1964,9 @@
}
},
"node_modules/@esbuild/linux-ia32": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz",
- "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz",
+ "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==",
"cpu": [
"ia32"
],
@@ -1974,9 +1980,9 @@
}
},
"node_modules/@esbuild/linux-loong64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz",
- "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz",
+ "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==",
"cpu": [
"loong64"
],
@@ -1990,9 +1996,9 @@
}
},
"node_modules/@esbuild/linux-mips64el": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz",
- "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz",
+ "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==",
"cpu": [
"mips64el"
],
@@ -2006,9 +2012,9 @@
}
},
"node_modules/@esbuild/linux-ppc64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz",
- "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz",
+ "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==",
"cpu": [
"ppc64"
],
@@ -2022,9 +2028,9 @@
}
},
"node_modules/@esbuild/linux-riscv64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz",
- "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz",
+ "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==",
"cpu": [
"riscv64"
],
@@ -2038,9 +2044,9 @@
}
},
"node_modules/@esbuild/linux-s390x": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz",
- "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz",
+ "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==",
"cpu": [
"s390x"
],
@@ -2054,9 +2060,9 @@
}
},
"node_modules/@esbuild/linux-x64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz",
- "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz",
+ "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==",
"cpu": [
"x64"
],
@@ -2070,9 +2076,9 @@
}
},
"node_modules/@esbuild/netbsd-x64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz",
- "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz",
+ "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==",
"cpu": [
"x64"
],
@@ -2086,9 +2092,9 @@
}
},
"node_modules/@esbuild/openbsd-x64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz",
- "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz",
+ "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==",
"cpu": [
"x64"
],
@@ -2102,9 +2108,9 @@
}
},
"node_modules/@esbuild/sunos-x64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz",
- "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz",
+ "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==",
"cpu": [
"x64"
],
@@ -2118,9 +2124,9 @@
}
},
"node_modules/@esbuild/win32-arm64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz",
- "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz",
+ "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==",
"cpu": [
"arm64"
],
@@ -2134,9 +2140,9 @@
}
},
"node_modules/@esbuild/win32-ia32": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz",
- "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz",
+ "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==",
"cpu": [
"ia32"
],
@@ -2150,9 +2156,9 @@
}
},
"node_modules/@esbuild/win32-x64": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz",
- "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz",
+ "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==",
"cpu": [
"x64"
],
@@ -2902,18 +2908,18 @@
}
},
"node_modules/@playwright/test": {
- "version": "1.44.1",
- "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.44.1.tgz",
- "integrity": "sha512-1hZ4TNvD5z9VuhNJ/walIjvMVvYkZKf71axoF/uiAqpntQJXpG64dlXhoDXE3OczPuTuvjf/M5KWFg5VAVUS3Q==",
+ "version": "1.45.1",
+ "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.45.1.tgz",
+ "integrity": "sha512-Wo1bWTzQvGA7LyKGIZc8nFSTFf2TkthGIFBR+QVNilvwouGzFd4PYukZe3rvf5PSqjHi1+1NyKSDZKcQWETzaA==",
"dev": true,
"dependencies": {
- "playwright": "1.44.1"
+ "playwright": "1.45.1"
},
"bin": {
"playwright": "cli.js"
},
"engines": {
- "node": ">=16"
+ "node": ">=18"
}
},
"node_modules/@rollup/rollup-android-arm-eabi": {
@@ -3283,9 +3289,9 @@
}
},
"node_modules/@types/node": {
- "version": "20.14.8",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.8.tgz",
- "integrity": "sha512-DO+2/jZinXfROG7j7WKFn/3C6nFwxy2lLpgLjEXJz+0XKphZlTLJ14mo8Vfg8X5BWN6XjyESXq+LcYdT7tR3bA==",
+ "version": "20.14.10",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz",
+ "integrity": "sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==",
"dev": true,
"dependencies": {
"undici-types": "~5.26.4"
@@ -3326,9 +3332,9 @@
"dev": true
},
"node_modules/acorn": {
- "version": "8.12.0",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz",
- "integrity": "sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==",
+ "version": "8.12.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz",
+ "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==",
"dev": true,
"bin": {
"acorn": "bin/acorn"
@@ -3800,9 +3806,9 @@
}
},
"node_modules/caniuse-lite": {
- "version": "1.0.30001634",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001634.tgz",
- "integrity": "sha512-fbBYXQ9q3+yp1q1gBk86tOFs4pyn/yxFm5ZNP18OXJDfA3txImOY9PhfxVggZ4vRHDqoU8NrKU81eN0OtzOgRA==",
+ "version": "1.0.30001640",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001640.tgz",
+ "integrity": "sha512-lA4VMpW0PSUrFnkmVuEKBUovSWKhj7puyCg8StBChgu298N1AtuF1sKWEvfDuimSEDbhlb/KqPKC3fs1HbuQUA==",
"dev": true,
"funding": [
{
@@ -3918,56 +3924,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/cli-truncate/node_modules/ansi-regex": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
- "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
- "dev": true,
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-regex?sponsor=1"
- }
- },
- "node_modules/cli-truncate/node_modules/emoji-regex": {
- "version": "10.3.0",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz",
- "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==",
- "dev": true
- },
- "node_modules/cli-truncate/node_modules/string-width": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz",
- "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==",
- "dev": true,
- "dependencies": {
- "emoji-regex": "^10.3.0",
- "get-east-asian-width": "^1.0.0",
- "strip-ansi": "^7.1.0"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/cli-truncate/node_modules/strip-ansi": {
- "version": "7.1.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
- "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
- "dev": true,
- "dependencies": {
- "ansi-regex": "^6.0.1"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/strip-ansi?sponsor=1"
- }
- },
"node_modules/cliui": {
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
@@ -3982,6 +3938,85 @@
"node": ">=12"
}
},
+ "node_modules/cliui/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/cliui/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/cliui/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/cliui/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/cliui/node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cliui/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cliui/node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
"node_modules/co": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
@@ -4327,9 +4362,9 @@
}
},
"node_modules/electron-to-chromium": {
- "version": "1.4.803",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.803.tgz",
- "integrity": "sha512-61H9mLzGOCLLVsnLiRzCbc63uldP0AniRYPV3hbGVtONA1pI7qSGILdbofR7A8TMbOypDocEAjH/e+9k1QIe3g==",
+ "version": "1.4.817",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.817.tgz",
+ "integrity": "sha512-3znu+lZMIbTe8ZOs360OMJvVroVF2NpNI8T5jfLnDetVvj0uNmIucZzQVYMSJfsu9f47Ssox1Gt46PR+R+1JUg==",
"dev": true
},
"node_modules/emittery": {
@@ -4345,9 +4380,9 @@
}
},
"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==",
+ "version": "10.3.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz",
+ "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==",
"dev": true
},
"node_modules/entities": {
@@ -4372,9 +4407,9 @@
}
},
"node_modules/esbuild": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz",
- "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==",
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
+ "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",
"dev": true,
"hasInstallScript": true,
"bin": {
@@ -4384,29 +4419,29 @@
"node": ">=12"
},
"optionalDependencies": {
- "@esbuild/aix-ppc64": "0.20.2",
- "@esbuild/android-arm": "0.20.2",
- "@esbuild/android-arm64": "0.20.2",
- "@esbuild/android-x64": "0.20.2",
- "@esbuild/darwin-arm64": "0.20.2",
- "@esbuild/darwin-x64": "0.20.2",
- "@esbuild/freebsd-arm64": "0.20.2",
- "@esbuild/freebsd-x64": "0.20.2",
- "@esbuild/linux-arm": "0.20.2",
- "@esbuild/linux-arm64": "0.20.2",
- "@esbuild/linux-ia32": "0.20.2",
- "@esbuild/linux-loong64": "0.20.2",
- "@esbuild/linux-mips64el": "0.20.2",
- "@esbuild/linux-ppc64": "0.20.2",
- "@esbuild/linux-riscv64": "0.20.2",
- "@esbuild/linux-s390x": "0.20.2",
- "@esbuild/linux-x64": "0.20.2",
- "@esbuild/netbsd-x64": "0.20.2",
- "@esbuild/openbsd-x64": "0.20.2",
- "@esbuild/sunos-x64": "0.20.2",
- "@esbuild/win32-arm64": "0.20.2",
- "@esbuild/win32-ia32": "0.20.2",
- "@esbuild/win32-x64": "0.20.2"
+ "@esbuild/aix-ppc64": "0.21.5",
+ "@esbuild/android-arm": "0.21.5",
+ "@esbuild/android-arm64": "0.21.5",
+ "@esbuild/android-x64": "0.21.5",
+ "@esbuild/darwin-arm64": "0.21.5",
+ "@esbuild/darwin-x64": "0.21.5",
+ "@esbuild/freebsd-arm64": "0.21.5",
+ "@esbuild/freebsd-x64": "0.21.5",
+ "@esbuild/linux-arm": "0.21.5",
+ "@esbuild/linux-arm64": "0.21.5",
+ "@esbuild/linux-ia32": "0.21.5",
+ "@esbuild/linux-loong64": "0.21.5",
+ "@esbuild/linux-mips64el": "0.21.5",
+ "@esbuild/linux-ppc64": "0.21.5",
+ "@esbuild/linux-riscv64": "0.21.5",
+ "@esbuild/linux-s390x": "0.21.5",
+ "@esbuild/linux-x64": "0.21.5",
+ "@esbuild/netbsd-x64": "0.21.5",
+ "@esbuild/openbsd-x64": "0.21.5",
+ "@esbuild/sunos-x64": "0.21.5",
+ "@esbuild/win32-arm64": "0.21.5",
+ "@esbuild/win32-ia32": "0.21.5",
+ "@esbuild/win32-x64": "0.21.5"
}
},
"node_modules/escalade": {
@@ -4965,12 +5000,15 @@
}
},
"node_modules/is-core-module": {
- "version": "2.13.1",
- "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz",
- "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==",
+ "version": "2.14.0",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.14.0.tgz",
+ "integrity": "sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==",
"dev": true,
"dependencies": {
- "hasown": "^2.0.0"
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -4986,12 +5024,15 @@
}
},
"node_modules/is-fullwidth-code-point": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
- "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz",
+ "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==",
"dev": true,
"engines": {
- "node": ">=8"
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/is-generator-fn": {
@@ -5064,9 +5105,9 @@
}
},
"node_modules/istanbul-lib-instrument": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.2.tgz",
- "integrity": "sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw==",
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz",
+ "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==",
"dev": true,
"dependencies": {
"@babel/core": "^7.23.9",
@@ -7098,85 +7139,6 @@
"node": ">=18.0.0"
}
},
- "node_modules/listr2/node_modules/ansi-regex": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
- "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
- "dev": true,
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-regex?sponsor=1"
- }
- },
- "node_modules/listr2/node_modules/ansi-styles": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
- "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
- "dev": true,
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/listr2/node_modules/emoji-regex": {
- "version": "10.3.0",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz",
- "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==",
- "dev": true
- },
- "node_modules/listr2/node_modules/string-width": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz",
- "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==",
- "dev": true,
- "dependencies": {
- "emoji-regex": "^10.3.0",
- "get-east-asian-width": "^1.0.0",
- "strip-ansi": "^7.1.0"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/listr2/node_modules/strip-ansi": {
- "version": "7.1.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
- "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
- "dev": true,
- "dependencies": {
- "ansi-regex": "^6.0.1"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/strip-ansi?sponsor=1"
- }
- },
- "node_modules/listr2/node_modules/wrap-ansi": {
- "version": "9.0.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz",
- "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==",
- "dev": true,
- "dependencies": {
- "ansi-styles": "^6.2.1",
- "string-width": "^7.0.0",
- "strip-ansi": "^7.1.0"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
- }
- },
"node_modules/locate-path": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
@@ -7256,12 +7218,6 @@
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
- "node_modules/log-update/node_modules/emoji-regex": {
- "version": "10.3.0",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz",
- "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==",
- "dev": true
- },
"node_modules/log-update/node_modules/is-fullwidth-code-point": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz",
@@ -7293,23 +7249,6 @@
"url": "https://github.com/chalk/slice-ansi?sponsor=1"
}
},
- "node_modules/log-update/node_modules/string-width": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz",
- "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==",
- "dev": true,
- "dependencies": {
- "emoji-regex": "^10.3.0",
- "get-east-asian-width": "^1.0.0",
- "strip-ansi": "^7.1.0"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/log-update/node_modules/strip-ansi": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
@@ -7325,23 +7264,6 @@
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
}
},
- "node_modules/log-update/node_modules/wrap-ansi": {
- "version": "9.0.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz",
- "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==",
- "dev": true,
- "dependencies": {
- "ansi-styles": "^6.2.1",
- "string-width": "^7.0.0",
- "strip-ansi": "^7.1.0"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
- }
- },
"node_modules/lru-cache": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
@@ -7728,33 +7650,33 @@
}
},
"node_modules/playwright": {
- "version": "1.44.1",
- "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.44.1.tgz",
- "integrity": "sha512-qr/0UJ5CFAtloI3avF95Y0L1xQo6r3LQArLIg/z/PoGJ6xa+EwzrwO5lpNr/09STxdHuUoP2mvuELJS+hLdtgg==",
+ "version": "1.45.1",
+ "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.45.1.tgz",
+ "integrity": "sha512-Hjrgae4kpSQBr98nhCj3IScxVeVUixqj+5oyif8TdIn2opTCPEzqAqNMeK42i3cWDCVu9MI+ZsGWw+gVR4ISBg==",
"dev": true,
"dependencies": {
- "playwright-core": "1.44.1"
+ "playwright-core": "1.45.1"
},
"bin": {
"playwright": "cli.js"
},
"engines": {
- "node": ">=16"
+ "node": ">=18"
},
"optionalDependencies": {
"fsevents": "2.3.2"
}
},
"node_modules/playwright-core": {
- "version": "1.44.1",
- "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.44.1.tgz",
- "integrity": "sha512-wh0JWtYTrhv1+OSsLPgFzGzt67Y7BE/ZS3jEqgGBlp2ppp1ZDj8c+9IARNW4dwf1poq5MgHreEM2KV/GuR4cFA==",
+ "version": "1.45.1",
+ "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.45.1.tgz",
+ "integrity": "sha512-LF4CUUtrUu2TCpDw4mcrAIuYrEjVDfT1cHbJMfwnE2+1b8PZcFzPNgvZCvq2JfQ4aTjRCCHw5EJ2tmr2NSzdPg==",
"dev": true,
"bin": {
"playwright-core": "cli.js"
},
"engines": {
- "node": ">=16"
+ "node": ">=18"
}
},
"node_modules/playwright/node_modules/fsevents": {
@@ -7772,9 +7694,9 @@
}
},
"node_modules/postcss": {
- "version": "8.4.38",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz",
- "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==",
+ "version": "8.4.39",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.39.tgz",
+ "integrity": "sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==",
"dev": true,
"funding": [
{
@@ -7792,7 +7714,7 @@
],
"dependencies": {
"nanoid": "^3.3.7",
- "picocolors": "^1.0.0",
+ "picocolors": "^1.0.1",
"source-map-js": "^1.2.0"
},
"engines": {
@@ -8290,18 +8212,6 @@
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
- "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz",
- "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==",
- "dev": true,
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
@@ -8389,17 +8299,47 @@
}
},
"node_modules/string-width": {
- "version": "4.2.3",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
- "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz",
+ "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==",
"dev": true,
"dependencies": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
+ "emoji-regex": "^10.3.0",
+ "get-east-asian-width": "^1.0.0",
+ "strip-ansi": "^7.1.0"
},
"engines": {
- "node": ">=8"
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/string-width/node_modules/ansi-regex": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
+ "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/string-width/node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
}
},
"node_modules/strip-ansi": {
@@ -8543,9 +8483,9 @@
}
},
"node_modules/ts-jest": {
- "version": "29.1.4",
- "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.4.tgz",
- "integrity": "sha512-YiHwDhSvCiItoAgsKtoLFCuakDzDsJ1DLDnSouTaTmdOcOwIkSzbLXduaQ6M5DRVhuZC/NYaaZ/mtHbWMv/S6Q==",
+ "version": "29.1.5",
+ "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.5.tgz",
+ "integrity": "sha512-UuClSYxM7byvvYfyWdFI+/2UxMmwNyJb0NPkZPQE2hew3RurV7l7zURgOHAd/1I1ZdPpe3GUsXNXAcN8TFKSIg==",
"dev": true,
"dependencies": {
"bs-logger": "0.x",
@@ -8651,12 +8591,12 @@
"dev": true
},
"node_modules/tsx": {
- "version": "4.15.6",
- "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.15.6.tgz",
- "integrity": "sha512-is0VQQlfNZRHEuSSTKA6m4xw74IU4AizmuB6lAYLRt9XtuyeQnyJYexhNZOPCB59SqC4JzmSzPnHGBXxf3k0hA==",
+ "version": "4.16.2",
+ "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.16.2.tgz",
+ "integrity": "sha512-C1uWweJDgdtX2x600HjaFaucXTilT7tgUZHbOE4+ypskZ1OP8CRCSDkCxG6Vya9EwaFIVagWwpaVAn5wzypaqQ==",
"dev": true,
"dependencies": {
- "esbuild": "~0.21.4",
+ "esbuild": "~0.21.5",
"get-tsconfig": "^4.7.5"
},
"bin": {
@@ -8669,412 +8609,6 @@
"fsevents": "~2.3.3"
}
},
- "node_modules/tsx/node_modules/@esbuild/aix-ppc64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
- "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==",
- "cpu": [
- "ppc64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "aix"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/android-arm": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz",
- "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/android-arm64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz",
- "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/android-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz",
- "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/darwin-arm64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz",
- "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/darwin-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz",
- "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/freebsd-arm64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz",
- "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/freebsd-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz",
- "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/linux-arm": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz",
- "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/linux-arm64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz",
- "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/linux-ia32": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz",
- "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/linux-loong64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz",
- "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==",
- "cpu": [
- "loong64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/linux-mips64el": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz",
- "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==",
- "cpu": [
- "mips64el"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/linux-ppc64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz",
- "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==",
- "cpu": [
- "ppc64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/linux-riscv64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz",
- "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==",
- "cpu": [
- "riscv64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/linux-s390x": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz",
- "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==",
- "cpu": [
- "s390x"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/linux-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz",
- "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/netbsd-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz",
- "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/openbsd-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz",
- "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/sunos-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz",
- "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "sunos"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/win32-arm64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz",
- "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/win32-ia32": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz",
- "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/tsx/node_modules/@esbuild/win32-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz",
- "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/tsx/node_modules/esbuild": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
- "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",
- "dev": true,
- "hasInstallScript": true,
- "bin": {
- "esbuild": "bin/esbuild"
- },
- "engines": {
- "node": ">=12"
- },
- "optionalDependencies": {
- "@esbuild/aix-ppc64": "0.21.5",
- "@esbuild/android-arm": "0.21.5",
- "@esbuild/android-arm64": "0.21.5",
- "@esbuild/android-x64": "0.21.5",
- "@esbuild/darwin-arm64": "0.21.5",
- "@esbuild/darwin-x64": "0.21.5",
- "@esbuild/freebsd-arm64": "0.21.5",
- "@esbuild/freebsd-x64": "0.21.5",
- "@esbuild/linux-arm": "0.21.5",
- "@esbuild/linux-arm64": "0.21.5",
- "@esbuild/linux-ia32": "0.21.5",
- "@esbuild/linux-loong64": "0.21.5",
- "@esbuild/linux-mips64el": "0.21.5",
- "@esbuild/linux-ppc64": "0.21.5",
- "@esbuild/linux-riscv64": "0.21.5",
- "@esbuild/linux-s390x": "0.21.5",
- "@esbuild/linux-x64": "0.21.5",
- "@esbuild/netbsd-x64": "0.21.5",
- "@esbuild/openbsd-x64": "0.21.5",
- "@esbuild/sunos-x64": "0.21.5",
- "@esbuild/win32-arm64": "0.21.5",
- "@esbuild/win32-ia32": "0.21.5",
- "@esbuild/win32-x64": "0.21.5"
- }
- },
"node_modules/type-detect": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
@@ -9097,9 +8631,9 @@
}
},
"node_modules/typescript": {
- "version": "5.4.5",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz",
- "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==",
+ "version": "5.5.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz",
+ "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==",
"dev": true,
"bin": {
"tsc": "bin/tsc",
@@ -9165,9 +8699,9 @@
}
},
"node_modules/update-browserslist-db": {
- "version": "1.0.16",
- "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz",
- "integrity": "sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==",
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz",
+ "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==",
"dev": true,
"funding": [
{
@@ -9217,9 +8751,9 @@
"dev": true
},
"node_modules/v8-to-istanbul": {
- "version": "9.2.0",
- "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz",
- "integrity": "sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==",
+ "version": "9.3.0",
+ "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz",
+ "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==",
"dev": true,
"dependencies": {
"@jridgewell/trace-mapping": "^0.3.12",
@@ -9231,13 +8765,13 @@
}
},
"node_modules/vite": {
- "version": "5.2.13",
- "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.13.tgz",
- "integrity": "sha512-SSq1noJfY9pR3I1TUENL3rQYDQCFqgD+lM6fTRAM8Nv6Lsg5hDLaXkjETVeBt+7vZBCMoibD+6IWnT2mJ+Zb/A==",
+ "version": "5.3.3",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-5.3.3.tgz",
+ "integrity": "sha512-NPQdeCU0Dv2z5fu+ULotpuq5yfCS1BzKUIPhNbP3YBfAMGJXbt2nS+sbTFu+qchaqWTD+H3JK++nRwr6XIcp6A==",
"dev": true,
"dependencies": {
- "esbuild": "^0.20.1",
- "postcss": "^8.4.38",
+ "esbuild": "^0.21.3",
+ "postcss": "^8.4.39",
"rollup": "^4.13.0"
},
"bin": {
@@ -9286,9 +8820,9 @@
}
},
"node_modules/vite-plugin-static-copy": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/vite-plugin-static-copy/-/vite-plugin-static-copy-1.0.5.tgz",
- "integrity": "sha512-02k0Rox+buYdEOfeilKZSgs1gXfPf9RjVztZEIYZgVIxjsVZi6AXssjzdi+qW6zYt00d3bq+tpP2voVXN2fKLw==",
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/vite-plugin-static-copy/-/vite-plugin-static-copy-1.0.6.tgz",
+ "integrity": "sha512-3uSvsMwDVFZRitqoWHj0t4137Kz7UynnJeq1EZlRW7e25h2068fyIZX4ORCCOAkfp1FklGxJNVJBkBOD+PZIew==",
"dev": true,
"dependencies": {
"chokidar": "^3.5.3",
@@ -9383,55 +8917,61 @@
}
},
"node_modules/wrap-ansi": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
- "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz",
+ "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==",
"dev": true,
"dependencies": {
- "ansi-styles": "^4.0.0",
- "string-width": "^4.1.0",
- "strip-ansi": "^6.0.0"
+ "ansi-styles": "^6.2.1",
+ "string-width": "^7.0.0",
+ "strip-ansi": "^7.1.0"
},
"engines": {
- "node": ">=10"
+ "node": ">=18"
},
"funding": {
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
- "node_modules/wrap-ansi/node_modules/ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "node_modules/wrap-ansi/node_modules/ansi-regex": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
+ "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
"dev": true,
- "dependencies": {
- "color-convert": "^2.0.1"
- },
"engines": {
- "node": ">=8"
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/ansi-styles": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
+ "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
- "node_modules/wrap-ansi/node_modules/color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
- "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "node_modules/wrap-ansi/node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
"dev": true,
"dependencies": {
- "color-name": "~1.1.4"
+ "ansi-regex": "^6.0.1"
},
"engines": {
- "node": ">=7.0.0"
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
}
},
- "node_modules/wrap-ansi/node_modules/color-name": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
- "dev": true
- },
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
@@ -9452,9 +8992,9 @@
}
},
"node_modules/ws": {
- "version": "8.17.1",
- "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
- "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==",
+ "version": "8.18.0",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz",
+ "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==",
"dev": true,
"engines": {
"node": ">=10.0.0"
@@ -9541,6 +9081,35 @@
"node": ">=12"
}
},
+ "node_modules/yargs/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/yargs/node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/yargs/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/yn": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
diff --git a/package.json b/package.json
index 3d33abccb..0a445275e 100644
--- a/package.json
+++ b/package.json
@@ -37,6 +37,7 @@
"zip-dir": "^2.0.0"
},
"dependencies": {
+ "@comfyorg/litegraph": "^0.7.20",
"dotenv": "^16.4.5",
"zod": "^3.23.8",
"zod-validation-error": "^3.3.0"
@@ -47,4 +48,4 @@
"git add"
]
}
-}
\ No newline at end of file
+}
diff --git a/public/style.css b/src/assets/css/style.css
similarity index 99%
rename from public/style.css
rename to src/assets/css/style.css
index e983b652a..0ac857aff 100644
--- a/public/style.css
+++ b/src/assets/css/style.css
@@ -1,5 +1,3 @@
-@import url("scripts/ui/menu/menu.css");
-
:root {
--fg-color: #000;
--bg-color: #fff;
diff --git a/src/extensions/core/colorPalette.ts b/src/extensions/core/colorPalette.ts
index fea9d8e4d..04912b3c5 100644
--- a/src/extensions/core/colorPalette.ts
+++ b/src/extensions/core/colorPalette.ts
@@ -1,6 +1,7 @@
import { app } from "../../scripts/app";
import { $el } from "../../scripts/ui";
import type { ColorPalettes } from "/types/colorPalette";
+import { LGraphCanvas, LiteGraph } from "@comfyorg/litegraph";
// Manage color palettes
@@ -427,6 +428,32 @@ const els: { select: HTMLSelectElement | null } = {
// const ctxMenu = LiteGraph.ContextMenu;
app.registerExtension({
name: id,
+ init() {
+ /**
+ * Changes the background color of the canvas.
+ *
+ * @method updateBackground
+ * @param {image} String
+ * @param {clearBackgroundColor} String
+ */
+ // @ts-ignore
+ LGraphCanvas.prototype.updateBackground = function (
+ image,
+ clearBackgroundColor
+ ) {
+ this._bg_img = new Image();
+ this._bg_img.name = image;
+ this._bg_img.src = image;
+ this._bg_img.onload = () => {
+ this.draw(true, true);
+ };
+ this.background_image = image;
+
+ this.clear_background = true;
+ this.clear_background_color = clearBackgroundColor;
+ this._pattern = null;
+ };
+ },
addCustomNodeDefs(node_defs) {
const sortObjectKeys = (unordered) => {
return Object.keys(unordered)
diff --git a/src/extensions/core/contextMenuFilter.ts b/src/extensions/core/contextMenuFilter.ts
index 39f1c1a42..166146693 100644
--- a/src/extensions/core/contextMenuFilter.ts
+++ b/src/extensions/core/contextMenuFilter.ts
@@ -1,3 +1,4 @@
+import { LiteGraph, LGraphCanvas } from "@comfyorg/litegraph";
import { app } from "../../scripts/app";
// Adds filtering to combo context menus
diff --git a/src/extensions/core/groupNode.ts b/src/extensions/core/groupNode.ts
index f9592d0ff..aa2f8cf72 100644
--- a/src/extensions/core/groupNode.ts
+++ b/src/extensions/core/groupNode.ts
@@ -2,7 +2,8 @@ import { app } from "../../scripts/app";
import { api } from "../../scripts/api";
import { mergeIfValid } from "./widgetInputs";
import { ManageGroupDialog } from "./groupNodeManage";
-import type { LGraphNode } from "/types/litegraph";
+import type { LGraphNode } from "@comfyorg/litegraph";
+import { LGraphCanvas, LiteGraph } from "@comfyorg/litegraph";
const GROUP = Symbol();
diff --git a/src/extensions/core/groupNodeManage.ts b/src/extensions/core/groupNodeManage.ts
index b76ab38aa..1b11f37b9 100644
--- a/src/extensions/core/groupNodeManage.ts
+++ b/src/extensions/core/groupNodeManage.ts
@@ -3,7 +3,11 @@ import { DraggableList } from "../../scripts/ui/draggableList";
import { GroupNodeConfig, GroupNodeHandler } from "./groupNode";
import "./groupNodeManage.css";
import { app, type ComfyApp } from "../../scripts/app";
-import type { LGraphNode, LGraphNodeConstructor } from "/types/litegraph";
+import {
+ LiteGraph,
+ type LGraphNode,
+ type LGraphNodeConstructor,
+} from "@comfyorg/litegraph";
const ORDER: symbol = Symbol();
diff --git a/src/extensions/core/groupOptions.ts b/src/extensions/core/groupOptions.ts
index f1e86f067..b992f5ee8 100644
--- a/src/extensions/core/groupOptions.ts
+++ b/src/extensions/core/groupOptions.ts
@@ -1,4 +1,5 @@
import { app } from "../../scripts/app";
+import { LGraphCanvas, LiteGraph } from "@comfyorg/litegraph";
function setNodeMode(node, mode) {
node.mode = mode;
diff --git a/src/extensions/core/invertMenuScrolling.ts b/src/extensions/core/invertMenuScrolling.ts
index 38a36a269..2783685c9 100644
--- a/src/extensions/core/invertMenuScrolling.ts
+++ b/src/extensions/core/invertMenuScrolling.ts
@@ -1,3 +1,4 @@
+import { LiteGraph } from "@comfyorg/litegraph";
import { app } from "../../scripts/app";
// Inverts the scrolling of context menus
diff --git a/src/extensions/core/linkRenderMode.ts b/src/extensions/core/linkRenderMode.ts
index c269e4652..adbd50e5c 100644
--- a/src/extensions/core/linkRenderMode.ts
+++ b/src/extensions/core/linkRenderMode.ts
@@ -1,5 +1,5 @@
import { app } from "../../scripts/app";
-
+import { LiteGraph } from "@comfyorg/litegraph";
const id = "Comfy.LinkRenderMode";
const ext = {
name: id,
diff --git a/src/extensions/core/nodeTemplates.ts b/src/extensions/core/nodeTemplates.ts
index fe813aa2a..d3e5a19bc 100644
--- a/src/extensions/core/nodeTemplates.ts
+++ b/src/extensions/core/nodeTemplates.ts
@@ -2,6 +2,7 @@ import { app } from "../../scripts/app";
import { api } from "../../scripts/api";
import { ComfyDialog, $el } from "../../scripts/ui";
import { GroupNodeConfig, GroupNodeHandler } from "./groupNode";
+import { LGraphCanvas } from "@comfyorg/litegraph";
// Adds the ability to save and add multiple nodes as a template
// To save:
diff --git a/src/extensions/core/noteNode.ts b/src/extensions/core/noteNode.ts
index f53c752d2..cf15743a8 100644
--- a/src/extensions/core/noteNode.ts
+++ b/src/extensions/core/noteNode.ts
@@ -1,3 +1,4 @@
+import { LiteGraph, LGraphCanvas } from "@comfyorg/litegraph";
import { app } from "../../scripts/app";
import { ComfyWidgets } from "../../scripts/widgets";
// Node that add notes to your project
@@ -8,11 +9,8 @@ app.registerExtension({
class NoteNode {
static category: string;
- // @ts-ignore
color = LGraphCanvas.node_colors.yellow.color;
- // @ts-ignore
bgcolor = LGraphCanvas.node_colors.yellow.bgcolor;
- // @ts-ignore
groupcolor = LGraphCanvas.node_colors.yellow.groupcolor;
properties: { text: string };
serialize_widgets: boolean;
diff --git a/src/extensions/core/rerouteNode.js b/src/extensions/core/rerouteNode.js
index 839bb8ef9..23694a8fe 100644
--- a/src/extensions/core/rerouteNode.js
+++ b/src/extensions/core/rerouteNode.js
@@ -1,5 +1,6 @@
import { app } from "../../scripts/app";
import { mergeIfValid, getWidgetConfig, setWidgetConfig } from "./widgetInputs";
+import { LiteGraph, LGraphCanvas } from "@comfyorg/litegraph";
// Node that allows you to redirect connections for cleaner graphs
diff --git a/src/extensions/core/simpleTouchSupport.ts b/src/extensions/core/simpleTouchSupport.ts
index 71551069d..257ecd4ab 100644
--- a/src/extensions/core/simpleTouchSupport.ts
+++ b/src/extensions/core/simpleTouchSupport.ts
@@ -1,4 +1,5 @@
import { app } from "../../scripts/app";
+import { LGraphCanvas, LiteGraph } from "@comfyorg/litegraph";
let touchZooming;
let touchCount = 0;
diff --git a/src/extensions/core/slotDefaults.js b/src/extensions/core/slotDefaults.js
index d2acf2bd0..a8fb76f30 100644
--- a/src/extensions/core/slotDefaults.js
+++ b/src/extensions/core/slotDefaults.js
@@ -1,5 +1,6 @@
import { app } from "../../scripts/app";
import { ComfyWidgets } from "../../scripts/widgets";
+import { LiteGraph } from "@comfyorg/litegraph";
// Adds defaults for quickly adding nodes with middle click on the input/output
app.registerExtension({
diff --git a/src/extensions/core/snapToGrid.ts b/src/extensions/core/snapToGrid.ts
index fc248dbde..28b30868f 100644
--- a/src/extensions/core/snapToGrid.ts
+++ b/src/extensions/core/snapToGrid.ts
@@ -1,4 +1,10 @@
import { app } from "../../scripts/app";
+import {
+ LGraphCanvas,
+ LGraphNode,
+ LGraphGroup,
+ LiteGraph,
+} from "@comfyorg/litegraph";
// Shift + drag/resize to snap to grid
@@ -77,12 +83,14 @@ app.registerExtension({
let w, h;
if (node.flags.collapsed) {
+ // @ts-ignore
w = node._collapsed_width;
h = LiteGraph.NODE_TITLE_HEIGHT;
shiftY -= LiteGraph.NODE_TITLE_HEIGHT;
} else {
w = node.size[0];
h = node.size[1];
+ // @ts-ignore
let titleMode = node.constructor.title_mode;
if (
titleMode !== LiteGraph.TRANSPARENT_TITLE &&
@@ -105,7 +113,7 @@ app.registerExtension({
* The currently moving, selected group only. Set after the `selected_group` has actually started
* moving.
*/
- let selectedAndMovingGroup = null;
+ let selectedAndMovingGroup: LGraphGroup | null = null;
/**
* Handles moving a group; tracking when a group has been moved (to show the ghost in `drawGroups`
@@ -154,13 +162,16 @@ app.registerExtension({
LGraphCanvas.prototype.drawGroups = function (canvas, ctx) {
if (this.selected_group && app.shiftDown) {
if (this.selected_group_resizing) {
+ // @ts-ignore
roundVectorToGrid(this.selected_group.size);
} else if (selectedAndMovingGroup) {
+ // @ts-ignore
const [x, y] = roundVectorToGrid([...selectedAndMovingGroup.pos]);
const f = ctx.fillStyle;
const s = ctx.strokeStyle;
ctx.fillStyle = "rgba(100, 100, 100, 0.33)";
ctx.strokeStyle = "rgba(100, 100, 100, 0.66)";
+ // @ts-ignore
ctx.rect(x, y, ...selectedAndMovingGroup.size);
ctx.fill();
ctx.stroke();
diff --git a/src/extensions/core/uploadAudio.ts b/src/extensions/core/uploadAudio.ts
index 28b4792af..4ab2b4c83 100644
--- a/src/extensions/core/uploadAudio.ts
+++ b/src/extensions/core/uploadAudio.ts
@@ -1,6 +1,6 @@
import { app } from "../../scripts/app";
import { api } from "../../scripts/api";
-import type { IWidget } from "/types/litegraph";
+import type { IWidget } from "@comfyorg/litegraph";
import type { DOMWidget } from "/scripts/domWidget";
import { ComfyNodeDef } from "/types/apiTypes";
diff --git a/src/extensions/core/widgetInputs.js b/src/extensions/core/widgetInputs.js
index fc4177923..b1c08010e 100644
--- a/src/extensions/core/widgetInputs.js
+++ b/src/extensions/core/widgetInputs.js
@@ -1,6 +1,7 @@
import { ComfyWidgets, addValueControlWidgets } from "../../scripts/widgets";
import { app } from "../../scripts/app";
import { applyTextReplacements } from "../../scripts/utils";
+import { LiteGraph } from "@comfyorg/litegraph";
const CONVERTED_TYPE = "converted-widget";
const VALID_TYPES = ["STRING", "combo", "number", "BOOLEAN"];
diff --git a/src/lib/litegraph.core.js b/src/lib/litegraph.core.js
deleted file mode 100644
index 4854b6105..000000000
--- a/src/lib/litegraph.core.js
+++ /dev/null
@@ -1,14873 +0,0 @@
-//packer version
-
-(function (global) {
- // *************************************************************
- // LiteGraph CLASS *******
- // *************************************************************
-
- /**
- * The Global Scope. It contains all the registered node classes.
- *
- * @class LiteGraph
- * @constructor
- */
-
- var LiteGraph = (global.LiteGraph = {
- VERSION: 0.4,
-
- CANVAS_GRID_SIZE: 10,
-
- NODE_TITLE_HEIGHT: 30,
- NODE_TITLE_TEXT_Y: 20,
- NODE_SLOT_HEIGHT: 20,
- NODE_WIDGET_HEIGHT: 20,
- NODE_WIDTH: 140,
- NODE_MIN_WIDTH: 50,
- NODE_COLLAPSED_RADIUS: 10,
- NODE_COLLAPSED_WIDTH: 80,
- NODE_TITLE_COLOR: "#999",
- NODE_SELECTED_TITLE_COLOR: "#FFF",
- NODE_TEXT_SIZE: 14,
- NODE_TEXT_COLOR: "#AAA",
- NODE_SUBTEXT_SIZE: 12,
- NODE_DEFAULT_COLOR: "#333",
- NODE_DEFAULT_BGCOLOR: "#353535",
- NODE_DEFAULT_BOXCOLOR: "#666",
- NODE_DEFAULT_SHAPE: "box",
- NODE_BOX_OUTLINE_COLOR: "#FFF",
- DEFAULT_SHADOW_COLOR: "rgba(0,0,0,0.5)",
- DEFAULT_GROUP_FONT: 24,
-
- WIDGET_BGCOLOR: "#222",
- WIDGET_OUTLINE_COLOR: "#666",
- WIDGET_TEXT_COLOR: "#DDD",
- WIDGET_SECONDARY_TEXT_COLOR: "#999",
-
- LINK_COLOR: "#9A9",
- EVENT_LINK_COLOR: "#A86",
- CONNECTING_LINK_COLOR: "#AFA",
-
- MAX_NUMBER_OF_NODES: 10000, //avoid infinite loops
- DEFAULT_POSITION: [100, 100], //default node position
- VALID_SHAPES: ["default", "box", "round", "card"], //,"circle"
-
- //shapes are used for nodes but also for slots
- BOX_SHAPE: 1,
- ROUND_SHAPE: 2,
- CIRCLE_SHAPE: 3,
- CARD_SHAPE: 4,
- ARROW_SHAPE: 5,
- GRID_SHAPE: 6, // intended for slot arrays
-
- //enums
- INPUT: 1,
- OUTPUT: 2,
-
- EVENT: -1, //for outputs
- ACTION: -1, //for inputs
-
- NODE_MODES: ["Always", "On Event", "Never", "On Trigger"], // helper, will add "On Request" and more in the future
- NODE_MODES_COLORS: ["#666", "#422", "#333", "#224", "#626"], // use with node_box_coloured_by_mode
- ALWAYS: 0,
- ON_EVENT: 1,
- NEVER: 2,
- ON_TRIGGER: 3,
-
- UP: 1,
- DOWN: 2,
- LEFT: 3,
- RIGHT: 4,
- CENTER: 5,
-
- LINK_RENDER_MODES: ["Straight", "Linear", "Spline"], // helper
- STRAIGHT_LINK: 0,
- LINEAR_LINK: 1,
- SPLINE_LINK: 2,
-
- NORMAL_TITLE: 0,
- NO_TITLE: 1,
- TRANSPARENT_TITLE: 2,
- AUTOHIDE_TITLE: 3,
- VERTICAL_LAYOUT: "vertical", // arrange nodes vertically
-
- proxy: null, //used to redirect calls
- node_images_path: "",
-
- debug: false,
- catch_exceptions: true,
- throw_errors: true,
- allow_scripts: false, //if set to true some nodes like Formula would be allowed to evaluate code that comes from unsafe sources (like node configuration), which could lead to exploits
- registered_node_types: {}, //nodetypes by string
- node_types_by_file_extension: {}, //used for dropping files in the canvas
- Nodes: {}, //node types by classname
- Globals: {}, //used to store vars between graphs
-
- searchbox_extras: {}, //used to add extra features to the search box
- auto_sort_node_types: false, // [true!] If set to true, will automatically sort node types / categories in the context menus
-
- node_box_coloured_when_on: false, // [true!] this make the nodes box (top left circle) coloured when triggered (execute/action), visual feedback
- node_box_coloured_by_mode: false, // [true!] nodebox based on node mode, visual feedback
-
- dialog_close_on_mouse_leave: false, // [false on mobile] better true if not touch device, TODO add an helper/listener to close if false
- dialog_close_on_mouse_leave_delay: 500,
-
- shift_click_do_break_link_from: false, // [false!] prefer false if results too easy to break links - implement with ALT or TODO custom keys
- click_do_break_link_to: false, // [false!]prefer false, way too easy to break links
-
- search_hide_on_mouse_leave: true, // [false on mobile] better true if not touch device, TODO add an helper/listener to close if false
- search_filter_enabled: false, // [true!] enable filtering slots type in the search widget, !requires auto_load_slot_types or manual set registered_slot_[in/out]_types and slot_types_[in/out]
- search_show_all_on_open: true, // [true!] opens the results list when opening the search widget
-
- auto_load_slot_types: false, // [if want false, use true, run, get vars values to be statically set, than disable] nodes types and nodeclass association with node types need to be calculated, if dont want this, calculate once and set registered_slot_[in/out]_types and slot_types_[in/out]
-
- // set these values if not using auto_load_slot_types
- registered_slot_in_types: {}, // slot types for nodeclass
- registered_slot_out_types: {}, // slot types for nodeclass
- slot_types_in: [], // slot types IN
- slot_types_out: [], // slot types OUT
- slot_types_default_in: [], // specify for each IN slot type a(/many) default node(s), use single string, array, or object (with node, title, parameters, ..) like for search
- slot_types_default_out: [], // specify for each OUT slot type a(/many) default node(s), use single string, array, or object (with node, title, parameters, ..) like for search
-
- alt_drag_do_clone_nodes: false, // [true!] very handy, ALT click to clone and drag the new node
-
- do_add_triggers_slots: false, // [true!] will create and connect event slots when using action/events connections, !WILL CHANGE node mode when using onTrigger (enable mode colors), onExecuted does not need this
-
- allow_multi_output_for_events: true, // [false!] being events, it is strongly reccomended to use them sequentially, one by one
-
- middle_click_slot_add_default_node: false, //[true!] allows to create and connect a ndoe clicking with the third button (wheel)
-
- release_link_on_empty_shows_menu: false, //[true!] dragging a link to empty space will open a menu, add from list, search or defaults
-
- pointerevents_method: "pointer", // "mouse"|"pointer" use mouse for retrocompatibility issues? (none found @ now)
- // TODO implement pointercancel, gotpointercapture, lostpointercapture, (pointerover, pointerout if necessary)
-
- ctrl_shift_v_paste_connect_unselected_outputs: true, //[true!] allows ctrl + shift + v to paste nodes with the outputs of the unselected nodes connected with the inputs of the newly pasted nodes
-
- // if true, all newly created nodes/links will use string UUIDs for their id fields instead of integers.
- // use this if you must have node IDs that are unique across all graphs and subgraphs.
- use_uuids: false,
-
- /**
- * Register a node class so it can be listed when the user wants to create a new one
- * @method registerNodeType
- * @param {String} type name of the node and path
- * @param {Class} base_class class containing the structure of a node
- */
-
- registerNodeType: function (type, base_class) {
- if (!base_class.prototype) {
- throw "Cannot register a simple object, it must be a class with a prototype";
- }
- base_class.type = type;
-
- if (LiteGraph.debug) {
- console.log("Node registered: " + type);
- }
-
- const classname = base_class.name;
-
- const pos = type.lastIndexOf("/");
- base_class.category = type.substring(0, pos);
-
- if (!base_class.title) {
- base_class.title = classname;
- }
-
- //extend class
- for (var i in LGraphNode.prototype) {
- if (!base_class.prototype[i]) {
- base_class.prototype[i] = LGraphNode.prototype[i];
- }
- }
-
- const prev = this.registered_node_types[type];
- if (prev) {
- console.log("replacing node type: " + type);
- }
- if (
- !Object.prototype.hasOwnProperty.call(base_class.prototype, "shape")
- ) {
- Object.defineProperty(base_class.prototype, "shape", {
- set: function (v) {
- switch (v) {
- case "default":
- delete this._shape;
- break;
- case "box":
- this._shape = LiteGraph.BOX_SHAPE;
- break;
- case "round":
- this._shape = LiteGraph.ROUND_SHAPE;
- break;
- case "circle":
- this._shape = LiteGraph.CIRCLE_SHAPE;
- break;
- case "card":
- this._shape = LiteGraph.CARD_SHAPE;
- break;
- default:
- this._shape = v;
- }
- },
- get: function () {
- return this._shape;
- },
- enumerable: true,
- configurable: true,
- });
-
- //used to know which nodes to create when dragging files to the canvas
- if (base_class.supported_extensions) {
- for (let i in base_class.supported_extensions) {
- const ext = base_class.supported_extensions[i];
- if (ext && ext.constructor === String) {
- this.node_types_by_file_extension[ext.toLowerCase()] = base_class;
- }
- }
- }
- }
-
- this.registered_node_types[type] = base_class;
- if (base_class.constructor.name) {
- this.Nodes[classname] = base_class;
- }
- if (LiteGraph.onNodeTypeRegistered) {
- LiteGraph.onNodeTypeRegistered(type, base_class);
- }
- if (prev && LiteGraph.onNodeTypeReplaced) {
- LiteGraph.onNodeTypeReplaced(type, base_class, prev);
- }
-
- //warnings
- if (base_class.prototype.onPropertyChange) {
- console.warn(
- "LiteGraph node class " +
- type +
- " has onPropertyChange method, it must be called onPropertyChanged with d at the end"
- );
- }
-
- // TODO one would want to know input and ouput :: this would allow through registerNodeAndSlotType to get all the slots types
- if (this.auto_load_slot_types) {
- new base_class(base_class.title || "tmpnode");
- }
- },
-
- /**
- * removes a node type from the system
- * @method unregisterNodeType
- * @param {String|Object} type name of the node or the node constructor itself
- */
- unregisterNodeType: function (type) {
- const base_class =
- type.constructor === String ? this.registered_node_types[type] : type;
- if (!base_class) {
- throw "node type not found: " + type;
- }
- delete this.registered_node_types[base_class.type];
- if (base_class.constructor.name) {
- delete this.Nodes[base_class.constructor.name];
- }
- },
-
- /**
- * Save a slot type and his node
- * @method registerSlotType
- * @param {String|Object} type name of the node or the node constructor itself
- * @param {String} slot_type name of the slot type (variable type), eg. string, number, array, boolean, ..
- */
- registerNodeAndSlotType: function (type, slot_type, out) {
- out = out || false;
- const base_class =
- type.constructor === String &&
- this.registered_node_types[type] !== "anonymous"
- ? this.registered_node_types[type]
- : type;
-
- const class_type = base_class.constructor.type;
-
- let allTypes = [];
- if (typeof slot_type === "string") {
- allTypes = slot_type.split(",");
- } else if (slot_type == this.EVENT || slot_type == this.ACTION) {
- allTypes = ["_event_"];
- } else {
- allTypes = ["*"];
- }
-
- for (let i = 0; i < allTypes.length; ++i) {
- let slotType = allTypes[i];
- if (slotType === "") {
- slotType = "*";
- }
- const registerTo = out
- ? "registered_slot_out_types"
- : "registered_slot_in_types";
- if (this[registerTo][slotType] === undefined) {
- this[registerTo][slotType] = { nodes: [] };
- }
- if (!this[registerTo][slotType].nodes.includes(class_type)) {
- this[registerTo][slotType].nodes.push(class_type);
- }
-
- // check if is a new type
- if (!out) {
- if (!this.slot_types_in.includes(slotType.toLowerCase())) {
- this.slot_types_in.push(slotType.toLowerCase());
- this.slot_types_in.sort();
- }
- } else {
- if (!this.slot_types_out.includes(slotType.toLowerCase())) {
- this.slot_types_out.push(slotType.toLowerCase());
- this.slot_types_out.sort();
- }
- }
- }
- },
-
- /**
- * Create a new nodetype by passing a function, it wraps it with a proper class and generates inputs according to the parameters of the function.
- * Useful to wrap simple methods that do not require properties, and that only process some input to generate an output.
- * @method wrapFunctionAsNode
- * @param {String} name node name with namespace (p.e.: 'math/sum')
- * @param {Function} func
- * @param {Array} param_types [optional] an array containing the type of every parameter, otherwise parameters will accept any type
- * @param {String} return_type [optional] string with the return type, otherwise it will be generic
- * @param {Object} properties [optional] properties to be configurable
- */
- wrapFunctionAsNode: function (
- name,
- func,
- param_types,
- return_type,
- properties
- ) {
- var params = Array(func.length);
- var code = "";
- var names = LiteGraph.getParameterNames(func);
- for (var i = 0; i < names.length; ++i) {
- code +=
- "this.addInput('" +
- names[i] +
- "'," +
- (param_types && param_types[i] ? "'" + param_types[i] + "'" : "0") +
- ");\n";
- }
- code +=
- "this.addOutput('out'," +
- (return_type ? "'" + return_type + "'" : 0) +
- ");\n";
- if (properties) {
- code += "this.properties = " + JSON.stringify(properties) + ";\n";
- }
- var classobj = Function(code);
- classobj.title = name.split("/").pop();
- classobj.desc = "Generated from " + func.name;
- classobj.prototype.onExecute = function onExecute() {
- for (var i = 0; i < params.length; ++i) {
- params[i] = this.getInputData(i);
- }
- var r = func.apply(this, params);
- this.setOutputData(0, r);
- };
- this.registerNodeType(name, classobj);
- },
-
- /**
- * Removes all previously registered node's types
- */
- clearRegisteredTypes: function () {
- this.registered_node_types = {};
- this.node_types_by_file_extension = {};
- this.Nodes = {};
- this.searchbox_extras = {};
- },
-
- /**
- * Adds this method to all nodetypes, existing and to be created
- * (You can add it to LGraphNode.prototype but then existing node types wont have it)
- * @method addNodeMethod
- * @param {Function} func
- */
- addNodeMethod: function (name, func) {
- LGraphNode.prototype[name] = func;
- for (var i in this.registered_node_types) {
- var type = this.registered_node_types[i];
- if (type.prototype[name]) {
- type.prototype["_" + name] = type.prototype[name];
- } //keep old in case of replacing
- type.prototype[name] = func;
- }
- },
-
- /**
- * Create a node of a given type with a name. The node is not attached to any graph yet.
- * @method createNode
- * @param {String} type full name of the node class. p.e. "math/sin"
- * @param {String} name a name to distinguish from other nodes
- * @param {Object} options to set options
- */
-
- createNode: function (type, title, options) {
- var base_class = this.registered_node_types[type];
- if (!base_class) {
- if (LiteGraph.debug) {
- console.log('GraphNode type "' + type + '" not registered.');
- }
- return null;
- }
-
- var prototype = base_class.prototype || base_class;
-
- title = title || base_class.title || type;
-
- var node = null;
-
- if (LiteGraph.catch_exceptions) {
- try {
- node = new base_class(title);
- } catch (err) {
- console.error(err);
- return null;
- }
- } else {
- node = new base_class(title);
- }
-
- node.type = type;
-
- if (!node.title && title) {
- node.title = title;
- }
- if (!node.properties) {
- node.properties = {};
- }
- if (!node.properties_info) {
- node.properties_info = [];
- }
- if (!node.flags) {
- node.flags = {};
- }
- if (!node.size) {
- node.size = node.computeSize();
- //call onresize?
- }
- if (!node.pos) {
- node.pos = LiteGraph.DEFAULT_POSITION.concat();
- }
- if (!node.mode) {
- node.mode = LiteGraph.ALWAYS;
- }
-
- //extra options
- if (options) {
- for (var i in options) {
- node[i] = options[i];
- }
- }
-
- // callback
- if (node.onNodeCreated) {
- node.onNodeCreated();
- }
-
- return node;
- },
-
- /**
- * Returns a registered node type with a given name
- * @method getNodeType
- * @param {String} type full name of the node class. p.e. "math/sin"
- * @return {Class} the node class
- */
- getNodeType: function (type) {
- return this.registered_node_types[type];
- },
-
- /**
- * Returns a list of node types matching one category
- * @method getNodeType
- * @param {String} category category name
- * @return {Array} array with all the node classes
- */
-
- getNodeTypesInCategory: function (category, filter) {
- var r = [];
- for (var i in this.registered_node_types) {
- var type = this.registered_node_types[i];
- if (type.filter != filter) {
- continue;
- }
-
- if (category == "") {
- if (type.category == null) {
- r.push(type);
- }
- } else if (type.category == category) {
- r.push(type);
- }
- }
-
- if (this.auto_sort_node_types) {
- r.sort(function (a, b) {
- return a.title.localeCompare(b.title);
- });
- }
-
- return r;
- },
-
- /**
- * Returns a list with all the node type categories
- * @method getNodeTypesCategories
- * @param {String} filter only nodes with ctor.filter equal can be shown
- * @return {Array} array with all the names of the categories
- */
- getNodeTypesCategories: function (filter) {
- var categories = { "": 1 };
- for (var i in this.registered_node_types) {
- var type = this.registered_node_types[i];
- if (type.category && !type.skip_list) {
- if (type.filter != filter) continue;
- categories[type.category] = 1;
- }
- }
- var result = [];
- for (var i in categories) {
- result.push(i);
- }
- return this.auto_sort_node_types ? result.sort() : result;
- },
-
- //debug purposes: reloads all the js scripts that matches a wildcard
- reloadNodes: function (folder_wildcard) {
- var tmp = document.getElementsByTagName("script");
- //weird, this array changes by its own, so we use a copy
- var script_files = [];
- for (var i = 0; i < tmp.length; i++) {
- script_files.push(tmp[i]);
- }
-
- var docHeadObj = document.getElementsByTagName("head")[0];
- folder_wildcard = document.location.href + folder_wildcard;
-
- for (var i = 0; i < script_files.length; i++) {
- var src = script_files[i].src;
- if (!src || src.substr(0, folder_wildcard.length) != folder_wildcard) {
- continue;
- }
-
- try {
- if (LiteGraph.debug) {
- console.log("Reloading: " + src);
- }
- var dynamicScript = document.createElement("script");
- dynamicScript.type = "text/javascript";
- dynamicScript.src = src;
- docHeadObj.appendChild(dynamicScript);
- docHeadObj.removeChild(script_files[i]);
- } catch (err) {
- if (LiteGraph.throw_errors) {
- throw err;
- }
- if (LiteGraph.debug) {
- console.log("Error while reloading " + src);
- }
- }
- }
-
- if (LiteGraph.debug) {
- console.log("Nodes reloaded");
- }
- },
-
- //separated just to improve if it doesn't work
- cloneObject: function (obj, target) {
- if (obj == null) {
- return null;
- }
- var r = JSON.parse(JSON.stringify(obj));
- if (!target) {
- return r;
- }
-
- for (var i in r) {
- target[i] = r[i];
- }
- return target;
- },
-
- /*
- * https://gist.github.com/jed/982883?permalink_comment_id=852670#gistcomment-852670
- */
- uuidv4: function () {
- return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (a) =>
- (a ^ ((Math.random() * 16) >> (a / 4))).toString(16)
- );
- },
-
- /**
- * Returns if the types of two slots are compatible (taking into account wildcards, etc)
- * @method isValidConnection
- * @param {String} type_a
- * @param {String} type_b
- * @return {Boolean} true if they can be connected
- */
- isValidConnection: function (type_a, type_b) {
- if (type_a == "" || type_a === "*") type_a = 0;
- if (type_b == "" || type_b === "*") type_b = 0;
- if (
- !type_a || //generic output
- !type_b || // generic input
- type_a == type_b || //same type (is valid for triggers)
- (type_a == LiteGraph.EVENT && type_b == LiteGraph.ACTION)
- ) {
- return true;
- }
-
- // Enforce string type to handle toLowerCase call (-1 number not ok)
- type_a = String(type_a);
- type_b = String(type_b);
- type_a = type_a.toLowerCase();
- type_b = type_b.toLowerCase();
-
- // For nodes supporting multiple connection types
- if (type_a.indexOf(",") == -1 && type_b.indexOf(",") == -1) {
- return type_a == type_b;
- }
-
- // Check all permutations to see if one is valid
- var supported_types_a = type_a.split(",");
- var supported_types_b = type_b.split(",");
- for (var i = 0; i < supported_types_a.length; ++i) {
- for (var j = 0; j < supported_types_b.length; ++j) {
- if (
- this.isValidConnection(supported_types_a[i], supported_types_b[j])
- ) {
- //if (supported_types_a[i] == supported_types_b[j]) {
- return true;
- }
- }
- }
-
- return false;
- },
-
- /**
- * Register a string in the search box so when the user types it it will recommend this node
- * @method registerSearchboxExtra
- * @param {String} node_type the node recommended
- * @param {String} description text to show next to it
- * @param {Object} data it could contain info of how the node should be configured
- * @return {Boolean} true if they can be connected
- */
- registerSearchboxExtra: function (node_type, description, data) {
- this.searchbox_extras[description.toLowerCase()] = {
- type: node_type,
- desc: description,
- data: data,
- };
- },
-
- /**
- * Wrapper to load files (from url using fetch or from file using FileReader)
- * @method fetchFile
- * @param {String|File|Blob} url the url of the file (or the file itself)
- * @param {String} type an string to know how to fetch it: "text","arraybuffer","json","blob"
- * @param {Function} on_complete callback(data)
- * @param {Function} on_error in case of an error
- * @return {FileReader|Promise} returns the object used to
- */
- fetchFile: function (url, type, on_complete, on_error) {
- var that = this;
- if (!url) return null;
-
- type = type || "text";
- if (url.constructor === String) {
- if (url.substr(0, 4) == "http" && LiteGraph.proxy) {
- url = LiteGraph.proxy + url.substr(url.indexOf(":") + 3);
- }
- return fetch(url)
- .then(function (response) {
- if (!response.ok) throw new Error("File not found"); //it will be catch below
- if (type == "arraybuffer") return response.arrayBuffer();
- else if (type == "text" || type == "string") return response.text();
- else if (type == "json") return response.json();
- else if (type == "blob") return response.blob();
- })
- .then(function (data) {
- if (on_complete) on_complete(data);
- })
- .catch(function (error) {
- console.error("error fetching file:", url);
- if (on_error) on_error(error);
- });
- } else if (url.constructor === File || url.constructor === Blob) {
- var reader = new FileReader();
- reader.onload = function (e) {
- var v = e.target.result;
- if (type == "json") v = JSON.parse(v);
- if (on_complete) on_complete(v);
- };
- if (type == "arraybuffer") return reader.readAsArrayBuffer(url);
- else if (type == "text" || type == "json")
- return reader.readAsText(url);
- else if (type == "blob") return reader.readAsBinaryString(url);
- }
- return null;
- },
- });
-
- //timer that works everywhere
- if (typeof performance != "undefined") {
- LiteGraph.getTime = performance.now.bind(performance);
- } else if (typeof Date != "undefined" && Date.now) {
- LiteGraph.getTime = Date.now.bind(Date);
- } else if (typeof process != "undefined") {
- LiteGraph.getTime = function () {
- var t = process.hrtime();
- return t[0] * 0.001 + t[1] * 1e-6;
- };
- } else {
- LiteGraph.getTime = function getTime() {
- return new Date().getTime();
- };
- }
-
- //*********************************************************************************
- // LGraph CLASS
- //*********************************************************************************
-
- /**
- * LGraph is the class that contain a full graph. We instantiate one and add nodes to it, and then we can run the execution loop.
- * supported callbacks:
- + onNodeAdded: when a new node is added to the graph
- + onNodeRemoved: when a node inside this graph is removed
- + onNodeConnectionChange: some connection has changed in the graph (connected or disconnected)
- *
- * @class LGraph
- * @constructor
- * @param {Object} o data from previous serialization [optional]
- */
-
- function LGraph(o) {
- if (LiteGraph.debug) {
- console.log("Graph created");
- }
- this.list_of_graphcanvas = null;
- this.clear();
-
- if (o) {
- this.configure(o);
- }
- }
-
- global.LGraph = LiteGraph.LGraph = LGraph;
-
- //default supported types
- LGraph.supported_types = ["number", "string", "boolean"];
-
- //used to know which types of connections support this graph (some graphs do not allow certain types)
- LGraph.prototype.getSupportedTypes = function () {
- return this.supported_types || LGraph.supported_types;
- };
-
- LGraph.STATUS_STOPPED = 1;
- LGraph.STATUS_RUNNING = 2;
-
- /**
- * Removes all nodes from this graph
- * @method clear
- */
-
- LGraph.prototype.clear = function () {
- this.stop();
- this.status = LGraph.STATUS_STOPPED;
-
- this.last_node_id = 0;
- this.last_link_id = 0;
-
- this._version = -1; //used to detect changes
-
- //safe clear
- if (this._nodes) {
- for (var i = 0; i < this._nodes.length; ++i) {
- var node = this._nodes[i];
- if (node.onRemoved) {
- node.onRemoved();
- }
- }
- }
-
- //nodes
- this._nodes = [];
- this._nodes_by_id = {};
- this._nodes_in_order = []; //nodes sorted in execution order
- this._nodes_executable = null; //nodes that contain onExecute sorted in execution order
-
- //other scene stuff
- this._groups = [];
-
- //links
- this.links = {}; //container with all the links
-
- //iterations
- this.iteration = 0;
-
- //custom data
- this.config = {};
- this.vars = {};
- this.extra = {}; //to store custom data
-
- //timing
- this.globaltime = 0;
- this.runningtime = 0;
- this.fixedtime = 0;
- this.fixedtime_lapse = 0.01;
- this.elapsed_time = 0.01;
- this.last_update_time = 0;
- this.starttime = 0;
-
- this.catch_errors = true;
-
- this.nodes_executing = [];
- this.nodes_actioning = [];
- this.nodes_executedAction = [];
-
- //subgraph_data
- this.inputs = {};
- this.outputs = {};
-
- //notify canvas to redraw
- this.change();
-
- this.sendActionToCanvas("clear");
- };
-
- /**
- * Attach Canvas to this graph
- * @method attachCanvas
- * @param {GraphCanvas} graph_canvas
- */
-
- LGraph.prototype.attachCanvas = function (graphcanvas) {
- if (graphcanvas.constructor != LGraphCanvas) {
- throw "attachCanvas expects a LGraphCanvas instance";
- }
- if (graphcanvas.graph && graphcanvas.graph != this) {
- graphcanvas.graph.detachCanvas(graphcanvas);
- }
-
- graphcanvas.graph = this;
-
- if (!this.list_of_graphcanvas) {
- this.list_of_graphcanvas = [];
- }
- this.list_of_graphcanvas.push(graphcanvas);
- };
-
- /**
- * Detach Canvas from this graph
- * @method detachCanvas
- * @param {GraphCanvas} graph_canvas
- */
- LGraph.prototype.detachCanvas = function (graphcanvas) {
- if (!this.list_of_graphcanvas) {
- return;
- }
-
- var pos = this.list_of_graphcanvas.indexOf(graphcanvas);
- if (pos == -1) {
- return;
- }
- graphcanvas.graph = null;
- this.list_of_graphcanvas.splice(pos, 1);
- };
-
- /**
- * Starts running this graph every interval milliseconds.
- * @method start
- * @param {number} interval amount of milliseconds between executions, if 0 then it renders to the monitor refresh rate
- */
-
- LGraph.prototype.start = function (interval) {
- if (this.status == LGraph.STATUS_RUNNING) {
- return;
- }
- this.status = LGraph.STATUS_RUNNING;
-
- if (this.onPlayEvent) {
- this.onPlayEvent();
- }
-
- this.sendEventToAllNodes("onStart");
-
- //launch
- this.starttime = LiteGraph.getTime();
- this.last_update_time = this.starttime;
- interval = interval || 0;
- var that = this;
-
- //execute once per frame
- if (
- interval == 0 &&
- typeof window != "undefined" &&
- window.requestAnimationFrame
- ) {
- function on_frame() {
- if (that.execution_timer_id != -1) {
- return;
- }
- window.requestAnimationFrame(on_frame);
- if (that.onBeforeStep) that.onBeforeStep();
- that.runStep(1, !that.catch_errors);
- if (that.onAfterStep) that.onAfterStep();
- }
- this.execution_timer_id = -1;
- on_frame();
- } else {
- //execute every 'interval' ms
- this.execution_timer_id = setInterval(function () {
- //execute
- if (that.onBeforeStep) that.onBeforeStep();
- that.runStep(1, !that.catch_errors);
- if (that.onAfterStep) that.onAfterStep();
- }, interval);
- }
- };
-
- /**
- * Stops the execution loop of the graph
- * @method stop execution
- */
-
- LGraph.prototype.stop = function () {
- if (this.status == LGraph.STATUS_STOPPED) {
- return;
- }
-
- this.status = LGraph.STATUS_STOPPED;
-
- if (this.onStopEvent) {
- this.onStopEvent();
- }
-
- if (this.execution_timer_id != null) {
- if (this.execution_timer_id != -1) {
- clearInterval(this.execution_timer_id);
- }
- this.execution_timer_id = null;
- }
-
- this.sendEventToAllNodes("onStop");
- };
-
- /**
- * Run N steps (cycles) of the graph
- * @method runStep
- * @param {number} num number of steps to run, default is 1
- * @param {Boolean} do_not_catch_errors [optional] if you want to try/catch errors
- * @param {number} limit max number of nodes to execute (used to execute from start to a node)
- */
-
- LGraph.prototype.runStep = function (num, do_not_catch_errors, limit) {
- num = num || 1;
-
- var start = LiteGraph.getTime();
- this.globaltime = 0.001 * (start - this.starttime);
-
- var nodes = this._nodes_executable ? this._nodes_executable : this._nodes;
- if (!nodes) {
- return;
- }
-
- limit = limit || nodes.length;
-
- if (do_not_catch_errors) {
- //iterations
- for (var i = 0; i < num; i++) {
- for (var j = 0; j < limit; ++j) {
- var node = nodes[j];
- if (node.mode == LiteGraph.ALWAYS && node.onExecute) {
- //wrap node.onExecute();
- node.doExecute();
- }
- }
-
- this.fixedtime += this.fixedtime_lapse;
- if (this.onExecuteStep) {
- this.onExecuteStep();
- }
- }
-
- if (this.onAfterExecute) {
- this.onAfterExecute();
- }
- } else {
- try {
- //iterations
- for (var i = 0; i < num; i++) {
- for (var j = 0; j < limit; ++j) {
- var node = nodes[j];
- if (node.mode == LiteGraph.ALWAYS && node.onExecute) {
- node.onExecute();
- }
- }
-
- this.fixedtime += this.fixedtime_lapse;
- if (this.onExecuteStep) {
- this.onExecuteStep();
- }
- }
-
- if (this.onAfterExecute) {
- this.onAfterExecute();
- }
- this.errors_in_execution = false;
- } catch (err) {
- this.errors_in_execution = true;
- if (LiteGraph.throw_errors) {
- throw err;
- }
- if (LiteGraph.debug) {
- console.log("Error during execution: " + err);
- }
- this.stop();
- }
- }
-
- var now = LiteGraph.getTime();
- var elapsed = now - start;
- if (elapsed == 0) {
- elapsed = 1;
- }
- this.execution_time = 0.001 * elapsed;
- this.globaltime += 0.001 * elapsed;
- this.iteration += 1;
- this.elapsed_time = (now - this.last_update_time) * 0.001;
- this.last_update_time = now;
- this.nodes_executing = [];
- this.nodes_actioning = [];
- this.nodes_executedAction = [];
- };
-
- /**
- * Updates the graph execution order according to relevance of the nodes (nodes with only outputs have more relevance than
- * nodes with only inputs.
- * @method updateExecutionOrder
- */
- LGraph.prototype.updateExecutionOrder = function () {
- this._nodes_in_order = this.computeExecutionOrder(false);
- this._nodes_executable = [];
- for (var i = 0; i < this._nodes_in_order.length; ++i) {
- if (this._nodes_in_order[i].onExecute) {
- this._nodes_executable.push(this._nodes_in_order[i]);
- }
- }
- };
-
- //This is more internal, it computes the executable nodes in order and returns it
- LGraph.prototype.computeExecutionOrder = function (
- only_onExecute,
- set_level
- ) {
- var L = [];
- var S = [];
- var M = {};
- var visited_links = {}; //to avoid repeating links
- var remaining_links = {}; //to a
-
- //search for the nodes without inputs (starting nodes)
- for (var i = 0, l = this._nodes.length; i < l; ++i) {
- var node = this._nodes[i];
- if (only_onExecute && !node.onExecute) {
- continue;
- }
-
- M[node.id] = node; //add to pending nodes
-
- var num = 0; //num of input connections
- if (node.inputs) {
- for (var j = 0, l2 = node.inputs.length; j < l2; j++) {
- if (node.inputs[j] && node.inputs[j].link != null) {
- num += 1;
- }
- }
- }
-
- if (num == 0) {
- //is a starting node
- S.push(node);
- if (set_level) {
- node._level = 1;
- }
- } //num of input links
- else {
- if (set_level) {
- node._level = 0;
- }
- remaining_links[node.id] = num;
- }
- }
-
- while (true) {
- if (S.length == 0) {
- break;
- }
-
- //get an starting node
- var node = S.shift();
- L.push(node); //add to ordered list
- delete M[node.id]; //remove from the pending nodes
-
- if (!node.outputs) {
- continue;
- }
-
- //for every output
- for (var i = 0; i < node.outputs.length; i++) {
- var output = node.outputs[i];
- //not connected
- if (
- output == null ||
- output.links == null ||
- output.links.length == 0
- ) {
- continue;
- }
-
- //for every connection
- for (var j = 0; j < output.links.length; j++) {
- var link_id = output.links[j];
- var link = this.links[link_id];
- if (!link) {
- continue;
- }
-
- //already visited link (ignore it)
- if (visited_links[link.id]) {
- continue;
- }
-
- var target_node = this.getNodeById(link.target_id);
- if (target_node == null) {
- visited_links[link.id] = true;
- continue;
- }
-
- if (
- set_level &&
- (!target_node._level || target_node._level <= node._level)
- ) {
- target_node._level = node._level + 1;
- }
-
- visited_links[link.id] = true; //mark as visited
- remaining_links[target_node.id] -= 1; //reduce the number of links remaining
- if (remaining_links[target_node.id] == 0) {
- S.push(target_node);
- } //if no more links, then add to starters array
- }
- }
- }
-
- //the remaining ones (loops)
- for (var i in M) {
- L.push(M[i]);
- }
-
- if (L.length != this._nodes.length && LiteGraph.debug) {
- console.warn("something went wrong, nodes missing");
- }
-
- var l = L.length;
-
- //save order number in the node
- for (var i = 0; i < l; ++i) {
- L[i].order = i;
- }
-
- //sort now by priority
- L = L.sort(function (A, B) {
- var Ap = A.constructor.priority || A.priority || 0;
- var Bp = B.constructor.priority || B.priority || 0;
- if (Ap == Bp) {
- //if same priority, sort by order
- return A.order - B.order;
- }
- return Ap - Bp; //sort by priority
- });
-
- //save order number in the node, again...
- for (var i = 0; i < l; ++i) {
- L[i].order = i;
- }
-
- return L;
- };
-
- /**
- * Returns all the nodes that could affect this one (ancestors) by crawling all the inputs recursively.
- * It doesn't include the node itself
- * @method getAncestors
- * @return {Array} an array with all the LGraphNodes that affect this node, in order of execution
- */
- LGraph.prototype.getAncestors = function (node) {
- var ancestors = [];
- var pending = [node];
- var visited = {};
-
- while (pending.length) {
- var current = pending.shift();
- if (!current.inputs) {
- continue;
- }
- if (!visited[current.id] && current != node) {
- visited[current.id] = true;
- ancestors.push(current);
- }
-
- for (var i = 0; i < current.inputs.length; ++i) {
- var input = current.getInputNode(i);
- if (input && ancestors.indexOf(input) == -1) {
- pending.push(input);
- }
- }
- }
-
- ancestors.sort(function (a, b) {
- return a.order - b.order;
- });
- return ancestors;
- };
-
- /**
- * Positions every node in a more readable manner
- * @method arrange
- */
- LGraph.prototype.arrange = function (margin, layout) {
- margin = margin || 100;
-
- const nodes = this.computeExecutionOrder(false, true);
- const columns = [];
- for (let i = 0; i < nodes.length; ++i) {
- const node = nodes[i];
- const col = node._level || 1;
- if (!columns[col]) {
- columns[col] = [];
- }
- columns[col].push(node);
- }
-
- let x = margin;
-
- for (let i = 0; i < columns.length; ++i) {
- const column = columns[i];
- if (!column) {
- continue;
- }
- let max_size = 100;
- let y = margin + LiteGraph.NODE_TITLE_HEIGHT;
- for (let j = 0; j < column.length; ++j) {
- const node = column[j];
- node.pos[0] = layout == LiteGraph.VERTICAL_LAYOUT ? y : x;
- node.pos[1] = layout == LiteGraph.VERTICAL_LAYOUT ? x : y;
- const max_size_index = layout == LiteGraph.VERTICAL_LAYOUT ? 1 : 0;
- if (node.size[max_size_index] > max_size) {
- max_size = node.size[max_size_index];
- }
- const node_size_index = layout == LiteGraph.VERTICAL_LAYOUT ? 0 : 1;
- y += node.size[node_size_index] + margin + LiteGraph.NODE_TITLE_HEIGHT;
- }
- x += max_size + margin;
- }
-
- this.setDirtyCanvas(true, true);
- };
-
- /**
- * Returns the amount of time the graph has been running in milliseconds
- * @method getTime
- * @return {number} number of milliseconds the graph has been running
- */
- LGraph.prototype.getTime = function () {
- return this.globaltime;
- };
-
- /**
- * Returns the amount of time accumulated using the fixedtime_lapse var. This is used in context where the time increments should be constant
- * @method getFixedTime
- * @return {number} number of milliseconds the graph has been running
- */
-
- LGraph.prototype.getFixedTime = function () {
- return this.fixedtime;
- };
-
- /**
- * Returns the amount of time it took to compute the latest iteration. Take into account that this number could be not correct
- * if the nodes are using graphical actions
- * @method getElapsedTime
- * @return {number} number of milliseconds it took the last cycle
- */
-
- LGraph.prototype.getElapsedTime = function () {
- return this.elapsed_time;
- };
-
- /**
- * Sends an event to all the nodes, useful to trigger stuff
- * @method sendEventToAllNodes
- * @param {String} eventname the name of the event (function to be called)
- * @param {Array} params parameters in array format
- */
- LGraph.prototype.sendEventToAllNodes = function (eventname, params, mode) {
- mode = mode || LiteGraph.ALWAYS;
-
- var nodes = this._nodes_in_order ? this._nodes_in_order : this._nodes;
- if (!nodes) {
- return;
- }
-
- for (var j = 0, l = nodes.length; j < l; ++j) {
- var node = nodes[j];
-
- if (node.constructor === LiteGraph.Subgraph && eventname != "onExecute") {
- if (node.mode == mode) {
- node.sendEventToAllNodes(eventname, params, mode);
- }
- continue;
- }
-
- if (!node[eventname] || node.mode != mode) {
- continue;
- }
- if (params === undefined) {
- node[eventname]();
- } else if (params && params.constructor === Array) {
- node[eventname].apply(node, params);
- } else {
- node[eventname](params);
- }
- }
- };
-
- LGraph.prototype.sendActionToCanvas = function (action, params) {
- if (!this.list_of_graphcanvas) {
- return;
- }
-
- for (var i = 0; i < this.list_of_graphcanvas.length; ++i) {
- var c = this.list_of_graphcanvas[i];
- if (c[action]) {
- c[action].apply(c, params);
- }
- }
- };
-
- /**
- * Adds a new node instance to this graph
- * @method add
- * @param {LGraphNode} node the instance of the node
- */
-
- LGraph.prototype.add = function (node, skip_compute_order) {
- if (!node) {
- return;
- }
-
- //groups
- if (node.constructor === LGraphGroup) {
- this._groups.push(node);
- this.setDirtyCanvas(true);
- this.change();
- node.graph = this;
- this._version++;
- return;
- }
-
- //nodes
- if (node.id != -1 && this._nodes_by_id[node.id] != null) {
- console.warn(
- "LiteGraph: there is already a node with this ID, changing it"
- );
- if (LiteGraph.use_uuids) {
- node.id = LiteGraph.uuidv4();
- } else {
- node.id = ++this.last_node_id;
- }
- }
-
- if (this._nodes.length >= LiteGraph.MAX_NUMBER_OF_NODES) {
- throw "LiteGraph: max number of nodes in a graph reached";
- }
-
- //give him an id
- if (LiteGraph.use_uuids) {
- if (node.id == null || node.id == -1) node.id = LiteGraph.uuidv4();
- } else {
- if (node.id == null || node.id == -1) {
- node.id = ++this.last_node_id;
- } else if (this.last_node_id < node.id) {
- this.last_node_id = node.id;
- }
- }
-
- node.graph = this;
- this._version++;
-
- this._nodes.push(node);
- this._nodes_by_id[node.id] = node;
-
- if (node.onAdded) {
- node.onAdded(this);
- }
-
- if (this.config.align_to_grid) {
- node.alignToGrid();
- }
-
- if (!skip_compute_order) {
- this.updateExecutionOrder();
- }
-
- if (this.onNodeAdded) {
- this.onNodeAdded(node);
- }
-
- this.setDirtyCanvas(true);
- this.change();
-
- return node; //to chain actions
- };
-
- /**
- * Removes a node from the graph
- * @method remove
- * @param {LGraphNode} node the instance of the node
- */
-
- LGraph.prototype.remove = function (node) {
- if (node.constructor === LiteGraph.LGraphGroup) {
- var index = this._groups.indexOf(node);
- if (index != -1) {
- this._groups.splice(index, 1);
- }
- node.graph = null;
- this._version++;
- this.setDirtyCanvas(true, true);
- this.change();
- return;
- }
-
- if (this._nodes_by_id[node.id] == null) {
- return;
- } //not found
-
- if (node.ignore_remove) {
- return;
- } //cannot be removed
-
- this.beforeChange(); //sure? - almost sure is wrong
-
- //disconnect inputs
- if (node.inputs) {
- for (var i = 0; i < node.inputs.length; i++) {
- var slot = node.inputs[i];
- if (slot.link != null) {
- node.disconnectInput(i);
- }
- }
- }
-
- //disconnect outputs
- if (node.outputs) {
- for (var i = 0; i < node.outputs.length; i++) {
- var slot = node.outputs[i];
- if (slot.links != null && slot.links.length) {
- node.disconnectOutput(i);
- }
- }
- }
-
- //node.id = -1; //why?
-
- //callback
- if (node.onRemoved) {
- node.onRemoved();
- }
-
- node.graph = null;
- this._version++;
-
- //remove from canvas render
- if (this.list_of_graphcanvas) {
- for (var i = 0; i < this.list_of_graphcanvas.length; ++i) {
- var canvas = this.list_of_graphcanvas[i];
- if (canvas.selected_nodes[node.id]) {
- delete canvas.selected_nodes[node.id];
- }
- if (canvas.node_dragged == node) {
- canvas.node_dragged = null;
- }
- }
- }
-
- //remove from containers
- var pos = this._nodes.indexOf(node);
- if (pos != -1) {
- this._nodes.splice(pos, 1);
- }
- delete this._nodes_by_id[node.id];
-
- if (this.onNodeRemoved) {
- this.onNodeRemoved(node);
- }
-
- //close panels
- this.sendActionToCanvas("checkPanels");
-
- this.setDirtyCanvas(true, true);
- this.afterChange(); //sure? - almost sure is wrong
- this.change();
-
- this.updateExecutionOrder();
- };
-
- /**
- * Returns a node by its id.
- * @method getNodeById
- * @param {Number} id
- */
-
- LGraph.prototype.getNodeById = function (id) {
- if (id == null) {
- return null;
- }
- return this._nodes_by_id[id];
- };
-
- /**
- * Returns a list of nodes that matches a class
- * @method findNodesByClass
- * @param {Class} classObject the class itself (not an string)
- * @return {Array} a list with all the nodes of this type
- */
- LGraph.prototype.findNodesByClass = function (classObject, result) {
- result = result || [];
- result.length = 0;
- for (var i = 0, l = this._nodes.length; i < l; ++i) {
- if (this._nodes[i].constructor === classObject) {
- result.push(this._nodes[i]);
- }
- }
- return result;
- };
-
- /**
- * Returns a list of nodes that matches a type
- * @method findNodesByType
- * @param {String} type the name of the node type
- * @return {Array} a list with all the nodes of this type
- */
- LGraph.prototype.findNodesByType = function (type, result) {
- var type = type.toLowerCase();
- result = result || [];
- result.length = 0;
- for (var i = 0, l = this._nodes.length; i < l; ++i) {
- if (this._nodes[i].type.toLowerCase() == type) {
- result.push(this._nodes[i]);
- }
- }
- return result;
- };
-
- /**
- * Returns the first node that matches a name in its title
- * @method findNodeByTitle
- * @param {String} name the name of the node to search
- * @return {Node} the node or null
- */
- LGraph.prototype.findNodeByTitle = function (title) {
- for (var i = 0, l = this._nodes.length; i < l; ++i) {
- if (this._nodes[i].title == title) {
- return this._nodes[i];
- }
- }
- return null;
- };
-
- /**
- * Returns a list of nodes that matches a name
- * @method findNodesByTitle
- * @param {String} name the name of the node to search
- * @return {Array} a list with all the nodes with this name
- */
- LGraph.prototype.findNodesByTitle = function (title) {
- var result = [];
- for (var i = 0, l = this._nodes.length; i < l; ++i) {
- if (this._nodes[i].title == title) {
- result.push(this._nodes[i]);
- }
- }
- return result;
- };
-
- /**
- * Returns the top-most node in this position of the canvas
- * @method getNodeOnPos
- * @param {number} x the x coordinate in canvas space
- * @param {number} y the y coordinate in canvas space
- * @param {Array} nodes_list a list with all the nodes to search from, by default is all the nodes in the graph
- * @return {LGraphNode} the node at this position or null
- */
- LGraph.prototype.getNodeOnPos = function (x, y, nodes_list, margin) {
- nodes_list = nodes_list || this._nodes;
- var nRet = null;
- for (var i = nodes_list.length - 1; i >= 0; i--) {
- var n = nodes_list[i];
- var skip_title = n.constructor.title_mode == LiteGraph.NO_TITLE;
- if (n.isPointInside(x, y, margin, skip_title)) {
- // check for lesser interest nodes (TODO check for overlapping, use the top)
- /*if (typeof n == "LGraphGroup"){
- nRet = n;
- }else{*/
- return n;
- /*}*/
- }
- }
- return nRet;
- };
-
- /**
- * Returns the top-most group in that position
- * @method getGroupOnPos
- * @param {number} x the x coordinate in canvas space
- * @param {number} y the y coordinate in canvas space
- * @return {LGraphGroup} the group or null
- */
- LGraph.prototype.getGroupOnPos = function (x, y) {
- for (var i = this._groups.length - 1; i >= 0; i--) {
- var g = this._groups[i];
- if (g.isPointInside(x, y, 2, true)) {
- return g;
- }
- }
- return null;
- };
-
- /**
- * Checks that the node type matches the node type registered, used when replacing a nodetype by a newer version during execution
- * this replaces the ones using the old version with the new version
- * @method checkNodeTypes
- */
- LGraph.prototype.checkNodeTypes = function () {
- var changes = false;
- for (var i = 0; i < this._nodes.length; i++) {
- var node = this._nodes[i];
- var ctor = LiteGraph.registered_node_types[node.type];
- if (node.constructor == ctor) {
- continue;
- }
- console.log("node being replaced by newer version: " + node.type);
- var newnode = LiteGraph.createNode(node.type);
- changes = true;
- this._nodes[i] = newnode;
- newnode.configure(node.serialize());
- newnode.graph = this;
- this._nodes_by_id[newnode.id] = newnode;
- if (node.inputs) {
- newnode.inputs = node.inputs.concat();
- }
- if (node.outputs) {
- newnode.outputs = node.outputs.concat();
- }
- }
- this.updateExecutionOrder();
- };
-
- // ********** GLOBALS *****************
-
- LGraph.prototype.onAction = function (action, param, options) {
- this._input_nodes = this.findNodesByClass(
- LiteGraph.GraphInput,
- this._input_nodes
- );
- for (var i = 0; i < this._input_nodes.length; ++i) {
- var node = this._input_nodes[i];
- if (node.properties.name != action) {
- continue;
- }
- //wrap node.onAction(action, param);
- node.actionDo(action, param, options);
- break;
- }
- };
-
- LGraph.prototype.trigger = function (action, param) {
- if (this.onTrigger) {
- this.onTrigger(action, param);
- }
- };
-
- /**
- * Tell this graph it has a global graph input of this type
- * @method addGlobalInput
- * @param {String} name
- * @param {String} type
- * @param {*} value [optional]
- */
- LGraph.prototype.addInput = function (name, type, value) {
- var input = this.inputs[name];
- if (input) {
- //already exist
- return;
- }
-
- this.beforeChange();
- this.inputs[name] = { name: name, type: type, value: value };
- this._version++;
- this.afterChange();
-
- if (this.onInputAdded) {
- this.onInputAdded(name, type);
- }
-
- if (this.onInputsOutputsChange) {
- this.onInputsOutputsChange();
- }
- };
-
- /**
- * Assign a data to the global graph input
- * @method setGlobalInputData
- * @param {String} name
- * @param {*} data
- */
- LGraph.prototype.setInputData = function (name, data) {
- var input = this.inputs[name];
- if (!input) {
- return;
- }
- input.value = data;
- };
-
- /**
- * Returns the current value of a global graph input
- * @method getInputData
- * @param {String} name
- * @return {*} the data
- */
- LGraph.prototype.getInputData = function (name) {
- var input = this.inputs[name];
- if (!input) {
- return null;
- }
- return input.value;
- };
-
- /**
- * Changes the name of a global graph input
- * @method renameInput
- * @param {String} old_name
- * @param {String} new_name
- */
- LGraph.prototype.renameInput = function (old_name, name) {
- if (name == old_name) {
- return;
- }
-
- if (!this.inputs[old_name]) {
- return false;
- }
-
- if (this.inputs[name]) {
- console.error("there is already one input with that name");
- return false;
- }
-
- this.inputs[name] = this.inputs[old_name];
- delete this.inputs[old_name];
- this._version++;
-
- if (this.onInputRenamed) {
- this.onInputRenamed(old_name, name);
- }
-
- if (this.onInputsOutputsChange) {
- this.onInputsOutputsChange();
- }
- };
-
- /**
- * Changes the type of a global graph input
- * @method changeInputType
- * @param {String} name
- * @param {String} type
- */
- LGraph.prototype.changeInputType = function (name, type) {
- if (!this.inputs[name]) {
- return false;
- }
-
- if (
- this.inputs[name].type &&
- String(this.inputs[name].type).toLowerCase() == String(type).toLowerCase()
- ) {
- return;
- }
-
- this.inputs[name].type = type;
- this._version++;
- if (this.onInputTypeChanged) {
- this.onInputTypeChanged(name, type);
- }
- };
-
- /**
- * Removes a global graph input
- * @method removeInput
- * @param {String} name
- * @param {String} type
- */
- LGraph.prototype.removeInput = function (name) {
- if (!this.inputs[name]) {
- return false;
- }
-
- delete this.inputs[name];
- this._version++;
-
- if (this.onInputRemoved) {
- this.onInputRemoved(name);
- }
-
- if (this.onInputsOutputsChange) {
- this.onInputsOutputsChange();
- }
- return true;
- };
-
- /**
- * Creates a global graph output
- * @method addOutput
- * @param {String} name
- * @param {String} type
- * @param {*} value
- */
- LGraph.prototype.addOutput = function (name, type, value) {
- this.outputs[name] = { name: name, type: type, value: value };
- this._version++;
-
- if (this.onOutputAdded) {
- this.onOutputAdded(name, type);
- }
-
- if (this.onInputsOutputsChange) {
- this.onInputsOutputsChange();
- }
- };
-
- /**
- * Assign a data to the global output
- * @method setOutputData
- * @param {String} name
- * @param {String} value
- */
- LGraph.prototype.setOutputData = function (name, value) {
- var output = this.outputs[name];
- if (!output) {
- return;
- }
- output.value = value;
- };
-
- /**
- * Returns the current value of a global graph output
- * @method getOutputData
- * @param {String} name
- * @return {*} the data
- */
- LGraph.prototype.getOutputData = function (name) {
- var output = this.outputs[name];
- if (!output) {
- return null;
- }
- return output.value;
- };
-
- /**
- * Renames a global graph output
- * @method renameOutput
- * @param {String} old_name
- * @param {String} new_name
- */
- LGraph.prototype.renameOutput = function (old_name, name) {
- if (!this.outputs[old_name]) {
- return false;
- }
-
- if (this.outputs[name]) {
- console.error("there is already one output with that name");
- return false;
- }
-
- this.outputs[name] = this.outputs[old_name];
- delete this.outputs[old_name];
- this._version++;
-
- if (this.onOutputRenamed) {
- this.onOutputRenamed(old_name, name);
- }
-
- if (this.onInputsOutputsChange) {
- this.onInputsOutputsChange();
- }
- };
-
- /**
- * Changes the type of a global graph output
- * @method changeOutputType
- * @param {String} name
- * @param {String} type
- */
- LGraph.prototype.changeOutputType = function (name, type) {
- if (!this.outputs[name]) {
- return false;
- }
-
- if (
- this.outputs[name].type &&
- String(this.outputs[name].type).toLowerCase() ==
- String(type).toLowerCase()
- ) {
- return;
- }
-
- this.outputs[name].type = type;
- this._version++;
- if (this.onOutputTypeChanged) {
- this.onOutputTypeChanged(name, type);
- }
- };
-
- /**
- * Removes a global graph output
- * @method removeOutput
- * @param {String} name
- */
- LGraph.prototype.removeOutput = function (name) {
- if (!this.outputs[name]) {
- return false;
- }
- delete this.outputs[name];
- this._version++;
-
- if (this.onOutputRemoved) {
- this.onOutputRemoved(name);
- }
-
- if (this.onInputsOutputsChange) {
- this.onInputsOutputsChange();
- }
- return true;
- };
-
- LGraph.prototype.triggerInput = function (name, value) {
- var nodes = this.findNodesByTitle(name);
- for (var i = 0; i < nodes.length; ++i) {
- nodes[i].onTrigger(value);
- }
- };
-
- LGraph.prototype.setCallback = function (name, func) {
- var nodes = this.findNodesByTitle(name);
- for (var i = 0; i < nodes.length; ++i) {
- nodes[i].setTrigger(func);
- }
- };
-
- //used for undo, called before any change is made to the graph
- LGraph.prototype.beforeChange = function (info) {
- if (this.onBeforeChange) {
- this.onBeforeChange(this, info);
- }
- this.sendActionToCanvas("onBeforeChange", this);
- };
-
- //used to resend actions, called after any change is made to the graph
- LGraph.prototype.afterChange = function (info) {
- if (this.onAfterChange) {
- this.onAfterChange(this, info);
- }
- this.sendActionToCanvas("onAfterChange", this);
- };
-
- LGraph.prototype.connectionChange = function (node, link_info) {
- this.updateExecutionOrder();
- if (this.onConnectionChange) {
- this.onConnectionChange(node);
- }
- this._version++;
- this.sendActionToCanvas("onConnectionChange");
- };
-
- /**
- * returns if the graph is in live mode
- * @method isLive
- */
-
- LGraph.prototype.isLive = function () {
- if (!this.list_of_graphcanvas) {
- return false;
- }
-
- for (var i = 0; i < this.list_of_graphcanvas.length; ++i) {
- var c = this.list_of_graphcanvas[i];
- if (c.live_mode) {
- return true;
- }
- }
- return false;
- };
-
- /**
- * clears the triggered slot animation in all links (stop visual animation)
- * @method clearTriggeredSlots
- */
- LGraph.prototype.clearTriggeredSlots = function () {
- for (var i in this.links) {
- var link_info = this.links[i];
- if (!link_info) {
- continue;
- }
- if (link_info._last_time) {
- link_info._last_time = 0;
- }
- }
- };
-
- /* Called when something visually changed (not the graph!) */
- LGraph.prototype.change = function () {
- if (LiteGraph.debug) {
- console.log("Graph changed");
- }
- this.sendActionToCanvas("setDirty", [true, true]);
- if (this.on_change) {
- this.on_change(this);
- }
- };
-
- LGraph.prototype.setDirtyCanvas = function (fg, bg) {
- this.sendActionToCanvas("setDirty", [fg, bg]);
- };
-
- /**
- * Destroys a link
- * @method removeLink
- * @param {Number} link_id
- */
- LGraph.prototype.removeLink = function (link_id) {
- var link = this.links[link_id];
- if (!link) {
- return;
- }
- var node = this.getNodeById(link.target_id);
- if (node) {
- node.disconnectInput(link.target_slot);
- }
- };
-
- //save and recover app state ***************************************
- /**
- * Creates a Object containing all the info about this graph, it can be serialized
- * @method serialize
- * @return {Object} value of the node
- */
- LGraph.prototype.serialize = function () {
- var nodes_info = [];
- for (var i = 0, l = this._nodes.length; i < l; ++i) {
- nodes_info.push(this._nodes[i].serialize());
- }
-
- //pack link info into a non-verbose format
- var links = [];
- for (var i in this.links) {
- //links is an OBJECT
- var link = this.links[i];
- if (!link.serialize) {
- //weird bug I havent solved yet
- console.warn(
- "weird LLink bug, link info is not a LLink but a regular object"
- );
- var link2 = new LLink();
- for (var j in link) {
- link2[j] = link[j];
- }
- this.links[i] = link2;
- link = link2;
- }
-
- links.push(link.serialize());
- }
-
- var groups_info = [];
- for (var i = 0; i < this._groups.length; ++i) {
- groups_info.push(this._groups[i].serialize());
- }
-
- var data = {
- last_node_id: this.last_node_id,
- last_link_id: this.last_link_id,
- nodes: nodes_info,
- links: links,
- groups: groups_info,
- config: this.config,
- extra: this.extra,
- version: LiteGraph.VERSION,
- };
-
- if (this.onSerialize) this.onSerialize(data);
-
- return data;
- };
-
- /**
- * Configure a graph from a JSON string
- * @method configure
- * @param {String} str configure a graph from a JSON string
- * @param {Boolean} returns if there was any error parsing
- */
- LGraph.prototype.configure = function (data, keep_old) {
- if (!data) {
- return;
- }
-
- if (!keep_old) {
- this.clear();
- }
-
- var nodes = data.nodes;
-
- //decode links info (they are very verbose)
- if (data.links && data.links.constructor === Array) {
- var links = [];
- for (var i = 0; i < data.links.length; ++i) {
- var link_data = data.links[i];
- if (!link_data) {
- //weird bug
- console.warn("serialized graph link data contains errors, skipping.");
- continue;
- }
- var link = new LLink();
- link.configure(link_data);
- links[link.id] = link;
- }
- data.links = links;
- }
-
- //copy all stored fields
- for (var i in data) {
- if (i == "nodes" || i == "groups")
- //links must be accepted
- continue;
- this[i] = data[i];
- }
-
- var error = false;
-
- //create nodes
- this._nodes = [];
- if (nodes) {
- for (var i = 0, l = nodes.length; i < l; ++i) {
- var n_info = nodes[i]; //stored info
- var node = LiteGraph.createNode(n_info.type, n_info.title);
- if (!node) {
- if (LiteGraph.debug) {
- console.log("Node not found or has errors: " + n_info.type);
- }
-
- //in case of error we create a replacement node to avoid losing info
- node = new LGraphNode();
- node.last_serialization = n_info;
- node.has_errors = true;
- error = true;
- //continue;
- }
-
- node.id = n_info.id; //id it or it will create a new id
- this.add(node, true); //add before configure, otherwise configure cannot create links
- }
-
- //configure nodes afterwards so they can reach each other
- for (var i = 0, l = nodes.length; i < l; ++i) {
- var n_info = nodes[i];
- var node = this.getNodeById(n_info.id);
- if (node) {
- node.configure(n_info);
- }
- }
- }
-
- //groups
- this._groups.length = 0;
- if (data.groups) {
- for (var i = 0; i < data.groups.length; ++i) {
- var group = new LiteGraph.LGraphGroup();
- group.configure(data.groups[i]);
- this.add(group);
- }
- }
-
- this.updateExecutionOrder();
-
- this.extra = data.extra || {};
-
- if (this.onConfigure) this.onConfigure(data);
-
- this._version++;
- this.setDirtyCanvas(true, true);
- return error;
- };
-
- LGraph.prototype.load = function (url, callback) {
- var that = this;
-
- //from file
- if (url.constructor === File || url.constructor === Blob) {
- var reader = new FileReader();
- reader.addEventListener("load", function (event) {
- var data = JSON.parse(event.target.result);
- that.configure(data);
- if (callback) callback();
- });
-
- reader.readAsText(url);
- return;
- }
-
- //is a string, then an URL
- var req = new XMLHttpRequest();
- req.open("GET", url, true);
- req.send(null);
- req.onload = function (oEvent) {
- if (req.status !== 200) {
- console.error("Error loading graph:", req.status, req.response);
- return;
- }
- var data = JSON.parse(req.response);
- that.configure(data);
- if (callback) callback();
- };
- req.onerror = function (err) {
- console.error("Error loading graph:", err);
- };
- };
-
- LGraph.prototype.onNodeTrace = function (node, msg, color) {
- //TODO
- };
-
- //this is the class in charge of storing link information
- function LLink(id, type, origin_id, origin_slot, target_id, target_slot) {
- this.id = id;
- this.type = type;
- this.origin_id = origin_id;
- this.origin_slot = origin_slot;
- this.target_id = target_id;
- this.target_slot = target_slot;
-
- this._data = null;
- this._pos = new Float32Array(2); //center
- }
-
- LLink.prototype.configure = function (o) {
- if (o.constructor === Array) {
- this.id = o[0];
- this.origin_id = o[1];
- this.origin_slot = o[2];
- this.target_id = o[3];
- this.target_slot = o[4];
- this.type = o[5];
- } else {
- this.id = o.id;
- this.type = o.type;
- this.origin_id = o.origin_id;
- this.origin_slot = o.origin_slot;
- this.target_id = o.target_id;
- this.target_slot = o.target_slot;
- }
- };
-
- LLink.prototype.serialize = function () {
- return [
- this.id,
- this.origin_id,
- this.origin_slot,
- this.target_id,
- this.target_slot,
- this.type,
- ];
- };
-
- LiteGraph.LLink = LLink;
-
- // *************************************************************
- // Node CLASS *******
- // *************************************************************
-
- /*
- title: string
- pos: [x,y]
- size: [x,y]
-
- input|output: every connection
- + { name:string, type:string, pos: [x,y]=Optional, direction: "input"|"output", links: Array });
-
- general properties:
- + clip_area: if you render outside the node, it will be clipped
- + unsafe_execution: not allowed for safe execution
- + skip_repeated_outputs: when adding new outputs, it wont show if there is one already connected
- + resizable: if set to false it wont be resizable with the mouse
- + horizontal: slots are distributed horizontally
- + widgets_start_y: widgets start at y distance from the top of the node
-
- flags object:
- + collapsed: if it is collapsed
-
- supported callbacks:
- + onAdded: when added to graph (warning: this is called BEFORE the node is configured when loading)
- + onRemoved: when removed from graph
- + onStart: when the graph starts playing
- + onStop: when the graph stops playing
- + onDrawForeground: render the inside widgets inside the node
- + onDrawBackground: render the background area inside the node (only in edit mode)
- + onMouseDown
- + onMouseMove
- + onMouseUp
- + onMouseEnter
- + onMouseLeave
- + onExecute: execute the node
- + onPropertyChanged: when a property is changed in the panel (return true to skip default behaviour)
- + onGetInputs: returns an array of possible inputs
- + onGetOutputs: returns an array of possible outputs
- + onBounding: in case this node has a bigger bounding than the node itself (the callback receives the bounding as [x,y,w,h])
- + onDblClick: double clicked in the node
- + onInputDblClick: input slot double clicked (can be used to automatically create a node connected)
- + onOutputDblClick: output slot double clicked (can be used to automatically create a node connected)
- + onConfigure: called after the node has been configured
- + onSerialize: to add extra info when serializing (the callback receives the object that should be filled with the data)
- + onSelected
- + onDeselected
- + onDropItem : DOM item dropped over the node
- + onDropFile : file dropped over the node
- + onConnectInput : if returns false the incoming connection will be canceled
- + onConnectionsChange : a connection changed (new one or removed) (LiteGraph.INPUT or LiteGraph.OUTPUT, slot, true if connected, link_info, input_info )
- + onAction: action slot triggered
- + getExtraMenuOptions: to add option to context menu
-*/
-
- /**
- * Base Class for all the node type classes
- * @class LGraphNode
- * @param {String} name a name for the node
- */
-
- function LGraphNode(title) {
- this._ctor(title);
- }
-
- global.LGraphNode = LiteGraph.LGraphNode = LGraphNode;
-
- LGraphNode.prototype._ctor = function (title) {
- this.title = title || "Unnamed";
- this.size = [LiteGraph.NODE_WIDTH, 60];
- this.graph = null;
-
- this._pos = new Float32Array(10, 10);
-
- Object.defineProperty(this, "pos", {
- set: function (v) {
- if (!v || v.length < 2) {
- return;
- }
- this._pos[0] = v[0];
- this._pos[1] = v[1];
- },
- get: function () {
- return this._pos;
- },
- enumerable: true,
- });
-
- if (LiteGraph.use_uuids) {
- this.id = LiteGraph.uuidv4();
- } else {
- this.id = -1; //not know till not added
- }
- this.type = null;
-
- //inputs available: array of inputs
- this.inputs = [];
- this.outputs = [];
- this.connections = [];
-
- //local data
- this.properties = {}; //for the values
- this.properties_info = []; //for the info
-
- this.flags = {};
- };
-
- /**
- * configure a node from an object containing the serialized info
- * @method configure
- */
- LGraphNode.prototype.configure = function (info) {
- if (this.graph) {
- this.graph._version++;
- }
- for (var j in info) {
- if (j == "properties") {
- //i don't want to clone properties, I want to reuse the old container
- for (var k in info.properties) {
- this.properties[k] = info.properties[k];
- if (this.onPropertyChanged) {
- this.onPropertyChanged(k, info.properties[k]);
- }
- }
- continue;
- }
-
- if (info[j] == null) {
- continue;
- } else if (typeof info[j] == "object") {
- //object
- if (this[j] && this[j].configure) {
- this[j].configure(info[j]);
- } else {
- this[j] = LiteGraph.cloneObject(info[j], this[j]);
- }
- } //value
- else {
- this[j] = info[j];
- }
- }
-
- if (!info.title) {
- this.title = this.constructor.title;
- }
-
- if (this.inputs) {
- for (var i = 0; i < this.inputs.length; ++i) {
- var input = this.inputs[i];
- var link_info = this.graph ? this.graph.links[input.link] : null;
- if (this.onConnectionsChange)
- this.onConnectionsChange(LiteGraph.INPUT, i, true, link_info, input); //link_info has been created now, so its updated
-
- if (this.onInputAdded) this.onInputAdded(input);
- }
- }
-
- if (this.outputs) {
- for (var i = 0; i < this.outputs.length; ++i) {
- var output = this.outputs[i];
- if (!output.links) {
- continue;
- }
- for (var j = 0; j < output.links.length; ++j) {
- var link_info = this.graph ? this.graph.links[output.links[j]] : null;
- if (this.onConnectionsChange)
- this.onConnectionsChange(
- LiteGraph.OUTPUT,
- i,
- true,
- link_info,
- output
- ); //link_info has been created now, so its updated
- }
-
- if (this.onOutputAdded) this.onOutputAdded(output);
- }
- }
-
- if (this.widgets) {
- for (var i = 0; i < this.widgets.length; ++i) {
- var w = this.widgets[i];
- if (!w) continue;
- if (
- w.options &&
- w.options.property &&
- this.properties[w.options.property] != undefined
- )
- w.value = JSON.parse(
- JSON.stringify(this.properties[w.options.property])
- );
- }
- if (info.widgets_values) {
- for (var i = 0; i < info.widgets_values.length; ++i) {
- if (this.widgets[i]) {
- this.widgets[i].value = info.widgets_values[i];
- }
- }
- }
- }
-
- if (this.onConfigure) {
- this.onConfigure(info);
- }
- };
-
- /**
- * serialize the content
- * @method serialize
- */
-
- LGraphNode.prototype.serialize = function () {
- //create serialization object
- var o = {
- id: this.id,
- type: this.type,
- pos: this.pos,
- size: this.size,
- flags: LiteGraph.cloneObject(this.flags),
- order: this.order,
- mode: this.mode,
- };
-
- //special case for when there were errors
- if (this.constructor === LGraphNode && this.last_serialization) {
- return this.last_serialization;
- }
-
- if (this.inputs) {
- o.inputs = this.inputs;
- }
-
- if (this.outputs) {
- //clear outputs last data (because data in connections is never serialized but stored inside the outputs info)
- for (var i = 0; i < this.outputs.length; i++) {
- delete this.outputs[i]._data;
- }
- o.outputs = this.outputs;
- }
-
- if (this.title && this.title != this.constructor.title) {
- o.title = this.title;
- }
-
- if (this.properties) {
- o.properties = LiteGraph.cloneObject(this.properties);
- }
-
- if (this.widgets && this.serialize_widgets) {
- o.widgets_values = [];
- for (var i = 0; i < this.widgets.length; ++i) {
- if (this.widgets[i]) o.widgets_values[i] = this.widgets[i].value;
- else o.widgets_values[i] = null;
- }
- }
-
- if (!o.type) {
- o.type = this.constructor.type;
- }
-
- if (this.color) {
- o.color = this.color;
- }
- if (this.bgcolor) {
- o.bgcolor = this.bgcolor;
- }
- if (this.boxcolor) {
- o.boxcolor = this.boxcolor;
- }
- if (this.shape) {
- o.shape = this.shape;
- }
-
- if (this.onSerialize) {
- if (this.onSerialize(o)) {
- console.warn(
- "node onSerialize shouldnt return anything, data should be stored in the object pass in the first parameter"
- );
- }
- }
-
- return o;
- };
-
- /* Creates a clone of this node */
- LGraphNode.prototype.clone = function () {
- var node = LiteGraph.createNode(this.type);
- if (!node) {
- return null;
- }
-
- //we clone it because serialize returns shared containers
- var data = LiteGraph.cloneObject(this.serialize());
-
- //remove links
- if (data.inputs) {
- for (var i = 0; i < data.inputs.length; ++i) {
- data.inputs[i].link = null;
- }
- }
-
- if (data.outputs) {
- for (var i = 0; i < data.outputs.length; ++i) {
- if (data.outputs[i].links) {
- data.outputs[i].links.length = 0;
- }
- }
- }
-
- delete data["id"];
-
- if (LiteGraph.use_uuids) {
- data["id"] = LiteGraph.uuidv4();
- }
-
- //remove links
- node.configure(data);
-
- return node;
- };
-
- /**
- * serialize and stringify
- * @method toString
- */
-
- LGraphNode.prototype.toString = function () {
- return JSON.stringify(this.serialize());
- };
- //LGraphNode.prototype.deserialize = function(info) {} //this cannot be done from within, must be done in LiteGraph
-
- /**
- * get the title string
- * @method getTitle
- */
-
- LGraphNode.prototype.getTitle = function () {
- return this.title || this.constructor.title;
- };
-
- /**
- * sets the value of a property
- * @method setProperty
- * @param {String} name
- * @param {*} value
- */
- LGraphNode.prototype.setProperty = function (name, value) {
- if (!this.properties) {
- this.properties = {};
- }
- if (value === this.properties[name]) return;
- var prev_value = this.properties[name];
- this.properties[name] = value;
- if (this.onPropertyChanged) {
- if (this.onPropertyChanged(name, value, prev_value) === false)
- //abort change
- this.properties[name] = prev_value;
- }
- if (this.widgets)
- //widgets could be linked to properties
- for (var i = 0; i < this.widgets.length; ++i) {
- var w = this.widgets[i];
- if (!w) continue;
- if (w.options.property == name) {
- w.value = value;
- break;
- }
- }
- };
-
- // Execution *************************
- /**
- * sets the output data
- * @method setOutputData
- * @param {number} slot
- * @param {*} data
- */
- LGraphNode.prototype.setOutputData = function (slot, data) {
- if (!this.outputs) {
- return;
- }
-
- //this maybe slow and a niche case
- //if(slot && slot.constructor === String)
- // slot = this.findOutputSlot(slot);
-
- if (slot == -1 || slot >= this.outputs.length) {
- return;
- }
-
- var output_info = this.outputs[slot];
- if (!output_info) {
- return;
- }
-
- //store data in the output itself in case we want to debug
- output_info._data = data;
-
- //if there are connections, pass the data to the connections
- if (this.outputs[slot].links) {
- for (var i = 0; i < this.outputs[slot].links.length; i++) {
- var link_id = this.outputs[slot].links[i];
- var link = this.graph.links[link_id];
- if (link) link.data = data;
- }
- }
- };
-
- /**
- * sets the output data type, useful when you want to be able to overwrite the data type
- * @method setOutputDataType
- * @param {number} slot
- * @param {String} datatype
- */
- LGraphNode.prototype.setOutputDataType = function (slot, type) {
- if (!this.outputs) {
- return;
- }
- if (slot == -1 || slot >= this.outputs.length) {
- return;
- }
- var output_info = this.outputs[slot];
- if (!output_info) {
- return;
- }
- //store data in the output itself in case we want to debug
- output_info.type = type;
-
- //if there are connections, pass the data to the connections
- if (this.outputs[slot].links) {
- for (var i = 0; i < this.outputs[slot].links.length; i++) {
- var link_id = this.outputs[slot].links[i];
- this.graph.links[link_id].type = type;
- }
- }
- };
-
- /**
- * Retrieves the input data (data traveling through the connection) from one slot
- * @method getInputData
- * @param {number} slot
- * @param {boolean} force_update if set to true it will force the connected node of this slot to output data into this link
- * @return {*} data or if it is not connected returns undefined
- */
- LGraphNode.prototype.getInputData = function (slot, force_update) {
- if (!this.inputs) {
- return;
- } //undefined;
-
- if (slot >= this.inputs.length || this.inputs[slot].link == null) {
- return;
- }
-
- var link_id = this.inputs[slot].link;
- var link = this.graph.links[link_id];
- if (!link) {
- //bug: weird case but it happens sometimes
- return null;
- }
-
- if (!force_update) {
- return link.data;
- }
-
- //special case: used to extract data from the incoming connection before the graph has been executed
- var node = this.graph.getNodeById(link.origin_id);
- if (!node) {
- return link.data;
- }
-
- if (node.updateOutputData) {
- node.updateOutputData(link.origin_slot);
- } else if (node.onExecute) {
- node.onExecute();
- }
-
- return link.data;
- };
-
- /**
- * Retrieves the input data type (in case this supports multiple input types)
- * @method getInputDataType
- * @param {number} slot
- * @return {String} datatype in string format
- */
- LGraphNode.prototype.getInputDataType = function (slot) {
- if (!this.inputs) {
- return null;
- } //undefined;
-
- if (slot >= this.inputs.length || this.inputs[slot].link == null) {
- return null;
- }
- var link_id = this.inputs[slot].link;
- var link = this.graph.links[link_id];
- if (!link) {
- //bug: weird case but it happens sometimes
- return null;
- }
- var node = this.graph.getNodeById(link.origin_id);
- if (!node) {
- return link.type;
- }
- var output_info = node.outputs[link.origin_slot];
- if (output_info) {
- return output_info.type;
- }
- return null;
- };
-
- /**
- * Retrieves the input data from one slot using its name instead of slot number
- * @method getInputDataByName
- * @param {String} slot_name
- * @param {boolean} force_update if set to true it will force the connected node of this slot to output data into this link
- * @return {*} data or if it is not connected returns null
- */
- LGraphNode.prototype.getInputDataByName = function (slot_name, force_update) {
- var slot = this.findInputSlot(slot_name);
- if (slot == -1) {
- return null;
- }
- return this.getInputData(slot, force_update);
- };
-
- /**
- * tells you if there is a connection in one input slot
- * @method isInputConnected
- * @param {number} slot
- * @return {boolean}
- */
- LGraphNode.prototype.isInputConnected = function (slot) {
- if (!this.inputs) {
- return false;
- }
- return slot < this.inputs.length && this.inputs[slot].link != null;
- };
-
- /**
- * tells you info about an input connection (which node, type, etc)
- * @method getInputInfo
- * @param {number} slot
- * @return {Object} object or null { link: id, name: string, type: string or 0 }
- */
- LGraphNode.prototype.getInputInfo = function (slot) {
- if (!this.inputs) {
- return null;
- }
- if (slot < this.inputs.length) {
- return this.inputs[slot];
- }
- return null;
- };
-
- /**
- * Returns the link info in the connection of an input slot
- * @method getInputLink
- * @param {number} slot
- * @return {LLink} object or null
- */
- LGraphNode.prototype.getInputLink = function (slot) {
- if (!this.inputs) {
- return null;
- }
- if (slot < this.inputs.length) {
- var slot_info = this.inputs[slot];
- return this.graph.links[slot_info.link];
- }
- return null;
- };
-
- /**
- * returns the node connected in the input slot
- * @method getInputNode
- * @param {number} slot
- * @return {LGraphNode} node or null
- */
- LGraphNode.prototype.getInputNode = function (slot) {
- if (!this.inputs) {
- return null;
- }
- if (slot >= this.inputs.length) {
- return null;
- }
- var input = this.inputs[slot];
- if (!input || input.link === null) {
- return null;
- }
- var link_info = this.graph.links[input.link];
- if (!link_info) {
- return null;
- }
- return this.graph.getNodeById(link_info.origin_id);
- };
-
- /**
- * returns the value of an input with this name, otherwise checks if there is a property with that name
- * @method getInputOrProperty
- * @param {string} name
- * @return {*} value
- */
- LGraphNode.prototype.getInputOrProperty = function (name) {
- if (!this.inputs || !this.inputs.length) {
- return this.properties ? this.properties[name] : null;
- }
-
- for (var i = 0, l = this.inputs.length; i < l; ++i) {
- var input_info = this.inputs[i];
- if (name == input_info.name && input_info.link != null) {
- var link = this.graph.links[input_info.link];
- if (link) {
- return link.data;
- }
- }
- }
- return this.properties[name];
- };
-
- /**
- * tells you the last output data that went in that slot
- * @method getOutputData
- * @param {number} slot
- * @return {Object} object or null
- */
- LGraphNode.prototype.getOutputData = function (slot) {
- if (!this.outputs) {
- return null;
- }
- if (slot >= this.outputs.length) {
- return null;
- }
-
- var info = this.outputs[slot];
- return info._data;
- };
-
- /**
- * tells you info about an output connection (which node, type, etc)
- * @method getOutputInfo
- * @param {number} slot
- * @return {Object} object or null { name: string, type: string, links: [ ids of links in number ] }
- */
- LGraphNode.prototype.getOutputInfo = function (slot) {
- if (!this.outputs) {
- return null;
- }
- if (slot < this.outputs.length) {
- return this.outputs[slot];
- }
- return null;
- };
-
- /**
- * tells you if there is a connection in one output slot
- * @method isOutputConnected
- * @param {number} slot
- * @return {boolean}
- */
- LGraphNode.prototype.isOutputConnected = function (slot) {
- if (!this.outputs) {
- return false;
- }
- return (
- slot < this.outputs.length &&
- this.outputs[slot].links &&
- this.outputs[slot].links.length
- );
- };
-
- /**
- * tells you if there is any connection in the output slots
- * @method isAnyOutputConnected
- * @return {boolean}
- */
- LGraphNode.prototype.isAnyOutputConnected = function () {
- if (!this.outputs) {
- return false;
- }
- for (var i = 0; i < this.outputs.length; ++i) {
- if (this.outputs[i].links && this.outputs[i].links.length) {
- return true;
- }
- }
- return false;
- };
-
- /**
- * retrieves all the nodes connected to this output slot
- * @method getOutputNodes
- * @param {number} slot
- * @return {array}
- */
- LGraphNode.prototype.getOutputNodes = function (slot) {
- if (!this.outputs || this.outputs.length == 0) {
- return null;
- }
-
- if (slot >= this.outputs.length) {
- return null;
- }
-
- var output = this.outputs[slot];
- if (!output.links || output.links.length == 0) {
- return null;
- }
-
- var r = [];
- for (var i = 0; i < output.links.length; i++) {
- var link_id = output.links[i];
- var link = this.graph.links[link_id];
- if (link) {
- var target_node = this.graph.getNodeById(link.target_id);
- if (target_node) {
- r.push(target_node);
- }
- }
- }
- return r;
- };
-
- LGraphNode.prototype.addOnTriggerInput = function () {
- var trigS = this.findInputSlot("onTrigger");
- if (trigS == -1) {
- //!trigS ||
- var input = this.addInput("onTrigger", LiteGraph.EVENT, {
- optional: true,
- nameLocked: true,
- });
- return this.findInputSlot("onTrigger");
- }
- return trigS;
- };
-
- LGraphNode.prototype.addOnExecutedOutput = function () {
- var trigS = this.findOutputSlot("onExecuted");
- if (trigS == -1) {
- //!trigS ||
- var output = this.addOutput("onExecuted", LiteGraph.ACTION, {
- optional: true,
- nameLocked: true,
- });
- return this.findOutputSlot("onExecuted");
- }
- return trigS;
- };
-
- LGraphNode.prototype.onAfterExecuteNode = function (param, options) {
- var trigS = this.findOutputSlot("onExecuted");
- if (trigS != -1) {
- //console.debug(this.id+":"+this.order+" triggering slot onAfterExecute");
- //console.debug(param);
- //console.debug(options);
- this.triggerSlot(trigS, param, null, options);
- }
- };
-
- LGraphNode.prototype.changeMode = function (modeTo) {
- switch (modeTo) {
- case LiteGraph.ON_EVENT:
- // this.addOnExecutedOutput();
- break;
-
- case LiteGraph.ON_TRIGGER:
- this.addOnTriggerInput();
- this.addOnExecutedOutput();
- break;
-
- case LiteGraph.NEVER:
- break;
-
- case LiteGraph.ALWAYS:
- break;
-
- case LiteGraph.ON_REQUEST:
- break;
-
- default:
- return false;
- break;
- }
- this.mode = modeTo;
- return true;
- };
-
- /**
- * Triggers the node code execution, place a boolean/counter to mark the node as being executed
- * @method execute
- * @param {*} param
- * @param {*} options
- */
- LGraphNode.prototype.doExecute = function (param, options) {
- options = options || {};
- if (this.onExecute) {
- // enable this to give the event an ID
- if (!options.action_call)
- options.action_call =
- this.id + "_exec_" + Math.floor(Math.random() * 9999);
-
- this.graph.nodes_executing[this.id] = true; //.push(this.id);
-
- this.onExecute(param, options);
-
- this.graph.nodes_executing[this.id] = false; //.pop();
-
- // save execution/action ref
- this.exec_version = this.graph.iteration;
- if (options && options.action_call) {
- this.action_call = options.action_call; // if (param)
- this.graph.nodes_executedAction[this.id] = options.action_call;
- }
- }
- this.execute_triggered = 2; // the nFrames it will be used (-- each step), means "how old" is the event
- if (this.onAfterExecuteNode) this.onAfterExecuteNode(param, options); // callback
- };
-
- /**
- * Triggers an action, wrapped by logics to control execution flow
- * @method actionDo
- * @param {String} action name
- * @param {*} param
- */
- LGraphNode.prototype.actionDo = function (action, param, options) {
- options = options || {};
- if (this.onAction) {
- // enable this to give the event an ID
- if (!options.action_call)
- options.action_call =
- this.id +
- "_" +
- (action ? action : "action") +
- "_" +
- Math.floor(Math.random() * 9999);
-
- this.graph.nodes_actioning[this.id] = action ? action : "actioning"; //.push(this.id);
-
- this.onAction(action, param, options);
-
- this.graph.nodes_actioning[this.id] = false; //.pop();
-
- // save execution/action ref
- if (options && options.action_call) {
- this.action_call = options.action_call; // if (param)
- this.graph.nodes_executedAction[this.id] = options.action_call;
- }
- }
- this.action_triggered = 2; // the nFrames it will be used (-- each step), means "how old" is the event
- if (this.onAfterExecuteNode) this.onAfterExecuteNode(param, options);
- };
-
- /**
- * Triggers an event in this node, this will trigger any output with the same name
- * @method trigger
- * @param {String} event name ( "on_play", ... ) if action is equivalent to false then the event is send to all
- * @param {*} param
- */
- LGraphNode.prototype.trigger = function (action, param, options) {
- if (!this.outputs || !this.outputs.length) {
- return;
- }
-
- if (this.graph) this.graph._last_trigger_time = LiteGraph.getTime();
-
- for (var i = 0; i < this.outputs.length; ++i) {
- var output = this.outputs[i];
- if (
- !output ||
- output.type !== LiteGraph.EVENT ||
- (action && output.name != action)
- )
- continue;
- this.triggerSlot(i, param, null, options);
- }
- };
-
- /**
- * Triggers a slot event in this node: cycle output slots and launch execute/action on connected nodes
- * @method triggerSlot
- * @param {Number} slot the index of the output slot
- * @param {*} param
- * @param {Number} link_id [optional] in case you want to trigger and specific output link in a slot
- */
- LGraphNode.prototype.triggerSlot = function (slot, param, link_id, options) {
- options = options || {};
- if (!this.outputs) {
- return;
- }
-
- if (slot == null) {
- console.error("slot must be a number");
- return;
- }
-
- if (slot.constructor !== Number)
- console.warn(
- "slot must be a number, use node.trigger('name') if you want to use a string"
- );
-
- var output = this.outputs[slot];
- if (!output) {
- return;
- }
-
- var links = output.links;
- if (!links || !links.length) {
- return;
- }
-
- if (this.graph) {
- this.graph._last_trigger_time = LiteGraph.getTime();
- }
-
- //for every link attached here
- for (var k = 0; k < links.length; ++k) {
- var id = links[k];
- if (link_id != null && link_id != id) {
- //to skip links
- continue;
- }
- var link_info = this.graph.links[links[k]];
- if (!link_info) {
- //not connected
- continue;
- }
- link_info._last_time = LiteGraph.getTime();
- var node = this.graph.getNodeById(link_info.target_id);
- if (!node) {
- //node not found?
- continue;
- }
-
- //used to mark events in graph
- var target_connection = node.inputs[link_info.target_slot];
-
- if (node.mode === LiteGraph.ON_TRIGGER) {
- // generate unique trigger ID if not present
- if (!options.action_call)
- options.action_call =
- this.id + "_trigg_" + Math.floor(Math.random() * 9999);
- if (node.onExecute) {
- // -- wrapping node.onExecute(param); --
- node.doExecute(param, options);
- }
- } else if (node.onAction) {
- // generate unique action ID if not present
- if (!options.action_call)
- options.action_call =
- this.id + "_act_" + Math.floor(Math.random() * 9999);
- //pass the action name
- var target_connection = node.inputs[link_info.target_slot];
- // wrap node.onAction(target_connection.name, param);
- node.actionDo(target_connection.name, param, options);
- }
- }
- };
-
- /**
- * clears the trigger slot animation
- * @method clearTriggeredSlot
- * @param {Number} slot the index of the output slot
- * @param {Number} link_id [optional] in case you want to trigger and specific output link in a slot
- */
- LGraphNode.prototype.clearTriggeredSlot = function (slot, link_id) {
- if (!this.outputs) {
- return;
- }
-
- var output = this.outputs[slot];
- if (!output) {
- return;
- }
-
- var links = output.links;
- if (!links || !links.length) {
- return;
- }
-
- //for every link attached here
- for (var k = 0; k < links.length; ++k) {
- var id = links[k];
- if (link_id != null && link_id != id) {
- //to skip links
- continue;
- }
- var link_info = this.graph.links[links[k]];
- if (!link_info) {
- //not connected
- continue;
- }
- link_info._last_time = 0;
- }
- };
-
- /**
- * changes node size and triggers callback
- * @method setSize
- * @param {vec2} size
- */
- LGraphNode.prototype.setSize = function (size) {
- this.size = size;
- if (this.onResize) this.onResize(this.size);
- };
-
- /**
- * add a new property to this node
- * @method addProperty
- * @param {string} name
- * @param {*} default_value
- * @param {string} type string defining the output type ("vec3","number",...)
- * @param {Object} extra_info this can be used to have special properties of the property (like values, etc)
- */
- LGraphNode.prototype.addProperty = function (
- name,
- default_value,
- type,
- extra_info
- ) {
- var o = { name: name, type: type, default_value: default_value };
- if (extra_info) {
- for (var i in extra_info) {
- o[i] = extra_info[i];
- }
- }
- if (!this.properties_info) {
- this.properties_info = [];
- }
- this.properties_info.push(o);
- if (!this.properties) {
- this.properties = {};
- }
- this.properties[name] = default_value;
- return o;
- };
-
- //connections
-
- /**
- * add a new output slot to use in this node
- * @method addOutput
- * @param {string} name
- * @param {string} type string defining the output type ("vec3","number",...)
- * @param {Object} extra_info this can be used to have special properties of an output (label, special color, position, etc)
- */
- LGraphNode.prototype.addOutput = function (name, type, extra_info) {
- var output = { name: name, type: type, links: null };
- if (extra_info) {
- for (var i in extra_info) {
- output[i] = extra_info[i];
- }
- }
-
- if (!this.outputs) {
- this.outputs = [];
- }
- this.outputs.push(output);
- if (this.onOutputAdded) {
- this.onOutputAdded(output);
- }
-
- if (LiteGraph.auto_load_slot_types)
- LiteGraph.registerNodeAndSlotType(this, type, true);
-
- this.setSize(this.computeSize());
- this.setDirtyCanvas(true, true);
- return output;
- };
-
- /**
- * add a new output slot to use in this node
- * @method addOutputs
- * @param {Array} array of triplets like [[name,type,extra_info],[...]]
- */
- LGraphNode.prototype.addOutputs = function (array) {
- for (var i = 0; i < array.length; ++i) {
- var info = array[i];
- var o = { name: info[0], type: info[1], link: null };
- if (array[2]) {
- for (var j in info[2]) {
- o[j] = info[2][j];
- }
- }
-
- if (!this.outputs) {
- this.outputs = [];
- }
- this.outputs.push(o);
- if (this.onOutputAdded) {
- this.onOutputAdded(o);
- }
-
- if (LiteGraph.auto_load_slot_types)
- LiteGraph.registerNodeAndSlotType(this, info[1], true);
- }
-
- this.setSize(this.computeSize());
- this.setDirtyCanvas(true, true);
- };
-
- /**
- * remove an existing output slot
- * @method removeOutput
- * @param {number} slot
- */
- LGraphNode.prototype.removeOutput = function (slot) {
- this.disconnectOutput(slot);
- this.outputs.splice(slot, 1);
- for (var i = slot; i < this.outputs.length; ++i) {
- if (!this.outputs[i] || !this.outputs[i].links) {
- continue;
- }
- var links = this.outputs[i].links;
- for (var j = 0; j < links.length; ++j) {
- var link = this.graph.links[links[j]];
- if (!link) {
- continue;
- }
- link.origin_slot -= 1;
- }
- }
-
- this.setSize(this.computeSize());
- if (this.onOutputRemoved) {
- this.onOutputRemoved(slot);
- }
- this.setDirtyCanvas(true, true);
- };
-
- /**
- * add a new input slot to use in this node
- * @method addInput
- * @param {string} name
- * @param {string} type string defining the input type ("vec3","number",...), it its a generic one use 0
- * @param {Object} extra_info this can be used to have special properties of an input (label, color, position, etc)
- */
- LGraphNode.prototype.addInput = function (name, type, extra_info) {
- type = type || 0;
- var input = { name: name, type: type, link: null };
- if (extra_info) {
- for (var i in extra_info) {
- input[i] = extra_info[i];
- }
- }
-
- if (!this.inputs) {
- this.inputs = [];
- }
-
- this.inputs.push(input);
- this.setSize(this.computeSize());
-
- if (this.onInputAdded) {
- this.onInputAdded(input);
- }
-
- LiteGraph.registerNodeAndSlotType(this, type);
-
- this.setDirtyCanvas(true, true);
- return input;
- };
-
- /**
- * add several new input slots in this node
- * @method addInputs
- * @param {Array} array of triplets like [[name,type,extra_info],[...]]
- */
- LGraphNode.prototype.addInputs = function (array) {
- for (var i = 0; i < array.length; ++i) {
- var info = array[i];
- var o = { name: info[0], type: info[1], link: null };
- if (array[2]) {
- for (var j in info[2]) {
- o[j] = info[2][j];
- }
- }
-
- if (!this.inputs) {
- this.inputs = [];
- }
- this.inputs.push(o);
- if (this.onInputAdded) {
- this.onInputAdded(o);
- }
-
- LiteGraph.registerNodeAndSlotType(this, info[1]);
- }
-
- this.setSize(this.computeSize());
- this.setDirtyCanvas(true, true);
- };
-
- /**
- * remove an existing input slot
- * @method removeInput
- * @param {number} slot
- */
- LGraphNode.prototype.removeInput = function (slot) {
- this.disconnectInput(slot);
- var slot_info = this.inputs.splice(slot, 1);
- for (var i = slot; i < this.inputs.length; ++i) {
- if (!this.inputs[i]) {
- continue;
- }
- var link = this.graph.links[this.inputs[i].link];
- if (!link) {
- continue;
- }
- link.target_slot -= 1;
- }
- this.setSize(this.computeSize());
- if (this.onInputRemoved) {
- this.onInputRemoved(slot, slot_info[0]);
- }
- this.setDirtyCanvas(true, true);
- };
-
- /**
- * add an special connection to this node (used for special kinds of graphs)
- * @method addConnection
- * @param {string} name
- * @param {string} type string defining the input type ("vec3","number",...)
- * @param {[x,y]} pos position of the connection inside the node
- * @param {string} direction if is input or output
- */
- LGraphNode.prototype.addConnection = function (name, type, pos, direction) {
- var o = {
- name: name,
- type: type,
- pos: pos,
- direction: direction,
- links: null,
- };
- this.connections.push(o);
- return o;
- };
-
- /**
- * computes the minimum size of a node according to its inputs and output slots
- * @method computeSize
- * @param {vec2} minHeight
- * @return {vec2} the total size
- */
- LGraphNode.prototype.computeSize = function (out) {
- if (this.constructor.size) {
- return this.constructor.size.concat();
- }
-
- var rows = Math.max(
- this.inputs ? this.inputs.length : 1,
- this.outputs ? this.outputs.length : 1
- );
- var size = out || new Float32Array([0, 0]);
- rows = Math.max(rows, 1);
- var font_size = LiteGraph.NODE_TEXT_SIZE; //although it should be graphcanvas.inner_text_font size
-
- var title_width = compute_text_size(this.title);
- var input_width = 0;
- var output_width = 0;
-
- if (this.inputs) {
- for (var i = 0, l = this.inputs.length; i < l; ++i) {
- var input = this.inputs[i];
- var text = input.label || input.name || "";
- var text_width = compute_text_size(text);
- if (input_width < text_width) {
- input_width = text_width;
- }
- }
- }
-
- if (this.outputs) {
- for (var i = 0, l = this.outputs.length; i < l; ++i) {
- var output = this.outputs[i];
- var text = output.label || output.name || "";
- var text_width = compute_text_size(text);
- if (output_width < text_width) {
- output_width = text_width;
- }
- }
- }
-
- size[0] = Math.max(input_width + output_width + 10, title_width);
- size[0] = Math.max(size[0], LiteGraph.NODE_WIDTH);
- if (this.widgets && this.widgets.length) {
- size[0] = Math.max(size[0], LiteGraph.NODE_WIDTH * 1.5);
- }
-
- size[1] =
- (this.constructor.slot_start_y || 0) + rows * LiteGraph.NODE_SLOT_HEIGHT;
-
- var widgets_height = 0;
- if (this.widgets && this.widgets.length) {
- for (var i = 0, l = this.widgets.length; i < l; ++i) {
- if (this.widgets[i].computeSize)
- widgets_height += this.widgets[i].computeSize(size[0])[1] + 4;
- else widgets_height += LiteGraph.NODE_WIDGET_HEIGHT + 4;
- }
- widgets_height += 8;
- }
-
- //compute height using widgets height
- if (this.widgets_up) size[1] = Math.max(size[1], widgets_height);
- else if (this.widgets_start_y != null)
- size[1] = Math.max(size[1], widgets_height + this.widgets_start_y);
- else size[1] += widgets_height;
-
- function compute_text_size(text) {
- if (!text) {
- return 0;
- }
- return font_size * text.length * 0.6;
- }
-
- if (this.constructor.min_height && size[1] < this.constructor.min_height) {
- size[1] = this.constructor.min_height;
- }
-
- size[1] += 6; //margin
-
- return size;
- };
-
- LGraphNode.prototype.inResizeCorner = function (canvasX, canvasY) {
- var rows = this.outputs ? this.outputs.length : 1;
- var outputs_offset =
- (this.constructor.slot_start_y || 0) + rows * LiteGraph.NODE_SLOT_HEIGHT;
- return isInsideRectangle(
- canvasX,
- canvasY,
- this.pos[0] + this.size[0] - 15,
- this.pos[1] + Math.max(this.size[1] - 15, outputs_offset),
- 20,
- 20
- );
- };
-
- /**
- * returns all the info available about a property of this node.
- *
- * @method getPropertyInfo
- * @param {String} property name of the property
- * @return {Object} the object with all the available info
- */
- LGraphNode.prototype.getPropertyInfo = function (property) {
- var info = null;
-
- //there are several ways to define info about a property
- //legacy mode
- if (this.properties_info) {
- for (var i = 0; i < this.properties_info.length; ++i) {
- if (this.properties_info[i].name == property) {
- info = this.properties_info[i];
- break;
- }
- }
- }
- //litescene mode using the constructor
- if (this.constructor["@" + property])
- info = this.constructor["@" + property];
-
- if (
- this.constructor.widgets_info &&
- this.constructor.widgets_info[property]
- )
- info = this.constructor.widgets_info[property];
-
- //litescene mode using the constructor
- if (!info && this.onGetPropertyInfo) {
- info = this.onGetPropertyInfo(property);
- }
-
- if (!info) info = {};
- if (!info.type) info.type = typeof this.properties[property];
- if (info.widget == "combo") info.type = "enum";
-
- return info;
- };
-
- /**
- * Defines a widget inside the node, it will be rendered on top of the node, you can control lots of properties
- *
- * @method addWidget
- * @param {String} type the widget type (could be "number","string","combo"
- * @param {String} name the text to show on the widget
- * @param {String} value the default value
- * @param {Function|String} callback function to call when it changes (optionally, it can be the name of the property to modify)
- * @param {Object} options the object that contains special properties of this widget
- * @return {Object} the created widget object
- */
- LGraphNode.prototype.addWidget = function (
- type,
- name,
- value,
- callback,
- options
- ) {
- if (!this.widgets) {
- this.widgets = [];
- }
-
- if (!options && callback && callback.constructor === Object) {
- options = callback;
- callback = null;
- }
-
- if (options && options.constructor === String)
- //options can be the property name
- options = { property: options };
-
- if (callback && callback.constructor === String) {
- //callback can be the property name
- if (!options) options = {};
- options.property = callback;
- callback = null;
- }
-
- if (callback && callback.constructor !== Function) {
- console.warn("addWidget: callback must be a function");
- callback = null;
- }
-
- var w = {
- type: type.toLowerCase(),
- name: name,
- value: value,
- callback: callback,
- options: options || {},
- };
-
- if (w.options.y !== undefined) {
- w.y = w.options.y;
- }
-
- if (!callback && !w.options.callback && !w.options.property) {
- console.warn(
- "LiteGraph addWidget(...) without a callback or property assigned"
- );
- }
- if (type == "combo" && !w.options.values) {
- throw "LiteGraph addWidget('combo',...) requires to pass values in options: { values:['red','blue'] }";
- }
- this.widgets.push(w);
- this.setSize(this.computeSize());
- return w;
- };
-
- LGraphNode.prototype.addCustomWidget = function (custom_widget) {
- if (!this.widgets) {
- this.widgets = [];
- }
- this.widgets.push(custom_widget);
- return custom_widget;
- };
-
- /**
- * returns the bounding of the object, used for rendering purposes
- * @method getBounding
- * @param out {Float32Array[4]?} [optional] a place to store the output, to free garbage
- * @param compute_outer {boolean?} [optional] set to true to include the shadow and connection points in the bounding calculation
- * @return {Float32Array[4]} the bounding box in format of [topleft_cornerx, topleft_cornery, width, height]
- */
- LGraphNode.prototype.getBounding = function (out, compute_outer) {
- out = out || new Float32Array(4);
- const nodePos = this.pos;
- const isCollapsed = this.flags.collapsed;
- const nodeSize = this.size;
-
- let left_offset = 0;
- // 1 offset due to how nodes are rendered
- let right_offset = 1;
- let top_offset = 0;
- let bottom_offset = 0;
-
- if (compute_outer) {
- // 4 offset for collapsed node connection points
- left_offset = 4;
- // 6 offset for right shadow and collapsed node connection points
- right_offset = 6 + left_offset;
- // 4 offset for collapsed nodes top connection points
- top_offset = 4;
- // 5 offset for bottom shadow and collapsed node connection points
- bottom_offset = 5 + top_offset;
- }
-
- out[0] = nodePos[0] - left_offset;
- out[1] = nodePos[1] - LiteGraph.NODE_TITLE_HEIGHT - top_offset;
- out[2] = isCollapsed
- ? (this._collapsed_width || LiteGraph.NODE_COLLAPSED_WIDTH) + right_offset
- : nodeSize[0] + right_offset;
- out[3] = isCollapsed
- ? LiteGraph.NODE_TITLE_HEIGHT + bottom_offset
- : nodeSize[1] + LiteGraph.NODE_TITLE_HEIGHT + bottom_offset;
-
- if (this.onBounding) {
- this.onBounding(out);
- }
- return out;
- };
-
- /**
- * checks if a point is inside the shape of a node
- * @method isPointInside
- * @param {number} x
- * @param {number} y
- * @return {boolean}
- */
- LGraphNode.prototype.isPointInside = function (x, y, margin, skip_title) {
- margin = margin || 0;
-
- var margin_top =
- this.graph && this.graph.isLive() ? 0 : LiteGraph.NODE_TITLE_HEIGHT;
- if (skip_title) {
- margin_top = 0;
- }
- if (this.flags && this.flags.collapsed) {
- //if ( distance([x,y], [this.pos[0] + this.size[0]*0.5, this.pos[1] + this.size[1]*0.5]) < LiteGraph.NODE_COLLAPSED_RADIUS)
- if (
- isInsideRectangle(
- x,
- y,
- this.pos[0] - margin,
- this.pos[1] - LiteGraph.NODE_TITLE_HEIGHT - margin,
- (this._collapsed_width || LiteGraph.NODE_COLLAPSED_WIDTH) +
- 2 * margin,
- LiteGraph.NODE_TITLE_HEIGHT + 2 * margin
- )
- ) {
- return true;
- }
- } else if (
- this.pos[0] - 4 - margin < x &&
- this.pos[0] + this.size[0] + 4 + margin > x &&
- this.pos[1] - margin_top - margin < y &&
- this.pos[1] + this.size[1] + margin > y
- ) {
- return true;
- }
- return false;
- };
-
- /**
- * checks if a point is inside a node slot, and returns info about which slot
- * @method getSlotInPosition
- * @param {number} x
- * @param {number} y
- * @return {Object} if found the object contains { input|output: slot object, slot: number, link_pos: [x,y] }
- */
- LGraphNode.prototype.getSlotInPosition = function (x, y) {
- //search for inputs
- var link_pos = new Float32Array(2);
- if (this.inputs) {
- for (var i = 0, l = this.inputs.length; i < l; ++i) {
- var input = this.inputs[i];
- this.getConnectionPos(true, i, link_pos);
- if (
- isInsideRectangle(x, y, link_pos[0] - 10, link_pos[1] - 5, 20, 10)
- ) {
- return { input: input, slot: i, link_pos: link_pos };
- }
- }
- }
-
- if (this.outputs) {
- for (var i = 0, l = this.outputs.length; i < l; ++i) {
- var output = this.outputs[i];
- this.getConnectionPos(false, i, link_pos);
- if (
- isInsideRectangle(x, y, link_pos[0] - 10, link_pos[1] - 5, 20, 10)
- ) {
- return { output: output, slot: i, link_pos: link_pos };
- }
- }
- }
-
- return null;
- };
-
- /**
- * returns the input slot with a given name (used for dynamic slots), -1 if not found
- * @method findInputSlot
- * @param {string} name the name of the slot
- * @param {boolean} returnObj if the obj itself wanted
- * @return {number_or_object} the slot (-1 if not found)
- */
- LGraphNode.prototype.findInputSlot = function (name, returnObj) {
- if (!this.inputs) {
- return -1;
- }
- for (var i = 0, l = this.inputs.length; i < l; ++i) {
- if (name == this.inputs[i].name) {
- return !returnObj ? i : this.inputs[i];
- }
- }
- return -1;
- };
-
- /**
- * returns the output slot with a given name (used for dynamic slots), -1 if not found
- * @method findOutputSlot
- * @param {string} name the name of the slot
- * @param {boolean} returnObj if the obj itself wanted
- * @return {number_or_object} the slot (-1 if not found)
- */
- LGraphNode.prototype.findOutputSlot = function (name, returnObj) {
- returnObj = returnObj || false;
- if (!this.outputs) {
- return -1;
- }
- for (var i = 0, l = this.outputs.length; i < l; ++i) {
- if (name == this.outputs[i].name) {
- return !returnObj ? i : this.outputs[i];
- }
- }
- return -1;
- };
-
- // TODO refactor: USE SINGLE findInput/findOutput functions! :: merge options
-
- /**
- * returns the first free input slot
- * @method findInputSlotFree
- * @param {object} options
- * @return {number_or_object} the slot (-1 if not found)
- */
- LGraphNode.prototype.findInputSlotFree = function (optsIn) {
- var optsIn = optsIn || {};
- var optsDef = { returnObj: false, typesNotAccepted: [] };
- var opts = Object.assign(optsDef, optsIn);
- if (!this.inputs) {
- return -1;
- }
- for (var i = 0, l = this.inputs.length; i < l; ++i) {
- if (this.inputs[i].link && this.inputs[i].link != null) {
- continue;
- }
- if (
- opts.typesNotAccepted &&
- opts.typesNotAccepted.includes &&
- opts.typesNotAccepted.includes(this.inputs[i].type)
- ) {
- continue;
- }
- return !opts.returnObj ? i : this.inputs[i];
- }
- return -1;
- };
-
- /**
- * returns the first output slot free
- * @method findOutputSlotFree
- * @param {object} options
- * @return {number_or_object} the slot (-1 if not found)
- */
- LGraphNode.prototype.findOutputSlotFree = function (optsIn) {
- var optsIn = optsIn || {};
- var optsDef = { returnObj: false, typesNotAccepted: [] };
- var opts = Object.assign(optsDef, optsIn);
- if (!this.outputs) {
- return -1;
- }
- for (var i = 0, l = this.outputs.length; i < l; ++i) {
- if (this.outputs[i].links && this.outputs[i].links != null) {
- continue;
- }
- if (
- opts.typesNotAccepted &&
- opts.typesNotAccepted.includes &&
- opts.typesNotAccepted.includes(this.outputs[i].type)
- ) {
- continue;
- }
- return !opts.returnObj ? i : this.outputs[i];
- }
- return -1;
- };
-
- /**
- * findSlotByType for INPUTS
- */
- LGraphNode.prototype.findInputSlotByType = function (
- type,
- returnObj,
- preferFreeSlot,
- doNotUseOccupied
- ) {
- return this.findSlotByType(
- true,
- type,
- returnObj,
- preferFreeSlot,
- doNotUseOccupied
- );
- };
-
- /**
- * findSlotByType for OUTPUTS
- */
- LGraphNode.prototype.findOutputSlotByType = function (
- type,
- returnObj,
- preferFreeSlot,
- doNotUseOccupied
- ) {
- return this.findSlotByType(
- false,
- type,
- returnObj,
- preferFreeSlot,
- doNotUseOccupied
- );
- };
-
- /**
- * returns the output (or input) slot with a given type, -1 if not found
- * @method findSlotByType
- * @param {boolean} input uise inputs instead of outputs
- * @param {string} type the type of the slot
- * @param {boolean} returnObj if the obj itself wanted
- * @param {boolean} preferFreeSlot if we want a free slot (if not found, will return the first of the type anyway)
- * @return {number_or_object} the slot (-1 if not found)
- */
- LGraphNode.prototype.findSlotByType = function (
- input,
- type,
- returnObj,
- preferFreeSlot,
- doNotUseOccupied
- ) {
- input = input || false;
- returnObj = returnObj || false;
- preferFreeSlot = preferFreeSlot || false;
- doNotUseOccupied = doNotUseOccupied || false;
- var aSlots = input ? this.inputs : this.outputs;
- if (!aSlots) {
- return -1;
- }
- // !! empty string type is considered 0, * !!
- if (type == "" || type == "*") type = 0;
- for (var i = 0, l = aSlots.length; i < l; ++i) {
- var tFound = false;
- var aSource = (type + "").toLowerCase().split(",");
- var aDest =
- aSlots[i].type == "0" || aSlots[i].type == "*" ? "0" : aSlots[i].type;
- aDest = (aDest + "").toLowerCase().split(",");
- for (var sI = 0; sI < aSource.length; sI++) {
- for (var dI = 0; dI < aDest.length; dI++) {
- if (aSource[sI] == "_event_") aSource[sI] = LiteGraph.EVENT;
- if (aDest[sI] == "_event_") aDest[sI] = LiteGraph.EVENT;
- if (aSource[sI] == "*") aSource[sI] = 0;
- if (aDest[sI] == "*") aDest[sI] = 0;
- if (aSource[sI] == aDest[dI]) {
- if (preferFreeSlot && aSlots[i].links && aSlots[i].links !== null)
- continue;
- return !returnObj ? i : aSlots[i];
- }
- }
- }
- }
- // if didnt find some, stop checking for free slots
- if (preferFreeSlot && !doNotUseOccupied) {
- for (var i = 0, l = aSlots.length; i < l; ++i) {
- var tFound = false;
- var aSource = (type + "").toLowerCase().split(",");
- var aDest =
- aSlots[i].type == "0" || aSlots[i].type == "*" ? "0" : aSlots[i].type;
- aDest = (aDest + "").toLowerCase().split(",");
- for (var sI = 0; sI < aSource.length; sI++) {
- for (var dI = 0; dI < aDest.length; dI++) {
- if (aSource[sI] == "*") aSource[sI] = 0;
- if (aDest[sI] == "*") aDest[sI] = 0;
- if (aSource[sI] == aDest[dI]) {
- return !returnObj ? i : aSlots[i];
- }
- }
- }
- }
- }
- return -1;
- };
-
- /**
- * connect this node output to the input of another node BY TYPE
- * @method connectByType
- * @param {number_or_string} slot (could be the number of the slot or the string with the name of the slot)
- * @param {LGraphNode} node the target node
- * @param {string} target_type the input slot type of the target node
- * @return {Object} the link_info is created, otherwise null
- */
- LGraphNode.prototype.connectByType = function (
- slot,
- target_node,
- target_slotType,
- optsIn
- ) {
- var optsIn = optsIn || {};
- var optsDef = {
- createEventInCase: true,
- firstFreeIfOutputGeneralInCase: true,
- generalTypeInCase: true,
- };
- var opts = Object.assign(optsDef, optsIn);
- if (target_node && target_node.constructor === Number) {
- target_node = this.graph.getNodeById(target_node);
- }
- var target_slot = target_node.findInputSlotByType(
- target_slotType,
- false,
- true
- );
- if (target_slot >= 0 && target_slot !== null) {
- //console.debug("CONNbyTYPE type "+target_slotType+" for "+target_slot)
- return this.connect(slot, target_node, target_slot);
- } else {
- //console.log("type "+target_slotType+" not found or not free?")
- if (opts.createEventInCase && target_slotType == LiteGraph.EVENT) {
- // WILL CREATE THE onTrigger IN SLOT
- //console.debug("connect WILL CREATE THE onTrigger "+target_slotType+" to "+target_node);
- return this.connect(slot, target_node, -1);
- }
- // connect to the first general output slot if not found a specific type and
- if (opts.generalTypeInCase) {
- var target_slot = target_node.findInputSlotByType(0, false, true, true);
- //console.debug("connect TO a general type (*, 0), if not found the specific type ",target_slotType," to ",target_node,"RES_SLOT:",target_slot);
- if (target_slot >= 0) {
- return this.connect(slot, target_node, target_slot);
- }
- }
- // connect to the first free input slot if not found a specific type and this output is general
- if (
- opts.firstFreeIfOutputGeneralInCase &&
- (target_slotType == 0 ||
- target_slotType == "*" ||
- target_slotType == "")
- ) {
- var target_slot = target_node.findInputSlotFree({
- typesNotAccepted: [LiteGraph.EVENT],
- });
- //console.debug("connect TO TheFirstFREE ",target_slotType," to ",target_node,"RES_SLOT:",target_slot);
- if (target_slot >= 0) {
- return this.connect(slot, target_node, target_slot);
- }
- }
-
- console.debug(
- "no way to connect type: ",
- target_slotType,
- " to targetNODE ",
- target_node
- );
- //TODO filter
-
- return null;
- }
- };
-
- /**
- * connect this node input to the output of another node BY TYPE
- * @method connectByType
- * @param {number_or_string} slot (could be the number of the slot or the string with the name of the slot)
- * @param {LGraphNode} node the target node
- * @param {string} target_type the output slot type of the target node
- * @return {Object} the link_info is created, otherwise null
- */
- LGraphNode.prototype.connectByTypeOutput = function (
- slot,
- source_node,
- source_slotType,
- optsIn
- ) {
- var optsIn = optsIn || {};
- var optsDef = {
- createEventInCase: true,
- firstFreeIfInputGeneralInCase: true,
- generalTypeInCase: true,
- };
- var opts = Object.assign(optsDef, optsIn);
- if (source_node && source_node.constructor === Number) {
- source_node = this.graph.getNodeById(source_node);
- }
- var source_slot = source_node.findOutputSlotByType(
- source_slotType,
- false,
- true
- );
- if (source_slot >= 0 && source_slot !== null) {
- //console.debug("CONNbyTYPE OUT! type "+source_slotType+" for "+source_slot)
- return source_node.connect(source_slot, this, slot);
- } else {
- // connect to the first general output slot if not found a specific type and
- if (opts.generalTypeInCase) {
- var source_slot = source_node.findOutputSlotByType(
- 0,
- false,
- true,
- true
- );
- if (source_slot >= 0) {
- return source_node.connect(source_slot, this, slot);
- }
- }
-
- if (opts.createEventInCase && source_slotType == LiteGraph.EVENT) {
- // WILL CREATE THE onExecuted OUT SLOT
- if (LiteGraph.do_add_triggers_slots) {
- var source_slot = source_node.addOnExecutedOutput();
- return source_node.connect(source_slot, this, slot);
- }
- }
- // connect to the first free output slot if not found a specific type and this input is general
- if (
- opts.firstFreeIfInputGeneralInCase &&
- (source_slotType == 0 ||
- source_slotType == "*" ||
- source_slotType == "")
- ) {
- var source_slot = source_node.findOutputSlotFree({
- typesNotAccepted: [LiteGraph.EVENT],
- });
- if (source_slot >= 0) {
- return source_node.connect(source_slot, this, slot);
- }
- }
-
- console.debug(
- "no way to connect byOUT type: ",
- source_slotType,
- " to sourceNODE ",
- source_node
- );
- //TODO filter
-
- //console.log("type OUT! "+source_slotType+" not found or not free?")
- return null;
- }
- };
-
- /**
- * connect this node output to the input of another node
- * @method connect
- * @param {number_or_string} slot (could be the number of the slot or the string with the name of the slot)
- * @param {LGraphNode} node the target node
- * @param {number_or_string} target_slot the input slot of the target node (could be the number of the slot or the string with the name of the slot, or -1 to connect a trigger)
- * @return {Object} the link_info is created, otherwise null
- */
- LGraphNode.prototype.connect = function (slot, target_node, target_slot) {
- target_slot = target_slot || 0;
-
- if (!this.graph) {
- //could be connected before adding it to a graph
- console.log(
- "Connect: Error, node doesn't belong to any graph. Nodes must be added first to a graph before connecting them."
- ); //due to link ids being associated with graphs
- return null;
- }
-
- //seek for the output slot
- if (slot.constructor === String) {
- slot = this.findOutputSlot(slot);
- if (slot == -1) {
- if (LiteGraph.debug) {
- console.log("Connect: Error, no slot of name " + slot);
- }
- return null;
- }
- } else if (!this.outputs || slot >= this.outputs.length) {
- if (LiteGraph.debug) {
- console.log("Connect: Error, slot number not found");
- }
- return null;
- }
-
- if (target_node && target_node.constructor === Number) {
- target_node = this.graph.getNodeById(target_node);
- }
- if (!target_node) {
- throw "target node is null";
- }
-
- //avoid loopback
- if (target_node == this) {
- return null;
- }
-
- //you can specify the slot by name
- if (target_slot.constructor === String) {
- target_slot = target_node.findInputSlot(target_slot);
- if (target_slot == -1) {
- if (LiteGraph.debug) {
- console.log("Connect: Error, no slot of name " + target_slot);
- }
- return null;
- }
- } else if (target_slot === LiteGraph.EVENT) {
- if (LiteGraph.do_add_triggers_slots) {
- //search for first slot with event? :: NO this is done outside
- //console.log("Connect: Creating triggerEvent");
- // force mode
- target_node.changeMode(LiteGraph.ON_TRIGGER);
- target_slot = target_node.findInputSlot("onTrigger");
- } else {
- return null; // -- break --
- }
- } else if (
- !target_node.inputs ||
- target_slot >= target_node.inputs.length
- ) {
- if (LiteGraph.debug) {
- console.log("Connect: Error, slot number not found");
- }
- return null;
- }
-
- var changed = false;
-
- var input = target_node.inputs[target_slot];
- var link_info = null;
- var output = this.outputs[slot];
-
- if (!this.outputs[slot]) {
- /*console.debug("Invalid slot passed: "+slot);
- console.debug(this.outputs);*/
- return null;
- }
-
- // allow target node to change slot
- if (target_node.onBeforeConnectInput) {
- // This way node can choose another slot (or make a new one?)
- target_slot = target_node.onBeforeConnectInput(target_slot); //callback
- }
-
- //check target_slot and check connection types
- if (
- target_slot === false ||
- target_slot === null ||
- !LiteGraph.isValidConnection(output.type, input.type)
- ) {
- this.setDirtyCanvas(false, true);
- if (changed) this.graph.connectionChange(this, link_info);
- return null;
- } else {
- //console.debug("valid connection",output.type, input.type);
- }
-
- //allows nodes to block connection, callback
- if (target_node.onConnectInput) {
- if (
- target_node.onConnectInput(
- target_slot,
- output.type,
- output,
- this,
- slot
- ) === false
- ) {
- return null;
- }
- }
- if (this.onConnectOutput) {
- // callback
- if (
- this.onConnectOutput(
- slot,
- input.type,
- input,
- target_node,
- target_slot
- ) === false
- ) {
- return null;
- }
- }
-
- //if there is something already plugged there, disconnect
- if (
- target_node.inputs[target_slot] &&
- target_node.inputs[target_slot].link != null
- ) {
- this.graph.beforeChange();
- target_node.disconnectInput(target_slot, { doProcessChange: false });
- changed = true;
- }
- if (output.links !== null && output.links.length) {
- switch (output.type) {
- case LiteGraph.EVENT:
- if (!LiteGraph.allow_multi_output_for_events) {
- this.graph.beforeChange();
- this.disconnectOutput(slot, false, { doProcessChange: false }); // Input(target_slot, {doProcessChange: false});
- changed = true;
- }
- break;
- default:
- break;
- }
- }
-
- var nextId;
- if (LiteGraph.use_uuids) nextId = LiteGraph.uuidv4();
- else nextId = ++this.graph.last_link_id;
-
- //create link class
- link_info = new LLink(
- nextId,
- input.type || output.type,
- this.id,
- slot,
- target_node.id,
- target_slot
- );
-
- //add to graph links list
- this.graph.links[link_info.id] = link_info;
-
- //connect in output
- if (output.links == null) {
- output.links = [];
- }
- output.links.push(link_info.id);
- //connect in input
- target_node.inputs[target_slot].link = link_info.id;
- if (this.graph) {
- this.graph._version++;
- }
- if (this.onConnectionsChange) {
- this.onConnectionsChange(LiteGraph.OUTPUT, slot, true, link_info, output);
- } //link_info has been created now, so its updated
- if (target_node.onConnectionsChange) {
- target_node.onConnectionsChange(
- LiteGraph.INPUT,
- target_slot,
- true,
- link_info,
- input
- );
- }
- if (this.graph && this.graph.onNodeConnectionChange) {
- this.graph.onNodeConnectionChange(
- LiteGraph.INPUT,
- target_node,
- target_slot,
- this,
- slot
- );
- this.graph.onNodeConnectionChange(
- LiteGraph.OUTPUT,
- this,
- slot,
- target_node,
- target_slot
- );
- }
-
- this.setDirtyCanvas(false, true);
- this.graph.afterChange();
- this.graph.connectionChange(this, link_info);
-
- return link_info;
- };
-
- /**
- * disconnect one output to an specific node
- * @method disconnectOutput
- * @param {number_or_string} slot (could be the number of the slot or the string with the name of the slot)
- * @param {LGraphNode} target_node the target node to which this slot is connected [Optional, if not target_node is specified all nodes will be disconnected]
- * @return {boolean} if it was disconnected successfully
- */
- LGraphNode.prototype.disconnectOutput = function (slot, target_node) {
- if (slot.constructor === String) {
- slot = this.findOutputSlot(slot);
- if (slot == -1) {
- if (LiteGraph.debug) {
- console.log("Connect: Error, no slot of name " + slot);
- }
- return false;
- }
- } else if (!this.outputs || slot >= this.outputs.length) {
- if (LiteGraph.debug) {
- console.log("Connect: Error, slot number not found");
- }
- return false;
- }
-
- //get output slot
- var output = this.outputs[slot];
- if (!output || !output.links || output.links.length == 0) {
- return false;
- }
-
- //one of the output links in this slot
- if (target_node) {
- if (target_node.constructor === Number) {
- target_node = this.graph.getNodeById(target_node);
- }
- if (!target_node) {
- throw "Target Node not found";
- }
-
- for (var i = 0, l = output.links.length; i < l; i++) {
- var link_id = output.links[i];
- var link_info = this.graph.links[link_id];
-
- //is the link we are searching for...
- if (link_info.target_id == target_node.id) {
- output.links.splice(i, 1); //remove here
- var input = target_node.inputs[link_info.target_slot];
- input.link = null; //remove there
- delete this.graph.links[link_id]; //remove the link from the links pool
- if (this.graph) {
- this.graph._version++;
- }
- if (target_node.onConnectionsChange) {
- target_node.onConnectionsChange(
- LiteGraph.INPUT,
- link_info.target_slot,
- false,
- link_info,
- input
- );
- } //link_info hasn't been modified so its ok
- if (this.onConnectionsChange) {
- this.onConnectionsChange(
- LiteGraph.OUTPUT,
- slot,
- false,
- link_info,
- output
- );
- }
- if (this.graph && this.graph.onNodeConnectionChange) {
- this.graph.onNodeConnectionChange(LiteGraph.OUTPUT, this, slot);
- }
- if (this.graph && this.graph.onNodeConnectionChange) {
- this.graph.onNodeConnectionChange(LiteGraph.OUTPUT, this, slot);
- this.graph.onNodeConnectionChange(
- LiteGraph.INPUT,
- target_node,
- link_info.target_slot
- );
- }
- break;
- }
- }
- } //all the links in this output slot
- else {
- for (var i = 0, l = output.links.length; i < l; i++) {
- var link_id = output.links[i];
- var link_info = this.graph.links[link_id];
- if (!link_info) {
- //bug: it happens sometimes
- continue;
- }
-
- var target_node = this.graph.getNodeById(link_info.target_id);
- var input = null;
- if (this.graph) {
- this.graph._version++;
- }
- if (target_node) {
- input = target_node.inputs[link_info.target_slot];
- input.link = null; //remove other side link
- if (target_node.onConnectionsChange) {
- target_node.onConnectionsChange(
- LiteGraph.INPUT,
- link_info.target_slot,
- false,
- link_info,
- input
- );
- } //link_info hasn't been modified so its ok
- if (this.graph && this.graph.onNodeConnectionChange) {
- this.graph.onNodeConnectionChange(
- LiteGraph.INPUT,
- target_node,
- link_info.target_slot
- );
- }
- }
- delete this.graph.links[link_id]; //remove the link from the links pool
- if (this.onConnectionsChange) {
- this.onConnectionsChange(
- LiteGraph.OUTPUT,
- slot,
- false,
- link_info,
- output
- );
- }
- if (this.graph && this.graph.onNodeConnectionChange) {
- this.graph.onNodeConnectionChange(LiteGraph.OUTPUT, this, slot);
- this.graph.onNodeConnectionChange(
- LiteGraph.INPUT,
- target_node,
- link_info.target_slot
- );
- }
- }
- output.links = null;
- }
-
- this.setDirtyCanvas(false, true);
- this.graph.connectionChange(this);
- return true;
- };
-
- /**
- * disconnect one input
- * @method disconnectInput
- * @param {number_or_string} slot (could be the number of the slot or the string with the name of the slot)
- * @return {boolean} if it was disconnected successfully
- */
- LGraphNode.prototype.disconnectInput = function (slot) {
- //seek for the output slot
- if (slot.constructor === String) {
- slot = this.findInputSlot(slot);
- if (slot == -1) {
- if (LiteGraph.debug) {
- console.log("Connect: Error, no slot of name " + slot);
- }
- return false;
- }
- } else if (!this.inputs || slot >= this.inputs.length) {
- if (LiteGraph.debug) {
- console.log("Connect: Error, slot number not found");
- }
- return false;
- }
-
- var input = this.inputs[slot];
- if (!input) {
- return false;
- }
-
- var link_id = this.inputs[slot].link;
- if (link_id != null) {
- this.inputs[slot].link = null;
-
- //remove other side
- var link_info = this.graph.links[link_id];
- if (link_info) {
- var target_node = this.graph.getNodeById(link_info.origin_id);
- if (!target_node) {
- return false;
- }
-
- var output = target_node.outputs[link_info.origin_slot];
- if (!output || !output.links || output.links.length == 0) {
- return false;
- }
-
- //search in the inputs list for this link
- for (var i = 0, l = output.links.length; i < l; i++) {
- if (output.links[i] == link_id) {
- output.links.splice(i, 1);
- break;
- }
- }
-
- delete this.graph.links[link_id]; //remove from the pool
- if (this.graph) {
- this.graph._version++;
- }
- if (this.onConnectionsChange) {
- this.onConnectionsChange(
- LiteGraph.INPUT,
- slot,
- false,
- link_info,
- input
- );
- }
- if (target_node.onConnectionsChange) {
- target_node.onConnectionsChange(
- LiteGraph.OUTPUT,
- i,
- false,
- link_info,
- output
- );
- }
- if (this.graph && this.graph.onNodeConnectionChange) {
- this.graph.onNodeConnectionChange(LiteGraph.OUTPUT, target_node, i);
- this.graph.onNodeConnectionChange(LiteGraph.INPUT, this, slot);
- }
- }
- } //link != null
-
- this.setDirtyCanvas(false, true);
- if (this.graph) this.graph.connectionChange(this);
- return true;
- };
-
- /**
- * returns the center of a connection point in canvas coords
- * @method getConnectionPos
- * @param {boolean} is_input true if if a input slot, false if it is an output
- * @param {number_or_string} slot (could be the number of the slot or the string with the name of the slot)
- * @param {vec2} out [optional] a place to store the output, to free garbage
- * @return {[x,y]} the position
- **/
- LGraphNode.prototype.getConnectionPos = function (
- is_input,
- slot_number,
- out
- ) {
- out = out || new Float32Array(2);
- var num_slots = 0;
- if (is_input && this.inputs) {
- num_slots = this.inputs.length;
- }
- if (!is_input && this.outputs) {
- num_slots = this.outputs.length;
- }
-
- var offset = LiteGraph.NODE_SLOT_HEIGHT * 0.5;
-
- if (this.flags.collapsed) {
- var w = this._collapsed_width || LiteGraph.NODE_COLLAPSED_WIDTH;
- if (this.horizontal) {
- out[0] = this.pos[0] + w * 0.5;
- if (is_input) {
- out[1] = this.pos[1] - LiteGraph.NODE_TITLE_HEIGHT;
- } else {
- out[1] = this.pos[1];
- }
- } else {
- if (is_input) {
- out[0] = this.pos[0];
- } else {
- out[0] = this.pos[0] + w;
- }
- out[1] = this.pos[1] - LiteGraph.NODE_TITLE_HEIGHT * 0.5;
- }
- return out;
- }
-
- //weird feature that never got finished
- if (is_input && slot_number == -1) {
- out[0] = this.pos[0] + LiteGraph.NODE_TITLE_HEIGHT * 0.5;
- out[1] = this.pos[1] + LiteGraph.NODE_TITLE_HEIGHT * 0.5;
- return out;
- }
-
- //hard-coded pos
- if (is_input && num_slots > slot_number && this.inputs[slot_number].pos) {
- out[0] = this.pos[0] + this.inputs[slot_number].pos[0];
- out[1] = this.pos[1] + this.inputs[slot_number].pos[1];
- return out;
- } else if (
- !is_input &&
- num_slots > slot_number &&
- this.outputs[slot_number].pos
- ) {
- out[0] = this.pos[0] + this.outputs[slot_number].pos[0];
- out[1] = this.pos[1] + this.outputs[slot_number].pos[1];
- return out;
- }
-
- //horizontal distributed slots
- if (this.horizontal) {
- out[0] = this.pos[0] + (slot_number + 0.5) * (this.size[0] / num_slots);
- if (is_input) {
- out[1] = this.pos[1] - LiteGraph.NODE_TITLE_HEIGHT;
- } else {
- out[1] = this.pos[1] + this.size[1];
- }
- return out;
- }
-
- //default vertical slots
- if (is_input) {
- out[0] = this.pos[0] + offset;
- } else {
- out[0] = this.pos[0] + this.size[0] + 1 - offset;
- }
- out[1] =
- this.pos[1] +
- (slot_number + 0.7) * LiteGraph.NODE_SLOT_HEIGHT +
- (this.constructor.slot_start_y || 0);
- return out;
- };
-
- /* Force align to grid */
- LGraphNode.prototype.alignToGrid = function () {
- this.pos[0] =
- LiteGraph.CANVAS_GRID_SIZE *
- Math.round(this.pos[0] / LiteGraph.CANVAS_GRID_SIZE);
- this.pos[1] =
- LiteGraph.CANVAS_GRID_SIZE *
- Math.round(this.pos[1] / LiteGraph.CANVAS_GRID_SIZE);
- };
-
- /* Console output */
- LGraphNode.prototype.trace = function (msg) {
- if (!this.console) {
- this.console = [];
- }
-
- this.console.push(msg);
- if (this.console.length > LGraphNode.MAX_CONSOLE) {
- this.console.shift();
- }
-
- if (this.graph.onNodeTrace) this.graph.onNodeTrace(this, msg);
- };
-
- /* Forces to redraw or the main canvas (LGraphNode) or the bg canvas (links) */
- LGraphNode.prototype.setDirtyCanvas = function (
- dirty_foreground,
- dirty_background
- ) {
- if (!this.graph) {
- return;
- }
- this.graph.sendActionToCanvas("setDirty", [
- dirty_foreground,
- dirty_background,
- ]);
- };
-
- LGraphNode.prototype.loadImage = function (url) {
- var img = new Image();
- img.src = LiteGraph.node_images_path + url;
- img.ready = false;
-
- var that = this;
- img.onload = function () {
- this.ready = true;
- that.setDirtyCanvas(true);
- };
- return img;
- };
-
- //safe LGraphNode action execution (not sure if safe)
- /*
-LGraphNode.prototype.executeAction = function(action)
-{
- if(action == "") return false;
-
- if( action.indexOf(";") != -1 || action.indexOf("}") != -1)
- {
- this.trace("Error: Action contains unsafe characters");
- return false;
- }
-
- var tokens = action.split("(");
- var func_name = tokens[0];
- if( typeof(this[func_name]) != "function")
- {
- this.trace("Error: Action not found on node: " + func_name);
- return false;
- }
-
- var code = action;
-
- try
- {
- var _foo = eval;
- eval = null;
- (new Function("with(this) { " + code + "}")).call(this);
- eval = _foo;
- }
- catch (err)
- {
- this.trace("Error executing action {" + action + "} :" + err);
- return false;
- }
-
- return true;
-}
-*/
-
- /* Allows to get onMouseMove and onMouseUp events even if the mouse is out of focus */
- LGraphNode.prototype.captureInput = function (v) {
- if (!this.graph || !this.graph.list_of_graphcanvas) {
- return;
- }
-
- var list = this.graph.list_of_graphcanvas;
-
- for (var i = 0; i < list.length; ++i) {
- var c = list[i];
- //releasing somebody elses capture?!
- if (!v && c.node_capturing_input != this) {
- continue;
- }
-
- //change
- c.node_capturing_input = v ? this : null;
- }
- };
-
- /**
- * Collapse the node to make it smaller on the canvas
- * @method collapse
- **/
- LGraphNode.prototype.collapse = function (force) {
- this.graph._version++;
- if (this.constructor.collapsable === false && !force) {
- return;
- }
- if (!this.flags.collapsed) {
- this.flags.collapsed = true;
- } else {
- this.flags.collapsed = false;
- }
- this.setDirtyCanvas(true, true);
- };
-
- /**
- * Forces the node to do not move or realign on Z
- * @method pin
- **/
-
- LGraphNode.prototype.pin = function (v) {
- this.graph._version++;
- if (v === undefined) {
- this.flags.pinned = !this.flags.pinned;
- } else {
- this.flags.pinned = v;
- }
- };
-
- LGraphNode.prototype.localToScreen = function (x, y, graphcanvas) {
- return [
- (x + this.pos[0]) * graphcanvas.scale + graphcanvas.offset[0],
- (y + this.pos[1]) * graphcanvas.scale + graphcanvas.offset[1],
- ];
- };
-
- function LGraphGroup(title) {
- this._ctor(title);
- }
-
- global.LGraphGroup = LiteGraph.LGraphGroup = LGraphGroup;
-
- LGraphGroup.prototype._ctor = function (title) {
- this.title = title || "Group";
- this.font_size = 24;
- this.color = LGraphCanvas.node_colors.pale_blue
- ? LGraphCanvas.node_colors.pale_blue.groupcolor
- : "#AAA";
- this._bounding = new Float32Array([10, 10, 140, 80]);
- this._pos = this._bounding.subarray(0, 2);
- this._size = this._bounding.subarray(2, 4);
- this._nodes = [];
- this.graph = null;
-
- Object.defineProperty(this, "pos", {
- set: function (v) {
- if (!v || v.length < 2) {
- return;
- }
- this._pos[0] = v[0];
- this._pos[1] = v[1];
- },
- get: function () {
- return this._pos;
- },
- enumerable: true,
- });
-
- Object.defineProperty(this, "size", {
- set: function (v) {
- if (!v || v.length < 2) {
- return;
- }
- this._size[0] = Math.max(140, v[0]);
- this._size[1] = Math.max(80, v[1]);
- },
- get: function () {
- return this._size;
- },
- enumerable: true,
- });
- };
-
- LGraphGroup.prototype.configure = function (o) {
- this.title = o.title;
- this._bounding.set(o.bounding);
- this.color = o.color;
- if (o.font_size) {
- this.font_size = o.font_size;
- }
- };
-
- LGraphGroup.prototype.serialize = function () {
- var b = this._bounding;
- return {
- title: this.title,
- bounding: [
- Math.round(b[0]),
- Math.round(b[1]),
- Math.round(b[2]),
- Math.round(b[3]),
- ],
- color: this.color,
- font_size: this.font_size,
- };
- };
-
- LGraphGroup.prototype.move = function (deltax, deltay, ignore_nodes) {
- this._pos[0] += deltax;
- this._pos[1] += deltay;
- if (ignore_nodes) {
- return;
- }
- for (var i = 0; i < this._nodes.length; ++i) {
- var node = this._nodes[i];
- node.pos[0] += deltax;
- node.pos[1] += deltay;
- }
- };
-
- LGraphGroup.prototype.recomputeInsideNodes = function () {
- this._nodes.length = 0;
- var nodes = this.graph._nodes;
- var node_bounding = new Float32Array(4);
-
- for (var i = 0; i < nodes.length; ++i) {
- var node = nodes[i];
- node.getBounding(node_bounding);
- if (!overlapBounding(this._bounding, node_bounding)) {
- continue;
- } //out of the visible area
- this._nodes.push(node);
- }
- };
-
- LGraphGroup.prototype.isPointInside = LGraphNode.prototype.isPointInside;
- LGraphGroup.prototype.setDirtyCanvas = LGraphNode.prototype.setDirtyCanvas;
-
- //****************************************
-
- //Scale and Offset
- function DragAndScale(element, skip_events) {
- this.offset = new Float32Array([0, 0]);
- this.scale = 1;
- this.max_scale = 10;
- this.min_scale = 0.1;
- this.onredraw = null;
- this.enabled = true;
- this.last_mouse = [0, 0];
- this.element = null;
- this.visible_area = new Float32Array(4);
-
- if (element) {
- this.element = element;
- if (!skip_events) {
- this.bindEvents(element);
- }
- }
- }
-
- LiteGraph.DragAndScale = DragAndScale;
-
- DragAndScale.prototype.bindEvents = function (element) {
- this.last_mouse = new Float32Array(2);
-
- this._binded_mouse_callback = this.onMouse.bind(this);
-
- LiteGraph.pointerListenerAdd(element, "down", this._binded_mouse_callback);
- LiteGraph.pointerListenerAdd(element, "move", this._binded_mouse_callback);
- LiteGraph.pointerListenerAdd(element, "up", this._binded_mouse_callback);
-
- element.addEventListener("mousewheel", this._binded_mouse_callback, false);
- element.addEventListener("wheel", this._binded_mouse_callback, false);
- };
-
- DragAndScale.prototype.computeVisibleArea = function (viewport) {
- if (!this.element) {
- this.visible_area[0] =
- this.visible_area[1] =
- this.visible_area[2] =
- this.visible_area[3] =
- 0;
- return;
- }
- var width = this.element.width;
- var height = this.element.height;
- var startx = -this.offset[0];
- var starty = -this.offset[1];
- if (viewport) {
- startx += viewport[0] / this.scale;
- starty += viewport[1] / this.scale;
- width = viewport[2];
- height = viewport[3];
- }
- var endx = startx + width / this.scale;
- var endy = starty + height / this.scale;
- this.visible_area[0] = startx;
- this.visible_area[1] = starty;
- this.visible_area[2] = endx - startx;
- this.visible_area[3] = endy - starty;
- };
-
- DragAndScale.prototype.onMouse = function (e) {
- if (!this.enabled) {
- return;
- }
-
- var canvas = this.element;
- var rect = canvas.getBoundingClientRect();
- var x = e.clientX - rect.left;
- var y = e.clientY - rect.top;
- e.canvasx = x;
- e.canvasy = y;
- e.dragging = this.dragging;
-
- var is_inside =
- !this.viewport ||
- (this.viewport &&
- x >= this.viewport[0] &&
- x < this.viewport[0] + this.viewport[2] &&
- y >= this.viewport[1] &&
- y < this.viewport[1] + this.viewport[3]);
-
- //console.log("pointerevents: DragAndScale onMouse "+e.type+" "+is_inside);
-
- var ignore = false;
- if (this.onmouse) {
- ignore = this.onmouse(e);
- }
-
- if (e.type == LiteGraph.pointerevents_method + "down" && is_inside) {
- this.dragging = true;
- LiteGraph.pointerListenerRemove(
- canvas,
- "move",
- this._binded_mouse_callback
- );
- LiteGraph.pointerListenerAdd(
- document,
- "move",
- this._binded_mouse_callback
- );
- LiteGraph.pointerListenerAdd(document, "up", this._binded_mouse_callback);
- } else if (e.type == LiteGraph.pointerevents_method + "move") {
- if (!ignore) {
- var deltax = x - this.last_mouse[0];
- var deltay = y - this.last_mouse[1];
- if (this.dragging) {
- this.mouseDrag(deltax, deltay);
- }
- }
- } else if (e.type == LiteGraph.pointerevents_method + "up") {
- this.dragging = false;
- LiteGraph.pointerListenerRemove(
- document,
- "move",
- this._binded_mouse_callback
- );
- LiteGraph.pointerListenerRemove(
- document,
- "up",
- this._binded_mouse_callback
- );
- LiteGraph.pointerListenerAdd(canvas, "move", this._binded_mouse_callback);
- } else if (
- is_inside &&
- (e.type == "mousewheel" ||
- e.type == "wheel" ||
- e.type == "DOMMouseScroll")
- ) {
- e.eventType = "mousewheel";
- if (e.type == "wheel") {
- e.wheel = -e.deltaY;
- } else {
- e.wheel = e.wheelDeltaY != null ? e.wheelDeltaY : e.detail * -60;
- }
-
- //from stack overflow
- e.delta = e.wheelDelta ? e.wheelDelta / 40 : e.deltaY ? -e.deltaY / 3 : 0;
- this.changeDeltaScale(1.0 + e.delta * 0.05);
- }
-
- this.last_mouse[0] = x;
- this.last_mouse[1] = y;
-
- if (is_inside) {
- e.preventDefault();
- e.stopPropagation();
- return false;
- }
- };
-
- DragAndScale.prototype.toCanvasContext = function (ctx) {
- ctx.scale(this.scale, this.scale);
- ctx.translate(this.offset[0], this.offset[1]);
- };
-
- DragAndScale.prototype.convertOffsetToCanvas = function (pos) {
- //return [pos[0] / this.scale - this.offset[0], pos[1] / this.scale - this.offset[1]];
- return [
- (pos[0] + this.offset[0]) * this.scale,
- (pos[1] + this.offset[1]) * this.scale,
- ];
- };
-
- DragAndScale.prototype.convertCanvasToOffset = function (pos, out) {
- out = out || [0, 0];
- out[0] = pos[0] / this.scale - this.offset[0];
- out[1] = pos[1] / this.scale - this.offset[1];
- return out;
- };
-
- DragAndScale.prototype.mouseDrag = function (x, y) {
- this.offset[0] += x / this.scale;
- this.offset[1] += y / this.scale;
-
- if (this.onredraw) {
- this.onredraw(this);
- }
- };
-
- DragAndScale.prototype.changeScale = function (value, zooming_center) {
- if (value < this.min_scale) {
- value = this.min_scale;
- } else if (value > this.max_scale) {
- value = this.max_scale;
- }
-
- if (value == this.scale) {
- return;
- }
-
- if (!this.element) {
- return;
- }
-
- var rect = this.element.getBoundingClientRect();
- if (!rect) {
- return;
- }
-
- zooming_center = zooming_center || [rect.width * 0.5, rect.height * 0.5];
- var center = this.convertCanvasToOffset(zooming_center);
- this.scale = value;
- if (Math.abs(this.scale - 1) < 0.01) {
- this.scale = 1;
- }
-
- var new_center = this.convertCanvasToOffset(zooming_center);
- var delta_offset = [new_center[0] - center[0], new_center[1] - center[1]];
-
- this.offset[0] += delta_offset[0];
- this.offset[1] += delta_offset[1];
-
- if (this.onredraw) {
- this.onredraw(this);
- }
- };
-
- DragAndScale.prototype.changeDeltaScale = function (value, zooming_center) {
- this.changeScale(this.scale * value, zooming_center);
- };
-
- DragAndScale.prototype.reset = function () {
- this.scale = 1;
- this.offset[0] = 0;
- this.offset[1] = 0;
- };
-
- //*********************************************************************************
- // LGraphCanvas: LGraph renderer CLASS
- //*********************************************************************************
-
- /**
- * This class is in charge of rendering one graph inside a canvas. And provides all the interaction required.
- * Valid callbacks are: onNodeSelected, onNodeDeselected, onShowNodePanel, onNodeDblClicked
- *
- * @class LGraphCanvas
- * @constructor
- * @param {HTMLCanvas} canvas the canvas where you want to render (it accepts a selector in string format or the canvas element itself)
- * @param {LGraph} graph [optional]
- * @param {Object} options [optional] { skip_rendering, autoresize, viewport }
- */
- function LGraphCanvas(canvas, graph, options) {
- this.options = options = options || {};
-
- //if(graph === undefined)
- // throw ("No graph assigned");
- this.background_image = LGraphCanvas.DEFAULT_BACKGROUND_IMAGE;
-
- if (canvas && canvas.constructor === String) {
- canvas = document.querySelector(canvas);
- }
-
- this.ds = new DragAndScale();
- this.zoom_modify_alpha = true; //otherwise it generates ugly patterns when scaling down too much
-
- this.title_text_font = "" + LiteGraph.NODE_TEXT_SIZE + "px Arial";
- this.inner_text_font = "normal " + LiteGraph.NODE_SUBTEXT_SIZE + "px Arial";
- this.node_title_color = LiteGraph.NODE_TITLE_COLOR;
- this.default_link_color = LiteGraph.LINK_COLOR;
- this.default_connection_color = {
- input_off: "#778",
- input_on: "#7F7", //"#BBD"
- output_off: "#778",
- output_on: "#7F7", //"#BBD"
- };
- this.default_connection_color_byType = {
- /*number: "#7F7",
- string: "#77F",
- boolean: "#F77",*/
- };
- this.default_connection_color_byTypeOff = {
- /*number: "#474",
- string: "#447",
- boolean: "#744",*/
- };
-
- this.highquality_render = true;
- this.use_gradients = false; //set to true to render titlebar with gradients
- this.editor_alpha = 1; //used for transition
- this.pause_rendering = false;
- this.clear_background = true;
- this.clear_background_color = "#222";
-
- this.read_only = false; //if set to true users cannot modify the graph
- this.render_only_selected = true;
- this.live_mode = false;
- this.show_info = true;
- this.allow_dragcanvas = true;
- this.allow_dragnodes = true;
- this.allow_interaction = true; //allow to control widgets, buttons, collapse, etc
- this.multi_select = false; //allow selecting multi nodes without pressing extra keys
- this.allow_searchbox = true;
- this.allow_reconnect_links = true; //allows to change a connection with having to redo it again
- this.align_to_grid = false; //snap to grid
-
- this.drag_mode = false;
- this.dragging_rectangle = null;
-
- this.filter = null; //allows to filter to only accept some type of nodes in a graph
-
- this.set_canvas_dirty_on_mouse_event = true; //forces to redraw the canvas if the mouse does anything
- this.always_render_background = false;
- this.render_shadows = true;
- this.render_canvas_border = true;
- this.render_connections_shadows = false; //too much cpu
- this.render_connections_border = true;
- this.render_curved_connections = false;
- this.render_connection_arrows = false;
- this.render_collapsed_slots = true;
- this.render_execution_order = false;
- this.render_title_colored = true;
- this.render_link_tooltip = true;
-
- this.links_render_mode = LiteGraph.SPLINE_LINK;
-
- this.mouse = [0, 0]; //mouse in canvas coordinates, where 0,0 is the top-left corner of the blue rectangle
- this.graph_mouse = [0, 0]; //mouse in graph coordinates, where 0,0 is the top-left corner of the blue rectangle
- this.canvas_mouse = this.graph_mouse; //LEGACY: REMOVE THIS, USE GRAPH_MOUSE INSTEAD
-
- //to personalize the search box
- this.onSearchBox = null;
- this.onSearchBoxSelection = null;
-
- //callbacks
- this.onMouse = null;
- this.onDrawBackground = null; //to render background objects (behind nodes and connections) in the canvas affected by transform
- this.onDrawForeground = null; //to render foreground objects (above nodes and connections) in the canvas affected by transform
- this.onDrawOverlay = null; //to render foreground objects not affected by transform (for GUIs)
- this.onDrawLinkTooltip = null; //called when rendering a tooltip
- this.onNodeMoved = null; //called after moving a node
- this.onSelectionChange = null; //called if the selection changes
- this.onConnectingChange = null; //called before any link changes
- this.onBeforeChange = null; //called before modifying the graph
- this.onAfterChange = null; //called after modifying the graph
-
- this.connections_width = 3;
- this.round_radius = 8;
-
- this.current_node = null;
- this.node_widget = null; //used for widgets
- this.over_link_center = null;
- this.last_mouse_position = [0, 0];
- this.visible_area = this.ds.visible_area;
- this.visible_links = [];
-
- this.viewport = options.viewport || null; //to constraint render area to a portion of the canvas
-
- //link canvas and graph
- if (graph) {
- graph.attachCanvas(this);
- }
-
- this.setCanvas(canvas, options.skip_events);
- this.clear();
-
- if (!options.skip_render) {
- this.startRendering();
- }
-
- this.autoresize = options.autoresize;
- }
-
- global.LGraphCanvas = LiteGraph.LGraphCanvas = LGraphCanvas;
-
- LGraphCanvas.DEFAULT_BACKGROUND_IMAGE =
- "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAIAAAD/gAIDAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAQBJREFUeNrs1rEKwjAUhlETUkj3vP9rdmr1Ysammk2w5wdxuLgcMHyptfawuZX4pJSWZTnfnu/lnIe/jNNxHHGNn//HNbbv+4dr6V+11uF527arU7+u63qfa/bnmh8sWLBgwYJlqRf8MEptXPBXJXa37BSl3ixYsGDBMliwFLyCV/DeLIMFCxYsWLBMwSt4Be/NggXLYMGCBUvBK3iNruC9WbBgwYJlsGApeAWv4L1ZBgsWLFiwYJmCV/AK3psFC5bBggULloJX8BpdwXuzYMGCBctgwVLwCl7Be7MMFixYsGDBsu8FH1FaSmExVfAxBa/gvVmwYMGCZbBg/W4vAQYA5tRF9QYlv/QAAAAASUVORK5CYII=";
-
- LGraphCanvas.link_type_colors = {
- "-1": LiteGraph.EVENT_LINK_COLOR,
- number: "#AAA",
- node: "#DCA",
- };
- LGraphCanvas.gradients = {}; //cache of gradients
-
- /**
- * clears all the data inside
- *
- * @method clear
- */
- LGraphCanvas.prototype.clear = function () {
- this.frame = 0;
- this.last_draw_time = 0;
- this.render_time = 0;
- this.fps = 0;
-
- //this.scale = 1;
- //this.offset = [0,0];
-
- this.dragging_rectangle = null;
-
- this.selected_nodes = {};
- this.selected_group = null;
-
- this.visible_nodes = [];
- this.node_dragged = null;
- this.node_over = null;
- this.node_capturing_input = null;
- this.connecting_node = null;
- this.highlighted_links = {};
-
- this.dragging_canvas = false;
-
- this.dirty_canvas = true;
- this.dirty_bgcanvas = true;
- this.dirty_area = null;
-
- this.node_in_panel = null;
- this.node_widget = null;
-
- this.last_mouse = [0, 0];
- this.last_mouseclick = 0;
- this.pointer_is_down = false;
- this.pointer_is_double = false;
- this.visible_area.set([0, 0, 0, 0]);
-
- if (this.onClear) {
- this.onClear();
- }
- };
-
- /**
- * assigns a graph, you can reassign graphs to the same canvas
- *
- * @method setGraph
- * @param {LGraph} graph
- */
- LGraphCanvas.prototype.setGraph = function (graph, skip_clear) {
- if (this.graph == graph) {
- return;
- }
-
- if (!skip_clear) {
- this.clear();
- }
-
- if (!graph && this.graph) {
- this.graph.detachCanvas(this);
- return;
- }
-
- graph.attachCanvas(this);
-
- //remove the graph stack in case a subgraph was open
- if (this._graph_stack) this._graph_stack = null;
-
- this.setDirty(true, true);
- };
-
- /**
- * returns the top level graph (in case there are subgraphs open on the canvas)
- *
- * @method getTopGraph
- * @return {LGraph} graph
- */
- LGraphCanvas.prototype.getTopGraph = function () {
- if (this._graph_stack.length) return this._graph_stack[0];
- return this.graph;
- };
-
- /**
- * opens a graph contained inside a node in the current graph
- *
- * @method openSubgraph
- * @param {LGraph} graph
- */
- LGraphCanvas.prototype.openSubgraph = function (graph) {
- if (!graph) {
- throw "graph cannot be null";
- }
-
- if (this.graph == graph) {
- throw "graph cannot be the same";
- }
-
- this.clear();
-
- if (this.graph) {
- if (!this._graph_stack) {
- this._graph_stack = [];
- }
- this._graph_stack.push(this.graph);
- }
-
- graph.attachCanvas(this);
- this.checkPanels();
- this.setDirty(true, true);
- };
-
- /**
- * closes a subgraph contained inside a node
- *
- * @method closeSubgraph
- * @param {LGraph} assigns a graph
- */
- LGraphCanvas.prototype.closeSubgraph = function () {
- if (!this._graph_stack || this._graph_stack.length == 0) {
- return;
- }
- var subgraph_node = this.graph._subgraph_node;
- var graph = this._graph_stack.pop();
- this.selected_nodes = {};
- this.highlighted_links = {};
- graph.attachCanvas(this);
- this.setDirty(true, true);
- if (subgraph_node) {
- this.centerOnNode(subgraph_node);
- this.selectNodes([subgraph_node]);
- }
- // when close sub graph back to offset [0, 0] scale 1
- this.ds.offset = [0, 0];
- this.ds.scale = 1;
- };
-
- /**
- * returns the visually active graph (in case there are more in the stack)
- * @method getCurrentGraph
- * @return {LGraph} the active graph
- */
- LGraphCanvas.prototype.getCurrentGraph = function () {
- return this.graph;
- };
-
- /**
- * assigns a canvas
- *
- * @method setCanvas
- * @param {Canvas} assigns a canvas (also accepts the ID of the element (not a selector)
- */
- LGraphCanvas.prototype.setCanvas = function (canvas, skip_events) {
- var that = this;
-
- if (canvas) {
- if (canvas.constructor === String) {
- canvas = document.getElementById(canvas);
- if (!canvas) {
- throw "Error creating LiteGraph canvas: Canvas not found";
- }
- }
- }
-
- if (canvas === this.canvas) {
- return;
- }
-
- if (!canvas && this.canvas) {
- //maybe detach events from old_canvas
- if (!skip_events) {
- this.unbindEvents();
- }
- }
-
- this.canvas = canvas;
- this.ds.element = canvas;
-
- if (!canvas) {
- return;
- }
-
- //this.canvas.tabindex = "1000";
- canvas.className += " lgraphcanvas";
- canvas.data = this;
- canvas.tabindex = "1"; //to allow key events
-
- //bg canvas: used for non changing stuff
- this.bgcanvas = null;
- if (!this.bgcanvas) {
- this.bgcanvas = document.createElement("canvas");
- this.bgcanvas.width = this.canvas.width;
- this.bgcanvas.height = this.canvas.height;
- }
-
- if (canvas.getContext == null) {
- if (canvas.localName != "canvas") {
- throw (
- "Element supplied for LGraphCanvas must be a