Skip to content

Commit 5edccd3

Browse files
Implement encoding and decoding functions (#1)
1 parent 00e6dfc commit 5edccd3

File tree

5 files changed

+141
-14
lines changed

5 files changed

+141
-14
lines changed

spago.dhall

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{ name = "js-uri"
2-
, dependencies = [ "console", "effect", "psci-support" ]
2+
, dependencies = [ "assert", "effect", "functions", "maybe", "psci-support" ]
33
, packages = ./packages.dhall
44
, sources = [ "src/**/*.purs", "test/**/*.purs" ]
55
}

src/JSURI.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
"use strict";
2+
3+
// A helper which transforms the result ofencodeURIComponent to be compliant
4+
// with RFC3896, as described in the MDN documentation here:
5+
//
6+
// https://web.archive.org/web/20201206001047/https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent
7+
function toRFC3896(input) {
8+
return input.replace(/[!'()*]/g, function (c) {
9+
return "%" + c.charCodeAt(0).toString(16);
10+
});
11+
}
12+
13+
exports._encodeURIComponent = function encode(fail, succeed, input) {
14+
try {
15+
return succeed(toRFC3896(encodeURIComponent(input)));
16+
} catch (err) {
17+
return fail(err);
18+
}
19+
};
20+
21+
exports._encodeFormURLComponent = function encode(fail, succeed, input) {
22+
try {
23+
return succeed(toRFC3896(encodeURIComponent(input)).replace(/%20/g, "+"));
24+
} catch (err) {
25+
return fail(err);
26+
}
27+
};
28+
29+
function _decodeURIComponent(fail, succeed, input) {
30+
try {
31+
return succeed(decodeURIComponent(input));
32+
} catch (err) {
33+
return fail(err);
34+
}
35+
}
36+
37+
exports._decodeURIComponent = _decodeURIComponent;
38+
39+
exports._decodeFormURLComponent = function encode(fail, succeed, input) {
40+
return _decodeURIComponent(fail, succeed, input.replace(/\+/g, " "));
41+
};

src/JSURI.purs

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
module JSURI
2+
( encodeURIComponent
3+
, encodeFormURLComponent
4+
, decodeURIComponent
5+
, decodeFormURLComponent
6+
) where
7+
8+
import Prelude
9+
10+
import Data.Function.Uncurried (Fn3, runFn3)
11+
import Data.Maybe (Maybe(..))
12+
13+
foreign import _encodeURIComponent :: Fn3 (String -> Maybe String) (String -> Maybe String) String (Maybe String)
14+
15+
-- | URI-encode a string according to RFC3896. Implemented using JavaScript's
16+
-- | `encodeURIComponent`.
17+
-- |
18+
-- | ```purs
19+
-- | > encodeURIComponent "https://purescript.org"
20+
-- | Just "https%3A%2F%2Fpurescript.org"
21+
-- | ```
22+
-- |
23+
-- | Encoding a URI can fail with a `URIError` if the string contains malformed
24+
-- | characters. If you are confident you are encoding a well-formed string then
25+
-- | you can run this function unsafely:
26+
-- |
27+
-- | ```purs
28+
-- | import Partial.Unsafe (unsafePartial)
29+
-- | import Data.Maybe (fromJust)
30+
-- |
31+
-- | unsafeEncode :: String -> String
32+
-- | unsafeEncode str = unsafePartial $ fromJust $ encodeURIComponent str
33+
-- | ```
34+
encodeURIComponent :: String -> Maybe String
35+
encodeURIComponent = runFn3 _encodeURIComponent (const Nothing) Just
36+
37+
foreign import _encodeFormURLComponent :: Fn3 (String -> Maybe String) (String -> Maybe String) String (Maybe String)
38+
39+
-- | URI-encode a string according to RFC3896, except with spaces encoded using
40+
-- | '+' instead of '%20' to comply with application/x-www-form-urlencoded.
41+
-- |
42+
-- | ```purs
43+
-- | > encodeURIComponent "abc ABC"
44+
-- | Just "abc%20ABC"
45+
-- |
46+
-- | > encodeFormURLComponent "abc ABC"
47+
-- | Just "abc+ABC"
48+
-- | ```
49+
encodeFormURLComponent :: String -> Maybe String
50+
encodeFormURLComponent = runFn3 _encodeFormURLComponent (const Nothing) Just
51+
52+
foreign import _decodeURIComponent :: Fn3 (String -> Maybe String) (String -> Maybe String) String (Maybe String)
53+
54+
-- | Decode a URI string according to RFC3896. Implemented using JavaScript's
55+
-- | `decodeURIComponent`.
56+
-- |
57+
-- | ```purs
58+
-- | > decodeURIComponent "https%3A%2F%2Fpurescript.org"
59+
-- | Just "https://purescript.org"
60+
-- | ```
61+
-- |
62+
-- | Decoding a URI can fail with a `URIError` if the string contains malformed
63+
-- | characters. If you are confident you are encoding a well-formed string then
64+
-- | you can run this function unsafely:
65+
-- |
66+
-- | ```purs
67+
-- | import Partial.Unsafe (unsafePartial)
68+
-- | import Data.Maybe (fromJust)
69+
-- |
70+
-- | unsafeDecode :: String -> String
71+
-- | unsafeDecode str = unsafePartial $ fromJust $ decodeURIComponent str
72+
-- | ```
73+
decodeURIComponent :: String -> Maybe String
74+
decodeURIComponent = runFn3 _decodeURIComponent (const Nothing) Just
75+
76+
foreign import _decodeFormURLComponent :: Fn3 (String -> Maybe String) (String -> Maybe String) String (Maybe String)
77+
78+
-- | Decode a URI according to application/x-www-form-urlencoded (for example,
79+
-- | a string containing '+' for spaces or query parameters).
80+
-- |
81+
-- | ```purs
82+
-- | > decodeURIComponent "https%3A%2F%2Fpurescript.org?search+query"
83+
-- | Just "https://purescript.org?search+query"
84+
-- |
85+
-- | > decodeFormURLComponent "https%3A%2F%2Fpurescript.org?search+query"
86+
-- | Just "https://purescript.org?search query"
87+
-- | ```
88+
decodeFormURLComponent :: String -> Maybe String
89+
decodeFormURLComponent = runFn3 _decodeFormURLComponent (const Nothing) Just

src/Main.purs

Lines changed: 0 additions & 10 deletions
This file was deleted.

test/Main.purs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,17 @@ module Test.Main where
22

33
import Prelude
44

5+
import Data.Maybe (Maybe(..))
56
import Effect (Effect)
6-
import Effect.Class.Console (log)
7+
import JSURI (decodeFormURLComponent, decodeURIComponent, encodeFormURLComponent, encodeURIComponent)
8+
import Test.Assert (assert)
79

810
main :: Effect Unit
911
main = do
10-
log "🍝"
11-
log "You should add some tests."
12+
assert $ encodeURIComponent "https://purescript.org" == Just "https%3A%2F%2Fpurescript.org"
13+
assert $ encodeURIComponent "abc ABC" == Just "abc%20ABC"
14+
assert $ encodeFormURLComponent "abc ABC" == Just "abc+ABC"
15+
16+
assert $ decodeURIComponent "https%3A%2F%2Fpurescript.org" == Just "https://purescript.org"
17+
assert $ decodeURIComponent "https%3A%2F%2Fpurescript.org?search+query" == Just "https://purescript.org?search+query"
18+
assert $ decodeFormURLComponent "https%3A%2F%2Fpurescript.org?search+query" == Just "https://purescript.org?search query"

0 commit comments

Comments
 (0)