diff --git a/src/Data/Aeson/Yaml.hs b/src/Data/Aeson/Yaml.hs index c9070c3..d1388a4 100644 --- a/src/Data/Aeson/Yaml.hs +++ b/src/Data/Aeson/Yaml.hs @@ -124,6 +124,8 @@ encodeText canMultiline alwaysQuote level s | canMultiline && "\n" `Text.isSuffixOf` s = encodeLines level (Text.lines s) -- s is a number, date, or boolString; single-quote | Text.all isNumberOrDateRelated s || isBoolString = singleQuote + -- s is a cird; single-quote + | isDigit headS && Text.all isCIDR tailS = singleQuote -- s should be quoted, AND s is not unsafe; single-quote | alwaysQuote && unquotable = singleQuote -- s should be quoted, OR s might be unsafe; double-quote @@ -134,6 +136,7 @@ encodeText canMultiline alwaysQuote level s noQuote = b (Text.Encoding.encodeUtf8 s) singleQuote = bs "'" <> noQuote <> bs "'" headS = Text.head s + tailS = Text.tail s unquotable -- s is unquotable if all are True = s /= "" && -- s is not empty @@ -152,6 +155,7 @@ encodeText canMultiline alwaysQuote level s (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '/' || c == '_' || c == '.' || c == '=' isNumberOrDateRelated c = isDigit c || c == '.' || c == 'e' || c == '-' + isCIDR c = isDigit c || c == '.' || c == '/' isAllowed c = isSafeAscii c || c == '-' || c == ':' || c == ' ' encodeLines :: Int -> [Text] -> Builder diff --git a/test/Test/Data/Aeson/Yaml.hs b/test/Test/Data/Aeson/Yaml.hs index 55c5fc4..8ae9d02 100644 --- a/test/Test/Data/Aeson/Yaml.hs +++ b/test/Test/Data/Aeson/Yaml.hs @@ -30,7 +30,7 @@ data TestCase = testCases :: [TestCase] testCases = - [tcDataTypes, tcNestedListsAndObjects, tcQuoted, tcEmptyList, tcHelloWorld] + [tcDataTypes, tcNestedListsAndObjects, tcQuoted, tcNetworkQuote, tcEmptyList, tcHelloWorld] tcEmptyList :: TestCase tcEmptyList = @@ -132,6 +132,7 @@ tcNestedListsAndObjects = { "command": [ "/data/bin/foo", + "/42", "--port=7654" ], "image": "ubuntu:latest", @@ -180,6 +181,7 @@ spec: containers: - command: - /data/bin/foo + - /42 - "--port=7654" image: ubuntu:latest name: "{{ .Release.Name }}-container" @@ -209,6 +211,24 @@ tcQuoted = , tcAlwaysQuote = True } +tcNetworkQuote :: TestCase +tcNetworkQuote = + TestCase + { tcName = "Network CIDR single quote" + , tcInput = + [s| +{ "ip": "127.0.0.1" +, "net": "127.0.0.1/8" +} +|] + , tcOutput = + [s|ip: '127.0.0.1' +net: '127.0.0.1/8' +|] + , tcAlwaysQuote = False + } + + tcHelloWorld :: TestCase tcHelloWorld = TestCase @@ -225,7 +245,7 @@ tcHelloWorld = } } ] - + } } |]