| Copyright | (C) 2016-2026 David M. Johnson |
|---|---|
| License | BSD3-style (see the file LICENSE) |
| Maintainer | David M. Johnson <code@dmj.io> |
| Stability | experimental |
| Portability | non-portable |
| Safe Haskell | None |
| Language | Haskell2010 |
Miso.Router
Description
Overview
Miso.Router provides a type-safe, bidirectional client-side router.
A Haskell sum type represents your application's routes; the Router
class encodes and decodes between that type and URL strings. The router
is used together with uriSub or
routerSub to react to browser navigation.
Approach 1 — Generic deriving (recommended)
{-# LANGUAGE DeriveGeneric, DeriveAnyClass, DerivingStrategies #-}
import GHC.Generics (Generic)
import Miso.Router
data Route
= Index -- "/"
| About -- "/about"
| User (Capture "id" Int) -- "/user/42"
| Search (QueryParam "q" MisoString) -- "/search?q=foo"
deriving stock (Show, Eq, Generic)
deriving anyclass Router
Decoding:
toRoute"/user/42" -- Right (User (Capture 42))toRoute"/search?q=hello" -- Right (Search (QueryParam (Just "hello")))
Encoding (type-safe links):
prettyRoute(User (Capture 42)) -- "/user/42" button_ [href_(User (Capture 42)) ] [ text "Profile" ]
Approach 2 — Manual instance
data Route = Widget Int deriving (Show, Eq) instanceRouterRoute where routeParser =routes[ Widget <$> (path"widget" *>capture) ] fromRoute (Widget n) = [toPath"widget",toCapturen ]
Generic naming rules
- Constructor name becomes the lowercase path segment:
About→/about,UserProfile→/user(first camel-case hump only). - The special name
Indexencodes the root path/. - The position of
CaptureandPathfields in the constructor determines their order in the URL path. The position ofQueryParamandQueryFlagdoes not matter.
URL types
Capturesym a- dynamic path segment —
Capture 42→/42 Pathsym- fixed path segment —
Path "foo"→/foo QueryParamsym a- optional query key —
QueryParam (Just 1)→?sym=1 QueryFlagsym- boolean query flag —
QueryFlag True→?sym Fragmentsym- hash fragment —
Fragment→#sym
Integration with history subscription
import Miso.Subscription.History (routerSub) subs :: [SubAction] subs = [routerSubRouteChanged ]
See also
- Miso.Subscription.History —
uriSub,routerSub,pushURI - Miso.Html.Property —
href_(plain string version)
Synopsis
- class Router route where
- fromRoute :: route -> [Token]
- toURI :: route -> URI
- route :: URI -> Either RoutingError route
- href_ :: route -> Attribute action
- prettyRoute :: route -> MisoString
- dumpURI :: route -> MisoString
- toRoute :: MisoString -> Either RoutingError route
- routeParser :: RouteParser route
- type RouteParser = ParserT URI [Token] []
- class GRouter (f :: k -> Type) where
- gFromRoute :: forall (route :: k). f route -> [Token]
- gRouteParser :: forall (route :: k). RouteParser (f route)
- newtype Capture (sym :: k) a = Capture a
- newtype Path (path :: Symbol) = Path MisoString
- newtype QueryParam (path :: Symbol) a = QueryParam (Maybe a)
- newtype QueryFlag (path :: Symbol) = QueryFlag Bool
- data Fragment (path :: Symbol) = Fragment
- data Token
- data URI = URI {}
- data RoutingError
- parseURI :: MisoString -> Either MisoString URI
- prettyURI :: URI -> MisoString
- prettyQueryString :: URI -> MisoString
- runRouter :: MisoString -> RouteParser route -> Either RoutingError route
- routes :: [RouteParser route] -> RouteParser route
- toQueryParam :: ToMisoString s => MisoString -> s -> Token
- toCapture :: ToMisoString string => string -> Token
- toPath :: MisoString -> Token
- emptyURI :: URI
- queryFlag :: forall (flag :: Symbol). KnownSymbol flag => RouteParser (QueryFlag flag)
- queryParam :: forall (param :: Symbol) a. (FromMisoString a, KnownSymbol param) => RouteParser (QueryParam param a)
- capture :: FromMisoString value => RouteParser value
- path :: MisoString -> RouteParser MisoString
- fragment :: MisoString -> RouteParser MisoString
- lexTokens :: MisoString -> Either LexerError [Token]
- tokensToURI :: [Token] -> URI
Classes
class Router route where Source #
Class used to facilitate routing for miso applications
Minimal complete definition
Nothing
Methods
fromRoute :: route -> [Token] Source #
toURI :: route -> URI Source #
Convert a 'Router route => route' into a URI
route :: URI -> Either RoutingError route Source #
Map a URI back to a route
href_ :: route -> Attribute action Source #
Convenience for specifying a URL as a hyperlink reference in View
prettyRoute :: route -> MisoString Source #
Route pretty printing
dumpURI :: route -> MisoString Source #
Route debugging
toRoute :: MisoString -> Either RoutingError route Source #
Route parsing from a MisoString
routeParser :: RouteParser route Source #
default routeParser :: (Generic route, GRouter (Rep route)) => RouteParser route Source #
class GRouter (f :: k -> Type) where Source #
Generic deriving for Router
Methods
gFromRoute :: forall (route :: k). f route -> [Token] Source #
gRouteParser :: forall (route :: k). RouteParser (f route) Source #
Instances
| GRouter (U1 :: k -> Type) Source # | |
Defined in Miso.Router Methods gFromRoute :: forall (route :: k). U1 route -> [Token] Source # gRouteParser :: forall (route :: k). RouteParser (U1 route) Source # | |
| (GRouter left, GRouter right) => GRouter (left :*: right :: k -> Type) Source # | |
Defined in Miso.Router Methods gFromRoute :: forall (route :: k). (left :*: right) route -> [Token] Source # gRouteParser :: forall (route :: k). RouteParser ((left :*: right) route) Source # | |
| (GRouter left, GRouter right) => GRouter (left :+: right :: k -> Type) Source # | |
Defined in Miso.Router Methods gFromRoute :: forall (route :: k). (left :+: right) route -> [Token] Source # gRouteParser :: forall (route :: k). RouteParser ((left :+: right) route) Source # | |
| (KnownSymbol name, GRouter next) => GRouter (C1 ('MetaCons name x y) next :: k -> Type) Source # | |
Defined in Miso.Router Methods gFromRoute :: forall (route :: k). C1 ('MetaCons name x y) next route -> [Token] Source # gRouteParser :: forall (route :: k). RouteParser (C1 ('MetaCons name x y) next route) Source # | |
| GRouter next => GRouter (D1 m next :: k -> Type) Source # | |
Defined in Miso.Router Methods gFromRoute :: forall (route :: k). D1 m next route -> [Token] Source # gRouteParser :: forall (route :: k). RouteParser (D1 m next route) Source # | |
| KnownSymbol frag => GRouter (K1 m (Fragment frag) :: k -> Type) Source # | |
Defined in Miso.Router Methods gFromRoute :: forall (route :: k). K1 m (Fragment frag) route -> [Token] Source # gRouteParser :: forall (route :: k). RouteParser (K1 m (Fragment frag) route) Source # | |
| KnownSymbol path => GRouter (K1 m (Path path) :: k -> Type) Source # | |
Defined in Miso.Router Methods gFromRoute :: forall (route :: k). K1 m (Path path) route -> [Token] Source # gRouteParser :: forall (route :: k). RouteParser (K1 m (Path path) route) Source # | |
| KnownSymbol flag => GRouter (K1 m (QueryFlag flag) :: k -> Type) Source # | |
Defined in Miso.Router Methods gFromRoute :: forall (route :: k). K1 m (QueryFlag flag) route -> [Token] Source # gRouteParser :: forall (route :: k). RouteParser (K1 m (QueryFlag flag) route) Source # | |
| (ToMisoString a, FromMisoString a, KnownSymbol param) => GRouter (K1 m (QueryParam param a) :: k -> Type) Source # | |
Defined in Miso.Router Methods gFromRoute :: forall (route :: k). K1 m (QueryParam param a) route -> [Token] Source # gRouteParser :: forall (route :: k). RouteParser (K1 m (QueryParam param a) route) Source # | |
| Router a => GRouter (K1 m a :: k -> Type) Source # | |
Defined in Miso.Router Methods gFromRoute :: forall (route :: k). K1 m a route -> [Token] Source # gRouteParser :: forall (route :: k). RouteParser (K1 m a route) Source # | |
| GRouter next => GRouter (S1 m next :: k -> Type) Source # | |
Defined in Miso.Router Methods gFromRoute :: forall (route :: k). S1 m next route -> [Token] Source # gRouteParser :: forall (route :: k). RouteParser (S1 m next route) Source # | |
| (FromMisoString a, ToMisoString a) => GRouter (K1 m (Capture sym a) :: k2 -> Type) Source # | |
Defined in Miso.Router Methods gFromRoute :: forall (route :: k2). K1 m (Capture sym a) route -> [Token] Source # gRouteParser :: forall (route :: k2). RouteParser (K1 m (Capture sym a) route) Source # | |
Types
newtype Capture (sym :: k) a Source #
Type used for representing capture variables
Constructors
| Capture a |
Instances
| (FromMisoString a, ToMisoString a) => GRouter (K1 m (Capture sym a) :: k2 -> Type) Source # | |
Defined in Miso.Router Methods gFromRoute :: forall (route :: k2). K1 m (Capture sym a) route -> [Token] Source # gRouteParser :: forall (route :: k2). RouteParser (K1 m (Capture sym a) route) Source # | |
| Show a => Show (Capture sym a) Source # | |
| Eq a => Eq (Capture sym a) Source # | |
| FromMisoString a => FromMisoString (Capture sym a) Source # | |
Defined in Miso.Router Methods fromMisoStringEither :: MisoString -> Either String (Capture sym a) Source # | |
| ToMisoString a => ToMisoString (Capture sym a) Source # | |
Defined in Miso.Router Methods toMisoString :: Capture sym a -> MisoString Source # | |
newtype Path (path :: Symbol) Source #
Type used for representing URL paths
Constructors
| Path MisoString |
Instances
| KnownSymbol path => GRouter (K1 m (Path path) :: k -> Type) Source # | |
Defined in Miso.Router Methods gFromRoute :: forall (route :: k). K1 m (Path path) route -> [Token] Source # gRouteParser :: forall (route :: k). RouteParser (K1 m (Path path) route) Source # | |
| IsString (Path path) Source # | |
Defined in Miso.Router Methods fromString :: String -> Path path # | |
| Show (Path path) Source # | |
| Eq (Path path) Source # | |
| ToMisoString (Path path) Source # | |
Defined in Miso.Router Methods toMisoString :: Path path -> MisoString Source # | |
newtype QueryParam (path :: Symbol) a Source #
Type used for representing query parameters
Constructors
| QueryParam (Maybe a) |
Instances
newtype QueryFlag (path :: Symbol) Source #
Type used for representing query flags
Instances
| KnownSymbol flag => GRouter (K1 m (QueryFlag flag) :: k -> Type) Source # | |
Defined in Miso.Router Methods gFromRoute :: forall (route :: k). K1 m (QueryFlag flag) route -> [Token] Source # gRouteParser :: forall (route :: k). RouteParser (K1 m (QueryFlag flag) route) Source # | |
| Show (QueryFlag path) Source # | |
| Eq (QueryFlag path) Source # | |
| KnownSymbol name => ToMisoString (QueryFlag name) Source # | |
Defined in Miso.Router Methods toMisoString :: QueryFlag name -> MisoString Source # | |
data Fragment (path :: Symbol) Source #
Type used for representing fragments
Constructors
| Fragment |
Instances
| KnownSymbol frag => GRouter (K1 m (Fragment frag) :: k -> Type) Source # | |
Defined in Miso.Router Methods gFromRoute :: forall (route :: k). K1 m (Fragment frag) route -> [Token] Source # gRouteParser :: forall (route :: k). RouteParser (K1 m (Fragment frag) route) Source # | |
| Show (Fragment path) Source # | |
| Eq (Fragment path) Source # | |
| KnownSymbol frag => ToMisoString (Fragment frag) Source # | |
Defined in Miso.Router Methods toMisoString :: Fragment frag -> MisoString Source # | |
A list of tokens are returned from a successful lex of a URI
Constructors
| QueryParamTokens [(MisoString, Maybe MisoString)] | |
| QueryParamToken MisoString (Maybe MisoString) | |
| CaptureOrPathToken MisoString | |
| FragmentToken MisoString | |
| IndexToken |
Instances
| Show Token Source # | |
| Eq Token Source # | |
| ToMisoString Token Source # | |
Defined in Miso.Router Methods toMisoString :: Token -> MisoString Source # | |
URI type. See the official specification
Constructors
| URI | |
Fields
| |
Instances
Errors
data RoutingError Source #
An error that can occur during lexing / parsing of a URI into a user-defined data type
Constructors
| ParseError MisoString [Token] | |
| AmbiguousParse MisoString [Token] | |
| LexError MisoString MisoString | |
| LexErrorEOF MisoString | |
| NoParses MisoString |
Instances
| Show RoutingError Source # | |
Defined in Miso.Router Methods showsPrec :: Int -> RoutingError -> ShowS # show :: RoutingError -> String # showList :: [RoutingError] -> ShowS # | |
| Eq RoutingError Source # | |
Defined in Miso.Router | |
Functions
parseURI :: MisoString -> Either MisoString URI Source #
URI parsing
prettyQueryString :: URI -> MisoString Source #
Pretty-prints a URI query string.
Manual Routing
Arguments
| :: MisoString | The raw URL string to parse |
| -> RouteParser route | Parser to apply against the tokenised URL |
| -> Either RoutingError route |
Smart constructor for building a RouteParser
data Route = Widget MisoString Int instance Router Route where routeParser = routes [ Widget <$> path "widget" <*> capture ] fromRoute (Widget path value) = [ toPath path, toCapture value ] router :: Router router => RouteParser router router = routes [ Widget <$> path "widget" <*> capture ] > Right (Widget "widget" 10)
routes :: [RouteParser route] -> RouteParser route Source #
Convenience for specifying multiple routes
Construction
Arguments
| :: ToMisoString s | |
| => MisoString | Query parameter key |
| -> s | Query parameter value |
| -> Token |
Smart constructor for building a QueryParamToken
toCapture :: ToMisoString string => string -> Token Source #
Smart constructor for building a capture variable
toPath :: MisoString -> Token Source #
Smart constructor for building a path fragment
Parser combinators
queryFlag :: forall (flag :: Symbol). KnownSymbol flag => RouteParser (QueryFlag flag) Source #
Query flag parser from a route
queryParam :: forall (param :: Symbol) a. (FromMisoString a, KnownSymbol param) => RouteParser (QueryParam param a) Source #
Query parameter parser from a route
capture :: FromMisoString value => RouteParser value Source #
Combinator for parsing a capture variable out of a URI
path :: MisoString -> RouteParser MisoString Source #
Combinator for parsing a path out of a URI
Lexing
lexTokens :: MisoString -> Either LexerError [Token] Source #
tokensToURI :: [Token] -> URI Source #
Converts a list of [Token] into an actual URI.