multimodalart's picture
Squashing commit
4450790 verified
#---------------------------------------------------------------------------------------------------------------------#
# Comfyroll Studio custom nodes by RockOfFire and Akatsuzi https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes
# for ComfyUI https://github.com/comfyanonymous/ComfyUI
#---------------------------------------------------------------------------------------------------------------------#
import os
import csv
import io
from ..categories import icons
class AnyType(str):
"""A special type that can be connected to any other types. Credit to pythongosssss"""
def __ne__(self, __value: object) -> bool:
return False
any_type = AnyType("*")
#---------------------------------------------------------------------------------------------------------------------#
# Text Util Nodes
#---------------------------------------------------------------------------------------------------------------------#
class CR_SplitString:
@classmethod
def INPUT_TYPES(s):
return {"required": {
"text": ("STRING", {"multiline": False, "default": "text"}),
},
"optional": {
"delimiter": ("STRING", {"multiline": False, "default": ","}),
}
}
RETURN_TYPES = (any_type, any_type, any_type, any_type, "STRING", )
RETURN_NAMES = ("string_1", "string_2", "string_3", "string_4", "show_help", )
FUNCTION = "split"
CATEGORY = icons.get("Comfyroll/Utils/Text")
def split(self, text, delimiter=""):
# Split the text string
parts = text.split(delimiter)
strings = [part.strip() for part in parts[:4]]
string_1, string_2, string_3, string_4 = strings + [""] * (4 - len(strings))
show_help = "https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Other-Nodes#cr-split-string"
return (string_1, string_2, string_3, string_4, show_help, )
#---------------------------------------------------------------------------------------------------------------------#
class CR_Text:
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"text": ("STRING", {"default": '', "multiline": True}),
}
}
RETURN_TYPES = (any_type, "STRING", )
RETURN_NAMES = ("text", "show_help", )
FUNCTION = "text_multiline"
CATEGORY = icons.get("Comfyroll/Utils/Text")
def text_multiline(self, text):
show_help = "https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Other-Nodes#cr-text"
return (text, show_help,)
#---------------------------------------------------------------------------------------------------------------------#
class CR_MultilineText:
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"text": ("STRING", {"default": '', "multiline": True}),
"convert_from_csv": ("BOOLEAN", {"default": False}),
"csv_quote_char": ("STRING", {"default": "'", "choices": ["'", '"']}),
"remove_chars": ("BOOLEAN", {"default": False}),
"chars_to_remove": ("STRING", {"multiline": False, "default": ""}),
"split_string": ("BOOLEAN", {"default": False}),
}
}
RETURN_TYPES = (any_type, "STRING", )
RETURN_NAMES = ("multiline_text", "show_help", )
FUNCTION = "text_multiline"
CATEGORY = icons.get("Comfyroll/Utils/Text")
def text_multiline(self, text, chars_to_remove, split_string=False, remove_chars=False, convert_from_csv=False, csv_quote_char="'"):
new_text = []
# Remove trailing commas
text = text.rstrip(',')
if convert_from_csv:
# Convert CSV to multiline text
csv_reader = csv.reader(io.StringIO(text), quotechar=csv_quote_char)
for row in csv_reader:
new_text.extend(row)
if split_string:
if text.startswith("'") and text.endswith("'"):
text = text[1:-1] # Remove outer single quotes
values = [value.strip() for value in text.split("', '")]
new_text.extend(values)
elif text.startswith('"') and text.endswith('"'):
text = text[1:-1] # Remove outer single quotes
values = [value.strip() for value in text.split('", "')]
new_text.extend(values)
elif ',' in text and text.count("'") % 2 == 0:
# Assume it's a list-like string and split accordingly
text = text.replace("'", '') # Remove single quotes
values = [value.strip() for value in text.split(",")]
new_text.extend(values)
elif ',' in text and text.count('"') % 2 == 0:
# Assume it's a list-like string and split accordingly
text = text.replace('"', '') # Remove single quotes
values = [value.strip() for value in text.split(",")]
new_text.extend(values)
if convert_from_csv == False and split_string == False:
# Process multiline text
for line in io.StringIO(text):
if not line.strip().startswith('#'):
if not line.strip().startswith("\n"):
line = line.replace("\n", '')
if remove_chars:
# Remove quotes from each line
line = line.replace(chars_to_remove, '')
new_text.append(line)
new_text = "\n".join(new_text)
show_help = "https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Other-Nodes#cr-multiline-text"
return (new_text, show_help,)
#---------------------------------------------------------------------------------------------------------------------#
class CR_SaveTextToFile:
@classmethod
def INPUT_TYPES(s):
return {"required": {
"multiline_text": ("STRING", {"multiline": True, "default": ""}),
"output_file_path": ("STRING", {"multiline": False, "default": ""}),
"file_name": ("STRING", {"multiline": False, "default": ""}),
"file_extension": (["txt", "csv"],),
}
}
RETURN_TYPES = ("STRING", )
RETURN_NAMES = ("show_help", )
OUTPUT_NODE= True
FUNCTION = 'save_list'
CATEGORY = icons.get("Comfyroll/Utils/Text")
def save_list(self, multiline_text, output_file_path, file_name, file_extension):
show_help = "https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/List-Nodes#cr-save-text-to-file"
filepath = output_file_path + "\\" + file_name + "." + file_extension
index = 1
if(output_file_path == "" or file_name == ""):
print(f"[Warning] CR Save Text List. No file details found. No file output.")
return ()
while os.path.exists(filepath):
if os.path.exists(filepath):
filepath = output_file_path + "\\" + file_name + "_" + str(index) + "." + file_extension
index = index + 1
else:
break
print(f"[Info] CR Save Text List: Saving to {filepath}")
if file_extension == "csv":
text_list = []
for i in multiline_text.split("\n"):
text_list.append(i.strip())
with open(filepath, "w", newline="") as csv_file:
csv_writer = csv.writer(csv_file)
# Write each line as a separate row in the CSV file
for line in text_list:
csv_writer.writerow([line])
else:
with open(filepath, "w", newline="") as text_file:
for line in multiline_text:
text_file.write(line)
return (show_help, )
#---------------------------------------------------------------------------------------------------------------------#
class CR_TextConcatenate:
@ classmethod
def INPUT_TYPES(cls):
return {"required": {
},
"optional": {
"text1": ("STRING", {"multiline": False, "default": "", "forceInput": True}),
"text2": ("STRING", {"multiline": False, "default": "", "forceInput": True}),
"separator": ("STRING", {"multiline": False, "default": ""}),
},
}
RETURN_TYPES = (any_type, "STRING", )
RETURN_NAMES = ("STRING", "show_help", )
FUNCTION = "concat_text"
CATEGORY = icons.get("Comfyroll/Utils/Text")
def concat_text(self, text1="", text2="", separator=""):
show_help = "https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/List-Nodes#cr-save-text-to-file"
return (text1 + separator + text2, )
#---------------------------------------------------------------------------------------------------------------------#
class CR_TextReplace:
@ classmethod
def INPUT_TYPES(cls):
return {
"required": {
"text": ("STRING", {"multiline": True, "default": "", "forceInput": True}),
},
"optional": {
"find1": ("STRING", {"multiline": False, "default": ""}),
"replace1": ("STRING", {"multiline": False, "default": ""}),
"find2": ("STRING", {"multiline": False, "default": ""}),
"replace2": ("STRING", {"multiline": False, "default": ""}),
"find3": ("STRING", {"multiline": False, "default": ""}),
"replace3": ("STRING", {"multiline": False, "default": ""}),
},
}
RETURN_TYPES = (any_type, "STRING", )
RETURN_NAMES = ("STRING", "show_help", )
FUNCTION = "replace_text"
CATEGORY = icons.get("Comfyroll/Utils/Text")
def replace_text(self, text, find1="", replace1="", find2="", replace2="", find3="", replace3=""):
show_help = "https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/List-Nodes#cr-text-replace"
text = text.replace(find1, replace1)
text = text.replace(find2, replace2)
text = text.replace(find3, replace3)
return (text, show_help)
#---------------------------------------------------------------------------------------------------------------------#
class CR_TextBlacklist:
@ classmethod
def INPUT_TYPES(cls):
return {
"required": {
"text": ("STRING", {"multiline": True, "default": "", "forceInput": True}),
"blacklist_words": ("STRING", {"multiline": True, "default": ""}),
},
"optional": {
"replacement_text": ("STRING", {"multiline": False, "default": ""}),
},
}
RETURN_TYPES = (any_type, "STRING", )
RETURN_NAMES = ("STRING", "show_help", )
FUNCTION = "replace_text"
CATEGORY = icons.get("Comfyroll/Utils/Text")
def replace_text(self, text, blacklist_words, replacement_text=""):
show_help = "https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/List-Nodes#cr-text-blacklist"
text_out = text
for line in blacklist_words.split('\n'): # Splitting based on line return
if line.strip():
text_out = text_out.replace(line.strip(), replacement_text)
return (text_out, show_help)
#---------------------------------------------------------------------------------------------------------------------#
class CR_TextOperation:
@ classmethod
def INPUT_TYPES(cls):
operations = ["uppercase", "lowercase", "capitalize", "invert_case", "reverse", "trim", "remove_spaces"]
return {
"required": {
"text": ("STRING", {"multiline": False, "default": "", "forceInput": True}),
"operation": (operations,),
},
}
RETURN_TYPES = (any_type, "STRING", )
RETURN_NAMES = ("STRING", "show_help", )
FUNCTION = "text_operation"
CATEGORY = icons.get("Comfyroll/Utils/Text")
def text_operation(self, text, operation):
show_help = "https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/List-Nodes#cr-text_operation"
if operation == "uppercase":
text_out = text.upper()
elif operation == "lowercase":
text_out = text.lower()
elif operation == "capitalize":
text_out = text.capitalize()
elif operation == "invert_case":
text_out = text.swapcase()
elif operation == "reverse":
text_out = text[::-1]
elif operation == "trim":
text_out = text.strip()
elif operation == "remove_spaces":
text_out = text.replace(" ", "")
else:
return "CR Text Operation: Invalid operation."
return (text_out, show_help, )
#---------------------------------------------------------------------------------------------------------------------#
class CR_TextLength:
@ classmethod
def INPUT_TYPES(cls):
return {
"required": {
"text": ("STRING", {"multiline": False, "default": "", "forceInput": True}),
},
}
RETURN_TYPES = ("INT", "STRING", )
RETURN_NAMES = ("INT", "show_help", )
FUNCTION = "len_text"
CATEGORY = icons.get("Comfyroll/Utils/Text")
def len_text(self, text):
show_help = "https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/List-Nodes#cr-text-length"
int_out = len(text)
return (int_out, show_help, )
#---------------------------------------------------------------------------------------------------------------------#
# MAPPINGS
#---------------------------------------------------------------------------------------------------------------------#
# For reference only, actual mappings are in __init__.py
'''
NODE_CLASS_MAPPINGS = {
### Utils Text
"CR Text": CR_Text,
"CR Multiline Text": CR_MultilineText,
"CR Split String": CR_SplitString,
"CR Text Concatenate": CR_TextConcatenate,
"CR Text Replace": CR_TextReplace,
"CR Text Blacklist": CR_TextBlacklist,
"CR Text Length": CR_TextLength,
"CR Text Operation": CR_TextOperation,
"CR Save Text To File": CR_SaveTextToFile,
}
'''