Insert literal replacement text verbatim when use_regex is off (review SE-2)

re.sub always parses the replacement as a template, so a backslash in
the replacement (e.g. C:\1) raised PatternError even in literal mode.
Also drop an unused import and align js import paths with the
documented two-level extension path. Bump to 2.0.13.
This commit is contained in:
BRADSEC
2026-07-03 10:52:03 +10:00
parent 29d6e99dc2
commit 67b5a0e37f
5 changed files with 21 additions and 6 deletions
+2 -2
View File
@@ -1,5 +1,5 @@
import { app } from "../../../scripts/app.js";
import { ComfyWidgets } from "../../../scripts/widgets.js";
import { app } from "../../scripts/app.js";
import { ComfyWidgets } from "../../scripts/widgets.js";
// Consistent sizing for all String Essentials nodes
const DEFAULT_NODE_WIDTH = 400;
+1 -1
View File
@@ -1,7 +1,7 @@
[project]
name = "comfyui_stringessentials"
description = "Simple string manipulation nodes for ComfyUI (strip/remove text strings, search and replace text strings, preview modified string outputs). Useful for modifying text prompts or results from LLM outputs. Nodes will be located under standard Add Node > utils menu. Node names: String Textbox, String Strip, String Multi Replace, String Conditional Append, String Contains Any and String Preview."
version = "2.0.12"
version = "2.0.13"
license = {file = "LICENSE"}
[project.urls]
-2
View File
@@ -1,5 +1,3 @@
import re
class StringConditionalAppendNode:
@classmethod
def INPUT_TYPES(cls):
+4 -1
View File
@@ -95,7 +95,10 @@ class StringMultiReplaceNode:
f"StringMultiReplace: invalid regex for search '{search_str}': {e}. "
f"Disable use_regex to treat search strings as literal text."
)
result = regex.sub(replace_str, result)
# re.sub always parses the replacement as a template (\1, \g<>);
# in literal mode insert the user's text verbatim instead.
replacement = replace_str if use_regex else replace_str.replace("\\", "\\\\")
result = regex.sub(replacement, result)
if remove_extra_spaces:
result = self.cleanup_text(result)
+14
View File
@@ -106,6 +106,20 @@ class TestStringNodes(unittest.TestCase):
)[0]
self.assertEqual(result, "Hello everyone")
def test_replace_literal_backslash_replacement(self):
# With use_regex disabled, replacement text is literal: backslash
# sequences must not be treated as re.sub group references.
result = self.replace_node.string_replace(
input_string="path is X",
replacement_pairs=r"X::C:\1",
replacement_delimiter="::",
match_case=False,
match_whole_string=True,
preserve_punctuation=True,
remove_extra_spaces=False
)[0]
self.assertEqual(result, r"path is C:\1")
def test_replace_multiple_pairs(self):
input_string = "The quick brown fox jumps over the lazy dog"
replacement_pairs = """quick::slow