From 6d56ac8027652b84982b5ec70b2c6f02c32a435b Mon Sep 17 00:00:00 2001 From: Dustin Spicuzza Date: Thu, 21 Aug 2025 02:19:16 -0400 Subject: [PATCH] marshal: don't escape quotes unnecessarily (#991) Only 3 consecutive quotation marks need to be quoted. We choose to quote all quotation marks in a sequence if there are 3 or more consecutive present. Fixes #990 --------- Co-authored-by: Thomas Pelletier --- marshaler.go | 18 ++++++++++++++++-- marshaler_test.go | 48 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/marshaler.go b/marshaler.go index 161acd9..7cf2602 100644 --- a/marshaler.go +++ b/marshaler.go @@ -517,12 +517,26 @@ func (enc *Encoder) encodeQuotedString(multiline bool, b []byte, v string) []byt del = 0x7f ) - for _, r := range []byte(v) { + bv := []byte(v) + for i := 0; i < len(bv); i++ { + r := bv[i] switch r { case '\\': b = append(b, `\\`...) case '"': - b = append(b, `\"`...) + if multiline { + // Quotation marks do not need to be quoted in multiline strings unless + // it contains 3 consecutive. If 3+ quotes appear, quote all of them + // because it's visually better + if i+2 > len(bv) || bv[i+1] != '"' || bv[i+2] != '"' { + b = append(b, r) + } else { + b = append(b, `\"\"\"`...) + i += 2 + } + } else { + b = append(b, `\"`...) + } case '\b': b = append(b, `\b`...) case '\f': diff --git a/marshaler_test.go b/marshaler_test.go index 9c069a0..b8d8134 100644 --- a/marshaler_test.go +++ b/marshaler_test.go @@ -387,6 +387,54 @@ name = 'Alice' expected: `A = """ hello world""" +`, + }, + { + desc: "multi-line quotation", + v: struct { + A string `toml:",multiline"` + }{ + A: "hello\n\"world\"", + }, + expected: `A = """ +hello +"world"""" +`, + }, + { + desc: "multi-line triple quotation", + v: struct { + A string `toml:",multiline"` + }{ + A: "hello\n\"\"\"world\"", + }, + expected: `A = """ +hello +\"\"\"world"""" +`, + }, + { + desc: "multi-line triple quotation", + v: struct { + A string `toml:",multiline"` + }{ + A: "hello\n\"world\"\"\"", + }, + expected: `A = """ +hello +"world\"\"\"""" +`, + }, + { + desc: "multi-line sextuple quotation", + v: struct { + A string `toml:",multiline"` + }{ + A: "hello\n\"\"\"\"\"\"world\"", + }, + expected: `A = """ +hello +\"\"\"\"\"\"world"""" `, }, {