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.
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)
If the DSL isn't enough for your needs, you can also use one of those escape hatches to build a custom matcher:
customParam
to build a param extractor from a Parser instance, so it can be used with the DSL ;parserMatcher
, takes aParser Route
instance ;rawMatcher
, takes aString -> Maybe Route
function.
See elm-combine for more information on parsers.
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" ]
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.
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" ]
- Based on an original idea of jasonzoladz,
- Built with elm-combine, an excellent parser combinator library.