Remove planning files

This commit is contained in:
BRADSEC
2026-03-03 20:26:55 +10:00
parent 5d645958bd
commit 30bbf06836
7 changed files with 0 additions and 1137 deletions
-168
View File
@@ -1,168 +0,0 @@
# Architecture
**Analysis Date:** 2026-03-03
## Pattern Overview
**Overall:** Node-based plugin architecture for ComfyUI
**Key Characteristics:**
- Modular node design where each node implements ComfyUI's node interface
- Each node is a standalone class with INPUT_TYPES, RETURN_TYPES, and execution methods
- Nodes are registered in a central registry for ComfyUI framework discovery
- String processing operations implemented using Python's `re` module for regex patterns
- No external dependencies beyond Python standard library
- Plugin loaded via `__init__.py` which exports node mappings
## Layers
**Node Layer:**
- Purpose: Implements individual string manipulation operations
- Location: Root directory - `string_textbox_node.py`, `string_strip_node.py`, `string_multi_replace_node.py`, `string_preview_node.py`, `string_conditional_append_node.py`, `string_contains_any_node.py`
- Contains: Node classes inheriting ComfyUI's node interface
- Depends on: Python `re` module for regex operations
- Used by: ComfyUI framework (loads via NODE_CLASS_MAPPINGS)
**Plugin Registry Layer:**
- Purpose: Provides node discovery and registration for ComfyUI
- Location: `__init__.py`
- Contains: NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS, WEB_DIRECTORY exports
- Depends on: All node modules
- Used by: ComfyUI framework at startup
**Testing Layer:**
- Purpose: Unit tests for all node functionalities
- Location: `test_string_nodes.py`
- Contains: unittest.TestCase subclass with comprehensive test suites
- Depends on: All node classes
- Used by: Developers running tests locally
## Data Flow
**String Processing Pipeline:**
1. Input received via `INPUT_TYPES` - user specifies string and processing parameters
2. ComfyUI calls node's FUNCTION method (e.g., `string_strip`, `string_replace`)
3. Processing method performs regex-based transformations
4. Optional cleanup via `cleanup_text()` if `remove_extra_spaces` is True
5. Return processed string(s) via RETURN_TYPES tuple
**Example - StringStripNode flow:**
1. User provides `input_string` and `strings_to_remove` (multiline)
2. `string_strip()` method parses removal list, sorted by length (longest first)
3. Regex patterns compiled with case sensitivity flags
4. Patterns applied sequentially to input string
5. Cleanup normalizes whitespace if enabled
6. Result returned as single-element tuple
**Example - StringConditionalAppendNode flow:**
1. User provides `input_string` and `strings_to_check` (multiline)
2. `conditional_append()` parses check list
3. Each string checked for presence in result (with case sensitivity option)
4. Missing strings appended at specified position (beginning/end)
5. Returns tuple of (modified_string, was_appended boolean)
**State Management:**
- Stateless nodes - each execution independent
- No shared state between invocations
- Only state change: modifying the input string passed through
## Key Abstractions
**Node Interface Pattern:**
- Purpose: Standardizes how nodes interact with ComfyUI framework
- Examples: `StringTextboxNode` (`string_textbox_node.py`), `StringStripNode` (`string_strip_node.py`)
- Pattern: Each node class implements three key class attributes:
- `INPUT_TYPES()` classmethod - declares input parameters and their types
- `RETURN_TYPES` tuple - declares output types
- `FUNCTION` string - method name to call for execution
- Execution method - performs actual processing and returns tuple
**Text Processing Pattern:**
- Purpose: Shared approach for string matching and replacement across nodes
- Examples: `string_strip_node.py`, `string_multi_replace_node.py`
- Pattern: Uses `re.compile()` with configurable flags (IGNORECASE), patterns include:
- Word boundary matching: `\b` for whole word matching
- Punctuation handling: conditional patterns with `(?:[,;:.])` for preservation/removal
- Regex escaping: `re.escape()` to treat user input as literals
**Text Cleanup Pattern:**
- Purpose: Normalize whitespace after text modifications
- Examples: `cleanup_text()` method in `string_strip_node.py`, `string_multi_replace_node.py`
- Pattern: Two-step regex approach:
1. Remove spaces before punctuation: `r'\s+([,;:.])'` → `r'\1'`
2. Normalize multiple spaces: `r'\s{2,}'` → `' '`
3. Strip leading/trailing whitespace
**Multi-value Processing Pattern:**
- Purpose: Handle comma-separated or line-separated lists of values
- Examples: All nodes with multiline string inputs
- Pattern: `.splitlines()` to split input, `.strip()` to clean each line, filter empty strings
## Entry Points
**ComfyUI Framework Loading:**
- Location: `__init__.py`
- Triggers: ComfyUI startup/refresh
- Responsibilities:
- Imports all node classes
- Exports NODE_CLASS_MAPPINGS for framework discovery
- Exports NODE_DISPLAY_NAME_MAPPINGS for UI display names
- Exports WEB_DIRECTORY for any client-side assets
**Individual Node Execution:**
- Location: Each node's FUNCTION method (e.g., `string_strip()` in `string_strip_node.py`)
- Triggers: ComfyUI workflow execution when node is evaluated
- Responsibilities:
- Accept parameters from INPUT_TYPES
- Perform string processing
- Return results as tuple matching RETURN_TYPES
**Output Display:**
- Location: `string_preview_node.py` - StringPreviewNode
- Triggers: Workflow execution
- Responsibilities:
- Display string output in UI via `preview_string()` method
- Force re-evaluation on every execution via `IS_CHANGED()` returning NaN
- Return both UI display data and result tuple
## Error Handling
**Strategy:** Defensive programming - validate and handle edge cases gracefully
**Patterns:**
- Empty input handling: All nodes check for empty strings and return sensible defaults
- Example: `string_contains_any_node.py` line 40-41 returns `(False, "")` for empty substrings
- Example: `string_conditional_append_node.py` line 44-45 returns unchanged input if no strings to check
- Line parsing robustness: `.strip()` applied to each line, whitespace-only lines filtered
- Example: `string_strip_node.py` line 36-38 skips empty/whitespace lines in removal list
- Regex compilation safety: `re.escape()` used to prevent regex injection from user input
- Example: `string_strip_node.py` line 55, 62 escape user strings before pattern compilation
- Delimiter handling: Split with `maxsplit=1` to allow delimiter characters in replacement text
- Example: `string_multi_replace_node.py` line 42 uses `split(delimiter, 1)` to preserve right side
## Cross-Cutting Concerns
**Logging:** Not implemented - ComfyUI framework handles logging
**Validation:**
- User input validation occurs at parsing stage (splitlines, strip, filter empty)
- Type validation handled by ComfyUI framework via INPUT_TYPES/RETURN_TYPES declarations
- No explicit validation errors thrown; nodes handle edge cases gracefully
**Authentication:** Not applicable - nodes are part of ComfyUI plugin
**Case Sensitivity:**
- All text nodes support configurable case-sensitive matching via `match_case` boolean parameter
- Implemented via `re.IGNORECASE` flag when `match_case=False`
- Example: `string_strip_node.py` line 47 sets `flags = 0 if match_case else re.IGNORECASE`
**Punctuation Handling:**
- Special feature introduced to preserve punctuation adjacent to matched text
- Controlled by `preserve_punctuation` boolean parameter
- Enabled by default in most nodes for safe prompt/syntax handling
- Example: `string_strip_node.py` lines 53-65 show pattern variants for punctuation preservation
---
*Architecture analysis: 2026-03-03*
-165
View File
@@ -1,165 +0,0 @@
# Codebase Concerns
**Analysis Date:** 2026-03-03
## Code Duplication
**Regex pattern compilation duplicated across node classes:**
- Issue: Both `StringStripNode` and `StringMultiReplaceNode` implement nearly identical regex pattern building logic for `match_whole_string` and `preserve_punctuation` combinations.
- Files: `string_strip_node.py` lines 52-72, `string_multi_replace_node.py` lines 59-75
- Impact: If regex patterns need adjustment (e.g., for new punctuation marks), changes must be made in multiple places, increasing maintenance burden and risk of inconsistency.
- Fix approach: Extract shared regex pattern building logic into a utility module `string_utils.py` with a function like `build_replacement_pattern(search_str, match_whole_string, preserve_punctuation)` that both nodes can use.
**Text cleanup logic duplicated:**
- Issue: `cleanup_text()` method is defined identically in both `StringStripNode` and `StringMultiReplaceNode`.
- Files: `string_strip_node.py` lines 27-30, `string_multi_replace_node.py` lines 29-32
- Impact: Bug fixes to space normalization or punctuation handling require changes in two places.
- Fix approach: Move `cleanup_text()` to a shared utility module.
## Input Validation Gaps
**No validation of `replacement_delimiter` parameter:**
- Issue: `StringMultiReplaceNode.string_replace()` accepts any string as `replacement_delimiter`, including empty strings or strings not present in replacement_pairs.
- Files: `string_multi_replace_node.py` lines 34-80
- Impact: Empty delimiter could cause silent failures or unexpected behavior. No error message guides users on correct format.
- Fix approach: Add validation to check if `replacement_delimiter` is non-empty and is actually present in at least one line of `replacement_pairs` when non-empty pairs are provided. Return error message if invalid.
**No null/None input handling:**
- Issue: All nodes assume string inputs are valid. If ComfyUI passes `None` or unexpected types, nodes will crash with unhelpful error messages.
- Files: All node classes (e.g., `string_strip_node.py` line 32)
- Impact: Silent failures in ComfyUI workflows without clear error reporting.
- Fix approach: Add type checking and explicit error handling at method entry points.
**Missing handling of extremely long strings:**
- Issue: Regex operations on very large strings (e.g., multi-megabyte text) could cause performance issues or regex complexity bombs.
- Files: All regex-based nodes (`string_strip_node.py`, `string_multi_replace_node.py`, `string_contains_any_node.py`)
- Impact: Workflows processing large text files could hang or crash unexpectedly.
- Fix approach: Add length checks and document maximum recommended input size.
## Pattern Matching Edge Cases
**Incomplete word boundary handling:**
- Issue: The `\b` word boundary in regex (lines 55, 62 in `string_strip_node.py`) doesn't work correctly at string boundaries with Unicode characters, accented characters, or special symbols.
- Files: `string_strip_node.py` lines 52-72, `string_multi_replace_node.py` lines 59-75
- Impact: Matching whole words in non-English text or with special characters produces unexpected results.
- Fix approach: Document this limitation or switch to a more robust word boundary detection method that handles Unicode properly.
**Regex special characters not escaped in `match_whole_string=False`:**
- Issue: In `preserve_punctuation=False` mode, the pattern `re.escape(search_str) + r'(?:[,;:.])?'` (line 72 in `string_multi_replace_node.py`) may not handle all edge cases where the search string itself contains pattern-matching characters.
- Files: `string_multi_replace_node.py` lines 70-72, `string_strip_node.py` lines 64-65
- Impact: While `re.escape()` is used, the added `(?:[,;:.])?` pattern creates assumptions about which punctuation marks follow matches. Other punctuation or symbols would not be handled.
- Fix approach: Either document the supported punctuation list or provide an option to make punctuation removal more flexible.
## Error Reporting
**No error messages returned to user:**
- Issue: Invalid inputs (malformed replacement pairs, empty delimiters, etc.) fail silently or with generic Python exceptions.
- Files: All node classes
- Impact: Users get no feedback about what went wrong. Debugging workflows is difficult.
- Fix approach: Return structured error messages or use ComfyUI's error reporting mechanism.
**Regex compilation errors not caught:**
- Issue: If a user's input accidentally creates an invalid regex pattern, the `re.compile()` call (lines 74 in `string_multi_replace_node.py`, line 67 in `string_strip_node.py`) will raise an exception that crashes the node without a helpful message.
- Files: `string_strip_node.py` line 67, `string_multi_replace_node.py` line 74
- Impact: Even simple typos in user input cause workflow failures with unhelpful error messages.
- Fix approach: Wrap `re.compile()` in try-except block and return meaningful error message.
## Performance Considerations
**Regex patterns compiled multiple times per execution:**
- Issue: In `StringStripNode.string_strip()`, patterns are compiled in a loop (line 67) and compiled separately in a list for each method call. For large lists of removals, this is inefficient.
- Files: `string_strip_node.py` lines 50-71
- Impact: Repeated calls with same removal patterns waste CPU cycles on recompilation.
- Fix approach: Consider memoizing compiled patterns if the same `strings_to_remove` is used repeatedly, or compile once and reuse within a single call.
**Sorting by length every execution:**
- Issue: Strings are sorted by length on every method call (lines 44 in `string_strip_node.py`, line 52 in `string_multi_replace_node.py`). This is necessary for correctness but could be optimized with caching if patterns are reused.
- Files: `string_strip_node.py` line 44, `string_multi_replace_node.py` line 52
- Impact: Minor performance impact for large replacement lists on repeated calls.
- Fix approach: Document the O(n log n) sorting behavior; consider caching if needed.
## Testing Coverage Gaps
**No tests for regex compilation failures:**
- What's not tested: Invalid regex patterns that would cause `re.compile()` to raise an exception.
- Files: `string_strip_node.py` line 67, `string_multi_replace_node.py` line 74, `test_string_nodes.py`
- Risk: Unexpected regex patterns from user input could crash the node without warning.
- Priority: Medium
**No tests for Unicode or special character handling:**
- What's not tested: Input strings with emoji, accented characters, or multi-byte Unicode.
- Files: `test_string_nodes.py`
- Risk: Real-world prompts with special characters may behave unexpectedly.
- Priority: Medium
**No tests for extreme input sizes:**
- What's not tested: Very long strings (megabytes), very long replacement lists, very long individual replacement pairs.
- Files: `test_string_nodes.py`
- Risk: Performance issues or stack overflow on large inputs would not be detected.
- Priority: Low
**No tests for StringTextboxNode:**
- What's not tested: The `StringTextboxNode.pass_string()` method has zero test coverage.
- Files: `string_textbox_node.py`, `test_string_nodes.py`
- Risk: Changes to this node's behavior would go undetected.
- Priority: Low (simple pass-through, but should be covered)
**No tests for StringPreviewNode:**
- What's not tested: The `StringPreviewNode.preview_string()` method and its special `IS_CHANGED()` behavior.
- Files: `string_preview_node.py`, `test_string_nodes.py`
- Risk: The `float("nan")` return value in `IS_CHANGED()` is unusual and not validated.
- Priority: Medium
## Architecture Concerns
**No base class for shared functionality:**
- Issue: Six independent node classes with duplicated methods and patterns indicate missing abstraction.
- Files: All `*_node.py` files
- Impact: Adding features (e.g., logging, input validation) requires changes to multiple files.
- Fix approach: Create a `BaseStringNode` class with shared validation, error handling, and utility methods.
**Inconsistent parameter naming:**
- Issue: `StringStripNode` uses `strings_to_remove`, `StringMultiReplaceNode` uses `replacement_pairs`, etc. Inconsistent naming makes workflows harder to understand and API harder to learn.
- Files: All node classes
- Impact: Users must remember different parameter names for similar operations.
- Fix approach: Standardize parameter names across nodes or document the reasoning for differences.
## Missing Features
**No logging of transformations:**
- Issue: Nodes silently perform transformations with no audit trail or debug output.
- Files: All node classes
- Impact: Users cannot see what replacements were actually made or debug complex workflows.
- Fix approach: Add optional debug output or logging parameter.
**No reuse of previous results:**
- Issue: Each node independently processes input; there's no way to chain results with visibility into intermediate states.
- Files: All output nodes
- Impact: Complex text processing requires many separate nodes instead of a single configurable pipeline.
- Fix approach: Consider a single "Text Processing Pipeline" node that chains multiple operations.
## Potential Security Concerns
**Regular expression denial of service (ReDoS) risk:**
- Issue: User-provided input in `strings_to_remove`, `replacement_pairs`, and `substrings` are used directly in regex patterns after `re.escape()`. While `re.escape()` prevents most ReDoS, deeply nested or pathological patterns could still cause issues.
- Files: `string_strip_node.py` lines 52-72, `string_multi_replace_node.py` lines 59-75, `string_contains_any_node.py` (simple substring search, low risk)
- Impact: Malicious or accidental input could cause CPU spike and freeze workflows.
- Fix approach: Add timeout to regex operations or limit complexity of patterns accepted.
## Known Limitations
**Word boundary matching fails with Unicode:**
- The `\b` anchor in regex patterns doesn't correctly identify word boundaries in non-ASCII text.
- Workaround: Test thoroughly with non-English text; consider providing separate "ASCII-only" and "Unicode-aware" modes.
**Punctuation handling is opinionated:**
- The hardcoded punctuation list `[,;:.]` only handles common English punctuation. Other languages or contexts may use different marks.
- Workaround: Make punctuation marks configurable, or document the list and allow users to add custom nodes for other punctuation.
**Case-insensitive matching doesn't handle Unicode case folding:**
- Python's `.lower()` method handles most Unicode, but some edge cases in Turkish, Greek, and other languages may not be handled optimally.
- Workaround: Document that case-insensitive matching is "best effort" for non-ASCII text.
---
*Concerns audit: 2026-03-03*
-186
View File
@@ -1,186 +0,0 @@
# Coding Conventions
**Analysis Date:** 2026-03-03
## Naming Patterns
**Files:**
- Node files: `string_<name>_node.py` (e.g., `string_strip_node.py`, `string_multi_replace_node.py`)
- Test file: `test_<module>.py` (e.g., `test_string_nodes.py`)
- Class names reflect file names in PascalCase (e.g., `StringStripNode` from `string_strip_node.py`)
**Classes:**
- Node classes: `String<FunctionName>Node` format (e.g., `StringStripNode`, `StringMultiReplaceNode`, `StringConditionalAppendNode`)
- All node classes follow ComfyUI convention with specific class methods and attributes
**Functions/Methods:**
- snake_case for method names (e.g., `string_strip`, `cleanup_text`, `conditional_append`, `contains_any`)
- Core execution method: `FUNCTION = "<method_name>"` points to the main processing method
- Helper methods: lower case with underscores (e.g., `cleanup_text`)
**Variables:**
- snake_case for local variables (e.g., `input_string`, `strings_to_remove`, `replacement_pairs`, `strings_list`)
- Boolean prefixes: `match_case`, `match_whole_string`, `preserve_punctuation`, `was_appended`, `was_any_appended`
**Constants:**
- UPPERCASE for class constants (e.g., `RETURN_TYPES`, `RETURN_NAMES`, `FUNCTION`, `CATEGORY`, `INPUT_TYPES`, `OUTPUT_NODE`)
## Code Style
**Formatting:**
- No detected formatter configuration (.prettierrc, black config, etc.)
- Standard Python conventions: 4-space indentation
- Line length varies, no strict limit enforced
- Blank lines used to separate logical sections within methods
**Linting:**
- No detected linting configuration (.pylintrc, .flake8, etc.)
- Code follows general PEP 8 style conventions
- Minimal deviation from standard Python conventions
**Class Structure Pattern:**
All node classes follow a consistent structure:
```python
class StringNodeName:
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"parameter_name": ("TYPE", {"configuration": "dict"})
}
}
RETURN_TYPES = ("STRING",) # or ("BOOLEAN", "STRING") etc.
RETURN_NAMES = ("return_name",)
FUNCTION = "method_name"
CATEGORY = "utils/StringEssentials"
def method_name(self, parameters):
# Implementation
return (result,) # Always return tuple
```
## Import Organization
**Order:**
1. Standard library imports (`import unittest`, `import re`)
2. Class imports from local modules (e.g., `from string_strip_node import StringStripNode`)
**Path Aliases:**
- No path aliases detected or used
**Module Organization:**
- `__init__.py` at `/home/mark/Code/ComfyUI_StringEssentials/__init__.py` imports all node classes
- NODE_CLASS_MAPPINGS and NODE_DISPLAY_NAME_MAPPINGS provide ComfyUI registry
- All modules use relative imports in `__init__.py`
## Error Handling
**Patterns:**
- Input validation through conditional checks (if not line: continue)
- Empty input handling: return default empty/false values (e.g., `return (False, "")`)
- No explicit try-catch blocks; relies on Python built-ins for error prevention
- String operations wrapped in safe calls (e.g., `.strip()`, `.split()`)
- All methods handle empty strings and whitespace gracefully
**Example from `string_contains_any_node.py`:**
```python
if not substrings_list:
return (False, "")
# Prepare strings for comparison
search_string = input_string if match_case else input_string.lower()
```
## Logging
**Framework:** Not detected - no logging module used in codebase
**Console Output:**
- No console logging throughout production code
- Tests use unittest assertions for verification
- No debug output or print statements in production code
## Comments
**When to Comment:**
- Comments reference issue numbers for fixes (e.g., "# Issue #6 fix", "# Test Issue #6", "# Issue #8")
- Comments explain regex patterns and matching behavior (e.g., "Remove spaces before punctuation", "Normalize multiple spaces")
- Docstrings minimal; only used in `StringContainsAnyNode` with class-level docstring
**JSDoc/TSDoc:**
- Not applicable - Python codebase without type hints
- Class methods have minimal/no docstrings
## Function Design
**Size:**
- Small to medium functions (methods range 10-50 lines)
- Core logic methods typically 30-50 lines: `string_strip`, `string_replace`, `conditional_append`
- Helper methods compact: `cleanup_text` is 3 lines
**Parameters:**
- Input parameters correspond directly to INPUT_TYPES definitions
- Boolean flags for feature toggling common (e.g., `match_case`, `preserve_punctuation`)
- String inputs often use multiline format for flexibility
**Return Values:**
- Always return tuples, matching RETURN_TYPES specification
- Single return: `(result,)`
- Multiple returns: `(result, boolean_flag)`
- Empty returns use falsy values: `(False, "")` or `(input_string, False)`
## Module Design
**Exports:**
- `__init__.py` at `/home/mark/Code/ComfyUI_StringEssentials/__init__.py` exports all node classes
- NODE_CLASS_MAPPINGS dict maps string names to classes for ComfyUI registration
- NODE_DISPLAY_NAME_MAPPINGS provides UI-friendly names
**Barrel Files:**
- Yes, `__init__.py` acts as barrel file with explicit imports
- Each node class imported individually
- WEB_DIRECTORY constant exported for ComfyUI
**Shared Utilities:**
- `cleanup_text()` method duplicated in both `StringStripNode` and `StringMultiReplaceNode` (not DRY, but isolated to context)
- No separate utils module; all logic encapsulated in node classes
## Common Patterns
**Regex Pattern Compilation:**
Patterns compiled once in a loop for performance:
```python
# From string_strip_node.py and string_multi_replace_node.py
patterns = []
for _, string_to_remove in removals:
# Build pattern
pattern = ...
patterns.append(re.compile(pattern, flags=flags))
# Apply all patterns
for pattern in patterns:
result = pattern.sub('', result)
```
**String Parsing (Multiline Input):**
Common pattern for parsing user input:
```python
strings_list = []
for line in strings_to_remove.splitlines():
line = line.strip()
if not line:
continue
strings_list.append(line)
```
**Case Sensitivity Handling:**
Consistent approach across nodes:
```python
flags = 0 if match_case else re.IGNORECASE
regex = re.compile(pattern, flags=flags)
```
---
*Convention analysis: 2026-03-03*
-81
View File
@@ -1,81 +0,0 @@
# External Integrations
**Analysis Date:** 2026-03-03
## APIs & External Services
**LLM Integration:**
- Compatible with outputs from Ollama, Claude.ai, OpenAI ChatGPT
- No direct SDK/client integration - processes text output from LLM services
- Purpose: Clean and transform LLM-generated prompts and descriptions
## Data Storage
**Databases:**
- Not applicable - Nodes process in-memory strings only, no persistent storage
**File Storage:**
- Local filesystem only - Custom node installed in ComfyUI custom_nodes directory
- No external file storage integrations
**Caching:**
- None - All operations are stateless transformations
## Authentication & Identity
**Auth Provider:**
- Not applicable - Standalone utility nodes with no authentication requirements
- Custom node registration managed by ComfyUI framework
## Monitoring & Observability
**Error Tracking:**
- None - Uses ComfyUI's native error handling and logging
**Logs:**
- ComfyUI application logs
- No external log aggregation
## CI/CD & Deployment
**Hosting:**
- GitHub repository: https://github.com/bradsec/ComfyUI_StringEssentials
- ComfyUI Registry: Registered via ComfyUI package registry (PublisherId: bradsec)
**CI Pipeline:**
- GitHub Actions workflow: `.github/workflows/publish.yml`
- Automated publishing to ComfyUI registry on release
## Environment Configuration
**Required env vars:**
- None - Zero environment variable dependencies
**Secrets location:**
- Not applicable - No secrets or credentials used
## Webhooks & Callbacks
**Incoming:**
- None
**Outgoing:**
- None
## Frontend Integration
**ComfyUI Web Interface:**
- JavaScript extensions in `js/string_essentials.js`
- Custom node widget initialization via ComfyUI's extension API
- Widget API: `ComfyWidgets` for STRING input display
- App API: `app.registerExtension()` for node lifecycle hooks
**Node Widget Configuration:**
- Multiline text inputs for string configuration
- Boolean toggles for matching options (case-sensitive, whole word, etc.)
- Dropdown selections for position (beginning/end)
- Custom separators configurable via STRING inputs
---
*Integration audit: 2026-03-03*
-79
View File
@@ -1,79 +0,0 @@
# Technology Stack
**Analysis Date:** 2026-03-03
## Languages
**Primary:**
- Python 3.x - Core node implementation and string manipulation logic
- JavaScript - Frontend UI extensions and ComfyUI widget integration
## Runtime
**Environment:**
- ComfyUI - Custom node framework for AI image generation workflows
**Package Manager:**
- pip - Python dependency management
- No Python dependencies or external modules required (pure Python implementation)
## Frameworks
**Core:**
- ComfyUI Custom Nodes Framework - Node registration and execution
- Uses `NODE_CLASS_MAPPINGS` and `NODE_DISPLAY_NAME_MAPPINGS` for node registration
- Located: `__init__.py`
**Testing:**
- unittest - Python standard library testing framework
- Config: No external test configuration file (uses unittest defaults)
- Test file: `test_string_nodes.py`
**Build/Dev:**
- No formal build system required
- Direct Python module installation into ComfyUI custom_nodes directory
## Key Dependencies
**Critical:**
- None - This is a zero-dependency ComfyUI custom node package
- All functionality implemented using Python standard library only (re module for regex)
**Infrastructure:**
- None - Standalone custom node implementation
## Configuration
**Environment:**
- No environment variables required
- No configuration files needed
- Simple cloning into ComfyUI custom_nodes directory
**Build:**
- `pyproject.toml` - Package metadata and ComfyUI registry information
- Version: 2.0.7
- Publisher: bradsec (ComfyUI Registry identifier)
- License: Included in LICENSE file
## Platform Requirements
**Development:**
- Python 3.x
- ComfyUI installation (as parent application)
- Git for repository cloning
**Production:**
- ComfyUI application
- Python 3.x runtime
- Custom node installed in `custom_nodes/ComfyUI_StringEssentials/` directory
## Platform Support
**Deployment Target:**
- ComfyUI custom nodes directory
- Cross-platform (Windows, macOS, Linux)
- Web-based ComfyUI interface with JavaScript frontend integration
---
*Stack analysis: 2026-03-03*
-207
View File
@@ -1,207 +0,0 @@
# 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_<operation>_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_<operation>_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 = "<method_name>"`
- 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_<node>_<scenario>` (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*
-251
View File
@@ -1,251 +0,0 @@
# Testing Patterns
**Analysis Date:** 2026-03-03
## Test Framework
**Runner:**
- unittest (Python standard library)
- Config: None (uses default unittest discovery)
- No pytest.ini, setup.cfg, or tox.ini configuration detected
**Assertion Library:**
- unittest.TestCase assertions (built-in)
**Run Commands:**
```bash
python -m unittest test_string_nodes.py # Run all tests
python -m unittest test_string_nodes.TestStringNodes # Run specific test class
python -m unittest test_string_nodes.TestStringNodes.test_<name> # Run specific test
```
**Test File Location:**
- `test_string_nodes.py` in project root alongside source files (`/home/mark/Code/ComfyUI_StringEssentials/test_string_nodes.py`)
- Co-located with source code (not in separate tests directory)
## Test File Organization
**Location:**
- Co-located pattern: test file in same directory as source modules
**Naming:**
- Test file: `test_string_nodes.py`
- Test class: `TestStringNodes` (PascalCase with Test prefix)
- Test methods: `test_<functionality>` format
**Structure:**
```
test_string_nodes.py
├── TestStringNodes (class)
│ ├── setUp() - Initialize node instances
│ ├── test_strip_* - Tests for StringStripNode
│ ├── test_replace_* - Tests for StringMultiReplaceNode
│ ├── test_append_* - Tests for StringConditionalAppendNode
│ └── test_contains_any_* - Tests for StringContainsAnyNode
└── if __name__ == '__main__': unittest.main()
```
## Test Structure
**Suite Organization:**
```python
class TestStringNodes(unittest.TestCase):
def setUp(self):
self.strip_node = StringStripNode()
self.replace_node = StringMultiReplaceNode()
self.append_node = StringConditionalAppendNode()
self.contains_any_node = StringContainsAnyNode()
```
**Patterns:**
- **Setup pattern:** `setUp()` method instantiates all node instances as instance variables for reuse across test methods
- **No teardown:** No `tearDown()` method (no cleanup needed)
- **Assertion pattern:** Direct method calls on node instances with parameter unpacking:
```python
result = self.strip_node.string_strip(
input_string=input_string,
strings_to_remove=strings_to_remove,
match_case=False,
match_whole_string=True,
preserve_punctuation=True,
remove_extra_spaces=True
)[0]
self.assertEqual(result, expected_output)
```
**Test Method Characteristics:**
- Each test is independent and focused on a single behavior
- Tests use explicit parameter names (keyword arguments) for clarity
- Return value tuple unpacking: `[0]` for single return, tuple unpacking for multiple returns
- Clear arrange-act-assert flow (input setup → method call → assertion)
## Test Coverage by Node
**StringStripNode Tests:**
- `test_strip_basic_functionality`: Single string removal
- `test_strip_multiple_strings`: Multiple removal patterns (multiline input)
- `test_strip_case_sensitivity`: Case-insensitive vs case-sensitive modes
- `test_strip_punctuation_preserved`: Punctuation preservation (Issue #6)
- `test_strip_punctuation_removed`: Legacy punctuation removal behavior
- Extra spaces handling covered in `test_extra_spaces_handling`
**StringMultiReplaceNode Tests:**
- `test_replace_basic_functionality`: Single replacement pair
- `test_replace_multiple_pairs`: Multiple replacement pairs from multiline input
- `test_replace_case_sensitivity`: Case-insensitive vs case-sensitive modes
- `test_replace_custom_delimiter`: Custom delimiter support (not just `::`
- `test_replace_punctuation_preserved`: Punctuation preservation (Issue #6)
- `test_replace_prompt_syntax_preserved`: Bracket syntax preservation (e.g., `[word1:word2:.5]`)
- `test_replace_with_space`: Trailing space preservation in replacements (Issue #8)
- `test_replace_with_leading_space`: Leading space in replacement strings (Issue #8)
- `test_replace_with_whitespace_only`: Multiple spaces in replacements (Issue #8)
- `test_replace_with_tab`: Tab character in replacements (Issue #8)
**StringConditionalAppendNode Tests:**
- `test_append_string_not_found`: Appending when string not present
- `test_append_string_found`: No append when string already present
- `test_append_beginning`: Position flag "beginning" vs "end"
- `test_append_case_insensitive`: Case-insensitive search
- `test_append_case_sensitive`: Case-sensitive search
- `test_append_custom_separator`: Custom separator handling
- `test_append_no_separator`: Empty string separator
- `test_append_multiple_strings`: Multiple check strings with mixed found/not found
- `test_append_multiple_all_found`: All strings already present (no append)
**StringContainsAnyNode Tests:**
- `test_contains_any_found`: Basic found case
- `test_contains_any_not_found`: Basic not found case
- `test_contains_any_multiple_first_match`: Returns first match from multiple options
- `test_contains_any_case_insensitive`: Default case-insensitive behavior
- `test_contains_any_case_sensitive`: Case-sensitive search
- `test_contains_any_case_sensitive_found`: Case-sensitive with matching case
- `test_contains_any_empty_input`: Empty input string handling
- `test_contains_any_empty_substrings`: Empty substrings input
- `test_contains_any_whitespace_substrings`: Whitespace-only lines are ignored
- `test_contains_any_partial_match`: Substring matching (anime matches animation)
## Mocking
**Framework:** None - unittest provides basic mocking but not used in this codebase
**Patterns:**
- No mock objects used
- No external dependencies mocked
- Tests use real node instances with direct method calls
- All test data is embedded in test methods (no external fixtures)
**What to Mock:**
- No mocking required; all node classes are stateless and dependency-free
**What NOT to Mock:**
- Don't mock the node classes - test them directly with real instances
## Fixtures and Factories
**Test Data:**
- All test data embedded directly in test methods
- No separate fixture files or factory classes
- Input strings created inline:
```python
input_string = "This is a test string with test word"
strings_to_remove = "test"
```
**Location:**
- Test data is co-located with test methods (no separate fixtures directory)
- Issue-specific test data clearly labeled with issue references:
```python
def test_strip_punctuation_preserved(self):
# Test Issue #6 fix: punctuation should be preserved
input_string = "Let's meet, Grandma!"
```
## Coverage
**Requirements:** None enforced (no coverage configuration detected)
**View Coverage:**
```bash
# Using unittest's built-in capabilities (limited):
python -m unittest discover -v
# Better coverage with coverage.py (not currently installed):
pip install coverage
coverage run -m unittest test_string_nodes.py
coverage report
```
**Observed Coverage:**
- **StringStripNode:** 100% - All major code paths tested (basic, multiple, case sensitivity, punctuation handling, spaces)
- **StringMultiReplaceNode:** 100% - All code paths tested (basic, multiple, case sensitivity, custom delimiter, punctuation, whitespace preservation)
- **StringConditionalAppendNode:** 100% - All code paths tested (found/not found, position, case sensitivity, separator options, multiple strings)
- **StringContainsAnyNode:** 100% - All code paths tested (found/not found, case sensitivity, empty inputs, whitespace handling, partial matching)
- **StringPreviewNode:** 0% - No tests (trivial pass-through logic)
- **StringTextboxNode:** 0% - No tests (trivial pass-through logic)
## Test Types
**Unit Tests:**
- Scope: Individual node class methods
- Approach: Direct method invocation with arranged inputs, assert on single output
- Example: `test_strip_basic_functionality` tests `string_strip()` method with specific parameters
- No test doubles or stubs - real objects used
**Integration Tests:**
- Not present in codebase (no multi-component interaction testing)
**E2E Tests:**
- Not present (ComfyUI-specific E2E would require full ComfyUI runtime)
**Issue-Driven Tests:**
- Tests explicitly tied to GitHub issues in comments
- Issue #6: Punctuation preservation tests
- Issue #8: Whitespace preservation in replacements tests
- Issue #9: StringContainsAnyNode feature tests
- Pattern: When fixing a bug, issue number added as comment and test created to verify fix
## Common Patterns
**Async Testing:**
- Not applicable - Python standard library code without async/await
**Error Testing:**
- No explicit error/exception testing
- Edge cases tested: empty strings, whitespace-only input, multiple spaces
- Validation through return values rather than exception handling
**Testing Multiline Input:**
```python
strings_to_remove = """test
More Text"""
result = self.strip_node.string_strip(
input_string=input_string,
strings_to_remove=strings_to_remove,
match_case=False,
match_whole_string=True,
preserve_punctuation=True,
remove_extra_spaces=True
)[0]
```
**Testing Multiple Parameters:**
```python
result, was_appended = self.append_node.conditional_append(
input_string=input_string,
strings_to_check=strings_to_check,
position="end",
match_case=False,
separator=", "
)
self.assertEqual(result, expected_string)
self.assertTrue(was_appended)
```
**Testing Boolean Returns:**
- StringConditionalAppendNode returns `(string, boolean)` tuple
- StringContainsAnyNode returns `(boolean, string)` tuple
- Tests unpack both return values and assert on each
---
*Testing analysis: 2026-03-03*