elm-route-parser
                                
                                
                                
                                    elm-route-parser copied to clipboard
                            
                            
                            
                        Route parser for Elm, based on parser combinators
Elm Route Parser
elm package install etaque/elm-route-parser
A typed route parser in Elm, with a nice DSL built on top of parser combinators. Designed to work well with path or hash signals from elm-history: just map an action on it and do a RouteParser.match to update your current route, then use this route to render the right view.
See elm-transit-router for a full featured SPA router compatible with this package.
Under the hood, it's just a list of matchers String -> Maybe Route, and the first match wins. For that, there is a DSL tailored to mimic path shapes, ensuring typesafety with the power of parser combinators without the surface complexity:
"/some/" int "/path"
If the dynamic param isn't parsable as an int, it won't match as an acceptable path for this route:
"/some/1/path" -- match!
"/some/wrong/path" -- no match
Note that you can create and use custom param parsers, and custom matchers.
Usage
DSL
Example:
import RouteParser exposing (..)
type Route
  = Home
  | Foo String
  | Bar Int
  | Baz Int String Int
matchers : List (Matcher Route)
matchers =
  [ static Home "/"
  , dyn1 Foo "/foo/" string ""
  , dyn2 (\id slug -> Bar id) "/bar/" int "-" string ""
  , dyn3 Baz "/baz/" int "/a/" string "/b/" int "/c"
  ]
-- static
match matchers "/" == Just Home
-- dyn1
match matchers "/foo/foo" == Just (Foo "foo")
-- dyn2
match matchers "/bar/12-some-slug" == Just (Bar 12)
match matchers "/bar/hey-some-slug" == Nothing
-- dyn3
match matchers "/baz/1/a/2/b/3/c" == Just (Baz 1 "2" 3)
Custom matchers
If the DSL isn't enough for your needs, you can also use one of those escape hatches to build a custom matcher:
customParamto build a param extractor from a Parser instance, so it can be used with the DSL ;parserMatcher, takes aParser Routeinstance ;rawMatcher, takes aString -> Maybe Routefunction.
See elm-combine for more information on parsers.
Route matching delegation
Use mapMatchers to delegate a bunch of routes to a component:
    -- global routing:
    type Route = Home | Admin AdminRoute
    matchers =
      [ static Home "/" ] ++ (mapMatchers Admin adminMatchers)
    -- can be delegated to a component without knowdedge of global routing:
    type AdminRoute = Dashboard | Users
    adminMatchers =
      [ static Dashboard "/admin", static Users "/admin/users" ]
Reverse routing
The reverse router has yet to be written manually:
toPath : Route -> String
toPath route =
  case route of
    Home -> "/"
    Foo s -> "/foo/" ++ s
    Bar i -> "/bar/" ++ (toString i)
    Baz i s j -> "/baz/" ++ (toString i) ++ "/a/" ++ s ++ (toString j) ++ "/c"
Glad to take any PR on that part, there is room for improvement.
Query string
A query string parser is also available under RouteParser.QueryString module:
import RouteParser.QueryString as QueryString
queryStringPart : String
queryStringPart =
  "?foo=1&bar=baz&bar=taz"
params : String -> Dict String (List String)
params = 
  QueryString.parse queryStringPart
  
-- Dict.get "foo" params == Just [ "1" ]
-- Dict.get "bar" params == Just [ "baz", "taz" ]
Credits
- Based on an original idea of jasonzoladz,
 - Built with elm-combine, an excellent parser combinator library.