diff --git a/CHANGELOG.md b/CHANGELOG.md index 337f57c..52dc2be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). +### Fixed + +- handle quoted strings containing single quotes (should always use double quotes) [#179](https://github.com/ufirstgroup/ymlr/issues/179), [#181](https://github.com/ufirstgroup/ymlr/pull/181) +- handle string with leading or trailing whitespaces [#180](https://github.com/ufirstgroup/ymlr/issues/180), [#181](https://github.com/ufirstgroup/ymlr/pull/181) + ## [5.1.0] - 2023-12-27 diff --git a/lib/ymlr/encode.ex b/lib/ymlr/encode.ex index 093ae82..3bf1b00 100644 --- a/lib/ymlr/encode.ex +++ b/lib/ymlr/encode.ex @@ -66,6 +66,7 @@ defmodule Ymlr.Encode do alias Ymlr.Encoder @quote_when_starts_with_strings [ + " ", # tag "!", # anchor @@ -120,7 +121,7 @@ defmodule Ymlr.Encode do @quote_when_contains_string [" #", ": "] - @quote_when_last_char ~c":" + @quote_when_last_char [?\s, ?:] @single_quote_when_exact [ "", @@ -317,6 +318,10 @@ defmodule Ymlr.Encode do end for data <- @quote_when_contains_string do + defp do_string_encoding_type(<>, :double_quoted) do + do_string_encoding_type(rest, :double_quoted) + end + defp do_string_encoding_type(<>, :maybe_double_quoted) do do_string_encoding_type(rest, :double_quoted) end @@ -326,8 +331,12 @@ defmodule Ymlr.Encode do end end - defp do_string_encoding_type(<>, _quotation) when char in @quote_when_last_char do - :single_quoted + defp do_string_encoding_type(<>, quotation) when char in @quote_when_last_char do + case quotation do + :double_quoted -> :double_quoted + :maybe_double_quoted -> :double_quoted + _ -> :single_quoted + end end defp do_string_encoding_type(<<_::utf8, rest::binary>>, quotation) do diff --git a/test/ymlr/encode_test.exs b/test/ymlr/encode_test.exs index 5fefa7e..aac8aa3 100644 --- a/test/ymlr/encode_test.exs +++ b/test/ymlr/encode_test.exs @@ -30,6 +30,21 @@ defmodule Ymlr.EncodeTest do # see http://blogs.perl.org/users/tinita/2018/03/strings-in-yaml---to-quote-or-not-to-quote.html + test "quoted strings - whitespace(s)" do + # only whitespace(s) + assert_identity_and_output(" ", ~S(' ')) + assert_identity(" ") + # leading whitespace(s) + assert_identity(" leading") + assert_identity(" leading") + assert_identity_and_output(" '", ~S(" '")) + # trailing whitespace(s) + assert_identity("trailing ") + assert_identity("trailing ") + assert_identity("a' ") + assert_identity_and_output("' ", ~S("' ")) + end + test "quoted strings - avoid type confusion" do assert_identity_and_output("yes", ~S('yes')) assert_identity_and_output("no", ~S('no')) @@ -122,6 +137,9 @@ defmodule Ymlr.EncodeTest do test "quoted strings - ends with colon" do assert_identity_and_output("some:entry:", ~S('some:entry:')) + # see https://github.com/ufirstgroup/ymlr/issues/179 + assert_identity_and_output("a'b:", ~S("a'b:")) + assert_identity_and_output("a'b':", ~S("a'b':")) end test "quoted strings - specialties inside the string" do @@ -131,6 +149,12 @@ defmodule Ymlr.EncodeTest do assert_identity_and_output("s'ome #entry", ~S("s'ome #entry")) end + # see https://github.com/ufirstgroup/ymlr/issues/179 + test "quoted strings - issue 179" do + assert_identity(~S{a'b': }) + assert_identity(~S{'': }) + end + test "quoted strings - tab char with and without quotes" do assert_identity_and_output("a\tb", ~s(a\tb)) assert_identity_and_output("!a\tb", ~s('!a\tb'))