From d0796891652fec69515b86e930ea558ed77f03ef Mon Sep 17 00:00:00 2001 From: Tristan Cartledge Date: Fri, 19 Jun 2026 15:48:45 +1000 Subject: [PATCH] fix: quote TOON array elements containing semicolons --- oq/format.go | 19 +++++++++++++++++-- oq/format_test.go | 18 ++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 oq/format_test.go diff --git a/oq/format.go b/oq/format.go index a3d24ac..056bce4 100644 --- a/oq/format.go +++ b/oq/format.go @@ -350,12 +350,24 @@ func toonValue(v expr.Value) string { case expr.KindBool: return strconv.FormatBool(v.Bool) case expr.KindArray: - return toonEscape(strings.Join(v.Arr, ";")) + return toonArrayValue(v.Arr) default: return "null" } } +func toonArrayValue(values []string) string { + parts := make([]string, len(values)) + for i, value := range values { + if strings.Contains(value, ";") { + parts[i] = toonQuote(value) + continue + } + parts[i] = toonEscape(value) + } + return strings.Join(parts, ";") +} + // toonEscape quotes a string if it needs escaping for TOON format. // A string must be quoted if it: is empty, contains comma/colon/quote/backslash/ // brackets/braces/control chars, has leading/trailing whitespace, or matches @@ -387,7 +399,10 @@ func toonEscape(s string) string { if !needsQuote { return s } - // Quote with escaping + return toonQuote(s) +} + +func toonQuote(s string) string { var sb strings.Builder sb.WriteByte('"') for _, ch := range s { diff --git a/oq/format_test.go b/oq/format_test.go new file mode 100644 index 0000000..3f8653e --- /dev/null +++ b/oq/format_test.go @@ -0,0 +1,18 @@ +package oq + +import ( + "testing" + + "github.com/speakeasy-api/openapi/oq/expr" + "github.com/stretchr/testify/assert" +) + +func TestToonValue_ArrayEscapesSemicolonElements(t *testing.T) { + t.Parallel() + + value := expr.ArrayVal([]string{"v1;deprecated", "v2;current"}) + + encoded := toonValue(value) + + assert.Equal(t, `"v1;deprecated";"v2;current"`, encoded, "array elements containing the delimiter should be quoted individually") +}