lydell / elm-app-url / AppUrl

URLs for applications.

Types


type alias AppUrl =
{ path : List String
, queryParameters : QueryParameters
, fragment : Maybe String 
}

You might recognize this diagram from the core Url type documentation:

  https://example.com:8042/over/there?name=ferret#nose
  \___/   \______________/\_________/ \_________/ \__/
    |            |            |            |        |
  scheme     authority       path        query   fragment

AppUrl represents only path + query + fragment:

  https://example.com:8042/over/there?name=ferret#nose
                          \__________________________/
                                        |
                                     AppUrl

That’s the part you’ll work the most with in your app.

An AppUrl is “more parsed“ than Url (where everything is a string):

Each path segment, query parameter key, query parameter value and the fragment are all percent decoded, so you never need to think about that. For example, %20 is turned into a space and %2F is turned into a slash.

You can think of Url as the type you get from Elm when using Browser.application. From it you can create an AppUrl, and that’s what you’ll use when parsing which page you’re on and when creating links.

Different ways of creating an AppUrl:


type alias QueryParameters =
Dict String (List String)

A dict of the query parameters, with keys mapped to the values. The same key might be given more than once, so each key is mapped to a list of values.

Get all values of a key:

Dict.get "myParam" url.queryParameters

Get the first value:

Dict.get "myParam" url.queryParameters |> Maybe.andThen List.head

Get the last value:

Dict.get "myParam" url.queryParameters |> Maybe.andThen List.Extra.last

Create query parameters:

Dict.fromList
    [ ( "myRequiredParam", [ "myValue" ] )

    -- Parameters set to the empty list are omitted.
    , ( "myOptionalParam", Maybe.Extra.toList someMaybeString )
    ]

See also choosing a query parameter and query parameter parsing for extra details.

Create

fromUrl : Url -> AppUrl

Turn a Url from elm/url into an AppUrl.

This removes one trailing slash from the end of the path (if any), for convenience. For example, /one/two and /one/two/ are both turned into [ "one", "two" ].

Some sites use a trailing slash, some don’t. Users don’t know what to use where. This lets you support both. It’s up to you if you want to update the URL in the location bar of the browser to a canonical version.

Note: You can add an empty string at the end of the path, like [ "one", "two", "" ] if you want to create a string with a trailing slash.

Example:

    AppUrl.fromUrl
        { protocol = Url.Https
        , host = "example.com"
        , port_ = Nothing
        , path = "/my/path"
        , query = Just "my=parameter"
        , fragment = Just "my-fragment"
        }
        --> { path = [ "my", "path" ]
        --  , queryParameters = Dict.singleton "my" [ "parameter" ]
        --  , fragment = Just "my-fragment"
        --  }

fromPath : List String -> AppUrl

Convenience function for creating an AppUrl from just a path, when you don’t need any query parameters or fragment.

It’s nothing more than this helper function:

fromPath : List String -> AppUrl
fromPath path =
    { path = path
    , queryParameters = Dict.empty
    , fragment = Nothing
    }

Example:

AppUrl.fromPath [ "my", "path" ]
--> { path = [ "my", "path" ], queryParameters = Dict.empty, fragment = Nothing }

Stringify

toString : AppUrl -> String

Turn an AppUrl into a string.

AppUrl.toString
    { path = [ "my", "path" ]
    , queryParameters = Dict.singleton "my" [ "parameter" ]
    , fragment = Just "my-fragment"
    }
    --> "/my/path?my=parameter#my-fragment"

Each path segment, query parameter key, query parameter value and the fragment are all percent encoded, but very minimally. See escaping and plus and space for details.

See also Full and relative URLs.

Parse

Are you looking for functions to parse routes in your app? There are none! The idea is to use good old pattern matching on .path. See the README example for inspiration.