Initial code commit

This commit is contained in:
HowToSD
2025-02-12 22:53:33 -08:00
parent 6a12658d73
commit 21437069c0
19 changed files with 858 additions and 0 deletions
+3
View File
@@ -0,0 +1,3 @@
__pycache__/
**/__pycache__/
+74
View File
@@ -0,0 +1,74 @@
from typing import Dict, Type, TypeVar
from .modules.matplotlib.mpl_bar import MPLBar
from .modules.matplotlib.mpl_line import MPLLine
from .modules.matplotlib.mpl_scatter import MPLScatter
from .modules.pandas.pandas_head import PandasHead
from .modules.pandas.pandas_join import PandasJoin
from .modules.pandas.pandas_load_csv import PandasLoadCSV
from .modules.pandas.pandas_select_columns import PandasSelectColumns
from .modules.pandas.pandas_select_rows import PandasSelectRows
from .modules.pandas.pandas_show_dataframe import PandasShowDataFrame
from .modules.pandas.pandas_sort import PandasSort
from .modules.pandas.pandas_summary import PandasSummary
from .modules.pandas.pandas_to_string import PandasToString
T = TypeVar("T")
NODE_CLASS_MAPPINGS: Dict[str, Type[T]] = {
"MPLBar": MPLBar,
"MPLLine": MPLLine,
"MPLScatter": MPLScatter,
"PandasHead": PandasHead,
"PandasJoin": PandasJoin,
"PandasLoadCSV": PandasLoadCSV,
"PandasSelectColumns": PandasSelectColumns,
"PandasSelectRows": PandasSelectRows,
"PandasShowDataFrame": PandasShowDataFrame,
"PandasSort": PandasSort,
"PandasSummary": PandasSummary,
"PandasToString": PandasToString,
}
"""
NODE_CLASS_MAPPINGS (Dict[str, Type[T]]):
A dictionary mapping node names to their corresponding class implementations.
- "MPLBar": Generates a bar chart from DataFrame data.
- "MPLLine": Generates a line plot from DataFrame data.
- "MPLScatter": Generates a scatter plot from DataFrame data.
- "PandasHead": Handles retrieving the first few rows of a DataFrame.
- "PandasJoin": Provides functionality to join multiple DataFrames.
- "PandasLoadCSV": Loads CSV data into a DataFrame.
- "PandasSelectColumns": Selects specific columns from a DataFrame.
- "PandasSelectRows": Filters specific rows from a DataFrame.
- "PandasShowDataFrame": Displays the content of the DataFrame.
- "PandasSort": Sorts a DataFrame based on given criteria.
- "PandasSummary": Provides a summary of a DataFrame.
- "PandasToString": Converts a DataFrame to a string representation.
"""
NODE_DISPLAY_NAME_MAPPINGS: Dict[str, str] = {
"MPLBar": "MPL Bar Chart",
"MPLLine": "MPL Line Plot",
"MPLScatter": "MPL Scatter Plot",
"PandasHead": "Pandas Head",
"PandasJoin": "Pandas Join",
"PandasLoadCSV": "Pandas Load CSV",
"PandasSelectColumns": "Pandas Select Columns",
"PandasSelectRows": "Pandas Select Rows",
"PandasShowDataFrame": "Pandas Show DataFrame",
"PandasSort": "Pandas Sort",
"PandasSummary": "Pandas Summary",
"PandasToString": "Pandas To String",
}
"""
NODE_DISPLAY_NAME_MAPPINGS (Dict[str, str]):
A dictionary mapping node names to user-friendly display names.
"""
"""
Below two lines were taken from:
https://github.com/pythongosssss/ComfyUI-Custom-Scripts/blob/main/__init__.py
See credit/credit.md for the full license.
"""
WEB_DIRECTORY = "./web"
__all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS", "WEB_DIRECTORY"]
+30
View File
@@ -0,0 +1,30 @@
# Third-party license
## pythongosssss/ComfyUI-Custom-Scripts
This software is licensed under the following license:
https://github.com/pythongosssss/ComfyUI-Custom-Scripts/blob/main/LICENSE
Full text:
```
MIT License
Copyright (c) 2023 pythongosssss
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```
+18
View File
@@ -0,0 +1,18 @@
def common_input_types():
"""
Defines the input types for a plot function.
Returns:
Dict[str, Any]: A dictionary specifying required input types.
"""
return {
"required": {
"dataframe_json": ("STRING", {"multiscatter": True}),
"x_column_name": ("STRING", {"default": ""}),
"y_column_name": ("STRING", {"default": ""}),
"title": ("STRING", {"default": ""}),
"x_axis_label": ("STRING", {"default": ""}),
"y_axis_label": ("STRING", {"default": ""}),
"x_tick_as_int": ("BOOLEAN", {"default": False}) # To show 2002 instead of 2002.5 on x-axis
}
}
+65
View File
@@ -0,0 +1,65 @@
from typing import Any, Dict
from matplotlib import pyplot as plt
import pandas as pd
from .common import common_input_types
from .util import plot_post_steps
class MPLBar:
"""
MPLBar:
A class for generating bar charts from a pandas DataFrame.
"""
@classmethod
def INPUT_TYPES(cls) -> Dict[str, Any]:
"""
Defines the input types for the `bar_chart` function.
Returns:
Dict[str, Any]: A dictionary specifying required input types.
"""
return common_input_types()
RETURN_TYPES: tuple = ("IMAGE",)
FUNCTION: str = "bar_chart"
CATEGORY: str = "Data Analysis"
def bar_chart(self,
dataframe_json: str,
x_column_name: str,
y_column_name: str,
title: str,
x_axis_label: str,
y_axis_label: str,
x_tick_as_int: bool) -> tuple:
"""
Generates a bar chart from a pandas DataFrame.
Args:
dataframe_json (str): A JSON string representation of the DataFrame.
x_column_name (str): The column name for the x-axis.
y_column_name (str): The column name for the y-axis.
title (str): The title of the plot.
x_axis_label (str): The label for the x-axis data.
y_axis_label (str): The label for the y-axis data.
x_tick_as_int (bool): If set, use integers for x ticks. For example,
if ticks show floating point numbers for years, e.g. 2002.5,
setting this flag will show integer values instead.
Returns:
tuple: A tuple containing the image tensor representation of the plot.
"""
# Deserialize JSON string to DataFrame
df = pd.read_json(dataframe_json)
# Create the plot
fig, ax = plt.subplots()
ax.bar(df[x_column_name], df[y_column_name])
return plot_post_steps(
fig,
ax,
plt,
title,
x_axis_label,
y_axis_label,
x_tick_as_int)
+65
View File
@@ -0,0 +1,65 @@
from typing import Any, Dict
from matplotlib import pyplot as plt
import pandas as pd
from .common import common_input_types
from .util import plot_post_steps
class MPLLine:
"""
MPLPlotLine:
A class for generating line plots from a pandas DataFrame.
"""
@classmethod
def INPUT_TYPES(cls) -> Dict[str, Any]:
"""
Defines the input types for the `line_plot` function.
Returns:
Dict[str, Any]: A dictionary specifying required input types.
"""
return common_input_types()
RETURN_TYPES: tuple = ("IMAGE",)
FUNCTION: str = "line_plot"
CATEGORY: str = "Data Analysis"
def line_plot(self,
dataframe_json: str,
x_column_name: str,
y_column_name: str,
title: str,
x_axis_label: str,
y_axis_label: str,
x_tick_as_int: bool) -> tuple:
"""
Generates a line plot from a pandas DataFrame.
Args:
dataframe_json (str): A JSON string representation of the DataFrame.
x_column_name (str): The column name for the x-axis.
y_column_name (str): The column name for the y-axis.
title (str): The title of the plot.
x_axis_label (str): The label for the x-axis data.
y_axis_label (str): The label for the y-axis data.
x_tick_as_int (bool): If set, use integers for x ticks. For example,
if ticks show floating point numbers for years, e.g. 2002.5,
setting this flag will show integer values instead.
Returns:
tuple: A tuple containing the image tensor representation of the plot.
"""
# Deserialize JSON string to DataFrame
df = pd.read_json(dataframe_json)
# Create the plot
fig, ax = plt.subplots()
ax.plot(df[x_column_name], df[y_column_name])
return plot_post_steps(
fig,
ax,
plt,
title,
x_axis_label,
y_axis_label,
x_tick_as_int)
+65
View File
@@ -0,0 +1,65 @@
from typing import Any, Dict
from matplotlib import pyplot as plt
import pandas as pd
from .common import common_input_types
from .util import plot_post_steps
class MPLScatter:
"""
MPLPlotScatter:
A class for generating scatter plots from a pandas DataFrame.
"""
@classmethod
def INPUT_TYPES(cls) -> Dict[str, Any]:
"""
Defines the input types for the `scatter_plot` function.
Returns:
Dict[str, Any]: A dictionary specifying required input types.
"""
return common_input_types()
RETURN_TYPES: tuple = ("IMAGE",)
FUNCTION: str = "scatter_plot"
CATEGORY: str = "Data Analysis"
def scatter_plot(self,
dataframe_json: str,
x_column_name: str,
y_column_name: str,
title: str,
x_axis_label: str,
y_axis_label: str,
x_tick_as_int: bool) -> tuple:
"""
Generates a scatter plot from a pandas DataFrame.
Args:
dataframe_json (str): A JSON string representation of the DataFrame.
x_column_name (str): The column name for the x-axis.
y_column_name (str): The column name for the y-axis.
title (str): The title of the plot.
x_axis_label (str): The label for the x-axis data.
y_axis_label (str): The label for the y-axis data.
x_tick_as_int (bool): If set, use integers for x ticks. For example,
if ticks show floating point numbers for years, e.g. 2002.5,
setting this flag will show integer values instead.
Returns:
tuple: A tuple containing the image tensor representation of the plot.
"""
# Deserialize JSON string to DataFrame
df = pd.read_json(dataframe_json)
# Create the plot
fig, ax = plt.subplots()
ax.plot(df[x_column_name], df[y_column_name])
return plot_post_steps(
fig,
ax,
plt,
title,
x_axis_label,
y_axis_label,
x_tick_as_int)
+56
View File
@@ -0,0 +1,56 @@
import io
from typing import Any, Dict
import numpy as np
import matplotlib.figure
import matplotlib.axes
from matplotlib import pyplot as plt
import matplotlib.ticker as mticker
import pandas as pd
from PIL import Image
import torch
def plot_post_steps(
fig: matplotlib.figure.Figure,
ax: matplotlib.axes.Axes,
plt: plt,
title: str,
x_axis_label: str,
y_axis_label: str,
x_tick_as_int: bool
) -> tuple:
r"""Plots a post-processed step plot using Matplotlib.
Args:
fig (matplotlib.figure.Figure): The figure object for the plot.
ax (matplotlib.axes.Axes): The axes object for the plot.
plt (module): The Matplotlib module.
title (str): The title of the plot.
x_axis_label (str): The label for the x-axis.
y_axis_label (str): The label for the y-axis.
x_tick_as_int (bool): If ``True``, use integers for x-axis ticks.
For example, if ticks display floating point numbers (e.g., 2002.5),
setting this flag forces integer values instead.
Returns:
tuple: A tuple containing the image tensor representation of the plot.
"""
if x_tick_as_int:
ax.xaxis.set_major_locator(mticker.MaxNLocator(integer=True))
# Set title and labels
ax.set_title(title)
ax.set_xlabel(x_axis_label)
ax.set_ylabel(y_axis_label)
# Save the plot to a buffer
buf = io.BytesIO()
fig.savefig(buf, format='PNG')
buf.seek(0)
plt.close(fig) # Close the figure to free memory
# Load image and convert to tensor
image = Image.open(buf).convert("RGB")
image_tensor = torch.from_numpy(np.array(image)).float() / 255.0 # Normalize to [0,1]
image_tensor = image_tensor.unsqueeze(0)
return (image_tensor,)
View File
+44
View File
@@ -0,0 +1,44 @@
from typing import Any, Dict
import pandas as pd
class PandasHead:
"""
PandasHead:
A class for retrieving the first few rows of a pandas DataFrame.
"""
@classmethod
def INPUT_TYPES(cls) -> Dict[str, Any]:
"""
Defines the input types for the `head` function.
Returns:
Dict[str, Any]: A dictionary specifying required input types.
"""
return {
"required": {
"dataframe_json": ("STRING", {"multiline": True}),
"rows": ("INT", {"default": 10, "min": 0, "max": 50})
}
}
RETURN_TYPES: tuple = ("STRING",)
FUNCTION: str = "head"
CATEGORY: str = "Data Analysis"
def head(self, dataframe_json: str, rows: int) -> tuple:
"""
Returns the first `rows` rows of a pandas DataFrame.
Args:
dataframe_json (str): A JSON string representation of the DataFrame.
rows (int): The number of rows to retrieve.
Returns:
tuple: A tuple containing a JSON string of the resulting DataFrame.
"""
# Deserialize JSON string to DataFrame
df = pd.read_json(dataframe_json)
df2 = df.head(rows)
return (df2.to_json(),)
+50
View File
@@ -0,0 +1,50 @@
from typing import Any, Dict
import pandas as pd
class PandasJoin:
"""
PandasJoin:
A class for merging two pandas DataFrames based on a common column.
"""
@classmethod
def INPUT_TYPES(cls) -> Dict[str, Any]:
"""
Defines the input types for the `sort_rows` function.
Returns:
Dict[str, Any]: A dictionary specifying required input types.
"""
return {
"required": {
"left_dataframe_json": ("STRING", {"multiline": True}),
"right_dataframe_json": ("STRING", {"multiline": True}),
"on_column_name": ("STRING", {"default": ""}),
"join_method":(("inner", "left", "right", "outer"),)
}
}
RETURN_TYPES: tuple = ("STRING",)
FUNCTION: str = "join_dataframes"
CATEGORY: str = "Data Analysis"
def join_dataframes(self, left_dataframe_json: str, right_dataframe_json: str, on_column_name: str, join_method: str) -> tuple:
"""
Merges two pandas DataFrames based on a common column using the specified join method.
Args:
left_dataframe_json (str): A JSON string representation of the left DataFrame.
right_dataframe_json (str): A JSON string representation of the right DataFrame.
on_column_name (str): The name of the column to join on.
join_method (str): The type of join to perform ("inner", "left", "right", "outer").
Returns:
tuple: A tuple containing a JSON string of the merged DataFrame.
"""
# Deserialize JSON string to DataFrame
df_left = pd.read_json(left_dataframe_json)
df_right = pd.read_json(right_dataframe_json)
df_out = pd.merge(df_left, df_right, on=on_column_name, how=join_method)
return (df_out.to_json(),)
+45
View File
@@ -0,0 +1,45 @@
from typing import Any, Dict
import pandas as pd
class PandasLoadCSV:
"""
PandasLoadCSV:
A class for loading CSV files into a pandas DataFrame.
"""
@classmethod
def INPUT_TYPES(cls) -> Dict[str, Any]:
"""
Defines the input types for the `load_csv` function.
Returns:
Dict[str, Any]: A dictionary specifying required input types.
"""
return {
"required": {
"file_path": ("STRING", {"multiline": False}),
}
}
RETURN_TYPES: tuple = ("STRING",)
FUNCTION: str = "load_csv"
CATEGORY: str = "Data Analysis"
def load_csv(self, file_path: str) -> tuple:
"""
Loads a CSV file into a pandas DataFrame and converts it to a JSON string.
Args:
file_path (str): The path to the CSV file.
Returns:
tuple: A tuple containing a JSON string representation of the DataFrame.
"""
# Read CSV file into DataFrame
df = pd.read_csv(file_path)
# Convert DataFrame to JSON
result_json = df.to_json()
return (result_json,)
+47
View File
@@ -0,0 +1,47 @@
from typing import Any, Dict
import pandas as pd
class PandasSelectColumns:
"""
PandasSelectColumns:
A class for selecting specific columns from a pandas DataFrame.
"""
@classmethod
def INPUT_TYPES(cls) -> Dict[str, Any]:
"""
Defines the input types for the `select_columns` function.
Returns:
Dict[str, Any]: A dictionary specifying required input types.
"""
return {
"required": {
"dataframe_json": ("STRING", {"multiline": True}),
"column_names": ("STRING", {"default": ""})
}
}
RETURN_TYPES: tuple = ("STRING",)
FUNCTION: str = "select_columns"
CATEGORY: str = "Data Analysis"
def select_columns(self, dataframe_json: str, column_names: str) -> tuple:
"""
Selects specific columns from a pandas DataFrame.
Args:
dataframe_json (str): A JSON string representation of the DataFrame.
column_names (str): A comma-separated string of column names to select.
Returns:
tuple: A tuple containing a JSON string of the DataFrame with selected columns.
"""
# Deserialize JSON string to DataFrame
df = pd.read_json(dataframe_json)
# Process column names
selected_columns = [col.strip() for col in column_names.split(",")]
df2 = df[selected_columns]
return (df2.to_json(),)
+47
View File
@@ -0,0 +1,47 @@
import ast
from typing import Any, Dict
import pandas as pd
class PandasSelectRows:
"""
PandasSelectRows:
A class for selecting specific rows from a pandas DataFrame based on a condition.
"""
@classmethod
def INPUT_TYPES(cls) -> Dict[str, Any]:
"""
Defines the input types for the `select_rows` function.
Returns:
Dict[str, Any]: A dictionary specifying required input types.
"""
return {
"required": {
"dataframe_json": ("STRING", {"multiline": True}),
"condition": ("STRING", {"default": ""})
}
}
RETURN_TYPES: tuple = ("STRING",)
FUNCTION: str = "select_rows"
CATEGORY: str = "Data Analysis"
def select_rows(self, dataframe_json: str, condition: str) -> tuple:
"""
Selects specific rows from a pandas DataFrame based on a given condition.
Args:
dataframe_json (str): A JSON string representation of the DataFrame.
condition (str): A string representing the condition to filter rows.
Returns:
tuple: A tuple containing a JSON string of the filtered DataFrame.
"""
# Deserialize JSON string to DataFrame
df = pd.read_json(dataframe_json)
# Apply condition
df2 = df.query(condition)
return (df2.to_json(),)
+53
View File
@@ -0,0 +1,53 @@
"""
This code is based on
https://github.com/pythongosssss/ComfyUI-Custom-Scripts/blob/main/py/show_text.py
See credit/credit.md for the full license.
"""
import pandas as pd
class PandasShowDataFrame:
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"dataframe_json": ("STRING", {"forceInput": True}),
},
"hidden": {
"unique_id": "UNIQUE_ID",
"extra_pnginfo": "EXTRA_PNGINFO",
},
}
INPUT_IS_LIST = True
RETURN_TYPES = ("STRING",)
FUNCTION = "notify"
OUTPUT_NODE = True
OUTPUT_IS_LIST = (True,)
CATEGORY = "Data Analysis"
def notify(self, dataframe_json, unique_id=None, extra_pnginfo=None):
text = None
if unique_id is not None and extra_pnginfo is not None:
if not isinstance(extra_pnginfo, list):
print("Error: extra_pnginfo is not a list")
elif (
not isinstance(extra_pnginfo[0], dict)
or "workflow" not in extra_pnginfo[0]
):
print("Error: extra_pnginfo[0] is not a dict or missing 'workflow' key")
else:
# Deserialize JSON string to DataFrame
df = pd.read_json(dataframe_json[0])
text = [str(df)] # wrap in list
workflow = extra_pnginfo[0]["workflow"]
node = next(
(x for x in workflow["nodes"] if str(x["id"]) == str(unique_id[0])),
None,
)
if node:
node["widgets_values"] = [text]
else:
print("unique_id or extra_pnginfo is None.")
return {"ui": {"text": text}, "result": (text,)}
+48
View File
@@ -0,0 +1,48 @@
from typing import Any, Dict
import pandas as pd
class PandasSort:
"""
PandasSort:
A class for sorting a pandas DataFrame by a specified column.
"""
@classmethod
def INPUT_TYPES(cls) -> Dict[str, Any]:
"""
Defines the input types for the `sort_rows` function.
Returns:
Dict[str, Any]: A dictionary specifying required input types.
"""
return {
"required": {
"dataframe_json": ("STRING", {"multiline": True}),
"column_name": ("STRING", {"default": ""}),
"ascending": ("BOOLEAN", {"default": True})
}
}
RETURN_TYPES: tuple = ("STRING",)
FUNCTION: str = "sort_rows"
CATEGORY: str = "Data Analysis"
def sort_rows(self, dataframe_json: str, column_name: str, ascending: bool) -> tuple:
"""
Sorts a pandas DataFrame by the specified column.
Args:
dataframe_json (str): A JSON string representation of the DataFrame.
column_name (str): The name of the column to sort by.
ascending (bool): Whether to sort in ascending order.
Returns:
tuple: A tuple containing a JSON string of the sorted DataFrame.
"""
# Deserialize JSON string to DataFrame
df = pd.read_json(dataframe_json)
# Sort DataFrame
df2 = df.sort_values(by=column_name, ascending=ascending)
return (df2.to_json(),)
+44
View File
@@ -0,0 +1,44 @@
from typing import Any, Dict
import pandas as pd
class PandasSummary:
"""
PandasSummary:
A class for analyzing and summarizing a pandas DataFrame.
"""
@classmethod
def INPUT_TYPES(cls) -> Dict[str, Any]:
"""
Defines the input types for the `analyze_dataframe` function.
Returns:
Dict[str, Any]: A dictionary specifying required input types.
"""
return {
"required": {
"dataframe_json": ("STRING", {"multiline": True}),
}
}
RETURN_TYPES: tuple = ("STRING",)
FUNCTION: str = "analyze_dataframe"
CATEGORY: str = "Data Analysis"
def analyze_dataframe(self, dataframe_json: str) -> tuple:
"""
Analyzes a pandas DataFrame and returns a summary.
Args:
dataframe_json (str): A JSON string representation of the DataFrame.
Returns:
tuple: A tuple containing a string representation of the DataFrame summary.
"""
# Deserialize JSON string to DataFrame
df = pd.read_json(dataframe_json)
# Perform summary operation
summary = df.describe()
return (str(summary),)
+40
View File
@@ -0,0 +1,40 @@
from typing import Any, Dict
import pandas as pd
class PandasToString:
"""
PandasToString:
A class for converting a pandas DataFrame to a string representation.
"""
@classmethod
def INPUT_TYPES(cls) -> Dict[str, Any]:
"""
Defines the input types for the `to_string` function.
Returns:
Dict[str, Any]: A dictionary specifying required input types.
"""
return {
"required": {
"dataframe_json": ("STRING", {"multiline": True}),
}
}
RETURN_TYPES: tuple = ("STRING",)
FUNCTION: str = "to_string"
CATEGORY: str = "Data Analysis"
def to_string(self, dataframe_json: str) -> tuple:
"""
Converts a pandas DataFrame to a string representation.
Args:
dataframe_json (str): A JSON string representation of the DataFrame.
Returns:
tuple: A tuple containing the string representation of the DataFrame.
"""
# Deserialize JSON string to DataFrame
df = pd.read_json(dataframe_json)
return (str(df),)
+64
View File
@@ -0,0 +1,64 @@
/*
This code is based on
https://github.com/pythongosssss/ComfyUI-Custom-Scripts/blob/main/web/js/showText.js
See credit/credit.md for the full license.
*/
import { app } from "../../../scripts/app.js";
import { ComfyWidgets } from "../../../scripts/widgets.js";
// Displays input text on a node
app.registerExtension({
name: "HowToSD.ShowDataFrame",
async beforeRegisterNodeDef(nodeType, nodeData, app) {
if (nodeData.name === "PandasShowDataFrame") { // This needs to match NODE_CLASS_MAPPINGS in Python
function populate(text) {
if (this.widgets) {
for (let i = 1; i < this.widgets.length; i++) {
this.widgets[i].onRemove?.();
}
this.widgets.length = 1;
}
const v = [...text];
if (!v[0]) {
v.shift();
}
for (const list of v) {
const w = ComfyWidgets["STRING"](this, "text2", ["STRING", { multiline: true }], app).widget;
w.inputEl.readOnly = true;
w.inputEl.style.opacity = 0.6;
w.value = list;
}
requestAnimationFrame(() => {
const sz = this.computeSize();
if (sz[0] < this.size[0]) {
sz[0] = this.size[0];
}
if (sz[1] < this.size[1]) {
sz[1] = this.size[1];
}
this.onResize?.(sz);
app.graph.setDirtyCanvas(true, false);
});
}
// When the node is executed we will be sent the input text, display this in the widget
const onExecuted = nodeType.prototype.onExecuted;
nodeType.prototype.onExecuted = function (message) {
onExecuted?.apply(this, arguments);
populate.call(this, message.text);
};
const onConfigure = nodeType.prototype.onConfigure;
nodeType.prototype.onConfigure = function () {
onConfigure?.apply(this, arguments);
if (this.widgets_values?.length) {
populate.call(this, this.widgets_values.slice(+this.widgets_values.length > 1));
}
};
}
},
});