Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix ID handling in toString #6

Merged
merged 4 commits into from Apr 5, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
53 changes: 47 additions & 6 deletions src/DotLang.elm
Expand Up @@ -36,7 +36,7 @@ Take a look at the grammar <https://www.graphviz.org/doc/info/lang.html>
import DoubleQuoteString as DQS
import Html.Parser exposing (Node(..), node, nodeToString)
import Parser exposing (..)
import Set
import Set exposing (Set)


{-| Parse a DOT string.
Expand Down Expand Up @@ -681,11 +681,11 @@ showId : ID -> String
showId id_ =
case id_ of
ID str ->
let
escaped =
String.replace "\"" "\\\"" str
in
if String.contains " " str || String.contains "\"" str then
if shouldBeQuoted str then
let
escaped =
String.replace "\"" "\\\"" str
in
"\"" ++ escaped ++ "\""

else
Expand All @@ -698,6 +698,47 @@ showId id_ =
String.fromFloat float


shouldBeQuoted : String -> Bool
shouldBeQuoted s =
String.isEmpty s || beginsWithADigit s || hasACharacterNotInWhiteList s


isInWhiteList : Char -> Bool
isInWhiteList char =
List.any identity
[ Char.isLower char
, Char.isUpper char
, '_' == char
, Char.isDigit char
, Set.member char asciiOctalFrom200To377
]


asciiOctalFrom200To377 : Set Char
asciiOctalFrom200To377 =
-- DOT says: "Any string of alphabetic ([a-zA-Z\200-\377]) characters"
-- \200-\377 in octal is \128-\255 in decimal according to this table:
-- https://www.autoitscript.com/autoit3/docs/appendix/ascii.htm
List.range 128 255
|> List.map Char.fromCode
|> Set.fromList


beginsWithADigit : String -> Bool
beginsWithADigit string =
case String.uncons string of
Just ( c, _ ) ->
Char.isDigit c

Nothing ->
False


hasACharacterNotInWhiteList : String -> Bool
hasACharacterNotInWhiteList =
String.any (isInWhiteList >> not)


showNodeId : NodeId -> String
showNodeId (NodeId id_ maybePort) =
showId id_
Expand Down
39 changes: 39 additions & 0 deletions tests/Main.elm
Expand Up @@ -767,4 +767,43 @@ testToString =
Expect.equal
(Result.map toString (fromString g))
(Ok g)
, test "can handle hex codes" <|
\_ ->
let
g =
String.join "\n"
[ "graph {"
, " color=\"#ffffff\""
, "}"
]
in
Expect.equal
(Result.map toString (fromString g))
(Ok g)
, test "can handle JSON" <|
\_ ->
let
g =
String.join "\n"
[ "graph {"
, " a -- \"{ \\\"key\\\": [ 123 ] }\""
, "}"
]
in
Expect.equal
(Result.map toString (fromString g))
(Ok g)
, test "can handle empty ID strings" <|
\_ ->
let
g =
String.join "\n"
[ "graph {"
, " a -- \"\""
, "}"
]
in
Expect.equal
(Result.map toString (fromString g))
(Ok g)
]