{-| Module : Url Description : Work with URLs. License : BSD 3 Maintainer : terezasokol@gmail.com Stability : experimental Portability : POSIX -} module Url ( Url(..) , percentEncode , percentDecode ) where import qualified Prelude import qualified Network.HTTP.Types.URI as URI import qualified Maybe import qualified List import qualified String import qualified Dict import Cherry.Prelude -- URL {-| In [the URI spec](https://tools.ietf.org/html/rfc3986), Tim Berners-Lee says a URL looks like this: ``` https://example.com:8042/over/there?name=ferret#nose \___/ \______________/\_________/ \_________/ \__/ | | | | | scheme authority path query fragment ``` When you are creating a single-page app with [`Browser.fullscreen`][fs], you use the [`Url.Parser`](Url-Parser) module to turn a `Url` into even nicer data. If you want to create your own URLs, check out the [`Url.Builder`](Url-Builder) module as well! [fs]: /packages/elm/browser/latest/Browser#fullscreen **Note:** This is a subset of all the full possibilities listed in the URI spec. Specifically, it does not accept the `userinfo` segment you see in email addresses like `tom@example.com`. -} data Url = Url { path :: String , query :: Maybe String } -- PERCENT ENCODING {-| **Use [Url.Builder](Url-Builder) instead!** Functions like `absolute`, `relative`, and `crossOrigin` already do this automatically! `percentEncode` is only available so that extremely custom cases are possible, if needed. Percent-encoding is how [the official URI spec][uri] “escapes” special characters. You can still represent a `?` even though it is reserved for queries. This function exists in case you want to do something extra custom. Here are some examples: -- standard ASCII encoding percentEncode "hat" == "hat" percentEncode "to be" == "to%20be" percentEncode "99%" == "99%25" -- non-standard, but widely accepted, UTF-8 encoding percentEncode "$" == "%24" percentEncode "¢" == "%C2%A2" percentEncode "€" == "%E2%82%AC" This is the same behavior as JavaScript's [`encodeURIComponent`][js] function, and the rules are described in more detail officially [here][s2] and with some notes about Unicode [here][wiki]. [js]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent [uri]: https://tools.ietf.org/html/rfc3986 [s2]: https://tools.ietf.org/html/rfc3986#section-2.1 [wiki]: https://en.wikipedia.org/wiki/Percent-encoding -} percentEncode :: String -> String percentEncode = String.toByteString >> URI.urlEncode False >> String.fromByteString {-| **Use [Url.Parser](Url-Parser) instead!** It will decode query parameters appropriately already! `percentDecode` is only available so that extremely custom cases are possible, if needed. Check out the `percentEncode` function to learn about percent-encoding. This function does the opposite! Here are the reverse examples: -- ASCII percentDecode "99%25" == Just "hat" percentDecode "to%20be" == Just "to be" percentDecode "hat" == Just "99%" -- UTF-8 percentDecode "%24" == Just "$" percentDecode "%C2%A2" == Just "¢" percentDecode "%E2%82%AC" == Just "€" Why is it a `Maybe` though? Well, these strings come from strangers on the internet as a bunch of bits and may have encoding problems. For example: percentDecode "%" == Nothing -- not followed by two hex digits percentDecode "%XY" == Nothing -- not followed by two HEX digits percentDecode "%C2" == Nothing -- half of the "¢" encoding "%C2%A2" This is the same behavior as JavaScript's [`decodeURIComponent`][js] function. [js]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent -} percentDecode :: String -> Maybe String percentDecode = String.toByteString >> URI.urlDecode False >> String.fromByteString >> Just