jpsim / Yams

A Sweet and Swifty YAML parser.
https://jpsim.com/Yams
MIT License
1.12k stars 144 forks source link

Strings with newlines should be encoded as multiline literals #405

Closed tejassharma96 closed 6 months ago

tejassharma96 commented 9 months ago

This code:

let testYaml = #"""
script:
  - |
    if [[ some test ]]; then
      echo "Hello world!"
    fi
"""#
let loaded = try Yams.load(yaml: testYaml) as? [String: Any]
print(loaded as Any)

prints

Optional(["script": ["if [[ some test ]]; then\n  echo \"Hello world!\"\nfi"]])

But when I try to encode something with newlines:

let dump = try Yams.dump(object: loaded)
print(dump)

prints

script:
- "if [[ some test ]]; then\n  echo \"Hello world!\"\nfi"

instead of using a multiline literal, it instead encodes them as \n. This is confusing, since Yams handles parsing these fine, but is unable to handle encoding them. If you'd like to maintain the current behaviour, I'd suggested adding something like this to Emitter.Options:

enum NewLineHandlingStrategy {
    /// Encode newlines in strings as \n
    case escapeNewlines
    /// Encode newlines in strings with a literal block, ie |
    case literal
    /// Encode newlines in strings with a foided block, ie >
    case folded
}

Here's a reference on these

Maxatma commented 6 months ago
/// Create `Emitter.Options` with the specified values.
    ///
    /// - parameter canonical:     Set if the output should be in the "canonical" format described in the YAML
    ///                            specification.
    /// - parameter indent:        Set the indentation value.
    /// - parameter width:         Set the preferred line width. -1 means unlimited.
    /// - parameter allowUnicode:  Set if unescaped non-ASCII characters are allowed.
    /// - parameter lineBreak:     Set the preferred line break.
    /// - parameter explicitStart: Explicit document start `---`.
    /// - parameter explicitEnd:   Explicit document end `...`.
    /// - parameter version:       The `%YAML` directive value or nil.
    /// - parameter sortKeys:      Set if emitter should sort keys in lexicographic order.
    /// - parameter sequenceStyle: Set the style for sequences (arrays / lists)
    /// - parameter mappingStyle:  Set the style for mappings (dictionaries)
    public init(canonical: Bool = false, indent: Int = 0, width: Int = 0, allowUnicode: Bool = false,
                lineBreak: Emitter.LineBreak = .ln, version: (major: Int, minor: Int)? = nil,
                sortKeys: Bool = false, sequenceStyle: Node.Sequence.Style = .any,
                mappingStyle: Node.Mapping.Style = .any, newLineScalarStyle: Node.Scalar.Style = .any) {

Parameters list comments could be updated to have newLineScalarStyle info 🙂