@@ -9,6 +9,8 @@ module Servant.JQuery.Internal where
9import Control.Applicative
9import Control.Applicative
10import Control.Lens
10import Control.Lens
11import Data.Char (toLower)
11import Data.Char (toLower)
12+import qualified Data.CharSet as Set
13+import qualified Data.CharSet.Unicode.Category as Set
12import Data.List
14import Data.List
13import Data.Monoid
15import Data.Monoid
14import Data.Proxy
16import Data.Proxy
@@ -64,17 +66,44 @@ data HeaderArg = HeaderArg
64 } deriving (Eq)
66 } deriving (Eq)
66instance Show HeaderArg where
68instance Show HeaderArg where
67− show (HeaderArg n) = "header" <> n
69+ show (HeaderArg n) = toValidFunctionName ("header" <> n)
68 show (ReplaceHeaderArg n p)
70 show (ReplaceHeaderArg n p)
69 | pn `startswith` p = pv <> " + \"" <> rp <> "\""
71 | pn `startswith` p = pv <> " + \"" <> rp <> "\""
70 | pn `endswith` p = "\"" <> rp <> "\" + " <> pv
72 | pn `endswith` p = "\"" <> rp <> "\" + " <> pv
71− | pn `isInfixOf` p = "\"" <> replace pn ("\"" <> pv <> "\"") p <> "\""
73+ | pn `isInfixOf` p = "\"" <> (replace pn ("\" + " <> pv <> " + \"") p) <> "\""
72 | otherwise = p
74 | otherwise = p
74− pv = "header" <> n
76+ pv = toValidFunctionName ("header" <> n)
75 pn = "{" <> n <> "}"
77 pn = "{" <> n <> "}"
76 rp = replace pn "" p
78 rp = replace pn "" p
80+-- | Attempts to reduce the function name provided to that allowed by JS.
81+-- https://mathiasbynens.be/notes/javascript-identifiers
82+-- Couldn't work out how to handle zero-width characters.
83+-- @TODO: specify better default function name, or throw error?
84+toValidFunctionName :: String -> String
85+toValidFunctionName (x:xs) = [setFirstChar x] <> filter remainder xs
87+ setFirstChar c = if firstChar c
90+ firstChar c = (prefixOK c) || (or . map (Set.member c) $ firstLetterOK)
91+ remainder c = (prefixOK c) || (or . map (Set.member c) $ remainderOK)
93+ prefixOK c = c `elem` ['$','_']
94+ -- Unicode character sets
95+ firstLetterOK = [ Set.lowercaseLetter
96+ , Set.uppercaseLetter
97+ , Set.titlecaseLetter
100+ , Set.letterNumber ]
101+ remainderOK = firstLetterOK <> [ Set.nonSpacingMark
102+ , Set.spacingCombiningMark
104+ , Set.connectorPunctuation ]
105+toValidFunctionName [] = "_"
78data Url = Url
107data Url = Url
79 { _path :: Path
108 { _path :: Path
80 , _queryStr :: [QueryArg]
109 , _queryStr :: [QueryArg]