import json import re class ConsoleLogNode: @classmethod def INPUT_TYPES(cls): return { "required": { "text": ("STRING", {"forceInput": True}), "prefix_label": ("STRING", {"default": "LOG TEXT"}), } } RETURN_TYPES = ("STRING",) RETURN_NAMES = ("text",) FUNCTION = "log_text_to_terminal" CATEGORY = "TextRandomizer/Debug" def log_text_to_terminal(self, text, prefix_label): cyan_start, yellow_start, color_reset = "\033[96m", "\033[93m", "\033[0m" # Check if the incoming data is a batch list or a single string if isinstance(text, list): print( f"\n{cyan_start}[ℹ️ {prefix_label} - BATCH COUNT: {len(text)}]{color_reset}" ) for idx, item in enumerate(text): print(f'{cyan_start} [{idx + 1}]:{yellow_start} "{item}"{color_reset}') print("") else: # Fallback for standard single string inputs print(f"\n{cyan_start}[ℹ️ {prefix_label}]{color_reset}") print(f'{yellow_start}"{text}"{color_reset}\n') return (text,) class LogToWorkspace: @classmethod def INPUT_TYPES(cls): return { "required": { "text": ("STRING", {"forceInput": True}), # Accepts any incoming string } } RETURN_TYPES = ("STRING",) RETURN_NAMES = ("text",) FUNCTION = "display_text" OUTPUT_NODE = True # Necessary so ComfyUI runs it even without downstream outputs CATEGORY = "TextRandomizer/Debug" def display_text(self, text): # Normalize: ensure text is wrapped into a clean, uniform list structure if isinstance(text, list): ui_text_list = [str(item) for item in text] # Convert list back to a string format for the node's standard execution pipeline output result_text = "\n".join(ui_text_list) else: ui_text_list = [str(text)] result_text = str(text) # ComfyUI's UI engine expects a uniform array of strings to iterate over on the frontend canvas return {"ui": {"text": ui_text_list}, "result": (result_text,)} class LogToWorkspaceAdv: @classmethod def INPUT_TYPES(cls): return { "required": { "text": ("STRING", {"forceInput": True}), # Toggles to control clean up and sanitization pipelines "remove_empty_commas": ("BOOLEAN", {"default": True}), "remove_empty_lines": ("BOOLEAN", {"default": True}), "collapse_spaces": ("BOOLEAN", {"default": True}), } } RETURN_TYPES = ("STRING",) RETURN_NAMES = ("text",) FUNCTION = "display_text" OUTPUT_NODE = True CATEGORY = "TextRandomizer/Debug" def display_text(self, text, remove_empty_commas, remove_empty_lines, collapse_spaces): # 1. Standardize processing into a unified text block string if isinstance(text, list): raw_text = "\n".join([str(item) for item in text]) else: raw_text = str(text) # 2. RUN SANITIZATION FILTERS # Scrub redundant, broken commas left behind by empty wildcards (e.g., ", ,", ",,") if remove_empty_commas: # Replaces multiple sequential commas (with optional spacing) with a single comma raw_text = re.sub(r',\s*,+', ',', raw_text) # Cleans up floating leading or trailing commas inside line strings raw_text = re.sub(r'^\s*,\s*|\s*,\s*$', '', raw_text, flags=re.MULTILINE) # Clean repeating whitespace blocks down to tight single space blocks if collapse_spaces: raw_text = re.sub(r'[ \t]+', ' ', raw_text) # Remove ghost breaks or stacked blank line carriage returns if remove_empty_lines: # Splitting lines to inspect individual strings safely lines = [line.strip() for line in raw_text.splitlines()] # Filter away completely empty arrays or spacer elements ui_text_list = [line for line in lines if line] result_text = "\n".join(ui_text_list) else: ui_text_list = raw_text.splitlines() result_text = raw_text # Fallback safeguard layout value if everything is wiped clean if not ui_text_list: ui_text_list = [""] result_text = "" return {"ui": {"text": ui_text_list}, "result": (result_text,)}