diff --git a/Yesod/Form.hs b/Yesod/Form.hs
index 8db1f2ef..237ddeb1 100644
--- a/Yesod/Form.hs
+++ b/Yesod/Form.hs
@@ -4,6 +4,7 @@
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE CPP #-}
+{-# LANGUAGE OverloadedStrings #-}
-- | Parse forms (and query strings).
module Yesod.Form
( -- * Data types
@@ -63,6 +64,8 @@ import Data.Char (toUpper, isUpper)
import Control.Arrow ((&&&))
import Data.List (group, sort)
import Data.Monoid (mempty)
+import Data.Text (Text)
+import Text.Blaze (toHtml)
#if __GLASGOW_HASKELL__ >= 700
#define HAMLET hamlet
@@ -88,7 +91,7 @@ fieldsToTable = mapFormXml $ mapM_ go
$maybe err <- fiErrors fi
#{err}
|]
- clazz fi = if fiRequired fi then "required" else "optional"
+ clazz fi = if fiRequired fi then "required" else "optional" :: Text
-- | Display the label, tooltip, input code and errors in a single div.
fieldsToDivs :: FormField sub y a -> Form sub y a
@@ -102,7 +105,7 @@ fieldsToDivs = mapFormXml $ mapM_ go
$maybe err <- fiErrors fi
#{err}
|]
- clazz fi = if fiRequired fi then "required" else "optional"
+ clazz fi = if fiRequired fi then "required" else "optional" :: Text
-- | Run a form against POST parameters, without CSRF protection.
runFormPostNoNonce :: GForm s m xml a -> GHandler s m (FormResult a, xml, Enctype)
@@ -133,7 +136,7 @@ runFormPost f = do
|]
-nonceName :: String
+nonceName :: Text
nonceName = "_nonce"
-- | Run a form against POST parameters. Please note that this does not provide
@@ -258,7 +261,7 @@ mkToForm =
just <- [|pure|]
nothing <- [|Nothing|]
let just' = just `AppE` ConE (mkName $ entityName t)
- string' <- [|string|]
+ string' <- [|toHtml|]
ftt <- [|fieldsToTable|]
ffs' <- [|FormFieldSettings|]
let stm "" = nothing
@@ -306,6 +309,6 @@ toLabel (x:rest) = toUpper x : go rest
| isUpper c = ' ' : c : go cs
| otherwise = c : go cs
-formFailures :: FormResult a -> Maybe [String]
+formFailures :: FormResult a -> Maybe [Text]
formFailures (FormFailure x) = Just x
formFailures _ = Nothing
diff --git a/Yesod/Form/Class.hs b/Yesod/Form/Class.hs
index 290b15d7..d6af8096 100644
--- a/Yesod/Form/Class.hs
+++ b/Yesod/Form/Class.hs
@@ -12,16 +12,24 @@ import Yesod.Form.Core
import Yesod.Form.Profiles (Textarea)
import Data.Int (Int64)
import Data.Time (Day, TimeOfDay)
+import Data.Text (Text)
class ToForm a y where
toForm :: Formlet sub y a
class ToFormField a y where
toFormField :: FormFieldSettings -> FormletField sub y a
+{- FIXME
instance ToFormField String y where
toFormField = stringField
instance ToFormField (Maybe String) y where
toFormField = maybeStringField
+-}
+
+instance ToFormField Text y where
+ toFormField = stringField
+instance ToFormField (Maybe Text) y where
+ toFormField = maybeStringField
instance ToFormField Int y where
toFormField = intField
diff --git a/Yesod/Form/Core.hs b/Yesod/Form/Core.hs
index b779b4a6..9b08fff9 100644
--- a/Yesod/Form/Core.hs
+++ b/Yesod/Form/Core.hs
@@ -52,6 +52,13 @@ import Text.Hamlet
import Text.Blaze (ToHtml (..))
import Data.String
import Control.Monad (join)
+import Data.Text (Text, pack)
+import qualified Data.Text as T
+import Prelude hiding ((++))
+import Data.Monoid (Monoid (mappend))
+
+(++) :: Monoid a => a -> a -> a
+(++) = mappend
-- | A form can produce three different results: there was no data available,
-- the data was invalid, or there was a successful parse.
@@ -59,7 +66,7 @@ import Control.Monad (join)
-- The 'Applicative' instance will concatenate the failure messages in two
-- 'FormResult's.
data FormResult a = FormMissing
- | FormFailure [String]
+ | FormFailure [Text]
| FormSuccess a
deriving Show
instance Functor FormResult where
@@ -92,7 +99,7 @@ instance Monoid Enctype where
data Ints = IntCons Int Ints | IntSingle Int
instance Show Ints where
show (IntSingle i) = show i
- show (IntCons i is) = show i ++ '-' : show is
+ show (IntCons i is) = show i ++ ('-' : show is)
incrInts :: Ints -> Ints
incrInts (IntSingle i) = IntSingle $ i + 1
@@ -113,16 +120,16 @@ type FormInner s m =
GHandler s m
)))
-type Env = [(String, String)]
-type FileEnv = [(String, FileInfo)]
+type Env = [(Text, Text)]
+type FileEnv = [(Text, FileInfo)]
-- | Get a unique identifier.
-newFormIdent :: Monad m => StateT Ints m String
+newFormIdent :: Monad m => StateT Ints m Text
newFormIdent = do
i <- get
let i' = incrInts i
put i'
- return $ 'f' : show i'
+ return $ pack $ 'f' : show i'
deeperFormIdent :: Monad m => StateT Ints m ()
deeperFormIdent = do
@@ -172,12 +179,12 @@ requiredFieldHelper (FieldProfile parse render mkWidget) ffs orig = toForm $ do
Left e -> (FormFailure [e], x)
Right y -> (FormSuccess y, x)
let fi = FieldInfo
- { fiLabel = string label
+ { fiLabel = toHtml label
, fiTooltip = tooltip
, fiIdent = theId
, fiInput = mkWidget theId name val True
, fiErrors = case res of
- FormFailure [x] -> Just $ string x
+ FormFailure [x] -> Just $ toHtml x
_ -> Nothing
, fiRequired = True
}
@@ -261,12 +268,12 @@ optionalFieldHelper (FieldProfile parse render mkWidget) ffs orig' = toForm $ do
Left e -> (FormFailure [e], x)
Right y -> (FormSuccess $ Just y, x)
let fi = FieldInfo
- { fiLabel = string label
+ { fiLabel = toHtml label
, fiTooltip = tooltip
, fiIdent = theId
, fiInput = mkWidget theId name val False
, fiErrors = case res of
- FormFailure x -> Just $ string $ unlines x
+ FormFailure x -> Just $ toHtml $ T.unlines x
_ -> Nothing
, fiRequired = False
}
@@ -290,29 +297,29 @@ mapFormXml f (GForm g) = GForm $ do
data FieldInfo sub y = FieldInfo
{ fiLabel :: Html
, fiTooltip :: Html
- , fiIdent :: String
+ , fiIdent :: Text
, fiInput :: GWidget sub y ()
, fiErrors :: Maybe Html
, fiRequired :: Bool
}
data FormFieldSettings = FormFieldSettings
- { ffsLabel :: String
+ { ffsLabel :: Text
, ffsTooltip :: Html
- , ffsId :: Maybe String
- , ffsName :: Maybe String
+ , ffsId :: Maybe Text
+ , ffsName :: Maybe Text
}
instance IsString FormFieldSettings where
- fromString s = FormFieldSettings s mempty Nothing Nothing
+ fromString s = FormFieldSettings (pack s) mempty Nothing Nothing
-- | A generic definition of a form field that can be used for generating both
-- required and optional fields. See 'requiredFieldHelper and
-- 'optionalFieldHelper'.
data FieldProfile sub y a = FieldProfile
- { fpParse :: String -> Either String a
- , fpRender :: a -> String
+ { fpParse :: Text -> Either Text a
+ , fpRender :: a -> Text
-- | ID, name, value, required
- , fpWidget :: String -> String -> String -> Bool -> GWidget sub y ()
+ , fpWidget :: Text -> Text -> Text -> Bool -> GWidget sub y ()
}
type Form sub y = GForm sub y (GWidget sub y ())
@@ -338,7 +345,7 @@ checkForm f (GForm form) = GForm $ do
--
-- Unlike 'checkForm', the validation error will appear in the generated HTML
-- of the form.
-checkField :: (a -> Either String b) -> FormField s m a -> FormField s m b
+checkField :: (a -> Either Text b) -> FormField s m a -> FormField s m b
checkField f (GForm form) = GForm $ do
(res, xml, enc) <- form
let (res', merr) =
@@ -355,7 +362,7 @@ checkField f (GForm form) = GForm $ do
Just err -> flip map xml $ \fi -> fi
{ fiErrors = Just $
case fiErrors fi of
- Nothing -> string err
+ Nothing -> toHtml err
Just x -> x
}
return (res', xml', enc)
diff --git a/Yesod/Form/Fields.hs b/Yesod/Form/Fields.hs
index ad46681f..ccf8bfef 100644
--- a/Yesod/Form/Fields.hs
+++ b/Yesod/Form/Fields.hs
@@ -2,6 +2,7 @@
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE CPP #-}
+{-# LANGUAGE OverloadedStrings #-}
module Yesod.Form.Fields
( -- * Fields
-- ** Required
@@ -62,6 +63,9 @@ import Text.Hamlet
import Data.Monoid
import Control.Monad (join)
import Data.Maybe (fromMaybe, isNothing)
+import Data.Text (Text, pack, unpack)
+import qualified Data.Text as T
+import Text.Blaze (toHtml)
#if __GLASGOW_HASKELL__ >= 700
#define HAMLET hamlet
@@ -69,28 +73,28 @@ import Data.Maybe (fromMaybe, isNothing)
#define HAMLET $hamlet
#endif
-stringField :: (IsForm f, FormType f ~ String)
- => FormFieldSettings -> Maybe String -> f
+stringField :: (IsForm f, FormType f ~ Text)
+ => FormFieldSettings -> Maybe Text -> f
stringField = requiredFieldHelper stringFieldProfile
-maybeStringField :: (IsForm f, FormType f ~ Maybe String)
- => FormFieldSettings -> Maybe (Maybe String) -> f
+maybeStringField :: (IsForm f, FormType f ~ Maybe Text)
+ => FormFieldSettings -> Maybe (Maybe Text) -> f
maybeStringField = optionalFieldHelper stringFieldProfile
-passwordField :: (IsForm f, FormType f ~ String)
- => FormFieldSettings -> Maybe String -> f
+passwordField :: (IsForm f, FormType f ~ Text)
+ => FormFieldSettings -> Maybe Text -> f
passwordField = requiredFieldHelper passwordFieldProfile
-maybePasswordField :: (IsForm f, FormType f ~ Maybe String)
- => FormFieldSettings -> Maybe (Maybe String) -> f
+maybePasswordField :: (IsForm f, FormType f ~ Maybe Text)
+ => FormFieldSettings -> Maybe (Maybe Text) -> f
maybePasswordField = optionalFieldHelper passwordFieldProfile
-intInput :: Integral i => String -> FormInput sub master i
+intInput :: Integral i => Text -> FormInput sub master i
intInput n =
mapFormXml fieldsToInput $
requiredFieldHelper intFieldProfile (nameSettings n) Nothing
-maybeIntInput :: Integral i => String -> FormInput sub master (Maybe i)
+maybeIntInput :: Integral i => Text -> FormInput sub master (Maybe i)
maybeIntInput n =
mapFormXml fieldsToInput $
optionalFieldHelper intFieldProfile (nameSettings n) Nothing
@@ -144,14 +148,14 @@ boolField ffs orig = toForm $ do
Just "false" -> (FormSuccess False, False)
Just _ -> (FormSuccess True, True)
let fi = FieldInfo
- { fiLabel = string label
+ { fiLabel = toHtml label
, fiTooltip = tooltip
, fiIdent = theId
, fiInput = [HAMLET|
|]
, fiErrors = case res of
- FormFailure [x] -> Just $ string x
+ FormFailure [x] -> Just $ toHtml x
_ -> Nothing
, fiRequired = True
}
@@ -181,7 +185,7 @@ selectField pairs ffs initial = toForm $ do
Nothing -> FormMissing
Just "none" -> FormFailure ["Field is required"]
Just x ->
- case reads x of
+ case reads $ unpack x of
(x', _):_ ->
case lookup x' pairs' of
Nothing -> FormFailure ["Invalid entry"]
@@ -203,19 +207,19 @@ selectField pairs ffs initial = toForm $ do