formlets 0.4.7 → 0.4.8
raw patch · 4 files changed
+45/−24 lines, 4 filesdep ~applicative-extrasPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependency ranges changed: applicative-extras
API changes (from Hackage documentation)
- Text.Formlets: class Plus a
- Text.Formlets: instance (Monad m, Applicative m, Plus xml) => Applicative (Form xml m)
- Text.Formlets: plus :: (Plus a) => a -> a -> a
- Text.Formlets: zero :: (Plus a) => a
- Text.XHtml.Strict.Formlets: instance Plus Html
+ Text.Formlets: instance (Monad m, Applicative m, Monoid xml) => Applicative (Form xml m)
+ Text.Formlets: optionalInput :: (Monad m) => (String -> xml) -> Form xml m (Maybe String)
+ Text.XHtml.Strict.Formlets: enumSelect :: (Show a, Bounded a, Enum a, Eq a) => Maybe a -> XHtmlForm IO a
+ Text.XHtml.Strict.Formlets: label :: (Monad m, HTML a) => a -> Form Html m ()
- Text.Formlets: massInput :: (Plus xml, Applicative m, Monad m) => (Form xml m (Maybe String)) -> Form xml m a -> ([String] -> xml) -> Form xml m [a]
+ Text.Formlets: massInput :: (Monoid xml, Applicative m, Monad m) => (Form xml m (Maybe String)) -> Form xml m a -> ([String] -> xml) -> Form xml m [a]
- Text.Formlets: plug :: (Monad m, Plus xml) => (xml -> xml1) -> Form xml m a -> Form xml1 m a
+ Text.Formlets: plug :: (Monad m, Monoid xml) => (xml -> xml1) -> Form xml m a -> Form xml1 m a
- Text.Formlets: pureM :: (Monad m, Plus xml) => m a -> Form xml m a
+ Text.Formlets: pureM :: (Monad m, Monoid xml) => m a -> Form xml m a
Files
- README +8/−0
- Text/Formlets.hs +22/−17
- Text/XHtml/Strict/Formlets.hs +7/−5
- formlets.cabal +8/−2
+ README view
@@ -0,0 +1,8 @@+The original author of this library is Jeremy Yallop. It is currently maintained+by Chris Eidhof.++Other contributors:+* MightyByte+* Eelco Lempsink++The formlets repository is hosted on github: http://github.com/chriseidhof/formlets/
Text/Formlets.hs view
@@ -1,15 +1,16 @@-module Text.Formlets ( input', inputFile, fmapFst, nothingIfNull+module Text.Formlets ( input', optionalInput, inputFile, fmapFst, nothingIfNull , check, ensure, ensures , ensureM, checkM, pureM , runFormState , massInput , xml, plug , withPrefix- , Env , Form , Plus (..)+ , Env , Form , File (..), ContentType (..), FormContentType (..) ) where +import Data.Monoid import Control.Applicative import Control.Applicative.Error import Control.Applicative.State@@ -31,10 +32,6 @@ } deriving (Eq, Show, Read) -class Plus a where- zero :: a- plus :: a -> a -> a- -- | Apply a predicate to a value and return Success or Failure as appropriate ensure :: Show a => (a -> Bool) -- ^ The predicate@@ -73,6 +70,14 @@ fromLeft n (Just (Left x)) = Success x fromLeft n _ = Failure [n ++ " is a file."] +optionalInput :: Monad m => (String -> xml) -> Form xml m (Maybe String)+optionalInput i = Form $ \env -> mkInput env <$> freshName+ where mkInput env name = (return . fromLeft name . (lookup name),+ return (i name), UrlEncoded)+ fromLeft n Nothing = Success Nothing+ fromLeft n (Just (Left x)) = Success (Just x)+ fromLeft n _ = Failure [n ++ " could not be recognized."]+ -- | A File input widget. inputFile :: Monad m => (String -> xml) -- ^ Generates the xml for the file-upload widget based on the name@@ -114,7 +119,7 @@ fmapFst f (a, b) = (f a, b) fmapFst3 f (a, b, c) = (f a, b, c) -instance (Monad m, Applicative m, Plus xml) => Applicative (Form xml m) where+instance (Monad m, Applicative m, Monoid xml) => Applicative (Form xml m) where pure = pureF (<*>) = applyF @@ -123,7 +128,7 @@ xml x = Form $ \env -> pure (const $ return $ Success (), return x, UrlEncoded) -- | Transform the XML component-plug :: (Monad m, Plus xml) => (xml -> xml1) -> Form xml m a -> Form xml1 m a+plug :: (Monad m, Monoid xml) => (xml -> xml1) -> Form xml m a -> Form xml1 m a f `plug` (Form m) = Form $ \env -> pure plugin <*> m env where plugin (c, x, t) = (c, liftM f x, t) @@ -133,16 +138,16 @@ -- | This form has to have the same variable-names as the original form, but prefixed by the prefix. -- | -- | Typically, some client-side code is needed to duplicate the original form and generate a unique prefix.-massInput :: (Plus xml, Applicative m, Monad m) => (Form xml m (Maybe String)) -> Form xml m a -> ([String] -> xml) -> Form xml m [a]+massInput :: (Monoid xml, Applicative m, Monad m) => (Form xml m (Maybe String)) -> Form xml m a -> ([String] -> xml) -> Form xml m [a] massInput h f showErrors = massInputHelper form showErrors where form = (,) <$> f <*> h -massInputHelper :: (Plus xml, Applicative m, Monad m) +massInputHelper :: (Monoid xml, Applicative m, Monad m) => Form xml m (a, Maybe String) -- The form -> ([String] -> xml) -- How to show errors -> Form xml m [a] massInputHelper f showErrors = join f- where join :: (Plus xml, Applicative m, Monad m) => Form xml m (a, Maybe String) -> Form xml m [a]+ where join :: (Monoid xml, Applicative m, Monad m) => Form xml m (a, Maybe String) -> Form xml m [a] join (Form f) = Form $ \env -> start (f env) env start :: (Monad m) => State FormState (Collector (m (Failing (a, Maybe String))), xml, FormContentType) -> Env -> State FormState (Collector (m (Failing [a])), xml, FormContentType) start f e = do currentState <- get@@ -194,15 +199,15 @@ orT x UrlEncoded = x orT x y = x -pureF :: (Monad m, Plus xml) => a -> Form xml m a-pureF v = Form $ \env -> pure (const (return $ Success v), return zero, UrlEncoded)+pureF :: (Monad m, Monoid xml) => a -> Form xml m a+pureF v = Form $ \env -> pure (const (return $ Success v), return mempty, UrlEncoded) -pureM :: (Monad m, Plus xml) => m a -> Form xml m a-pureM v = Form $ \env -> pure (const (liftM Success v), return zero, UrlEncoded)+pureM :: (Monad m, Monoid xml) => m a -> Form xml m a+pureM v = Form $ \env -> pure (const (liftM Success v), return mempty, UrlEncoded) -applyF :: (Monad m, Applicative m, Plus xml) => Form xml m (a -> b) -> Form xml m a -> Form xml m b+applyF :: (Monad m, Applicative m, Monoid xml) => Form xml m (a -> b) -> Form xml m a -> Form xml m b (Form f) `applyF` (Form v) = Form $ \env -> combine <$> f env <*> v env- where combine (v1, xml1, t1) (v2, xml2, t2) = (first v1 v2, (plus <$> xml1 <*> xml2), t1 `orT` t2)+ where combine (v1, xml1, t1) (v2, xml2, t2) = (first v1 v2, (mappend <$> xml1 <*> xml2), t1 `orT` t2) first v1 v2 e = do x <- v1 e y <- v2 e return $ x <*> y
Text/XHtml/Strict/Formlets.hs view
@@ -1,6 +1,7 @@ module Text.XHtml.Strict.Formlets ( input, textarea, password, file , hidden, inputInteger, radio, enumRadio- , selectRaw, select+ , label+ , selectRaw, select, enumSelect , XHtmlForm , module Text.Formlets ) where@@ -14,10 +15,6 @@ type XHtmlForm m a = Form X.Html m a -instance Plus X.Html where- zero = X.noHtml- plus = (+++)- -- | An input field with an optional value input :: Monad m => Maybe String -> XHtmlForm m String input = input' (\n v -> X.textfield n ! [X.value v])@@ -58,6 +55,8 @@ where toS = fmapFst (show . fromEnum) convert v = maybeRead' v "Conversion error" +label str = xml $ X.label $ X.toHtml str+ selectRaw :: Monad m => [(String, String)] -> Maybe String -> XHtmlForm m String selectRaw choices = input' mkChoices -- todo: validate that the result was in the choices where mkChoices name selected = X.select ! [X.name name] $ X.concatHtml $ map (mkChoice selected) choices@@ -73,3 +72,6 @@ convert i | i >= length ls || i < 0 = Failure ["Out of bounds"] | otherwise = Success $ fst $ ls !! i asInt s = maybeRead' s (s ++ " is not a valid int")++enumSelect :: (Show a, Bounded a, Enum a, Eq a) => Maybe a -> XHtmlForm IO a+enumSelect = select (zip items (map show items)) where items = [minBound ..]
formlets.cabal view
@@ -1,5 +1,5 @@ Name: formlets-Version: 0.4.7+Version: 0.4.8 Synopsis: Formlets implemented in Haskell Description: A modular way to build forms based on applicative functors, as described in:@@ -17,4 +17,10 @@ Exposed-Modules: Text.Formlets , Text.XHtml.Strict.Formlets Build-Type: Simple-Build-Depends: base, haskell98, mtl, xhtml, applicative-extras, bytestring+Build-Depends: base, + haskell98, + mtl, + xhtml, + applicative-extras >= 0.1.3, + bytestring+Extra-Source-Files: README