Skip to content

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

@ltrzesniewski

Description

@ltrzesniewski

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:

if (style == ScalarStyle.Literal || style == ScalarStyle.Folded)
{
if (!scalarData.isBlockAllowed || flowLevel != 0 || isSimpleKeyContext)
{
style = ScalarStyle.DoubleQuoted;
}
}

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

if (space_break || special_characters)
{
scalarData.isFlowPlainAllowed = false;
scalarData.isBlockPlainAllowed = false;
scalarData.isSingleQuotedAllowed = false;
scalarData.isBlockAllowed = false;
}

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

if (!special_characters && !buffer.IsPrintable())
{
special_characters = true;
}

CR and LF are not considered printable:

internal static bool IsPrintable(char character)
{
return
(character >= '\x20' && character <= '\x7E') ||
character == '\x85' ||
(character >= '\xA0' && character <= '\xD7FF') ||
(character >= '\xE000' && character <= '\xFFFD');
}

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

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions