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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use Svg.Keyed for the top level node #12

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
3 changes: 2 additions & 1 deletion elm.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -27,4 +28,4 @@
"direct": {},
"indirect": {}
}
}
}
5 changes: 5 additions & 0 deletions src/List/Extra.elm
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module List.Extra exposing (indexed)

indexed : List a -> List (Int, a)
indexed list =
List.indexedMap (\index value -> (index, value)) list
72 changes: 52 additions & 20 deletions src/Svg2Elm/Generator.elm
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
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)
Expand All @@ -21,38 +23,66 @@ 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 _ ->
" "

_ ->
", "

renderNode : ( Int, SvgNode ) -> String -> String
renderNode =
case mbKey of
Just key ->
\( 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 ]
in
List.foldl (\node b -> b ++ nodeJoin node ++ compileNode False node) ""
>> String.dropLeft 1
children
|> List.indexed
|> List.foldl renderNode ""
|> String.dropLeft 1


compileNode : Bool -> SvgNode -> String
compileNode attrs node =
compileNode : Maybe String -> Bool -> SvgNode -> String
compileNode mbKey attrs node =
case node of
SvgElement { name, attributes, children } ->
"Svg.node "
++ quote name
++ " (["
++ compileAttributes attributes
++ (if attrs then
"] ++ attrs) "

else
"]) "
)
++ "["
++ compileChildren children
++ "]"
String.concat
[ if Maybe.isJust mbKey then
"Svg.Keyed.node "

else
"Svg.node "
, quote name
, " (["
, compileAttributes attributes
, if attrs then
"] ++ attrs) "

else
"]) "
, "["
, compileChildren mbKey children
, "]"
]

SvgText text ->
"Svg.text(" ++ quote text ++ ")"
Expand All @@ -77,4 +107,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 = ")
)
1 change: 1 addition & 0 deletions src/svg2elm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export function generateModuleHeader(moduleName: string) {
return `module ${moduleName} exposing (..)

import Svg
import Svg.Keyed
import VirtualDom exposing (Attribute, attribute)
`;
}
Expand Down
Loading