From 45ae089fdcf9e239cbbf46b25ea46032eb576e27 Mon Sep 17 00:00:00 2001 From: BRADSEC Date: Mon, 9 Mar 2026 16:29:12 +1000 Subject: [PATCH] fix: declare input_string in Python INPUT_TYPES for Nodes 2.0 compatibility (Issue #12) --- js/string_essentials.js | 121 ++++++++++++++++-------------- pyproject.toml | 2 +- string_conditional_append_node.py | 4 + string_multi_replace_node.py | 4 + string_preview_node.py | 9 ++- string_strip_node.py | 4 + 6 files changed, 83 insertions(+), 61 deletions(-) diff --git a/js/string_essentials.js b/js/string_essentials.js index 834b3a4..2f04366 100644 --- a/js/string_essentials.js +++ b/js/string_essentials.js @@ -2,90 +2,95 @@ import { app } from "../../../scripts/app.js"; import { ComfyWidgets } from "../../../scripts/widgets.js"; // Consistent sizing for all String Essentials nodes -const DEFAULT_NODE_SIZE = [400, 200]; +const DEFAULT_NODE_WIDTH = 400; app.registerExtension({ name: "string.strip", - async beforeRegisterNodeDef(nodeType) { - if (nodeType.comfyClass === "StringStrip") { - nodeType.prototype.onNodeCreated = function() { - this.addInput("input_string", "STRING"); - this.setSize(DEFAULT_NODE_SIZE); - }; - } + async beforeRegisterNodeDef(nodeType, nodeData) { + if (nodeData.name !== "StringStrip") return; + + const onNodeCreated = nodeType.prototype.onNodeCreated; + nodeType.prototype.onNodeCreated = function () { + const result = onNodeCreated?.apply(this, arguments); + if (this.size) this.size[0] = DEFAULT_NODE_WIDTH; + return result; + }; } }); app.registerExtension({ name: "string.multireplace", - async beforeRegisterNodeDef(nodeType) { - if (nodeType.comfyClass === "StringMultiReplace") { - nodeType.prototype.onNodeCreated = function() { - this.addInput("input_string", "STRING"); - this.setSize(DEFAULT_NODE_SIZE); - }; - } + async beforeRegisterNodeDef(nodeType, nodeData) { + if (nodeData.name !== "StringMultiReplace") return; + + const onNodeCreated = nodeType.prototype.onNodeCreated; + nodeType.prototype.onNodeCreated = function () { + const result = onNodeCreated?.apply(this, arguments); + if (this.size) this.size[0] = DEFAULT_NODE_WIDTH; + return result; + }; } }); app.registerExtension({ name: "string.preview", async beforeRegisterNodeDef(nodeType, nodeData) { - if (nodeType.comfyClass === "StringPreview") { - nodeType.prototype.onNodeCreated = function() { - this.addInput("input_string", "STRING"); - this.showValueWidget = ComfyWidgets["STRING"](this, "preview", ["STRING", { multiline: true }], app).widget; - this.showValueWidget.inputEl.readOnly = true; - this.showValueWidget.inputEl.style.opacity = 0.6; - this.setSize(DEFAULT_NODE_SIZE); - }; + if (nodeData.name !== "StringPreview") return; - const onExecuted = nodeType.prototype.onExecuted; - nodeType.prototype.onExecuted = function(message) { - onExecuted?.apply(this, arguments); - if (message?.text?.[0] !== undefined) { - this.showValueWidget.value = message.text[0]; - } else { - // Clear preview if no text received - this.showValueWidget.value = ""; - } - }; + const onNodeCreated = nodeType.prototype.onNodeCreated; + nodeType.prototype.onNodeCreated = function () { + const result = onNodeCreated?.apply(this, arguments); + this.showValueWidget = ComfyWidgets["STRING"](this, "preview", ["STRING", { multiline: true }], app).widget; + this.showValueWidget.inputEl.readOnly = true; + this.showValueWidget.inputEl.style.opacity = 0.6; + if (this.size) this.size[0] = DEFAULT_NODE_WIDTH; + return result; + }; - // Clear preview when input is disconnected - const onConnectionsChange = nodeType.prototype.onConnectionsChange; - nodeType.prototype.onConnectionsChange = function(type, index, connected, link_info) { - if (onConnectionsChange) { - onConnectionsChange.apply(this, arguments); - } + const onExecuted = nodeType.prototype.onExecuted; + nodeType.prototype.onExecuted = function (message) { + onExecuted?.apply(this, arguments); + if (message?.text?.[0] !== undefined) { + this.showValueWidget.value = message.text[0]; + } else { + this.showValueWidget.value = ""; + } + }; - // If input was disconnected, clear the preview - if (type === 1 && !connected) { // type 1 = input - this.showValueWidget.value = ""; - } - }; - } + const onConnectionsChange = nodeType.prototype.onConnectionsChange; + nodeType.prototype.onConnectionsChange = function (type, index, connected, link_info) { + onConnectionsChange?.apply(this, arguments); + if (type === 1 && !connected) { + this.showValueWidget.value = ""; + } + }; } }); app.registerExtension({ name: "string.conditionalappend", - async beforeRegisterNodeDef(nodeType) { - if (nodeType.comfyClass === "StringConditionalAppend") { - nodeType.prototype.onNodeCreated = function() { - this.addInput("input_string", "STRING"); - this.setSize(DEFAULT_NODE_SIZE); - }; - } + async beforeRegisterNodeDef(nodeType, nodeData) { + if (nodeData.name !== "StringConditionalAppend") return; + + const onNodeCreated = nodeType.prototype.onNodeCreated; + nodeType.prototype.onNodeCreated = function () { + const result = onNodeCreated?.apply(this, arguments); + if (this.size) this.size[0] = DEFAULT_NODE_WIDTH; + return result; + }; } }); app.registerExtension({ name: "string.textbox", - async beforeRegisterNodeDef(nodeType) { - if (nodeType.comfyClass === "StringTextbox") { - nodeType.prototype.onNodeCreated = function() { - this.setSize(DEFAULT_NODE_SIZE); - }; - } + async beforeRegisterNodeDef(nodeType, nodeData) { + if (nodeData.name !== "StringTextbox") return; + + const onNodeCreated = nodeType.prototype.onNodeCreated; + nodeType.prototype.onNodeCreated = function () { + const result = onNodeCreated?.apply(this, arguments); + if (this.size) this.size[0] = DEFAULT_NODE_WIDTH; + return result; + }; } }); diff --git a/pyproject.toml b/pyproject.toml index 7b300a3..54b54f8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "comfyui_stringessentials" description = "Simple string manipulation nodes for ComfyUI (strip/remove text strings, search and replace text strings, preview modified string outputs). Useful for modifying text prompts or results from LLM outputs. Nodes will be located under standard Add Node > utils menu. Node names: String Textbox, String Strip, String Multi Replace, String Conditional Append, String Contains Any and String Preview." -version = "2.0.8" +version = "2.0.9" license = {file = "LICENSE"} [project.urls] diff --git a/string_conditional_append_node.py b/string_conditional_append_node.py index a0c18f6..bb6608f 100644 --- a/string_conditional_append_node.py +++ b/string_conditional_append_node.py @@ -5,6 +5,10 @@ class StringConditionalAppendNode: def INPUT_TYPES(cls): return { "required": { + "input_string": ("STRING", { + "forceInput": True, + "tooltip": "The string to process" + }), "strings_to_check": ("STRING", { "multiline": True, "default": "", diff --git a/string_multi_replace_node.py b/string_multi_replace_node.py index 57b24b4..bf04500 100644 --- a/string_multi_replace_node.py +++ b/string_multi_replace_node.py @@ -5,6 +5,10 @@ class StringMultiReplaceNode: def INPUT_TYPES(cls): return { "required": { + "input_string": ("STRING", { + "forceInput": True, + "tooltip": "The string to process" + }), "replacement_pairs": ("STRING", {"multiline": True, "default": "", "placeholder": "Enter replacement pairs (one per line)", "tooltip": "Enter replacement pairs (one per line). Format: 'searchreplace'. Default delimiter is ':' (colon)"}), "replacement_delimiter": ("STRING", {"default": "::", diff --git a/string_preview_node.py b/string_preview_node.py index 436c8e3..02f7cd1 100644 --- a/string_preview_node.py +++ b/string_preview_node.py @@ -2,7 +2,12 @@ class StringPreviewNode: @classmethod def INPUT_TYPES(cls): return { - "required": {}, + "required": { + "input_string": ("STRING", { + "forceInput": True, + "tooltip": "The string to preview" + }), + }, } RETURN_TYPES = ("STRING",) @@ -16,5 +21,5 @@ class StringPreviewNode: # Force re-evaluation every time to ensure fresh data in PNG metadata return float("nan") - def preview_string(self, input_string=""): + def preview_string(self, input_string): return {"ui": {"text": (input_string,)}, "result": (input_string,)} \ No newline at end of file diff --git a/string_strip_node.py b/string_strip_node.py index f1937e9..4fde873 100644 --- a/string_strip_node.py +++ b/string_strip_node.py @@ -5,6 +5,10 @@ class StringStripNode: def INPUT_TYPES(cls): return { "required": { + "input_string": ("STRING", { + "forceInput": True, + "tooltip": "The string to process" + }), "strings_to_remove": ("STRING", {"multiline": True, "default": "", "placeholder": "Enter strings to remove (one per line)", "tooltip": "Enter strings to remove (one per line). Can include multiple words or strings on one line like: 'This image is'. This will only match this entire string."}), "match_case": ("BOOLEAN", {"default": False,