xoofx / SharpYaml

SharpYaml is a .NET library for YAML compatible with CoreCLR
Other
336 stars 61 forks source link

Multiline strings are not emitted in the literal/folded style #98

Open ltrzesniewski opened 2 years ago

ltrzesniewski commented 2 years ago

I noticed that SharpYaml doesn't emit multiline strings in the literal or folded style.

At first, I thought I missed a setting, but after digging a bit in the code this seems unintentional:

First, here's a repro to show what I mean:

using System;
using System.Collections.Generic;

namespace ConsoleApp;

public static class Program
{
    public static void Main()
    {
        var data = new Dictionary<string, string> { { "Key", "Foo\r\nBar" } };

        Console.WriteLine(new YamlDotNet.Serialization.SerializerBuilder().Build().Serialize(data));
        Console.WriteLine("---");
        Console.WriteLine(new SharpYaml.Serialization.Serializer(new() { EmitTags = false }).Serialize(data));
    }
}

Output:

Key: >-
  Foo

  Bar

---
Key: "Foo\r\nBar"

Bonus points if SharpYaml could use literal style by default instead: 🙂

Key: |-
  Foo
  Bar

I suppose you may want to add a setting to tell if the serialized value needs to be round-trippable regarding the \r character, as YAML would normalize the line break to \n on deserialization.


Here's what happens:

The following code turns ScalarStyle.Folded into ScalarStyle.DoubleQuoted when isBlockAllowed is false:

https://github.com/xoofx/SharpYaml/blob/3105d16b39f83997857d997fc8d3649ca3c9a0d6/src/SharpYaml/Emitter.cs#L1524-L1530

Here, isBlockAllowed is set to false when special_characters is true:

https://github.com/xoofx/SharpYaml/blob/3105d16b39f83997857d997fc8d3649ca3c9a0d6/src/SharpYaml/Emitter.cs#L549-L555

And here, special_characters is set to true when !buffer.IsPrintable():

https://github.com/xoofx/SharpYaml/blob/3105d16b39f83997857d997fc8d3649ca3c9a0d6/src/SharpYaml/Emitter.cs#L462-L465

CR and LF are not considered printable:

https://github.com/xoofx/SharpYaml/blob/3105d16b39f83997857d997fc8d3649ca3c9a0d6/src/SharpYaml/Emitter.cs#L1110-L1117

I'm not sure at which point a change would need to be applied. YamlDotNet has a different logic for setting isBlockAllowed to false.