Skip to content

Commit

Permalink
Implement encoding and decoding functions (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
thomashoneyman authored Dec 16, 2020
1 parent 00e6dfc commit 5edccd3
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 14 deletions.
2 changes: 1 addition & 1 deletion spago.dhall
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{ name = "js-uri"
, dependencies = [ "console", "effect", "psci-support" ]
, dependencies = [ "assert", "effect", "functions", "maybe", "psci-support" ]
, packages = ./packages.dhall
, sources = [ "src/**/*.purs", "test/**/*.purs" ]
}
41 changes: 41 additions & 0 deletions src/JSURI.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
"use strict";

// A helper which transforms the result ofencodeURIComponent to be compliant
// with RFC3896, as described in the MDN documentation here:
//
// https://web.archive.org/web/20201206001047/https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent
function toRFC3896(input) {
return input.replace(/[!'()*]/g, function (c) {
return "%" + c.charCodeAt(0).toString(16);
});
}

exports._encodeURIComponent = function encode(fail, succeed, input) {
try {
return succeed(toRFC3896(encodeURIComponent(input)));
} catch (err) {
return fail(err);
}
};

exports._encodeFormURLComponent = function encode(fail, succeed, input) {
try {
return succeed(toRFC3896(encodeURIComponent(input)).replace(/%20/g, "+"));
} catch (err) {
return fail(err);
}
};

function _decodeURIComponent(fail, succeed, input) {
try {
return succeed(decodeURIComponent(input));
} catch (err) {
return fail(err);
}
}

exports._decodeURIComponent = _decodeURIComponent;

exports._decodeFormURLComponent = function encode(fail, succeed, input) {
return _decodeURIComponent(fail, succeed, input.replace(/\+/g, " "));
};
89 changes: 89 additions & 0 deletions src/JSURI.purs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
module JSURI
( encodeURIComponent
, encodeFormURLComponent
, decodeURIComponent
, decodeFormURLComponent
) where

import Prelude

import Data.Function.Uncurried (Fn3, runFn3)
import Data.Maybe (Maybe(..))

foreign import _encodeURIComponent :: Fn3 (String -> Maybe String) (String -> Maybe String) String (Maybe String)

-- | URI-encode a string according to RFC3896. Implemented using JavaScript's
-- | `encodeURIComponent`.
-- |
-- | ```purs
-- | > encodeURIComponent "https://purescript.org"
-- | Just "https%3A%2F%2Fpurescript.org"
-- | ```
-- |
-- | Encoding a URI can fail with a `URIError` if the string contains malformed
-- | characters. If you are confident you are encoding a well-formed string then
-- | you can run this function unsafely:
-- |
-- | ```purs
-- | import Partial.Unsafe (unsafePartial)
-- | import Data.Maybe (fromJust)
-- |
-- | unsafeEncode :: String -> String
-- | unsafeEncode str = unsafePartial $ fromJust $ encodeURIComponent str
-- | ```
encodeURIComponent :: String -> Maybe String
encodeURIComponent = runFn3 _encodeURIComponent (const Nothing) Just

foreign import _encodeFormURLComponent :: Fn3 (String -> Maybe String) (String -> Maybe String) String (Maybe String)

-- | URI-encode a string according to RFC3896, except with spaces encoded using
-- | '+' instead of '%20' to comply with application/x-www-form-urlencoded.
-- |
-- | ```purs
-- | > encodeURIComponent "abc ABC"
-- | Just "abc%20ABC"
-- |
-- | > encodeFormURLComponent "abc ABC"
-- | Just "abc+ABC"
-- | ```
encodeFormURLComponent :: String -> Maybe String
encodeFormURLComponent = runFn3 _encodeFormURLComponent (const Nothing) Just

foreign import _decodeURIComponent :: Fn3 (String -> Maybe String) (String -> Maybe String) String (Maybe String)

-- | Decode a URI string according to RFC3896. Implemented using JavaScript's
-- | `decodeURIComponent`.
-- |
-- | ```purs
-- | > decodeURIComponent "https%3A%2F%2Fpurescript.org"
-- | Just "https://purescript.org"
-- | ```
-- |
-- | Decoding a URI can fail with a `URIError` if the string contains malformed
-- | characters. If you are confident you are encoding a well-formed string then
-- | you can run this function unsafely:
-- |
-- | ```purs
-- | import Partial.Unsafe (unsafePartial)
-- | import Data.Maybe (fromJust)
-- |
-- | unsafeDecode :: String -> String
-- | unsafeDecode str = unsafePartial $ fromJust $ decodeURIComponent str
-- | ```
decodeURIComponent :: String -> Maybe String
decodeURIComponent = runFn3 _decodeURIComponent (const Nothing) Just

foreign import _decodeFormURLComponent :: Fn3 (String -> Maybe String) (String -> Maybe String) String (Maybe String)

-- | Decode a URI according to application/x-www-form-urlencoded (for example,
-- | a string containing '+' for spaces or query parameters).
-- |
-- | ```purs
-- | > decodeURIComponent "https%3A%2F%2Fpurescript.org?search+query"
-- | Just "https://purescript.org?search+query"
-- |
-- | > decodeFormURLComponent "https%3A%2F%2Fpurescript.org?search+query"
-- | Just "https://purescript.org?search query"
-- | ```
decodeFormURLComponent :: String -> Maybe String
decodeFormURLComponent = runFn3 _decodeFormURLComponent (const Nothing) Just
10 changes: 0 additions & 10 deletions src/Main.purs

This file was deleted.

13 changes: 10 additions & 3 deletions test/Main.purs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,17 @@ module Test.Main where

import Prelude

import Data.Maybe (Maybe(..))
import Effect (Effect)
import Effect.Class.Console (log)
import JSURI (decodeFormURLComponent, decodeURIComponent, encodeFormURLComponent, encodeURIComponent)
import Test.Assert (assert)

main :: Effect Unit
main = do
log "🍝"
log "You should add some tests."
assert $ encodeURIComponent "https://purescript.org" == Just "https%3A%2F%2Fpurescript.org"
assert $ encodeURIComponent "abc ABC" == Just "abc%20ABC"
assert $ encodeFormURLComponent "abc ABC" == Just "abc+ABC"

assert $ decodeURIComponent "https%3A%2F%2Fpurescript.org" == Just "https://purescript.org"
assert $ decodeURIComponent "https%3A%2F%2Fpurescript.org?search+query" == Just "https://purescript.org?search+query"
assert $ decodeFormURLComponent "https%3A%2F%2Fpurescript.org?search+query" == Just "https://purescript.org?search query"

0 comments on commit 5edccd3

Please sign in to comment.