# Codebase Structure **Analysis Date:** 2026-03-03 ## Directory Layout ``` ComfyUI_StringEssentials/ ├── __init__.py # Node registry and exports ├── pyproject.toml # Project metadata and configuration ├── README.md # Documentation ├── LICENSE # License file ├── string_textbox_node.py # String Textbox node ├── string_strip_node.py # String Strip node ├── string_multi_replace_node.py # String Multi Replace node ├── string_preview_node.py # String Preview node ├── string_conditional_append_node.py # String Conditional Append node ├── string_contains_any_node.py # String Contains Any node ├── test_string_nodes.py # Unit tests ├── .planning/ # Planning and analysis docs (not committed) │ └── codebase/ # Architecture documentation ├── .pytest_cache/ # Pytest cache (gitignored) ├── js/ # Client-side assets (currently empty) └── images/ # Documentation images ``` ## Directory Purposes **Root Directory:** - Purpose: Contains all Python node implementations and project config - Contains: Node classes, tests, project metadata - Key files: All `*_node.py` files, `__init__.py`, `pyproject.toml`, `test_string_nodes.py` **js/ Directory:** - Purpose: Placeholder for client-side JavaScript/web assets - Contains: Currently empty, referenced in `__init__.py` WEB_DIRECTORY - Committed: Yes (directory exists, may have assets) **images/ Directory:** - Purpose: Documentation images for README - Contains: PNG screenshots of node interfaces and example workflows - Committed: Yes **.planning/codebase/ Directory:** - Purpose: Architecture and analysis documentation generated by GSD tools - Contains: ARCHITECTURE.md, STRUCTURE.md, CONVENTIONS.md, TESTING.md, etc. - Committed: No (git ignored) **.pytest_cache/ Directory:** - Purpose: Pytest runtime cache - Contains: Test execution metadata - Committed: No (git ignored) ## Key File Locations **Entry Points:** - `__init__.py`: Module initialization - imports nodes and exports NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS, WEB_DIRECTORY **Node Implementations:** - `string_textbox_node.py`: StringTextboxNode - simple text input passthrough (5 lines of logic) - `string_strip_node.py`: StringStripNode - removes specified strings with regex patterns - `string_multi_replace_node.py`: StringMultiReplaceNode - replaces text using delimiter-separated pairs - `string_preview_node.py`: StringPreviewNode - displays string output in ComfyUI UI - `string_conditional_append_node.py`: StringConditionalAppendNode - appends text only if not present - `string_contains_any_node.py`: StringContainsAnyNode - checks if any of multiple substrings exist **Configuration:** - `pyproject.toml`: Project metadata including name, version (2.0.7), description, repository URL **Testing:** - `test_string_nodes.py`: 62 unit tests covering all node functionalities **Documentation:** - `README.md`: User-facing documentation with node descriptions and usage examples ## Naming Conventions **Files:** - Node files: `string__node.py` format - Examples: `string_strip_node.py`, `string_multi_replace_node.py` - Pattern: snake_case with `_node.py` suffix **Classes:** - Node classes: PascalCase with "Node" suffix - Examples: `StringTextboxNode`, `StringStripNode`, `StringMultiReplaceNode` - Pattern: Convert filename from snake_case to PascalCase, append "Node" **Methods:** - Execution methods: verb_noun_v1 format (snake_case) - Examples: `string_strip()`, `string_replace()`, `conditional_append()`, `contains_any()`, `pass_string()`, `preview_string()` - Pattern: Descriptive snake_case names indicating operation **Variables:** - Instance variables: snake_case with descriptive names - Examples: `input_string`, `strings_to_remove`, `match_case`, `preserve_punctuation` - Pattern: Clear names indicating type and purpose **Constants:** - Node metadata: UPPERCASE - Examples: `RETURN_TYPES`, `RETURN_NAMES`, `FUNCTION`, `CATEGORY`, `INPUT_TYPES`, `OUTPUT_NODE` - Pattern: ComfyUI convention for node interface ## Where to Add New Code **New String Operation Node:** 1. Create file: `string__node.py` in root directory 2. Class structure (follow pattern from existing nodes): - Define `INPUT_TYPES()` classmethod with parameter definitions - Define `RETURN_TYPES` tuple with output types - Define `RETURN_NAMES` tuple with output names - Set `FUNCTION = ""` - Set `CATEGORY = "utils/StringEssentials"` - Implement execution method with logic 3. Add to `__init__.py`: - Import the new class at top - Add entry to `NODE_CLASS_MAPPINGS` dict (key = class name as string) - Add entry to `NODE_DISPLAY_NAME_MAPPINGS` dict (key = class name, value = display name) 4. Add tests to `test_string_nodes.py`: - Create test class or add methods to `TestStringNodes` - Test basic functionality, edge cases, parameter variations **Example node implementation pattern from `string_strip_node.py`:** ```python import re class StringStripNode: @classmethod def INPUT_TYPES(cls): return { "required": { "input_string": ("STRING", {...}), "strings_to_remove": ("STRING", {...}), "match_case": ("BOOLEAN", {...}), # ... more parameters } } RETURN_TYPES = ("STRING",) RETURN_NAMES = ("modified_string",) FUNCTION = "string_strip" CATEGORY = "utils/StringEssentials" def cleanup_text(self, text): # Helper method for text normalization pass def string_strip(self, input_string, strings_to_remove, ...): # Parse input (splitlines, strip, filter empty) # Compile regex patterns # Apply patterns # Cleanup if needed return (result,) ``` **Utilities/Helpers:** - Shared helper methods: Add to individual node class if only used there - Common patterns: Currently duplicated in `cleanup_text()` across nodes (consider extraction if adding more nodes) - Location: Keep at root level - no separate utils directory used **Tests:** - Add test methods to `TestStringNodes` class in `test_string_nodes.py` - Follow naming: `test__` (e.g., `test_strip_basic_functionality`) - Setup: Use `self.setUp()` to instantiate node classes - Pattern: Call node method directly with test parameters, assert expected results ## Special Directories **js/ Directory:** - Purpose: ComfyUI web assets (referenced in WEB_DIRECTORY in `__init__.py`) - Generated: No - Committed: Yes (directory exists, may be empty or contain future web assets) - Note: Currently unused but available for client-side node customization **images/ Directory:** - Purpose: Screenshots and diagrams for documentation - Generated: No (manually created/updated) - Committed: Yes - Files: PNG images referenced in README.md **.planning/codebase/ Directory:** - Purpose: GSD (Get Shit Done) architecture analysis documents - Generated: Yes (by GSD tools) - Committed: No (git ignored) - Contains: ARCHITECTURE.md, STRUCTURE.md, CONVENTIONS.md, TESTING.md, CONCERNS.md **.pytest_cache/ Directory:** - Purpose: Pytest internal cache for test discovery and execution - Generated: Yes (auto-created by pytest) - Committed: No (git ignored) ## File Organization Rationale **Flat root structure for nodes:** Each node is a separate file at root level - Rationale: Simple discovery by ComfyUI, clear 1:1 mapping between file and node class - Alternative avoided: Subdirectory organization (would complicate imports in `__init__.py`) **Single test file:** All tests in `test_string_nodes.py` - Rationale: Small codebase, all nodes similar in nature, easy to run all tests together - Scalability: If adding more nodes, consider splitting tests by node when >100 test methods **Shared patterns duplicated:** `cleanup_text()` method exists in both `string_strip_node.py` and `string_multi_replace_node.py` - Current state: Intentionally duplicated to keep each node self-contained - Future improvement: Extract to shared module if >3 nodes need it --- *Structure analysis: 2026-03-03*