@@ -9,6 +9,8 @@ module Servant.JQuery.Internal where
99import Control.Applicative
1010import Control.Lens
1111import Data.Char (toLower)
12+import qualified Data.CharSet as Set
13+import qualified Data.CharSet.Unicode.Category as Set
1214import Data.List
1315import Data.Monoid
1416import Data.Proxy
@@ -64,17 +66,44 @@ data HeaderArg = HeaderArg
6466 } deriving (Eq)
6567
6668instance Show HeaderArg where
67− show (HeaderArg n) = "header" <> n
69+ show (HeaderArg n) = toValidFunctionName ("header" <> n)
6870 show (ReplaceHeaderArg n p)
6971 | pn `startswith` p = pv <> " + \"" <> rp <> "\""
7072 | pn `endswith` p = "\"" <> rp <> "\" + " <> pv
71− | pn `isInfixOf` p = "\"" <> replace pn ("\"" <> pv <> "\"") p <> "\""
73+ | pn `isInfixOf` p = "\"" <> (replace pn ("\" + " <> pv <> " + \"") p) <> "\""
7274 | otherwise = p
7375 where
74− pv = "header" <> n
76+ pv = toValidFunctionName ("header" <> n)
7577 pn = "{" <> n <> "}"
7678 rp = replace pn "" p
7779
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
86+ where
87+ setFirstChar c = if firstChar c
88+ then c
89+ else '_'
90+ firstChar c = (prefixOK c) || (or . map (Set.member c) $ firstLetterOK)
91+ remainder c = (prefixOK c) || (or . map (Set.member c) $ remainderOK)
92+ -- Valid prefixes
93+ prefixOK c = c `elem` ['$','_']
94+ -- Unicode character sets
95+ firstLetterOK = [ Set.lowercaseLetter
96+ , Set.uppercaseLetter
97+ , Set.titlecaseLetter
98+ , Set.modifierLetter
99+ , Set.otherLetter
100+ , Set.letterNumber ]
101+ remainderOK = firstLetterOK <> [ Set.nonSpacingMark
102+ , Set.spacingCombiningMark
103+ , Set.decimalNumber
104+ , Set.connectorPunctuation ]
105+toValidFunctionName [] = "_"
106+
78107data Url = Url
79108 { _path :: Path
80109 , _queryStr :: [QueryArg]