15 Commits
Author SHA1 Message Date
filtered a4bf3aebd5 v1.1.1 (#5) 2025-04-22 04:41:26 +10:00
filtered 7306f17499 Update to match 1.16 frontend requirements (#4) 2025-04-22 04:35:32 +10:00
filtered 0f9599ca35 Merge pull request #3 from ComfyNodePRs/update-publish-yaml
Update Github Action for Publishing to Comfy Registry
2025-04-11 03:20:53 +10:00
snomiao 9076a7f23d chore(publish): update workflow for node publishing
- Added permissions for issue writing in the workflow.
- Modified condition to check repository owner instead of fork status.
- Updated action version from `main` to `v1` for stability.
2025-01-25 04:56:59 +00:00
filtered 64ace2c933 v1.1.0 2024-09-10 23:08:31 +10:00
filtered 318201cb4e Add link colour fix - set link type on connection change 2024-09-05 07:22:50 +10:00
filtered 143058b91b Fix None check 2024-09-05 07:16:48 +10:00
filtered 8f633400c8 Update pyproject.toml 2024-08-05 20:46:34 +10:00
filtered ab177722be Merge pull request #1 from ComfyNodePRs/pyproject
Add pyproject.toml for Custom Node Registry
2024-08-05 20:44:42 +10:00
filtered db3ab8b112 Merge pull request #2 from ComfyNodePRs/publish
Add Github Action for Publishing to Comfy Registry
2024-08-05 20:44:15 +10:00
snomiao 614b690fc5 chore(pyproject): Add pyproject.toml for Custom Node Registry 2024-07-31 13:39:40 +00:00
snomiao 8aca1a39b4 chore(publish): Add Github Action for Publishing to Comfy Registry 2024-07-31 13:39:39 +00:00
webfiltered 5992abe727 Fix Exception on run - missed while adding feature 2024-07-30 00:41:44 +10:00
webfiltered d899afff89 Fix textareas not resizing on list shrink 2024-07-29 20:32:15 +10:00
filtered 9235482b2b Initial README.md 2024-07-29 19:53:33 +10:00
5 changed files with 156 additions and 99 deletions
+26
View File
@@ -0,0 +1,26 @@
name: Publish to Comfy registry
on:
workflow_dispatch:
push:
branches:
- main
- master
paths:
- "pyproject.toml"
permissions:
issues: write
jobs:
publish-node:
name: Publish Custom Node to registry
runs-on: ubuntu-latest
if: ${{ github.repository_owner == 'NODE_AUTHOR_OWNER' }}
steps:
- name: Check out code
uses: actions/checkout@v4
- name: Publish Custom Node
uses: Comfy-Org/publish-node-action@v1
with:
## Add your own personal access token to your Github Repository secrets and reference it here.
personal_access_token: ${{ secrets.REGISTRY_ACCESS_TOKEN }}
+17 -1
View File
@@ -1 +1,17 @@
# WTF? - a debug node for ComfyUI
# WTF? - a debug node for ComfyUI
This node provides a simple way to view the output of many nodes, without leaving ComfyUI.
### Simple string
![image](https://github.com/user-attachments/assets/f3b2f797-77f2-4fb5-b3f0-8b768b386448)
### Tensor
![image](https://github.com/user-attachments/assets/79f17776-0bcf-4066-9f8a-33ec16a19d6d)
### An OUTPUT_IS_LIST node (Rebatched images)
![image](https://github.com/user-attachments/assets/edf500ac-edce-4b58-8d2a-074bf1b8c4cc)
### A list node without OUTPUT_IS_LIST
![image](https://github.com/user-attachments/assets/d065ca60-189b-4b0b-826e-248da1a73a2e)
_"What's that field?"_
+2 -2
View File
@@ -68,10 +68,10 @@ class WTFDebugNode:
except Exception as e:
info["shape"] = str(e)
info["value"] = str(item) if item != None else None
info["value"] = str(item) if item is not None else None
out.append(info)
return { "ui": { "items": out, "length": len(anything) } }
return { "ui": { "items": out } }
NODE_CLASS_MAPPINGS = {
"WTFDebugNode": WTFDebugNode,
+97 -96
View File
@@ -1,117 +1,118 @@
import { app } from "../../scripts/app.js";
import { ComfyWidgets } from "../../scripts/widgets.js";
import { app } from "../../scripts/app.js"
import { ComfyWidgets } from "../../scripts/widgets.js"
const hardLimit = 100
// Does most of the regular textarea cleanup, but leaks a ref in domWidget.js -> elementWidgets until the node is removed
function removeWidget(node, widget) {
widget.onRemove?.()
const index = node.widgets.indexOf(widget)
if (index !== -1)
node.widgets.splice(index, 1)
widget.onRemove?.()
const index = node.widgets.indexOf(widget)
if (index !== -1)
node.widgets.splice(index, 1)
}
function removeAllWidgets(node) {
for (const widget of node.widgets) {
widget.onRemove?.()
}
node.widgets.length = 0
for (const widget of node.widgets) {
widget.onRemove?.()
}
node.widgets.length = 0
}
// Main logic
app.registerExtension({
name: "WTFDebugNode",
async beforeRegisterNodeDef(nodeType, nodeData, app) {
if (nodeData.name === "WTFDebugNode") {
name: "WTFDebugNode",
async beforeRegisterNodeDef(nodeType, nodeData, app) {
if (nodeData.name !== "WTFDebugNode") return
const origOnExecuted = nodeType.prototype.onExecuted;
nodeType.prototype.onExecuted = function (message) {
const r = origOnExecuted
? origOnExecuted?.apply(this, arguments)
: undefined
// Ensure attached links keep their colours
const origOnConnectionsChange = nodeType.prototype.onConnectionsChange
nodeType.prototype.onConnectionsChange = function (type, slotIndex, isConnected, link, ioSlot) {
origOnConnectionsChange?.apply(this, arguments)
// Because debug
console.log(message)
if (isConnected && link?.type === "*")
link.type = this.graph.getNodeById(link.origin_id)?.outputs?.[link.origin_slot]?.type
}
// Sanity init
this.widgets ??= []
this.serialize_widgets = false
const baseOpacity = app.canvas.editor_alpha
// Show the text in the UI
const origOnExecuted = nodeType.prototype.onExecuted
nodeType.prototype.onExecuted = function (message) {
const r = origOnExecuted
? origOnExecuted?.apply(this, arguments)
: undefined
// Clear if invalid
const itemsLength = parseInt(message?.items?.length)
if (isNaN(itemsLength)) {
removeAllWidgets(this)
return r
}
// Because debug
console.log(message)
const isMultiItem = itemsLength > 1
const wasMultiItem = this.debugNodeLength !== 1
// Sanity init
this.widgets ??= []
this.serialize_widgets = false
const baseOpacity = app.canvas.editor_alpha
// Clean up existing widgets if required
if (isMultiItem !== wasMultiItem) {
removeAllWidgets(this)
}
// Remove only widgets we can't reuse
else if (this.debugNodeLength > itemsLength) {
for (let i = itemsLength; i <= this.debugNodeLength; i++) {
for (const widget of this.widgets.filter(x => x.name.endsWith(` ${i}`))) {
removeWidget(this, widget)
}
}
}
// Clear if invalid
const itemsLength = parseInt(message?.items?.length)
if (isNaN(itemsLength)) {
removeAllWidgets(this)
return r
}
this.debugNodeLength = itemsLength
const maxItems = Math.min(itemsLength, hardLimit)
const isMultiItem = itemsLength > 1
const wasMultiItem = this.debugNodeLength !== 1
// Create / update widget values for each item
for (let i = 0; i < maxItems; i++) {
const item = message.items[i]
const type = item.type
const len = item.len
const shape = item.shape
const firstIterItem = item.firstIterItem
const value = item.value
function processWidget(node, name, value, isMultiline = false) {
const numberedName = isMultiItem
? `${name} ${i}`
: name
const comfyType = isMultiline
? ["STRING", { multiline: true }]
: "STRING"
const current = node.widgets.find(x => x.name === numberedName)
const widget = current ?? ComfyWidgets.STRING(node, numberedName, comfyType, app).widget
if (!widget.options)
widget.options = {}
widget.options.serialize = false
widget.value = value
widget.disabled = value === null || value === undefined
if (isMultiline) {
widget.element.style.opacity = widget.disabled
? baseOpacity * 0.5
: baseOpacity
}
}
processWidget(this, "type", type)
processWidget(this, "len()", len)
processWidget(this, "shape", shape)
processWidget(this, "type of first iter() item", firstIterItem)
processWidget(this, "value", value, true)
}
requestAnimationFrame(() => {
const size = this.computeSize();
for (const widget of this.widgets.filter(x => x.element)) {
widget.onResize?.(size)
}
})
return r
}
// Clean up existing widgets if required
if (isMultiItem !== wasMultiItem) {
removeAllWidgets(this)
}
// Remove only widgets we can't reuse
else if (this.debugNodeLength > itemsLength) {
for (let i = itemsLength; i <= this.debugNodeLength; i++) {
for (const widget of this.widgets.filter(x => x.name.endsWith(` ${i}`))) {
removeWidget(this, widget)
}
}
},
});
}
this.debugNodeLength = itemsLength
const maxItems = Math.min(itemsLength, hardLimit)
// Create / update widget values for each item
for (let i = 0; i < maxItems; i++) {
const item = message.items[i]
const { type, len, shape, firstIterItem, value } = item
function processWidget(node, name, value, isMultiline = false) {
const numberedName = isMultiItem
? `${name} ${i}`
: name
const comfyType = isMultiline
? ["STRING", { multiline: true }]
: ["STRING", {}]
const current = node.widgets.find(x => x.name === numberedName)
const widget = current ?? ComfyWidgets.STRING(node, numberedName, comfyType, app).widget
widget.options ??= {}
widget.options.serialize = false
widget.value = value
widget.disabled = value == null
if (isMultiline) {
widget.element.style.opacity = widget.disabled
? baseOpacity * 0.5
: baseOpacity
}
}
processWidget(this, "type", type)
processWidget(this, "len()", len)
processWidget(this, "shape", shape)
processWidget(this, "type of first iter() item", firstIterItem)
processWidget(this, "value", value, true)
}
requestAnimationFrame(() => {
this.onResize?.(this.size)
})
return r
}
},
})
+14
View File
@@ -0,0 +1,14 @@
[project]
name = "debugnode-comfyui"
description = "This node provides a simple way to view the output of many nodes, without leaving ComfyUI."
version = "1.1.1"
license = {file = "LICENSE"}
[project.urls]
Repository = "https://github.com/webfiltered/DebugNode-ComfyUI"
# Used by Comfy Registry https://comfyregistry.org
[tool.comfy]
PublisherId = "filtered"
DisplayName = "DebugNode-ComfyUI"
Icon = ""