diff --git a/marshaler.go b/marshaler.go index 161acd93..7cf26024 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 9c069a04..b8d81347 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"""" `, }, {