|
1 |
| -module Routing.Parser ( |
2 |
| - parse |
3 |
| - ) where |
| 1 | +module Routing.Parser (parse) where |
4 | 2 |
|
5 |
| -import Control.MonadPlus (guard) |
| 3 | +import Prelude |
| 4 | + |
| 5 | +import Routing.Types (Route, RoutePart(..)) |
6 | 6 | import Data.Array as A
|
7 |
| -import Data.Either (fromRight) |
8 |
| -import Data.List (fromFoldable, List) |
9 | 7 | import Data.Map as M
|
10 |
| -import Data.Maybe (Maybe, fromMaybe) |
11 | 8 | import Data.String as S
|
12 |
| -import Data.String.Regex (Regex, regex, split) as R |
13 |
| -import Data.String.Regex.Flags (noFlags) as R |
| 9 | +import Control.MonadPlus (guard) |
| 10 | +import Data.List as L |
| 11 | +import Data.Maybe (Maybe(..)) |
14 | 12 | import Data.Traversable (traverse)
|
15 | 13 | import Data.Tuple (Tuple(..))
|
16 |
| -import Partial.Unsafe (unsafePartial) |
17 |
| -import Prelude (map, discard, (>>>), ($), (<<<), (==), (<*>), (<$>), (<=)) |
18 |
| -import Routing.Types (Route, RoutePart(..)) |
19 | 14 |
|
20 |
| --- | Parse part of hash. Will return `Query (Map String String)` for query |
| 15 | +-- | Parse query part of hash. Will return `Map String String` for query |
21 | 16 | -- | i.e. `"?foo=bar&bar=baz"` -->
|
22 |
| --- | `Query (fromList [Tuple "foo" "bar", Tuple "bar" "baz"])` |
23 |
| -parsePart :: String -> RoutePart |
24 |
| -parsePart str = fromMaybe (Path str) do |
25 |
| - guard $ S.take 1 str == "?" |
26 |
| - map (Query <<< M.fromFoldable) |
27 |
| - $ traverse part2tuple parts |
| 17 | +-- | `fromList [Tuple "foo" "bar", Tuple "bar" "baz"]` |
| 18 | +parseQueryPart :: (String -> String) -> String -> Maybe (M.Map String String) |
| 19 | +parseQueryPart decoder = |
| 20 | + map M.fromFoldable <<< traverse part2tuple <<< S.split (S.Pattern "&") |
28 | 21 | where
|
29 |
| - parts :: List String |
30 |
| - parts = fromFoldable $ S.split (S.Pattern "&") $ S.drop 1 str |
31 |
| - |
32 |
| - part2tuple :: String -> Maybe (Tuple String String) |
33 |
| - part2tuple input = do |
34 |
| - let keyVal = S.split (S.Pattern "=") input |
35 |
| - guard $ A.length keyVal <= 2 |
36 |
| - Tuple <$> (A.head keyVal) <*> (keyVal A.!! 1) |
37 |
| - |
38 |
| - |
39 |
| -splitRegex :: R.Regex |
40 |
| -splitRegex = unsafePartial fromRight $ R.regex "\\/|(?=\\?)" R.noFlags |
| 22 | + part2tuple :: String -> Maybe (Tuple String String) |
| 23 | + part2tuple input = do |
| 24 | + let keyVal = decoder <$> S.split (S.Pattern "=") input |
| 25 | + guard $ A.length keyVal <= 2 |
| 26 | + Tuple <$> A.head keyVal <*> keyVal A.!! 1 |
41 | 27 |
|
42 | 28 | -- | Parse hash string to `Route` with `decoder` function
|
43 | 29 | -- | applied to every hash part (usually `decodeURIComponent`)
|
44 | 30 | parse :: (String -> String) -> String -> Route
|
45 | 31 | parse decoder hash =
|
46 |
| - map ( decoder >>> parsePart ) $ fromFoldable (R.split splitRegex hash) |
| 32 | + case flip S.splitAt hash =<< S.indexOf (S.Pattern "?") hash of |
| 33 | + Just { before, after } -> |
| 34 | + pathParts before |
| 35 | + <> map Query (L.fromFoldable (parseQueryPart decoder (S.drop 1 after))) |
| 36 | + Nothing -> |
| 37 | + pathParts hash |
| 38 | + where |
| 39 | + pathParts str = |
| 40 | + let |
| 41 | + parts = L.fromFoldable $ map Path (S.split (S.Pattern "/") str) |
| 42 | + in |
| 43 | + case L.unsnoc parts of |
| 44 | + Just { init, last: Path "" } -> init |
| 45 | + _ -> parts |
0 commit comments