From ec8a0542af81251aa61434143d6871c0a8333d6d Mon Sep 17 00:00:00 2001 From: Yousef Rafat <81116377+yousef-rafat@users.noreply.github.com> Date: Mon, 25 May 2026 17:12:10 +0300 Subject: [PATCH] Add Save Text Node --- comfy_extras/nodes_dataset.py | 2 +- comfy_extras/nodes_text.py | 64 +++++++++++++++++++++++++++++++++++ nodes.py | 1 + 3 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 comfy_extras/nodes_text.py diff --git a/comfy_extras/nodes_dataset.py b/comfy_extras/nodes_dataset.py index 22f5ff203..75eccd787 100644 --- a/comfy_extras/nodes_dataset.py +++ b/comfy_extras/nodes_dataset.py @@ -1604,4 +1604,4 @@ class DatasetExtension(ComfyExtension): async def comfy_entrypoint() -> DatasetExtension: - return DatasetExtension() + return DatasetExtension() \ No newline at end of file diff --git a/comfy_extras/nodes_text.py b/comfy_extras/nodes_text.py new file mode 100644 index 000000000..64133718c --- /dev/null +++ b/comfy_extras/nodes_text.py @@ -0,0 +1,64 @@ +import os +import json +from typing_extensions import override +from comfy_api.latest import io, ComfyExtension, ui +import folder_paths +import logging + + +class SaveTextNode(io.ComfyNode): + """Save text content to .txt, .md, or .json.""" + + @classmethod + def define_schema(cls): + return io.Schema( + node_id="SaveText", + search_aliases=["save text", "write text", "export text"], + display_name="Save Text", + category="text", + description="Save text content to a file in the output directory.", + inputs=[ + io.String.Input("text", force_input=True), + io.String.Input("filename_prefix", default="ComfyUI"), + io.Combo.Input("format", options=["txt", "md", "json"], default="txt"), + ], + is_output_node=True, + ) + + @classmethod + def execute(cls, text, filename_prefix, format): + full_output_folder, filename, counter, subfolder, filename_prefix = folder_paths.get_save_image_path( + filename_prefix, + folder_paths.get_output_directory(), + 1, + 1, + ) + + file = f"{filename}_{counter:05}_.{format}" + filepath = os.path.join(full_output_folder, file) + + if format == "json": + # tries to pretty print otherwise saves normally + try: + data = json.loads(text) + with open(filepath, "w", encoding="utf-8") as f: + json.dump(data, f, indent=2, ensure_ascii=False) + except json.JSONDecodeError: + logging.warning("Saved JSON as a raw text") + with open(filepath, "w", encoding="utf-8") as f: + f.write(text) + else: + with open(filepath, "w", encoding="utf-8") as f: + f.write(text) + + return io.NodeOutput(ui=ui.PreviewText(text)) + +class TextExtension(ComfyExtension): + @override + async def get_node_list(self) -> list[type[io.ComfyNode]]: + return [ + SaveTextNode + ] + +async def comfy_entrypoint() -> TextExtension: + return TextExtension() diff --git a/nodes.py b/nodes.py index 13e46ac8a..24870c118 100644 --- a/nodes.py +++ b/nodes.py @@ -2445,6 +2445,7 @@ async def init_builtin_extra_nodes(): "nodes_save_3d.py", "nodes_moge.py", "nodes_mediapipe.py", + "nodes_text.py", ] import_failed = []