From 3c7bf04455dc10bdb81c7a12b4dd8b50be06ca86 Mon Sep 17 00:00:00 2001 From: gillchristian Date: Wed, 15 May 2024 12:56:03 +0200 Subject: [PATCH 1/4] Use Svg.Keyed for the top level node --- src/Svg2Elm/Generator.elm | 84 ++++++++++++++++++++++++++------------- src/svg2elm.ts | 1 + 2 files changed, 58 insertions(+), 27 deletions(-) diff --git a/src/Svg2Elm/Generator.elm b/src/Svg2Elm/Generator.elm index 0f641cc..0767988 100644 --- a/src/Svg2Elm/Generator.elm +++ b/src/Svg2Elm/Generator.elm @@ -21,9 +21,10 @@ compileAttributes = (\( name, val ) -> "attribute " ++ quote name ++ " " ++ quote val) -compileChildren : List SvgNode -> String -compileChildren = +compileChildren : Maybe String -> List SvgNode -> String +compileChildren mbKey children = let + nodeJoin : SvgNode -> String nodeJoin node = case node of SvgComment _ -> @@ -31,33 +32,60 @@ compileChildren = _ -> ", " + + renderNode : SvgNode -> String -> String + renderNode = + case mbKey of + Just key -> + \node b -> String.concat [ b, nodeJoin node, "( ", key, ",", compileNode Nothing True node, " )" ] + + Nothing -> + \node b -> String.concat [ b, nodeJoin node, compileNode Nothing True node ] in - List.foldl (\node b -> b ++ nodeJoin node ++ compileNode False node) "" - >> String.dropLeft 1 - - -compileNode : Bool -> SvgNode -> String -compileNode attrs node = - case node of - SvgElement { name, attributes, children } -> - "Svg.node " - ++ quote name - ++ " ([" - ++ compileAttributes attributes - ++ (if attrs then - "] ++ attrs) " - - else - "]) " - ) - ++ "[" - ++ compileChildren children - ++ "]" - - SvgText text -> + children + |> List.foldl renderNode "" + |> String.dropLeft 1 + + +compileNode : Maybe String -> Bool -> SvgNode -> String +compileNode mbKey attrs node = + case ( node, mbKey ) of + ( SvgElement { name, attributes, children }, Just key ) -> + String.concat + [ "Svg.Keyed.node " + , quote name + , " ([" + , compileAttributes attributes + , if attrs then + "] ++ attrs) " + + else + "]) " + , "[" + , compileChildren (Just key) children + , "]" + ] + + ( SvgElement { name, attributes, children }, Nothing ) -> + String.concat + [ "Svg.node " + , quote name + , " ([" + , compileAttributes attributes + , if attrs then + "] ++ attrs) " + + else + "]) " + , "[" + , compileChildren Nothing children + , "]" + ] + + ( SvgText text, _ ) -> "Svg.text(" ++ quote text ++ ")" - SvgComment comment -> + ( SvgComment comment, _ ) -> "{-" ++ comment ++ "-}" @@ -77,4 +105,6 @@ compileFunction name code = in parseToNode fixedCode |> Result.map - (compileNode True >> (++) (fnName ++ " : List (Attribute msg) -> Svg.Svg msg\n" ++ fnName ++ " attrs = ")) + (compileNode (Just fnName) True + >> (++) (fnName ++ " : List (Attribute msg) -> Svg.Svg msg\n" ++ fnName ++ " attrs = ") + ) diff --git a/src/svg2elm.ts b/src/svg2elm.ts index 37d3932..c79d86f 100644 --- a/src/svg2elm.ts +++ b/src/svg2elm.ts @@ -39,6 +39,7 @@ export function generateModuleHeader(moduleName: string) { return `module ${moduleName} exposing (..) import Svg +import Svg.Keyed import VirtualDom exposing (Attribute, attribute) `; } From f4564de669229632a3286ecef42338f92c99165d Mon Sep 17 00:00:00 2001 From: gillchristian Date: Wed, 15 May 2024 12:59:38 +0200 Subject: [PATCH 2/4] Simplify pattern matching --- elm.json | 3 ++- src/Svg2Elm/Generator.elm | 29 +++++++++-------------------- 2 files changed, 11 insertions(+), 21 deletions(-) diff --git a/elm.json b/elm.json index 4a68ecd..600abb5 100644 --- a/elm.json +++ b/elm.json @@ -7,6 +7,7 @@ "dependencies": { "direct": { "Garados007/elm-svg-parser": "1.0.0", + "elm-community/maybe-extra": "5.3.0", "elm/core": "1.0.4", "elm/json": "1.1.3", "elm/regex": "1.0.0", @@ -27,4 +28,4 @@ "direct": {}, "indirect": {} } -} \ No newline at end of file +} diff --git a/src/Svg2Elm/Generator.elm b/src/Svg2Elm/Generator.elm index 0767988..8f9d7cc 100644 --- a/src/Svg2Elm/Generator.elm +++ b/src/Svg2Elm/Generator.elm @@ -3,6 +3,7 @@ module Svg2Elm.Generator exposing (compileFunction) import Regex import String.Case exposing (toCamelCaseLower) import SvgParser exposing (SvgAttribute, SvgNode(..), parseToNode) +import Maybe.Extra as Maybe quote : String -> String @@ -49,26 +50,14 @@ compileChildren mbKey children = compileNode : Maybe String -> Bool -> SvgNode -> String compileNode mbKey attrs node = - case ( node, mbKey ) of - ( SvgElement { name, attributes, children }, Just key ) -> + case node of + SvgElement { name, attributes, children } -> String.concat - [ "Svg.Keyed.node " - , quote name - , " ([" - , compileAttributes attributes - , if attrs then - "] ++ attrs) " + [ if Maybe.isJust mbKey then + "Svg.Keyed.node " else - "]) " - , "[" - , compileChildren (Just key) children - , "]" - ] - - ( SvgElement { name, attributes, children }, Nothing ) -> - String.concat - [ "Svg.node " + "Svg.node " , quote name , " ([" , compileAttributes attributes @@ -78,14 +67,14 @@ compileNode mbKey attrs node = else "]) " , "[" - , compileChildren Nothing children + , compileChildren mbKey children , "]" ] - ( SvgText text, _ ) -> + SvgText text -> "Svg.text(" ++ quote text ++ ")" - ( SvgComment comment, _ ) -> + SvgComment comment -> "{-" ++ comment ++ "-}" From c788cd19e644b5a5d7392d929bd75937238098fe Mon Sep 17 00:00:00 2001 From: gillchristian Date: Wed, 15 May 2024 13:12:58 +0200 Subject: [PATCH 3/4] Add index to key --- src/List/Extra.elm | 5 +++++ src/Svg2Elm/Generator.elm | 21 +++++++++++++++++---- 2 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 src/List/Extra.elm diff --git a/src/List/Extra.elm b/src/List/Extra.elm new file mode 100644 index 0000000..3f69ebf --- /dev/null +++ b/src/List/Extra.elm @@ -0,0 +1,5 @@ +module List.Extra exposing (indexed) + +indexed : List a -> List (Int, a) +indexed list = + List.indexedMap (\index value -> (index, value)) list diff --git a/src/Svg2Elm/Generator.elm b/src/Svg2Elm/Generator.elm index 8f9d7cc..324701c 100644 --- a/src/Svg2Elm/Generator.elm +++ b/src/Svg2Elm/Generator.elm @@ -1,9 +1,10 @@ module Svg2Elm.Generator exposing (compileFunction) +import List.Extra as List +import Maybe.Extra as Maybe import Regex import String.Case exposing (toCamelCaseLower) import SvgParser exposing (SvgAttribute, SvgNode(..), parseToNode) -import Maybe.Extra as Maybe quote : String -> String @@ -34,16 +35,28 @@ compileChildren mbKey children = _ -> ", " - renderNode : SvgNode -> String -> String + renderNode : ( Int, SvgNode ) -> String -> String renderNode = case mbKey of Just key -> - \node b -> String.concat [ b, nodeJoin node, "( ", key, ",", compileNode Nothing True node, " )" ] + \( i, node ) b -> + String.concat + [ b + , nodeJoin node + , "( " + , key + , "-" + , String.fromInt i + , "," + , compileNode Nothing True node + , " )" + ] Nothing -> - \node b -> String.concat [ b, nodeJoin node, compileNode Nothing True node ] + \( _, node ) b -> String.concat [ b, nodeJoin node, compileNode Nothing True node ] in children + |> List.indexed |> List.foldl renderNode "" |> String.dropLeft 1 From d709699fccc4584af4c006b5245361e7f70c1871 Mon Sep 17 00:00:00 2001 From: gillchristian Date: Wed, 15 May 2024 13:13:11 +0200 Subject: [PATCH 4/4] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7fa0a8a..9daa913 100644 --- a/README.md +++ b/README.md @@ -39,10 +39,11 @@ $ svg2elm --module Acme.Icons chevron.svg > Acme/Icons.elm module Acme.Icons exposing (..) import Svg +import Svg.Keyed import VirtualDom exposing (Attribute, attribute) chevron : List (Attribute msg) -> Svg.Svg msg -chevron attrs = Svg.node "svg" ([attribute "xmlns" "http://www.w3.org/2000/svg", attribute "viewBox" "0 0 100 100"] ++ attrs) [ Svg.node "line" ([attribute "x1" "1", attribute "y1" "1", attribute "x2" "50", attribute "y2" "50", attribute "stroke-linecap" "round"]) [], Svg.node "line" ([attribute "x1" "50", attribute "y1" "50", attribute "x2" "1", attribute "y2" "99", attribute "stroke-linecap" "round"]) []] +chevron attrs = Svg.Keyed.node "svg" ([attribute "xmlns" "http://www.w3.org/2000/svg", attribute "viewBox" "0 0 100 100"] ++ attrs) [("chevron-1", Svg.node "line" ([attribute "x1" "1", attribute "y1" "1", attribute "x2" "50", attribute "y2" "50", attribute "stroke-linecap" "round"]) [], Svg.node "line" ([attribute "x1" "50", attribute "y1" "50", attribute "x2" "1", attribute "y2" "99", attribute "stroke-linecap" "round"]) [])] ``` We are now ready to embed the icon in our app! Since the generated function returns an [Svg](https://package.elm-lang.org/packages/elm/svg/latest/Svg#Svg) node, we can use it like any other element: