Skip to content
This repository was archived by the owner on Dec 18, 2020. It is now read-only.
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
4 changes: 4 additions & 0 deletions bower.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,9 @@
"devDependencies": {
"purescript-assert": "^4.0.0",
"purescript-console": "^4.0.0"
},
"dependencies": {
"purescript-maybe": "^4.0.1",
"purescript-functions": "^4.0.0"
}
}
31 changes: 31 additions & 0 deletions src/Global.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,34 @@ exports.readInt = function (radix) {
};

exports.readFloat = parseFloat;

var formatNumber = function (format) {
return function (fail, succ, digits, n) {
try {
return succ(n[format](digits));
}
catch (e) {
return fail(e.message);
}
};
};

exports._toFixed = formatNumber("toFixed");
exports._toExponential = formatNumber("toExponential");
exports._toPrecision = formatNumber("toPrecision");

var encdecURI = function (encdec) {
return function (fail, succ, s) {
try {
return succ(encdec(s));
}
catch (e) {
return fail(e.message);
}
};
};

exports._decodeURI = encdecURI(decodeURI);
exports._encodeURI = encdecURI(encodeURI);
exports._decodeURIComponent = encdecURI(decodeURIComponent);
exports._encodeURIComponent = encdecURI(encodeURIComponent);
74 changes: 73 additions & 1 deletion src/Global.purs
Original file line number Diff line number Diff line change
@@ -1,6 +1,24 @@
-- | This module defines types for some global Javascript functions
-- | and values.
module Global where
module Global
( nan
, isNaN
, infinity
, isFinite
, readInt
, readFloat
, toFixed
, toExponential
, toPrecision
, decodeURI
, encodeURI
, decodeURIComponent
, encodeURIComponent
) where

import Prelude
import Data.Function.Uncurried (Fn3, Fn4, runFn3, runFn4)
import Data.Maybe (Maybe(..))

-- | Not a number (NaN)
foreign import nan :: Number
Expand All @@ -19,3 +37,57 @@ foreign import readInt :: Int -> String -> Number

-- | Parse a floating point value from a `String`
foreign import readFloat :: String -> Number

foreign import _toFixed :: forall a. Fn4 (String -> a) (String -> a) Int Number a

foreign import _toExponential :: forall a. Fn4 (String -> a) (String -> a) Int Number a

foreign import _toPrecision :: forall a. Fn4 (String -> a) (String -> a) Int Number a

-- | Formats Number as a String with limited number of digits after the dot.
-- | May return `Nothing` when specified number of digits is less than 0 or
-- | greater than 20. See ECMA-262 for more information.
toFixed :: Int -> Number -> Maybe String
toFixed digits n = runFn4 _toFixed (const Nothing) Just digits n

-- | Formats Number as String in exponential notation limiting number of digits
-- | after the decimal dot. May return `Nothing` when specified number of
-- | digits is less than 0 or greater than 20 depending on the implementation.
-- | See ECMA-262 for more information.
toExponential :: Int -> Number -> Maybe String
toExponential digits n = runFn4 _toExponential (const Nothing) Just digits n

-- | Formats Number as String in fixed-point or exponential notation rounded
-- | to specified number of significant digits. May return `Nothing` when
-- | precision is less than 1 or greater than 21 depending on the
-- | implementation. See ECMA-262 for more information.
toPrecision :: Int -> Number -> Maybe String
toPrecision digits n = runFn4 _toPrecision (const Nothing) Just digits n

foreign import _decodeURI :: forall a. Fn3 (String -> a) (String -> a) String a

foreign import _encodeURI :: forall a. Fn3 (String -> a) (String -> a) String a

foreign import _decodeURIComponent :: forall a. Fn3 (String -> a) (String -> a) String a

foreign import _encodeURIComponent :: forall a. Fn3 (String -> a) (String -> a) String a

-- | URI decoding. Returns `Nothing` when given a value with undecodeable
-- | escape sequences.
decodeURI :: String -> Maybe String
decodeURI s = runFn3 _decodeURI (const Nothing) Just s

-- | URI encoding. Returns `Nothing` when given a value with unencodeable
-- | characters.
encodeURI :: String -> Maybe String
encodeURI s = runFn3 _encodeURI (const Nothing) Just s

-- | URI component decoding. Returns `Nothing` when given a value with
-- | undecodeable escape sequences.
decodeURIComponent :: String -> Maybe String
decodeURIComponent s = runFn3 _decodeURIComponent (const Nothing) Just s

-- | URI component encoding. Returns `Nothing` when given a value with
-- | unencodeable characters.
encodeURIComponent :: String -> Maybe String
encodeURIComponent s = runFn3 _encodeURIComponent (const Nothing) Just s
1 change: 1 addition & 0 deletions test/Test/Main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
exports.unencodable = "\uDFFF";
59 changes: 58 additions & 1 deletion test/Test/Main.purs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,25 @@ module Test.Main where

import Prelude

import Data.Maybe (Maybe(..))
import Effect (Effect)
import Effect.Console (log)

import Global (readFloat, readInt, isFinite, infinity, nan, isNaN)
import Global
( readFloat
, readInt
, isFinite
, infinity
, nan
, isNaN
, toPrecision
, toExponential
, toFixed
, decodeURI
, encodeURI
, decodeURIComponent
, encodeURIComponent
)
import Global.Unsafe (unsafeToPrecision, unsafeToExponential, unsafeToFixed)

import Test.Assert (assert)
Expand Down Expand Up @@ -61,3 +76,45 @@ main = do
log $ "unsafeToPrecision 6" <> (show num) <> " == \"12345.7\""
assert $ unsafeToPrecision 6 num == "12345.7"

-- note the rounding
log $ "toFixed 1" <> (show num) <> " == (Just \"12345.7\")"
assert $ toFixed 1 num == Just "12345.7"

-- padded with zeros
log $ "toFixed 6" <> (show num) <> " == (Just \"12345.678900\")"
assert $ toFixed 6 num == Just "12345.678900"

log $ "toExponential 4" <> (show num) <> " == (Just \"1.2346e+4\")"
assert $ toExponential 4 num == Just "1.2346e+4"

log $ "toPrecision 3" <> (show num) <> " == (Just \"1.23e+4\")"
assert $ toPrecision 3 num == Just "1.23e+4"

log $ "toPrecision 6" <> (show num) <> " == (Just \"12345.7\")"
assert $ toPrecision 6 num == Just "12345.7"

log $ "decodeURI \"http://test/api?q=hello%20world\" == Just \"http://test/api?q=hello world\""
assert $ decodeURI "http://test/api?q=hello%20world" == Just "http://test/api?q=hello world"

log $ "decodeURI \"http://test/api?q=hello%8\" == Nothing\""
assert $ decodeURI "http://test/api?q=hello%8" == Nothing

log $ "encodeURI \"http://test/api?q=hello world\" == Just \"http://test/api?q=hello%20world\""
assert $ encodeURI "http://test/api?q=hello world" == Just "http://test/api?q=hello%20world"

log $ "encodeURI \"http://test/api?q=" <> unencodable <> "\" == Nothing"
assert $ encodeURI ("http://test/api?q=" <> unencodable) == Nothing

log $ "decodeURIComponent \"hello%20world\" == Just \"hello world\""
assert $ decodeURIComponent "hello%20world" == Just "hello world"

log $ "decodeURIComponent \"hello%8\" == Nothing"
assert $ decodeURIComponent "hello%8" == Nothing

log $ "encodeURIComponent \"hello world\" == Just \"hello%20world\""
assert $ encodeURIComponent "hello world" == Just "hello%20world"

log $ "encodeURIComponent \"" <> unencodable <> "\" == Nothing"
assert $ encodeURIComponent unencodable == Nothing

foreign import unencodable :: String