Add slugify string node

This commit is contained in:
2026-08-05 12:34:51 +00:00
parent c26f97785b
commit 285eb40c92
3 changed files with 53 additions and 0 deletions
+7
View File
@@ -31,6 +31,11 @@
- Output: cleaned `STRING` - Output: cleaned `STRING`
- Removes a trailing `_<digits>` iteration suffix before the file extension, for example `asset_003.png -> asset.png`. - Removes a trailing `_<digits>` iteration suffix before the file extension, for example `asset_003.png -> asset.png`.
- `Dumas Slugify String`
- Input: `text`
- Output: slug `STRING`
- Converts text into a lowercase URL/file-safe slug, for example `Crème brûlée 2026 -> creme-brulee-2026`.
- `Dumas JSON Get Value` - `Dumas JSON Get Value`
- Inputs: `json_object`, `path` - Inputs: `json_object`, `path`
- Output: `JSON` - Output: `JSON`
@@ -167,6 +172,8 @@ decr -> use index - 1
`Dumas Strip Iteration Suffix` only strips a final numeric suffix. Names like `my_asset_final.png` are left untouched, while `my_asset_012.png` becomes `my_asset.png`. `Dumas Strip Iteration Suffix` only strips a final numeric suffix. Names like `my_asset_final.png` are left untouched, while `my_asset_012.png` becomes `my_asset.png`.
`Dumas Slugify String` lowercases text, strips accents, replaces non-alphanumeric runs with `-`, and trims leading or trailing dashes.
## Roadmap ## Roadmap
This repo is intended to grow into a broader set of Dumas-branded generic utility nodes, including JSON helpers and adjacent data-manipulation tools. This repo is intended to grow into a broader set of Dumas-branded generic utility nodes, including JSON helpers and adjacent data-manipulation tools.
+31
View File
@@ -2,6 +2,8 @@ from functools import lru_cache
from itertools import islice from itertools import islice
import json import json
import os import os
import re
import unicodedata
def _clone_container(value): def _clone_container(value):
@@ -259,6 +261,16 @@ def _strip_iteration_suffix(value):
return f"{prefix}{extension}" return f"{prefix}{extension}"
def _slugify_string(value):
if not isinstance(value, str):
return ""
normalized = unicodedata.normalize("NFKD", value)
ascii_value = normalized.encode("ascii", "ignore").decode("ascii")
slug = re.sub(r"[^a-zA-Z0-9]+", "-", ascii_value.lower())
return slug.strip("-")
class DumasJSONStringToObjectNode: class DumasJSONStringToObjectNode:
CATEGORY = "Dumas/JSON" CATEGORY = "Dumas/JSON"
RETURN_TYPES = ("JSON",) RETURN_TYPES = ("JSON",)
@@ -298,6 +310,23 @@ class DumasStripIterationSuffixNode:
return (_strip_iteration_suffix(filename),) return (_strip_iteration_suffix(filename),)
class DumasSlugifyStringNode:
CATEGORY = "Dumas/String"
RETURN_TYPES = ("STRING",)
FUNCTION = "slugify_string"
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"text": ("STRING", {"default": "", "multiline": False}),
}
}
def slugify_string(self, text):
return (_slugify_string(text),)
class DumasJSONObjectToStringNode: class DumasJSONObjectToStringNode:
CATEGORY = "Dumas/JSON" CATEGORY = "Dumas/JSON"
RETURN_TYPES = ("STRING",) RETURN_TYPES = ("STRING",)
@@ -630,6 +659,7 @@ class DumasJSONUnflattenNode:
NODE_CLASS_MAPPINGS = { NODE_CLASS_MAPPINGS = {
"DumasJSONStringToObject": DumasJSONStringToObjectNode, "DumasJSONStringToObject": DumasJSONStringToObjectNode,
"DumasStripIterationSuffix": DumasStripIterationSuffixNode, "DumasStripIterationSuffix": DumasStripIterationSuffixNode,
"DumasSlugifyString": DumasSlugifyStringNode,
"DumasJSONObjectToString": DumasJSONObjectToStringNode, "DumasJSONObjectToString": DumasJSONObjectToStringNode,
"DumasJSONGetValue": DumasJSONGetValueNode, "DumasJSONGetValue": DumasJSONGetValueNode,
"DumasJSONSetValue": DumasJSONSetValueNode, "DumasJSONSetValue": DumasJSONSetValueNode,
@@ -650,6 +680,7 @@ NODE_CLASS_MAPPINGS = {
NODE_DISPLAY_NAME_MAPPINGS = { NODE_DISPLAY_NAME_MAPPINGS = {
"DumasJSONStringToObject": "Dumas JSON String to Object", "DumasJSONStringToObject": "Dumas JSON String to Object",
"DumasStripIterationSuffix": "Dumas Strip Iteration Suffix", "DumasStripIterationSuffix": "Dumas Strip Iteration Suffix",
"DumasSlugifyString": "Dumas Slugify String",
"DumasJSONObjectToString": "Dumas JSON Object to String", "DumasJSONObjectToString": "Dumas JSON Object to String",
"DumasJSONGetValue": "Dumas JSON Get Value", "DumasJSONGetValue": "Dumas JSON Get Value",
"DumasJSONSetValue": "Dumas JSON Set Value", "DumasJSONSetValue": "Dumas JSON Set Value",
+15
View File
@@ -17,6 +17,7 @@ from dumas_json_nodes import (
DumasJSONObjectToStringNode, DumasJSONObjectToStringNode,
DumasJSONStringToObjectNode, DumasJSONStringToObjectNode,
DumasJSONSetValueNode, DumasJSONSetValueNode,
DumasSlugifyStringNode,
DumasStripIterationSuffixNode, DumasStripIterationSuffixNode,
) )
@@ -63,6 +64,20 @@ class DumasJSONNodeTests(unittest.TestCase):
self.assertEqual(result, ("my_asset_final.png",)) self.assertEqual(result, ("my_asset_final.png",))
def test_slugify_string_normalizes_text(self):
node = DumasSlugifyStringNode()
result = node.slugify_string("Hello, World! This is Dumas.")
self.assertEqual(result, ("hello-world-this-is-dumas",))
def test_slugify_string_strips_accents_and_repeated_symbols(self):
node = DumasSlugifyStringNode()
result = node.slugify_string("Crème brûlée___2026")
self.assertEqual(result, ("creme-brulee-2026",))
def test_get_value_reads_nested_paths(self): def test_get_value_reads_nested_paths(self):
node = DumasJSONGetValueNode() node = DumasJSONGetValueNode()