Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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"