From 8a46f44e40a34203748c81dad1dfd8f4c24d302b Mon Sep 17 00:00:00 2001 From: Shaun Johnston Date: Tue, 16 Dec 2025 09:31:49 +1000 Subject: [PATCH] interactive --- README.md | 9 +++--- js/multi_replace.js | 56 +++++++++++++++++++++---------------- nodes/find_replace_pairs.py | 8 ++++-- 3 files changed, 42 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index 00003be..0f6ca62 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,8 @@ A ComfyUI custom node package for creating and applying multiple find/replace pa - **Find/Replace Pairs Node**: Create an arbitrary number of find/replace pairs - Starts with one pair, click "➕ Add Pair" button to add more - Right-click menu also provides Add/Remove pair options - - All pairs are input connectors for easy connection from other nodes + - Text fields with optional input connectors (right-click → Convert to Input) + - Connected inputs override widget values - Outputs: pairs object, JSON, and CSV formats - **Text Replacer Node**: Apply find/replace pairs to text @@ -40,7 +41,7 @@ A ComfyUI custom node package for creating and applying multiple find/replace pa ### Connecting Dynamic Values -All find/replace pairs are input connectors, making it easy to connect values from other nodes (e.g., text prompts, primitives, or other string outputs). +Right-click any find or replace text field and select "Convert to Input" to create a connector. Connected inputs override the widget value, following the standard ComfyUI pattern. ### Chaining Replacers @@ -65,8 +66,8 @@ The Text Replacer node passes through the pairs object, allowing you to chain mu | Input | Type | Description | |-------|------|-------------| -| `find_N` | STRING (connector) | Find pattern for pair N | -| `replace_N` | STRING (connector) | Replacement for pair N | +| `find_N` | STRING | Find pattern for pair N (text field, convertible to input) | +| `replace_N` | STRING | Replacement for pair N (text field, convertible to input) | **Buttons:** - **➕ Add Pair** - Add a new find/replace pair diff --git a/js/multi_replace.js b/js/multi_replace.js index 2327387..3441058 100644 --- a/js/multi_replace.js +++ b/js/multi_replace.js @@ -43,9 +43,31 @@ app.registerExtension({ this.pairCount++; const idx = this.pairCount; - // Add input connectors for find and replace - this.addInput(`find_${idx}`, "STRING"); - this.addInput(`replace_${idx}`, "STRING"); + // Insert new widgets before the buttons + const buttonIndex = this.widgets.indexOf(this.addPairButton); + + // Create find widget + const findWidget = ComfyWidgets.STRING( + this, + `find_${idx}`, + ["STRING", { default: "", multiline: false }], + app + ).widget; + + // Create replace widget + const replaceWidget = ComfyWidgets.STRING( + this, + `replace_${idx}`, + ["STRING", { default: "", multiline: false }], + app + ).widget; + + // Move the new widgets before the buttons + this.widgets.splice(this.widgets.length - 2, 2); + this.widgets.splice(buttonIndex, 0, findWidget, replaceWidget); + + // Re-add buttons at end + this.widgets.push(this.addPairButton, this.removePairButton); this.updateRemoveButtonState(); this.setSize(this.computeSize()); @@ -60,7 +82,12 @@ app.registerExtension({ const findName = `find_${idx}`; const replaceName = `replace_${idx}`; - // Remove inputs + // Remove widgets + this.widgets = this.widgets.filter(w => + w.name !== findName && w.name !== replaceName + ); + + // Remove inputs if they were converted const findInputIdx = this.inputs?.findIndex(i => i.name === findName); if (findInputIdx !== undefined && findInputIdx >= 0) { this.removeInput(findInputIdx); @@ -153,25 +180,6 @@ app.registerExtension({ }, async nodeCreated(node) { - if (node.comfyClass === "FindReplacePairs") { - // First pair should also be input connectors - convert widgets to inputs - setTimeout(() => { - // Remove the default widgets for find_1 and replace_1 - if (node.widgets) { - node.widgets = node.widgets.filter(w => - w.name !== "find_1" && w.name !== "replace_1" - ); - } - // Add as input connectors instead - if (!node.inputs?.find(i => i.name === "find_1")) { - node.addInput("find_1", "STRING"); - } - if (!node.inputs?.find(i => i.name === "replace_1")) { - node.addInput("replace_1", "STRING"); - } - node.setSize(node.computeSize()); - app.graph.setDirtyCanvas(true, true); - }, 50); - } + // Nothing special needed - widgets automatically support "Convert to Input" } }); diff --git a/nodes/find_replace_pairs.py b/nodes/find_replace_pairs.py index 667d598..de0d7ff 100644 --- a/nodes/find_replace_pairs.py +++ b/nodes/find_replace_pairs.py @@ -18,16 +18,18 @@ class FindReplacePairs: def INPUT_TYPES(cls): """ Define base inputs. Additional pairs are added dynamically via JS. - All pairs are input connectors. + Text fields with optional input connectors that override widget values. """ return { "required": {}, "optional": { "find_1": ("STRING", { - "forceInput": True, + "default": "", + "multiline": False, }), "replace_1": ("STRING", { - "forceInput": True, + "default": "", + "multiline": False, }), }, "hidden": {