Fix text processing to treat input as array if input is an array (#21743)

This commit is contained in:
Wang Qi authored and GitHub committed 2026-10-30 12:46:07 +08:00
1 parent 9ba49c523e
commit 8189ce5274
1 file changed
+31 -4
+31 -4
View File
@@ -30,6 +30,7 @@ package component
import (
"context"
"fmt"
"reflect"
"regexp"
"strings"
@@ -45,7 +46,7 @@ type stringTransformParam struct {
Method string `json:"method"` // "split" or "merge"
Script string `json:"script"` // merge mode: template
SplitRef string `json:"split_ref"` // split mode: state ref to read
Delimiters []string `json:"delimiters"` // split mode: literal delimiters
Delimiters []string `json:"delimiters"` // split: literal delimiters; merge: first delimiter joins arrays
}
// Update copies a fresh param map into the receiver.
@@ -309,11 +310,37 @@ func (s *StringTransformComponent) doSplit(_ context.Context, state *runtime.Can
// the resolved script.
func (s *StringTransformComponent) doMerge(_ context.Context, state *runtime.CanvasState, inputs map[string]any) map[string]any {
script := s.param.Script
formatValue := func(value any) string {
v := reflect.ValueOf(value)
if v.Kind() == reflect.Slice || v.Kind() == reflect.Array {
parts := make([]string, v.Len())
for i := range parts {
parts[i] = fmt.Sprintf("%v", v.Index(i).Interface())
}
return strings.Join(parts, s.param.Delimiters[0])
}
return fmt.Sprintf("%v", value)
}
// First pass: state-level template resolution for any runtime ref
// syntax the canvas supports, including single-brace legacy refs and
// iteration aliases like {item}/{index}.
if resolved, err := runtime.ResolveTemplateAuto(script, state); err == nil {
// iteration aliases like {item}/{index}. Resolve arrays before the
// generic template renderer can stringify them.
if !runtime.ContainsJinjaSyntax(script) {
resolved := true
merged := runtime.VarRefPattern.ReplaceAllStringFunc(script, func(match string) string {
ref := runtime.VarRefPattern.FindStringSubmatch(match)[1]
value, err := state.GetVar(ref)
if err != nil || value == nil {
resolved = false
return match
}
return formatValue(value)
})
if resolved {
script = merged
}
} else if resolved, err := runtime.ResolveTemplateAuto(script, state); err == nil {
script = resolved
}
@@ -332,7 +359,7 @@ func (s *StringTransformComponent) doMerge(_ context.Context, state *runtime.Can
} else {
value = ""
}
script = strings.ReplaceAll(script, placeholder, fmt.Sprintf("%v", value))
script = strings.ReplaceAll(script, placeholder, formatValue(value))
}
return map[string]any{"result": script}
}