yesod 0.9.2.2 → 0.9.3
raw patch · 37 files changed
+716/−1190 lines, 37 files
Files
- Devel.hs +2/−2
- Scaffolding/Scaffolder.hs +39/−16
- scaffold/Application.hs.cg +15/−44
- scaffold/Foundation.hs.cg +35/−106
- scaffold/Handler/Root.hs.cg +1/−2
- scaffold/Settings.hs.cg +13/−155
- scaffold/Settings/StaticFiles.hs.cg +1/−10
- scaffold/cassius/default-layout.cassius.cg +0/−3
- scaffold/cassius/homepage.cassius.cg +0/−5
- scaffold/config/mongoDB.yml.cg +3/−0
- scaffold/config/postgresql.yml.cg +4/−0
- scaffold/config/settings.yml.cg +2/−2
- scaffold/config/sqlite.yml.cg +3/−0
- scaffold/deploy/Procfile.cg +25/−6
- scaffold/hamlet/boilerplate-layout.hamlet.cg +0/−1
- scaffold/hamlet/default-layout-wrapper.hamlet.cg +8/−0
- scaffold/hamlet/default-layout.hamlet.cg +3/−10
- scaffold/hamlet/homepage.hamlet.cg +1/−12
- scaffold/julius/homepage.julius.cg +1/−3
- scaffold/lucius/default-layout.lucius.cg +4/−0
- scaffold/lucius/homepage.lucius.cg +7/−0
- scaffold/lucius/normalize.lucius.cg +439/−0
- scaffold/main.hs.cg +4/−66
- scaffold/messages/en.msg.cg +1/−0
- scaffold/mongoDBConnPool.cg +4/−12
- scaffold/postgresqlConnPool.cg +3/−16
- scaffold/project.cabal.cg +21/−40
- scaffold/sqliteConnPool.cg +3/−11
- scaffold/static/css/normalize.css.cg +0/−439
- scaffold/static/js/modernizr.js.cg +4/−0
- scaffold/tiny/Application.hs.cg +7/−26
- scaffold/tiny/Foundation.hs.cg +25/−19
- scaffold/tiny/Handler/Root.hs.cg +0/−18
- scaffold/tiny/Settings.hs.cg +9/−133
- scaffold/tiny/hamlet/homepage.hamlet.cg +0/−2
- scaffold/tiny/project.cabal.cg +15/−24
- yesod.cabal +14/−7
Devel.hs view
@@ -66,8 +66,8 @@ checkCabalFile gpd _ <- if isDevel- then rawSystem "cabal-dev" ["configure", "--cabal-install-arg=-fdevel"]- else rawSystem "cabal" ["configure", "-fdevel"]+ then rawSystem "cabal-dev" ["configure", "--cabal-install-arg=-fdevel", "--disable-library-profiling"]+ else rawSystem "cabal" ["configure", "-fdevel", "--disable-library-profiling"] T.writeFile "dist/devel.hs" (develFile pid)
Scaffolding/Scaffolder.hs view
@@ -66,9 +66,9 @@ backendC <- prompt $ flip elem $ map (return . toLower . head . show) backends let (backend, importGenericDB, dbMonad, importPersist, mkPersistSettings) = case backendC of- "s" -> (Sqlite, "GenericSql", "SqlPersist", "Sqlite\n", "sqlSettings")- "p" -> (Postgresql, "GenericSql", "SqlPersist", "Postgresql\n", "sqlSettings")- "m" -> (MongoDB, "MongoDB", "Action", "MongoDB\nimport Control.Applicative (Applicative)\n", "MkPersistSettings { mpsBackend = ConT ''Action }")+ "s" -> (Sqlite, "GenericSql", "SqlPersist", "Sqlite", "sqlSettings")+ "p" -> (Postgresql, "GenericSql", "SqlPersist", "Postgresql", "sqlSettings")+ "m" -> (MongoDB, "MongoDB", "Action", "MongoDB", "MkPersistSettings { mpsBackend = ConT ''Action }") "t" -> (Tiny, "","","",undefined) _ -> error $ "Invalid backend: " ++ backendC (modelImports) = case backend of@@ -84,8 +84,27 @@ let runMigration = case backend of MongoDB -> ""- _ -> "\n runConnectionPool (runMigration migrateAll) p"+ _ -> "\n Database.Persist.Base.runPool dbconf (runMigration migrateAll) p" + let importMigration =+ case backend of+ MongoDB -> ""+ _ -> "\nimport Database.Persist.GenericSql (runMigration)"++ let dbConfigFile =+ case backend of+ MongoDB -> "mongoDB"+ Sqlite -> "sqlite"+ Postgresql -> "postgres"+ Tiny -> error "Accessing dbConfigFile for Tiny"++ let configPersist =+ case backend of+ MongoDB -> "MongoConf"+ Sqlite -> "SqliteConf"+ Postgresql -> "PostgresConf"+ Tiny -> error "Accessing configPersist for Tiny"+ putStrLn "That's it! I'm creating your files now..." let withConnectionPool = case backend of@@ -94,10 +113,6 @@ MongoDB -> $(codegen $ "mongoDBConnPool") Tiny -> "" - settingsTextImport = case backend of- Postgresql -> "import Data.Text (Text, pack, concat)\nimport Prelude hiding (concat)"- _ -> "import Data.Text (Text, pack)"- packages = if backend == MongoDB then " , persistent-mongoDB >= 0.6.1 && < 0.7\n , mongoDB >= 1.1\n , bson >= 0.1.5\n"@@ -124,6 +139,7 @@ mkDir "Model" mkDir "deploy" mkDir "Settings"+ mkDir "messages" writeFile' ("deploy/Procfile") $(codegen "deploy/Procfile") @@ -143,24 +159,31 @@ writeFile' "LICENSE" $(codegen "LICENSE") writeFile' ("Foundation.hs") $ ifTiny $(codegen "tiny/Foundation.hs") $(codegen "Foundation.hs") writeFile' "Application.hs" $ ifTiny $(codegen "tiny/Application.hs") $(codegen "Application.hs")- writeFile' "Handler/Root.hs" $ ifTiny $(codegen "tiny/Handler/Root.hs") $(codegen "Handler/Root.hs")+ writeFile' "Handler/Root.hs" $(codegen "Handler/Root.hs") unless isTiny $ writeFile' "Model.hs" $(codegen "Model.hs") writeFile' "Settings.hs" $ ifTiny $(codegen "tiny/Settings.hs") $(codegen "Settings.hs") writeFile' "Settings/StaticFiles.hs" $(codegen "Settings/StaticFiles.hs")- writeFile' "cassius/default-layout.cassius"- $(codegen "cassius/default-layout.cassius")+ writeFile' "lucius/default-layout.lucius"+ $(codegen "lucius/default-layout.lucius") writeFile' "hamlet/default-layout.hamlet" $(codegen "hamlet/default-layout.hamlet")+ writeFile' "hamlet/default-layout-wrapper.hamlet"+ $(codegen "hamlet/default-layout-wrapper.hamlet") writeFile' "hamlet/boilerplate-layout.hamlet" $(codegen "hamlet/boilerplate-layout.hamlet")- writeFile' "static/css/normalize.css"- $(codegen "static/css/normalize.css")- writeFile' "hamlet/homepage.hamlet" $ ifTiny $(codegen "tiny/hamlet/homepage.hamlet") $(codegen "hamlet/homepage.hamlet")+ writeFile' "lucius/normalize.lucius"+ $(codegen "lucius/normalize.lucius")+ writeFile' "hamlet/homepage.hamlet" $(codegen "hamlet/homepage.hamlet") writeFile' "config/routes" $ ifTiny $(codegen "tiny/config/routes") $(codegen "config/routes")- writeFile' "cassius/homepage.cassius" $(codegen "cassius/homepage.cassius")+ writeFile' "lucius/homepage.lucius" $(codegen "lucius/homepage.lucius") writeFile' "julius/homepage.julius" $(codegen "julius/homepage.julius") unless isTiny $ writeFile' "config/models" $(codegen "config/models")- + writeFile' "messages/en.msg" $(codegen "messages/en.msg")++ S.writeFile (dir ++ "/static/js/modernizr.js")+ $(runIO (S.readFile "scaffold/static/js/modernizr.js.cg") >>= \bs ->+ [|S.pack $(return $ LitE $ StringL $ S.unpack bs)|])+ S.writeFile (dir ++ "/config/favicon.ico") $(runIO (S.readFile "scaffold/config/favicon.ico.cg") >>= \bs -> do pack <- [|S.pack|]
scaffold/Application.hs.cg view
@@ -1,6 +1,5 @@ {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE CPP #-} {-# OPTIONS_GHC -fno-warn-orphans #-} module Application@@ -10,19 +9,15 @@ import Foundation import Settings-import Settings.StaticFiles (static)+import Yesod.Static import Yesod.Auth-import Yesod.Logger (makeLogger, flushLogger, Logger, logString, logLazyText)-import Database.Persist.~importGenericDB~+import Yesod.Default.Config+import Yesod.Default.Main+import Yesod.Default.Handlers+import Yesod.Logger (Logger) import Data.ByteString (ByteString) import Data.Dynamic (Dynamic, toDyn)-import Network.Wai.Middleware.Debug (debugHandle)--#ifndef WINDOWS-import qualified System.Posix.Signals as Signal-import Control.Concurrent (forkIO, killThread)-import Control.Concurrent.MVar (newEmptyMVar, putMVar, takeMVar)-#endif+import qualified Database.Persist.Base~importMigration~ -- Import all relevant handler modules here. import Handler.Root@@ -32,47 +27,23 @@ -- the comments there for more details. mkYesodDispatch "~sitearg~" resources~sitearg~ --- Some default handlers that ship with the Yesod site template. You will--- very rarely need to modify this.-getFaviconR :: Handler ()-getFaviconR = sendFile "image/x-icon" "config/favicon.ico"--getRobotsR :: Handler RepPlain-getRobotsR = return $ RepPlain $ toContent ("User-agent: *" :: ByteString)- -- This function allocates resources (such as a database connection pool), -- performs initialization and creates a WAI application. This is also the -- place to put your migrate statements to have automatic database -- migrations handled by Yesod.-with~sitearg~ :: AppConfig -> Logger -> (Application -> IO a) -> IO ()+with~sitearg~ :: AppConfig DefaultEnv -> Logger -> (Application -> IO ()) -> IO () with~sitearg~ conf logger f = do+#ifdef PRODUCTION s <- static Settings.staticDir- Settings.withConnectionPool conf $ \p -> do~runMigration~- let h = ~sitearg~ conf logger s p-#ifdef WINDOWS- toWaiApp h >>= f >> return () #else- tid <- forkIO $ toWaiApp h >>= f >> return ()- flag <- newEmptyMVar- _ <- Signal.installHandler Signal.sigINT (Signal.CatchOnce $ do- putStrLn "Caught an interrupt"- killThread tid- putMVar flag ()) Nothing- takeMVar flag+ s <- staticDevel Settings.staticDir #endif+ dbconf <- withYamlEnvironment "config/~dbConfigFile~.yml" (appEnv conf)+ $ either error return . Database.Persist.Base.loadConfig+ Database.Persist.Base.withPool (dbconf :: Settings.PersistConfig) $ \p -> do~runMigration~+ let h = ~sitearg~ conf logger s p+ defaultRunner f h -- for yesod devel withDevelAppPort :: Dynamic-withDevelAppPort =- toDyn go- where- go :: ((Int, Application) -> IO ()) -> IO ()- go f = do- conf <- Settings.loadConfig Settings.Development- let port = appPort conf- logger <- makeLogger- logString logger $ "Devel application launched, listening on port " ++ show port- with~sitearg~ conf logger $ \app -> f (port, debugHandle (logHandle logger) app)- flushLogger logger- where- logHandle logger msg = logLazyText logger msg >> flushLogger logger+withDevelAppPort = toDyn $ defaultDevelApp with~sitearg~
scaffold/Foundation.hs.cg view
@@ -4,6 +4,7 @@ module Foundation ( ~sitearg~ (..) , ~sitearg~Route (..)+ , ~sitearg~Message (..) , resources~sitearg~ , Handler , Widget@@ -21,36 +22,38 @@ import Settings.StaticFiles import Yesod.Auth import Yesod.Auth.OpenId-import Yesod.Auth.Email+import Yesod.Default.Config+import Yesod.Default.Util (addStaticContentExternal) import Yesod.Logger (Logger, logLazyText) import qualified Settings-import System.Directory import qualified Data.ByteString.Lazy as L+import qualified Database.Persist.Base import Database.Persist.~importGenericDB~-import Settings (hamletFile, cassiusFile, luciusFile, juliusFile, widgetFile)+import Settings (widgetFile) import Model-import Data.Maybe (isJust)-import Control.Monad (join, unless)-import Network.Mail.Mime-import qualified Data.Text.Lazy.Encoding import Text.Jasmine (minifym)-import qualified Data.Text as T import Web.ClientSession (getKey)-import Text.Blaze.Renderer.Utf8 (renderHtml)-import Text.Hamlet (shamlet)-import Text.Shakespeare.Text (stext)+import Text.Hamlet (hamletFile)+#if PRODUCTION+import Network.Mail.Mime (sendmail)+#else+import qualified Data.Text.Lazy.Encoding+#endif -- | The site argument for your application. This can be a good place to -- keep settings and values requiring initialization before your application -- starts running, such as database connections. Every handler will have -- access to the data present here. data ~sitearg~ = ~sitearg~- { settings :: Settings.AppConfig+ { settings :: AppConfig DefaultEnv , getLogger :: Logger , getStatic :: Static -- ^ Settings for static file serving.- , connPool :: Settings.ConnectionPool -- ^ Database connection pool.+ , connPool :: Database.Persist.Base.PersistConfigPool Settings.PersistConfig -- ^ Database connection pool. } +-- Set up i18n messages. See the message folder.+mkMessage "~sitearg~" "messages" "en"+ -- This is where we define all of the routes in our application. For a full -- explanation of the syntax, please see: -- http://www.yesodweb.com/book/handler@@ -75,17 +78,24 @@ -- Please see the documentation for the Yesod typeclass. There are a number -- of settings which can be configured by overriding methods here. instance Yesod ~sitearg~ where- approot = Settings.appRoot . settings+ approot = appRoot . settings -- Place the session key file in the config folder encryptKey _ = fmap Just $ getKey "config/client_session_key.aes" defaultLayout widget = do mmsg <- getMessage++ -- We break up the default layout into two components:+ -- default-layout is the contents of the body tag, and+ -- default-layout-wrapper is the entire page. Since the final+ -- value passed to hamletToRepHtml cannot be a widget, this allows+ -- you to use normal widget features in default-layout.+ pc <- widgetToPageContent $ do- widget- addCassius $(cassiusFile "default-layout")- hamletToRepHtml $(hamletFile "default-layout")+ $(widgetFile "normalize")+ $(widgetFile "default-layout")+ hamletToRepHtml $(hamletFile "hamlet/default-layout-wrapper.hamlet") -- This is done to provide an optimization for serving static files from -- a separate domain. Please see the staticRoot setting in Settings.hs@@ -103,27 +113,16 @@ -- and names them based on a hash of their content. This allows -- expiration dates to be set far in the future without worry of -- users receiving stale content.- addStaticContent ext' _ content = do- let fn = base64md5 content ++ '.' : T.unpack ext'- let content' =- if ext' == "js"- then case minifym content of- Left _ -> content- Right y -> y- else content- let statictmp = Settings.staticDir ++ "/tmp/"- liftIO $ createDirectoryIfMissing True statictmp- let fn' = statictmp ++ fn- exists <- liftIO $ doesFileExist fn'- unless exists $ liftIO $ L.writeFile fn' content'- return $ Just $ Right (StaticR $ StaticRoute ["tmp", T.pack fn] [], [])+ addStaticContent = addStaticContentExternal minifym base64md5 Settings.staticDir (StaticR . flip StaticRoute []) + -- Enable Javascript async loading+ yepnopeJs _ = Just $ Right $ StaticR js_modernizr_js -- How to run database actions. instance YesodPersist ~sitearg~ where type YesodPersistBackend ~sitearg~ = ~dbMonad~ runDB f = liftIOHandler- $ fmap connPool getYesod >>= Settings.runConnectionPool f+ $ fmap connPool getYesod >>= Database.Persist.Base.runPool (undefined :: Settings.PersistConfig) f instance YesodAuth ~sitearg~ where type AuthId ~sitearg~ = UserId@@ -140,9 +139,8 @@ Nothing -> do fmap Just $ insert $ User (credsIdent creds) Nothing - authPlugins = [ authOpenId- , authEmail- ]+ -- You can add other plugins like BrowserID, email or OAuth here+ authPlugins = [authOpenId] -- Sends off your mail. Requires sendmail in production! deliver :: ~sitearg~ -> L.ByteString -> IO ()@@ -152,76 +150,7 @@ deliver y = logLazyText (getLogger y) . Data.Text.Lazy.Encoding.decodeUtf8 #endif -instance YesodAuthEmail ~sitearg~ where- type AuthEmailId ~sitearg~ = EmailId-- addUnverified email verkey =- runDB $ insert $ Email email Nothing $ Just verkey-- sendVerifyEmail email _ verurl = do- y <- getYesod- liftIO $ deliver y =<< renderMail' Mail- {- mailHeaders =- [ ("From", "noreply")- , ("To", email)- , ("Subject", "Verify your email address")- ]- , mailParts = [[textPart, htmlPart]]- }- where- textPart = Part- { partType = "text/plain; charset=utf-8"- , partEncoding = None- , partFilename = Nothing- , partContent = Data.Text.Lazy.Encoding.encodeUtf8 [stext|-Please confirm your email address by clicking on the link below.--\#{verurl}--Thank you-|]- , partHeaders = []- }- htmlPart = Part- { partType = "text/html; charset=utf-8"- , partEncoding = None- , partFilename = Nothing- , partContent = renderHtml [~qq~shamlet|-<p>Please confirm your email address by clicking on the link below.-<p>- <a href=#{verurl}>#{verurl}-<p>Thank you-|]- , partHeaders = []- }- getVerifyKey = runDB . fmap (join . fmap emailVerkey) . get- setVerifyKey eid key = runDB $ update eid [EmailVerkey =. Just key]- verifyAccount eid = runDB $ do- me <- get eid- case me of- Nothing -> return Nothing- Just e -> do- let email = emailEmail e- case emailUser e of- Just uid -> return $ Just uid- Nothing -> do- uid <- insert $ User email Nothing- update eid [EmailUser =. Just uid, EmailVerkey =. Nothing]- return $ Just uid- getPassword = runDB . fmap (join . fmap userPassword) . get- setPassword uid pass = runDB $ update uid [UserPassword =. Just pass]- getEmailCreds email = runDB $ do- me <- getBy $ UniqueEmail email- case me of- Nothing -> return Nothing- Just (eid, e) -> return $ Just EmailCreds- { emailCredsId = eid- , emailCredsAuthId = emailUser e- , emailCredsStatus = isJust $ emailUser e- , emailCredsVerkey = emailVerkey e- }- getEmail = runDB . fmap (fmap emailEmail) . get-+-- This instance is required to use forms. You can modify renderMessage to+-- achieve customized and internationalized form validation messages. instance RenderMessage ~sitearg~ FormMessage where renderMessage _ _ = defaultFormMessage
scaffold/Handler/Root.hs.cg view
@@ -12,8 +12,7 @@ -- inclined, or create a single monolithic file. getRootR :: Handler RepHtml getRootR = do- mu <- maybeAuth defaultLayout $ do h2id <- lift newIdent setTitle "~project~ homepage"- addWidget $(widgetFile "homepage")+ $(widgetFile "homepage")
scaffold/Settings.hs.cg view
@@ -7,100 +7,21 @@ -- by overriding methods in the Yesod typeclass. That instance is -- declared in the Foundation.hs file. module Settings- ( hamletFile- , cassiusFile- , juliusFile- , luciusFile- , textFile- , widgetFile- , ConnectionPool- , withConnectionPool- , runConnectionPool+ ( widgetFile+ , PersistConfig , staticRoot , staticDir- , loadConfig- , AppEnvironment(..)- , AppConfig(..) ) where -import qualified Text.Hamlet as S-import qualified Text.Cassius as S-import qualified Text.Julius as S-import qualified Text.Lucius as S-import qualified Text.Shakespeare.Text as S import Text.Shakespeare.Text (st) import Language.Haskell.TH.Syntax-import Database.Persist.~importPersist~-import Yesod (liftIO, MonadControlIO, addWidget, addCassius, addJulius, addLucius, whamletFile)-import Data.Monoid (mempty)-import System.Directory (doesFileExist)-~settingsTextImport~-import Data.Object-import qualified Data.Object.Yaml as YAML-import Control.Monad (join)--data AppEnvironment = Test- | Development- | Staging- | Production- deriving (Eq, Show, Read, Enum, Bounded)---- | Dynamic per-environment configuration loaded from the YAML file Settings.yaml.--- Use dynamic settings to avoid the need to re-compile the application (between staging and production environments).------ By convention these settings should be overwritten by any command line arguments.--- See config/Foundation.hs for command line arguments--- Command line arguments provide some convenience but are also required for hosting situations where a setting is read from the environment (appPort on Heroku).----data AppConfig = AppConfig {- appEnv :: AppEnvironment-- , appPort :: Int-- -- | Your application will keep a connection pool and take connections from- -- there as necessary instead of continually creating new connections. This- -- value gives the maximum number of connections to be open at a given time.- -- If your application requests a connection when all connections are in- -- use, that request will fail. Try to choose a number that will work well- -- with the system resources available to you while providing enough- -- connections for your expected load.- --- -- Connections are returned to the pool as quickly as possible by- -- Yesod to avoid resource exhaustion. A connection is only considered in- -- use while within a call to runDB.- , connectionPoolSize :: Int-- -- | The base URL for your application. This will usually be different for- -- development and production. Yesod automatically constructs URLs for you,- -- so this value must be accurate to create valid links.- -- Please note that there is no trailing slash.- --- -- You probably want to change this! If your domain name was "yesod.com",- -- you would probably want it to be:- -- > "http://yesod.com"- , appRoot :: Text-} deriving (Show)+import Database.Persist.~importPersist~ (~configPersist~)+import Yesod.Default.Config+import qualified Yesod.Default.Util+import Data.Text (Text) -loadConfig :: AppEnvironment -> IO AppConfig-loadConfig env = do- allSettings <- (join $ YAML.decodeFile ("config/settings.yml" :: String)) >>= fromMapping- settings <- lookupMapping (show env) allSettings- hostS <- lookupScalar "host" settings- port <- fmap read $ lookupScalar "port" settings- connectionPoolSizeS <- lookupScalar "connectionPoolSize" settings- return $ AppConfig {- appEnv = env- , appPort = port- , appRoot = pack $ hostS ++ addPort port- , connectionPoolSize = read connectionPoolSizeS- }- where- addPort :: Int -> String-#ifdef PRODUCTION- addPort _ = ""-#else- addPort p = ":" ++ (show p)-#endif+-- | Which Persistent backend this site is using.+type PersistConfig = ~configPersist~ -- Static setting below. Changing these requires a recompile @@ -122,79 +43,16 @@ -- have to make a corresponding change here. -- -- To see how this value is used, see urlRenderOverride in Foundation.hs-staticRoot :: AppConfig -> Text+staticRoot :: AppConfig DefaultEnv -> Text staticRoot conf = [st|#{appRoot conf}/static|] -- The rest of this file contains settings which rarely need changing by a -- user. --- The next functions are for allocating a connection pool and running--- database actions using a pool, respectively. They are used internally--- by the scaffolded application, and therefore you will rarely need to use--- them yourself.-~withConnectionPool~---- The following functions are used for calling HTML, CSS,--- Javascript, and plain text templates from your Haskell code. During development,--- the "Debug" versions of these functions are used so that changes to--- the templates are immediately reflected in an already running--- application. When making a production compile, the non-debug version--- is used for increased performance.------ You can see an example of how to call these functions in Handler/Root.hs------ Note: due to polymorphic Hamlet templates, hamletFileDebug is no longer--- used; to get the same auto-loading effect, it is recommended that you--- use the devel server.---- | expects a root folder for each type, e.g: hamlet/ lucius/ julius/-globFile :: String -> String -> FilePath-globFile kind x = kind ++ "/" ++ x ++ "." ++ kind--hamletFile :: FilePath -> Q Exp-hamletFile = S.hamletFile . globFile "hamlet"--cassiusFile :: FilePath -> Q Exp-cassiusFile = -#ifdef PRODUCTION- S.cassiusFile . globFile "cassius"-#else- S.cassiusFileDebug . globFile "cassius"-#endif--luciusFile :: FilePath -> Q Exp-luciusFile = -#ifdef PRODUCTION- S.luciusFile . globFile "lucius"-#else- S.luciusFileDebug . globFile "lucius"-#endif--juliusFile :: FilePath -> Q Exp-juliusFile =-#ifdef PRODUCTION- S.juliusFile . globFile "julius"-#else- S.juliusFileDebug . globFile "julius"-#endif--textFile :: FilePath -> Q Exp-textFile =-#ifdef PRODUCTION- S.textFile . globFile "text"+widgetFile :: String -> Q Exp+#if PRODUCTION+widgetFile = Yesod.Default.Util.widgetFileProduction #else- S.textFileDebug . globFile "text"+widgetFile = Yesod.Default.Util.widgetFileDebug #endif--widgetFile :: FilePath -> Q Exp-widgetFile x = do- let h = whenExists (globFile "hamlet") (whamletFile . globFile "hamlet")- let c = whenExists (globFile "cassius") cassiusFile- let j = whenExists (globFile "julius") juliusFile- let l = whenExists (globFile "lucius") luciusFile- [|addWidget $h >> addCassius $c >> addJulius $j >> addLucius $l|]- where- whenExists tofn f = do- e <- qRunIO $ doesFileExist $ tofn x- if e then f x else [|mempty|]
scaffold/Settings/StaticFiles.hs.cg view
@@ -1,16 +1,7 @@ {-# LANGUAGE CPP, QuasiQuotes, TemplateHaskell, TypeFamilies #-} module Settings.StaticFiles where -import Yesod.Static-import qualified Yesod.Static as Static--static :: FilePath -> IO Static-#ifdef PRODUCTION-static = Static.static-#else-static = Static.staticDevel-#endif-+import Yesod.Static (staticFiles, StaticRoute (StaticRoute)) -- | This generates easy references to files in the static directory at compile time. -- The upside to this is that you have compile-time verification that referenced files
− scaffold/cassius/default-layout.cassius.cg
@@ -1,3 +0,0 @@-body- font-family: sans-serif-
− scaffold/cassius/homepage.cassius.cg
@@ -1,5 +0,0 @@-h1- text-align: center-h2##{h2id}- color: #990-
scaffold/config/mongoDB.yml.cg view
@@ -4,6 +4,7 @@ host: localhost port: 27017 database: ~project~+ poolsize: 10 Development: <<: *defaults@@ -14,8 +15,10 @@ Staging: database: ~project~_staging+ poolsize: 100 <<: *defaults Production: database: ~project~_production+ poolsize: 100 <<: *defaults
scaffold/config/postgresql.yml.cg view
@@ -4,6 +4,7 @@ host: localhost port: 5432 database: ~project~+ poolsize: 10 Development: <<: *defaults@@ -14,7 +15,10 @@ Staging: database: ~project~_staging+ poolsize: 100+ <<: *defaults Production: database: ~project~_production+ poolsize: 100 <<: *defaults
scaffold/config/settings.yml.cg view
@@ -1,7 +1,6 @@ Default: &defaults- host: "http://localhost"+ host: "localhost" port: 3000- connectionPoolSize: 10 Development: <<: *defaults@@ -13,4 +12,5 @@ <<: *defaults Production:+ approot: "http://www.example.com" <<: *defaults
scaffold/config/sqlite.yml.cg view
@@ -1,5 +1,6 @@ Default: &defaults database: ~project~.sqlite3+ poolsize: 10 Development: <<: *defaults@@ -10,8 +11,10 @@ Staging: database: ~project~_staging.sqlite3+ poolsize: 100 <<: *defaults Production: database: ~project~_production.sqlite3+ poolsize: 100 <<: *defaults
scaffold/deploy/Procfile.cg view
@@ -1,20 +1,21 @@-# Simple and free deployment to Heroku.+# Free deployment to Heroku. # # !! Warning: You must use a 64 bit machine to compile !! # # This could mean using a virtual machine. Give your VM as much memory as you can to speed up linking. #-# Yesod setup:+# Basic Yesod setup: # # * Move this file out of the deploy directory and into your root directory # # mv deploy/Procfile ./ #-# * Create an empty Gemfile and Gemfile.lock-#-# touch Gemfile && touch Gemfile.lock+# * Create an empty package.json+# echo '{ "name": "~project~", "version": "0.0.1", "dependencies": {} }' >> package.json+# +# Postgresql Yesod setup: #-# * TODO: code to read DATABASE_URL environment variable.+# * add code to read DATABASE_URL environment variable. # # import System.Environment # main = do@@ -22,6 +23,22 @@ # # parse env variable # # pass settings to withConnectionPool instead of directly using loadConnStr #+# * add a dependency on the "heroku" package in your cabal file+# +# * add code in Settings.hs to turn that url into connection parameters. The below works for Postgresql.+#+# #ifdef PRODUCTION+# import qualified Web.Heroku+# #endif+#+# dbConnParams :: AppEnvironment -> IO [(Text, Text)]+# #ifdef PRODUCTION+# dbConnParams _ = Web.Heroku.dbConnParams+# #else+# dbConnParams env = do+# ...+#+# # Heroku setup: # Find the Heroku guide. Roughly: #@@ -36,7 +53,9 @@ # Repeat these steps to deploy: # * add your web executable binary (referenced below) to the git repository #+# git checkout deploy # git add ./dist/build/~project~/~project~+# git commit -m deploy # # * push to Heroku #
scaffold/hamlet/boilerplate-layout.hamlet.cg view
@@ -15,7 +15,6 @@ <title>#{pageTitle pc} - <link rel="stylesheet" href=@{StaticR css_normalize_css}> ^{pageHead pc} <!--[if lt IE 9]>
+ scaffold/hamlet/default-layout-wrapper.hamlet.cg view
@@ -0,0 +1,8 @@+!!!+<html>+ <head+ <title>#{pageTitle pc}+ ^{pageHead pc}+ <body+ ^{pageBody pc}+
scaffold/hamlet/default-layout.hamlet.cg view
@@ -1,11 +1,4 @@-!!!-<html- <head- <title>#{pageTitle pc}- <link rel="stylesheet" href=@{StaticR css_normalize_css}>- ^{pageHead pc}- <body- $maybe msg <- mmsg- <div #message>#{msg}- ^{pageBody pc}+$maybe msg <- mmsg+ <div #message>#{msg}+^{widget}
scaffold/hamlet/homepage.hamlet.cg view
@@ -1,13 +1,2 @@-<h1>Hello+<h1>_{MsgHello} <h2 ##{h2id}>You do not have Javascript enabled.-$maybe u <- mu- <p- You are logged in as #{userIdent $ snd u}. #- <a href=@{AuthR LogoutR}>Logout- .-$nothing- <p- You are not logged in. #- <a href=@{AuthR LoginR}>Login now- .-
scaffold/julius/homepage.julius.cg view
@@ -1,4 +1,2 @@-window.onload = function(){- document.getElementById("#{h2id}").innerHTML = "<i>Added from JavaScript.</i>";-}+document.getElementById("#{h2id}").innerHTML = "<i>Added from JavaScript.</i>";
+ scaffold/lucius/default-layout.lucius.cg view
@@ -0,0 +1,4 @@+body {+ font-family: sans-serif;+}+
+ scaffold/lucius/homepage.lucius.cg view
@@ -0,0 +1,7 @@+h1 {+ text-align: center+}+h2##{h2id} {+ color: #990+}+
+ scaffold/lucius/normalize.lucius.cg view
@@ -0,0 +1,439 @@+/*! normalize.css 2011-08-12T17:28 UTC · http://github.com/necolas/normalize.css */++/* =============================================================================+ HTML5 display definitions+ ========================================================================== */++/*+ * Corrects block display not defined in IE6/7/8/9 & FF3+ */++article,+aside,+details,+figcaption,+figure,+footer,+header,+hgroup,+nav,+section {+ display: block;+}++/*+ * Corrects inline-block display not defined in IE6/7/8/9 & FF3+ */++audio,+canvas,+video {+ display: inline-block;+ *display: inline;+ *zoom: 1;+}++/*+ * Prevents modern browsers from displaying 'audio' without controls+ */++audio:not([controls]) {+ display: none;+}++/*+ * Addresses styling for 'hidden' attribute not present in IE7/8/9, FF3, S4+ * Known issue: no IE6 support+ */++[hidden] {+ display: none;+}+++/* =============================================================================+ Base+ ========================================================================== */++/*+ * 1. Corrects text resizing oddly in IE6/7 when body font-size is set using em units+ * http://clagnut.com/blog/348/#c790+ * 2. Keeps page centred in all browsers regardless of content height+ * 3. Prevents iOS text size adjust after orientation change, without disabling user zoom+ * www.456bereastreet.com/archive/201012/controlling_text_size_in_safari_for_ios_without_disabling_user_zoom/+ */++html {+ font-size: 100%; /* 1 */+ overflow-y: scroll; /* 2 */+ -webkit-text-size-adjust: 100%; /* 3 */+ -ms-text-size-adjust: 100%; /* 3 */+}++/*+ * Addresses margins handled incorrectly in IE6/7+ */++body {+ margin: 0;+}++/* + * Addresses font-family inconsistency between 'textarea' and other form elements.+ */++body,+button,+input,+select,+textarea {+ font-family: sans-serif;+}+++/* =============================================================================+ Links+ ========================================================================== */++a {+ color: #00e;+}++a:visited {+ color: #551a8b;+}++/*+ * Addresses outline displayed oddly in Chrome+ */++a:focus {+ outline: thin dotted;+}++/*+ * Improves readability when focused and also mouse hovered in all browsers+ * people.opera.com/patrickl/experiments/keyboard/test+ */++a:hover,+a:active {+ outline: 0;+}+++/* =============================================================================+ Typography+ ========================================================================== */++/*+ * Addresses styling not present in IE7/8/9, S5, Chrome+ */++abbr[title] {+ border-bottom: 1px dotted;+}++/*+ * Addresses style set to 'bolder' in FF3/4, S4/5, Chrome+*/++b, +strong { + font-weight: bold; +}++blockquote {+ margin: 1em 40px;+}++/*+ * Addresses styling not present in S5, Chrome+ */++dfn {+ font-style: italic;+}++/*+ * Addresses styling not present in IE6/7/8/9+ */++mark {+ background: #ff0;+ color: #000;+}++/*+ * Corrects font family set oddly in IE6, S4/5, Chrome+ * en.wikipedia.org/wiki/User:Davidgothberg/Test59+ */++pre,+code,+kbd,+samp {+ font-family: monospace, serif;+ _font-family: 'courier new', monospace;+ font-size: 1em;+}++/*+ * Improves readability of pre-formatted text in all browsers+ */++pre {+ white-space: pre;+ white-space: pre-wrap;+ word-wrap: break-word;+}++/*+ * 1. Addresses CSS quotes not supported in IE6/7+ * 2. Addresses quote property not supported in S4+ */++/* 1 */++q {+ quotes: none;+}++/* 2 */++q:before,+q:after {+ content: '';+ content: none;+}++small {+ font-size: 75%;+}++/*+ * Prevents sub and sup affecting line-height in all browsers+ * gist.github.com/413930+ */++sub,+sup {+ font-size: 75%;+ line-height: 0;+ position: relative;+ vertical-align: baseline;+}++sup {+ top: -0.5em;+}++sub {+ bottom: -0.25em;+}+++/* =============================================================================+ Lists+ ========================================================================== */++ul,+ol {+ margin: 1em 0;+ padding: 0 0 0 40px;+}++dd {+ margin: 0 0 0 40px;+}++nav ul,+nav ol {+ list-style: none;+ list-style-image: none;+}+++/* =============================================================================+ Embedded content+ ========================================================================== */++/*+ * 1. Removes border when inside 'a' element in IE6/7/8/9+ * 2. Improves image quality when scaled in IE7+ * code.flickr.com/blog/2008/11/12/on-ui-quality-the-little-things-client-side-image-resizing/+ */++img {+ border: 0; /* 1 */+ -ms-interpolation-mode: bicubic; /* 2 */+}++/*+ * Corrects overflow displayed oddly in IE9 + */++svg:not(:root) {+ overflow: hidden;+}+++/* =============================================================================+ Figures+ ========================================================================== */++/*+ * Addresses margin not present in IE6/7/8/9, S5, O11+ */++figure {+ margin: 0;+}+++/* =============================================================================+ Forms+ ========================================================================== */++/*+ * Corrects margin displayed oddly in IE6/7+ */++form {+ margin: 0;+}++/*+ * Define consistent margin and padding+ */++fieldset {+ margin: 0 2px;+ padding: 0.35em 0.625em 0.75em;+}++/*+ * 1. Corrects color not being inherited in IE6/7/8/9+ * 2. Corrects alignment displayed oddly in IE6/7+ */++legend {+ border: 0; /* 1 */+ *margin-left: -7px; /* 2 */+}++/*+ * 1. Corrects font size not being inherited in all browsers+ * 2. Addresses margins set differently in IE6/7, F3/4, S5, Chrome+ * 3. Improves appearance and consistency in all browsers+ */++button,+input,+select,+textarea {+ font-size: 100%; /* 1 */+ margin: 0; /* 2 */+ vertical-align: baseline; /* 3 */+ *vertical-align: middle; /* 3 */+}++/*+ * 1. Addresses FF3/4 setting line-height using !important in the UA stylesheet+ * 2. Corrects inner spacing displayed oddly in IE6/7+ */++button,+input {+ line-height: normal; /* 1 */+ *overflow: visible; /* 2 */+}++/*+ * Corrects overlap and whitespace issue for buttons and inputs in IE6/7+ * Known issue: reintroduces inner spacing+ */++table button,+table input {+ *overflow: auto;+}++/*+ * 1. Improves usability and consistency of cursor style between image-type 'input' and others+ * 2. Corrects inability to style clickable 'input' types in iOS+ */++button,+html input[type="button"], +input[type="reset"], +input[type="submit"] {+ cursor: pointer; /* 1 */+ -webkit-appearance: button; /* 2 */+}++/*+ * 1. Addresses box sizing set to content-box in IE8/9+ * 2. Addresses excess padding in IE8/9+ */++input[type="checkbox"],+input[type="radio"] {+ box-sizing: border-box; /* 1 */+ padding: 0; /* 2 */+}++/*+ * 1. Addresses appearance set to searchfield in S5, Chrome+ * 2. Addresses box sizing set to border-box in S5, Chrome (include -moz to future-proof)+ */++input[type="search"] {+ -webkit-appearance: textfield; /* 1 */+ -moz-box-sizing: content-box;+ -webkit-box-sizing: content-box; /* 2 */+ box-sizing: content-box;+}++/*+ * Corrects inner padding displayed oddly in S5, Chrome on OSX+ */++input[type="search"]::-webkit-search-decoration {+ -webkit-appearance: none;+}++/*+ * Corrects inner padding and border displayed oddly in FF3/4+ * www.sitepen.com/blog/2008/05/14/the-devils-in-the-details-fixing-dojos-toolbar-buttons/+ */++button::-moz-focus-inner,+input::-moz-focus-inner {+ border: 0;+ padding: 0;+}++/*+ * 1. Removes default vertical scrollbar in IE6/7/8/9+ * 2. Improves readability and alignment in all browsers+ */++textarea {+ overflow: auto; /* 1 */+ vertical-align: top; /* 2 */+}+++/* =============================================================================+ Tables+ ========================================================================== */++/* + * Remove most spacing between table cells+ */++table {+ border-collapse: collapse;+ border-spacing: 0;+}
scaffold/main.hs.cg view
@@ -1,68 +1,6 @@-{-# LANGUAGE CPP, DeriveDataTypeable #-}-import Settings (AppEnvironment(..), AppConfig(..), loadConfig)-import Application (with~sitearg~)-import Network.Wai.Handler.Warp (run)-import System.Console.CmdArgs hiding (args)-import Data.Char (toUpper, toLower)--#ifndef PRODUCTION-import Network.Wai.Middleware.Debug (debugHandle)-import Yesod.Logger (logString, logLazyText, flushLogger, makeLogger)-#else-import Yesod.Logger (makeLogger)-#endif+import Yesod.Default.Config (fromArgs)+import Yesod.Default.Main (defaultMain)+import Application (with~sitearg~) main :: IO ()-main = do- logger <- makeLogger- args <- cmdArgs argConfig- env <- getAppEnv args- config <- loadConfig env- let c = if port args /= 0- then config { appPort = port args }- else config--#if PRODUCTION- with~sitearg~ c logger $ run (appPort c)-#else- logString logger $ (show env) ++ " application launched, listening on port " ++ show (appPort c)- with~sitearg~ c logger $ run (appPort c) . debugHandle (logHandle logger)- flushLogger logger-- where- logHandle logger msg = logLazyText logger msg >> flushLogger logger-#endif--data ArgConfig = ArgConfig- { environment :: String- , port :: Int- } deriving (Show, Data, Typeable)--argConfig :: ArgConfig-argConfig = ArgConfig- { environment = def - &= help ("application environment, one of: " ++ (foldl1 (\a b -> a ++ ", " ++ b) environments))- &= typ "ENVIRONMENT"- , port = def- &= typ "PORT"- }--environments :: [String]-environments = map ((map toLower) . show) ([minBound..maxBound] :: [AppEnvironment])---- | retrieve the -e environment option-getAppEnv :: ArgConfig -> IO AppEnvironment-getAppEnv cfg = do- let e = if environment cfg /= ""- then environment cfg- else-#if PRODUCTION- "production"-#else- "development"-#endif- return $ read $ capitalize e-- where- capitalize [] = []- capitalize (x:xs) = toUpper x : map toLower xs+main = defaultMain fromArgs with~sitearg~
+ scaffold/messages/en.msg.cg view
@@ -0,0 +1,1 @@+Hello: Hello
scaffold/mongoDBConnPool.cg view
@@ -1,16 +1,8 @@ runConnectionPool :: MonadControlIO m => Action m a -> ConnectionPool -> m a runConnectionPool = runMongoDBConn (ConfirmWrites [u"j" =: True]) -withConnectionPool :: (MonadControlIO m, Applicative m) => AppConfig -> (ConnectionPool -> m b) -> m b+withConnectionPool :: (MonadControlIO m, Applicative m) => AppConfig DefaultEnv -> (ConnectionPool -> m b) -> m b withConnectionPool conf f = do- (database,host) <- liftIO $ loadConnParams (appEnv conf)- withMongoDBPool (u database) host (connectionPoolSize conf) f- where- -- | The database connection parameters.- -- loadConnParams :: AppEnvironment -> IO (Database, HostName)- loadConnParams env = do- allSettings <- (join $ YAML.decodeFile ("config/mongoDB.yml" :: String)) >>= fromMapping- settings <- lookupMapping (show env) allSettings- database <- lookupScalar "database" settings- host <- lookupScalar "host" settings- return (database, host)+ dbConf <- liftIO $ loadMongo (appEnv conf)+ withMongoDBPool (u $ mgDatabase dbConf) (mgHost dbConf) (mgPoolSize dbConf) f+
scaffold/postgresqlConnPool.cg view
@@ -1,23 +1,10 @@ runConnectionPool :: MonadControlIO m => SqlPersist m a -> ConnectionPool -> m a runConnectionPool = runSqlPool -withConnectionPool :: MonadControlIO m => AppConfig -> (ConnectionPool -> m a) -> m a+withConnectionPool :: MonadControlIO m => AppConfig DefaultEnv -> (ConnectionPool -> m a) -> m a withConnectionPool conf f = do- cs <- liftIO $ loadConnStr (appEnv conf)- with~upper~Pool cs (connectionPoolSize conf) f- where- -- | The database connection string. The meaning of this string is backend-- -- specific.- loadConnStr :: AppEnvironment -> IO Text- loadConnStr env = do- allSettings <- (join $ YAML.decodeFile ("config/~backendLower~.yml" :: String)) >>= fromMapping- settings <- lookupMapping (show env) allSettings- database <- lookupScalar "database" settings :: IO Text-- connPart <- fmap concat $ (flip mapM) ["user", "password", "host", "port"] $ \key -> do- value <- lookupScalar key settings- return $ [st| #{key}=#{value} |]- return $ [st|#{connPart} dbname=#{database}|]+ dbConf <- liftIO $ load~upper~ (appEnv conf)+ with~upper~Pool (pgConnStr dbConf) (pgPoolSize dbConf) f -- Example of making a dynamic configuration static -- use /return $(mkConnStr Production)/ instead of loadConnStr
scaffold/project.cabal.cg view
@@ -26,10 +26,6 @@ else Buildable: False - if os(windows)- cpp-options: -DWINDOWS-- hs-source-dirs: . exposed-modules: Application other-modules: Foundation Model@@ -37,6 +33,8 @@ Settings.StaticFiles Handler.Root + ghc-options: -Wall -threaded -O0+ executable ~project~ if flag(devel) Buildable: False@@ -45,43 +43,26 @@ cpp-options: -DPRODUCTION ghc-options: -Wall -threaded -O2 else- ghc-options: -Wall -threaded-- if os(windows)- cpp-options: -DWINDOWS+ ghc-options: -Wall -threaded -O0 main-is: main.hs- hs-source-dirs: . - build-depends: base >= 4 && < 5- , yesod >= 0.9 && < 0.10- , yesod-core- , yesod-auth- , yesod-static- , blaze-html- , yesod-form- , mime-mail- , clientsession- , wai-extra- , directory- , bytestring- , text- , persistent- , persistent-template- , persistent-~backendLower~ >= 0.6 && < 0.7- ~packages~+ build-depends: base >= 4 && < 5+ , yesod >= 0.9 && < 0.10+ , yesod-core >= 0.9.3 && < 0.10+ , yesod-auth >= 0.7.3 && < 0.8+ , yesod-static >= 0.3.1 && < 0.4+ , yesod-default >= 0.3.1 && < 0.4+ , yesod-form >= 0.3.3 && < 0.4+ , mime-mail >= 0.3.0.3 && < 0.4+ , clientsession >= 0.7.3 && < 0.8+ , bytestring >= 0.9 && < 0.10+ , text >= 0.11 && < 0.12+ , persistent >= 0.6.2 && < 0.7+ , persistent-~backendLower~ >= 0.6 && < 0.7 , template-haskell- , hamlet >= 0.10 && < 0.11- , shakespeare-css >= 0.10 && < 0.11- , shakespeare-js >= 0.10 && < 0.11- , shakespeare-text >= 0.10 && < 0.11- , hjsmin- , transformers- , data-object- , data-object-yaml- , warp- , blaze-builder- , cmdargs-- if !os(windows)- build-depends: unix+ , hamlet >= 0.10 && < 0.11+ , shakespeare-css >= 0.10 && < 0.11+ , shakespeare-js >= 0.10 && < 0.11+ , shakespeare-text >= 0.10 && < 0.11+ , hjsmin >= 0.0.14 && < 0.1
scaffold/sqliteConnPool.cg view
@@ -1,18 +1,10 @@ runConnectionPool :: MonadControlIO m => SqlPersist m a -> ConnectionPool -> m a runConnectionPool = runSqlPool -withConnectionPool :: MonadControlIO m => AppConfig -> (ConnectionPool -> m a) -> m a+withConnectionPool :: MonadControlIO m => AppConfig DefaultEnv -> (ConnectionPool -> m a) -> m a withConnectionPool conf f = do- cs <- liftIO $ loadConnStr (appEnv conf)- with~upper~Pool cs (connectionPoolSize conf) f- where- -- | The database connection string. The meaning of this string is backend-- -- specific.- loadConnStr :: AppEnvironment -> IO Text- loadConnStr env = do- allSettings <- (join $ YAML.decodeFile ("config/~backendLower~.yml" :: String)) >>= fromMapping- settings <- lookupMapping (show env) allSettings- lookupScalar "database" settings+ dbConf <- liftIO $ load~upper~ (appEnv conf)+ with~upper~Pool (sqlDatabase dbConf) (sqlPoolSize dbConf) f -- Example of making a dynamic configuration static -- use /return $(mkConnStr Production)/ instead of loadConnStr
− scaffold/static/css/normalize.css.cg
@@ -1,439 +0,0 @@-/*! normalize.css 2011-08-12T17:28 UTC · http://github.com/necolas/normalize.css */--/* =============================================================================- HTML5 display definitions- ========================================================================== */--/*- * Corrects block display not defined in IE6/7/8/9 & FF3- */--article,-aside,-details,-figcaption,-figure,-footer,-header,-hgroup,-nav,-section {- display: block;-}--/*- * Corrects inline-block display not defined in IE6/7/8/9 & FF3- */--audio,-canvas,-video {- display: inline-block;- *display: inline;- *zoom: 1;-}--/*- * Prevents modern browsers from displaying 'audio' without controls- */--audio:not([controls]) {- display: none;-}--/*- * Addresses styling for 'hidden' attribute not present in IE7/8/9, FF3, S4- * Known issue: no IE6 support- */--[hidden] {- display: none;-}---/* =============================================================================- Base- ========================================================================== */--/*- * 1. Corrects text resizing oddly in IE6/7 when body font-size is set using em units- * http://clagnut.com/blog/348/#c790- * 2. Keeps page centred in all browsers regardless of content height- * 3. Prevents iOS text size adjust after orientation change, without disabling user zoom- * www.456bereastreet.com/archive/201012/controlling_text_size_in_safari_for_ios_without_disabling_user_zoom/- */--html {- font-size: 100%; /* 1 */- overflow-y: scroll; /* 2 */- -webkit-text-size-adjust: 100%; /* 3 */- -ms-text-size-adjust: 100%; /* 3 */-}--/*- * Addresses margins handled incorrectly in IE6/7- */--body {- margin: 0;-}--/* - * Addresses font-family inconsistency between 'textarea' and other form elements.- */--body,-button,-input,-select,-textarea {- font-family: sans-serif;-}---/* =============================================================================- Links- ========================================================================== */--a {- color: #00e;-}--a:visited {- color: #551a8b;-}--/*- * Addresses outline displayed oddly in Chrome- */--a:focus {- outline: thin dotted;-}--/*- * Improves readability when focused and also mouse hovered in all browsers- * people.opera.com/patrickl/experiments/keyboard/test- */--a:hover,-a:active {- outline: 0;-}---/* =============================================================================- Typography- ========================================================================== */--/*- * Addresses styling not present in IE7/8/9, S5, Chrome- */--abbr[title] {- border-bottom: 1px dotted;-}--/*- * Addresses style set to 'bolder' in FF3/4, S4/5, Chrome-*/--b, -strong { - font-weight: bold; -}--blockquote {- margin: 1em 40px;-}--/*- * Addresses styling not present in S5, Chrome- */--dfn {- font-style: italic;-}--/*- * Addresses styling not present in IE6/7/8/9- */--mark {- background: #ff0;- color: #000;-}--/*- * Corrects font family set oddly in IE6, S4/5, Chrome- * en.wikipedia.org/wiki/User:Davidgothberg/Test59- */--pre,-code,-kbd,-samp {- font-family: monospace, serif;- _font-family: 'courier new', monospace;- font-size: 1em;-}--/*- * Improves readability of pre-formatted text in all browsers- */--pre {- white-space: pre;- white-space: pre-wrap;- word-wrap: break-word;-}--/*- * 1. Addresses CSS quotes not supported in IE6/7- * 2. Addresses quote property not supported in S4- */--/* 1 */--q {- quotes: none;-}--/* 2 */--q:before,-q:after {- content: '';- content: none;-}--small {- font-size: 75%;-}--/*- * Prevents sub and sup affecting line-height in all browsers- * gist.github.com/413930- */--sub,-sup {- font-size: 75%;- line-height: 0;- position: relative;- vertical-align: baseline;-}--sup {- top: -0.5em;-}--sub {- bottom: -0.25em;-}---/* =============================================================================- Lists- ========================================================================== */--ul,-ol {- margin: 1em 0;- padding: 0 0 0 40px;-}--dd {- margin: 0 0 0 40px;-}--nav ul,-nav ol {- list-style: none;- list-style-image: none;-}---/* =============================================================================- Embedded content- ========================================================================== */--/*- * 1. Removes border when inside 'a' element in IE6/7/8/9- * 2. Improves image quality when scaled in IE7- * code.flickr.com/blog/2008/11/12/on-ui-quality-the-little-things-client-side-image-resizing/- */--img {- border: 0; /* 1 */- -ms-interpolation-mode: bicubic; /* 2 */-}--/*- * Corrects overflow displayed oddly in IE9 - */--svg:not(:root) {- overflow: hidden;-}---/* =============================================================================- Figures- ========================================================================== */--/*- * Addresses margin not present in IE6/7/8/9, S5, O11- */--figure {- margin: 0;-}---/* =============================================================================- Forms- ========================================================================== */--/*- * Corrects margin displayed oddly in IE6/7- */--form {- margin: 0;-}--/*- * Define consistent margin and padding- */--fieldset {- margin: 0 2px;- padding: 0.35em 0.625em 0.75em;-}--/*- * 1. Corrects color not being inherited in IE6/7/8/9- * 2. Corrects alignment displayed oddly in IE6/7- */--legend {- border: 0; /* 1 */- *margin-left: -7px; /* 2 */-}--/*- * 1. Corrects font size not being inherited in all browsers- * 2. Addresses margins set differently in IE6/7, F3/4, S5, Chrome- * 3. Improves appearance and consistency in all browsers- */--button,-input,-select,-textarea {- font-size: 100%; /* 1 */- margin: 0; /* 2 */- vertical-align: baseline; /* 3 */- *vertical-align: middle; /* 3 */-}--/*- * 1. Addresses FF3/4 setting line-height using !important in the UA stylesheet- * 2. Corrects inner spacing displayed oddly in IE6/7- */--button,-input {- line-height: normal; /* 1 */- *overflow: visible; /* 2 */-}--/*- * Corrects overlap and whitespace issue for buttons and inputs in IE6/7- * Known issue: reintroduces inner spacing- */--table button,-table input {- *overflow: auto;-}--/*- * 1. Improves usability and consistency of cursor style between image-type 'input' and others- * 2. Corrects inability to style clickable 'input' types in iOS- */--button,-html input[type="button"], -input[type="reset"], -input[type="submit"] {- cursor: pointer; /* 1 */- -webkit-appearance: button; /* 2 */-}--/*- * 1. Addresses box sizing set to content-box in IE8/9- * 2. Addresses excess padding in IE8/9- */--input[type="checkbox"],-input[type="radio"] {- box-sizing: border-box; /* 1 */- padding: 0; /* 2 */-}--/*- * 1. Addresses appearance set to searchfield in S5, Chrome- * 2. Addresses box sizing set to border-box in S5, Chrome (include -moz to future-proof)- */--input[type="search"] {- -webkit-appearance: textfield; /* 1 */- -moz-box-sizing: content-box;- -webkit-box-sizing: content-box; /* 2 */- box-sizing: content-box;-}--/*- * Corrects inner padding displayed oddly in S5, Chrome on OSX- */--input[type="search"]::-webkit-search-decoration {- -webkit-appearance: none;-}--/*- * Corrects inner padding and border displayed oddly in FF3/4- * www.sitepen.com/blog/2008/05/14/the-devils-in-the-details-fixing-dojos-toolbar-buttons/- */--button::-moz-focus-inner,-input::-moz-focus-inner {- border: 0;- padding: 0;-}--/*- * 1. Removes default vertical scrollbar in IE6/7/8/9- * 2. Improves readability and alignment in all browsers- */--textarea {- overflow: auto; /* 1 */- vertical-align: top; /* 2 */-}---/* =============================================================================- Tables- ========================================================================== */--/* - * Remove most spacing between table cells- */--table {- border-collapse: collapse;- border-spacing: 0;-}
+ scaffold/static/js/modernizr.js.cg view
@@ -0,0 +1,4 @@+/* Modernizr 2.0.6 (Custom Build) | MIT & BSD + * Build: http://www.modernizr.com/download/#-fontface-backgroundsize-borderimage-borderradius-boxshadow-flexbox-hsla-multiplebgs-opacity-rgba-textshadow-cssanimations-csscolumns-generatedcontent-cssgradients-cssreflections-csstransforms-csstransforms3d-csstransitions-applicationcache-canvas-canvastext-draganddrop-hashchange-history-audio-video-indexeddb-input-inputtypes-localstorage-postmessage-sessionstorage-websockets-websqldatabase-webworkers-geolocation-inlinesvg-smil-svg-svgclippaths-touch-webgl-iepp-cssclasses-teststyles-testprop-testallprops-hasevent-prefixes-domprefixes-load + */ +;window.Modernizr=function(a,b,c){function H(){e.input=function(a){for(var b=0,c=a.length;b<c;b++)t[a[b]]=a[b]in l;return t}("autocomplete autofocus list placeholder max min multiple pattern required step".split(" ")),e.inputtypes=function(a){for(var d=0,e,f,h,i=a.length;d<i;d++)l.setAttribute("type",f=a[d]),e=l.type!=="text",e&&(l.value=m,l.style.cssText="position:absolute;visibility:hidden;",/^range$/.test(f)&&l.style.WebkitAppearance!==c?(g.appendChild(l),h=b.defaultView,e=h.getComputedStyle&&h.getComputedStyle(l,null).WebkitAppearance!=="textfield"&&l.offsetHeight!==0,g.removeChild(l)):/^(search|tel)$/.test(f)||(/^(url|email)$/.test(f)?e=l.checkValidity&&l.checkValidity()===!1:/^color$/.test(f)?(g.appendChild(l),g.offsetWidth,e=l.value!=m,g.removeChild(l)):e=l.value!=m)),s[a[d]]=!!e;return s}("search tel url email datetime date month week time datetime-local number range color".split(" "))}function F(a,b){var c=a.charAt(0).toUpperCase()+a.substr(1),d=(a+" "+p.join(c+" ")+c).split(" ");return E(d,b)}function E(a,b){for(var d in a)if(k[a[d]]!==c)return b=="pfx"?a[d]:!0;return!1}function D(a,b){return!!~(""+a).indexOf(b)}function C(a,b){return typeof a===b}function B(a,b){return A(o.join(a+";")+(b||""))}function A(a){k.cssText=a}var d="2.0.6",e={},f=!0,g=b.documentElement,h=b.head||b.getElementsByTagName("head")[0],i="modernizr",j=b.createElement(i),k=j.style,l=b.createElement("input"),m=":)",n=Object.prototype.toString,o=" -webkit- -moz- -o- -ms- -khtml- ".split(" "),p="Webkit Moz O ms Khtml".split(" "),q={svg:"http://www.w3.org/2000/svg"},r={},s={},t={},u=[],v=function(a,c,d,e){var f,h,j,k=b.createElement("div");if(parseInt(d,10))while(d--)j=b.createElement("div"),j.id=e?e[d]:i+(d+1),k.appendChild(j);f=["­","<style>",a,"</style>"].join(""),k.id=i,k.innerHTML+=f,g.appendChild(k),h=c(k,a),k.parentNode.removeChild(k);return!!h},w=function(){function d(d,e){e=e||b.createElement(a[d]||"div"),d="on"+d;var f=d in e;f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=C(e[d],"function"),C(e[d],c)||(e[d]=c),e.removeAttribute(d))),e=null;return f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),x,y={}.hasOwnProperty,z;!C(y,c)&&!C(y.call,c)?z=function(a,b){return y.call(a,b)}:z=function(a,b){return b in a&&C(a.constructor.prototype[b],c)};var G=function(c,d){var f=c.join(""),g=d.length;v(f,function(c,d){var f=b.styleSheets[b.styleSheets.length-1],h=f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"",i=c.childNodes,j={};while(g--)j[i[g].id]=i[g];e.touch="ontouchstart"in a||j.touch.offsetTop===9,e.csstransforms3d=j.csstransforms3d.offsetLeft===9,e.generatedcontent=j.generatedcontent.offsetHeight>=1,e.fontface=/src/i.test(h)&&h.indexOf(d.split(" ")[0])===0},g,d)}(['@font-face {font-family:"font";src:url("https://")}',["@media (",o.join("touch-enabled),("),i,")","{#touch{top:9px;position:absolute}}"].join(""),["@media (",o.join("transform-3d),("),i,")","{#csstransforms3d{left:9px;position:absolute}}"].join(""),['#generatedcontent:after{content:"',m,'";visibility:hidden}'].join("")],["fontface","touch","csstransforms3d","generatedcontent"]);r.flexbox=function(){function c(a,b,c,d){a.style.cssText=o.join(b+":"+c+";")+(d||"")}function a(a,b,c,d){b+=":",a.style.cssText=(b+o.join(c+";"+b)).slice(0,-b.length)+(d||"")}var d=b.createElement("div"),e=b.createElement("div");a(d,"display","box","width:42px;padding:0;"),c(e,"box-flex","1","width:10px;"),d.appendChild(e),g.appendChild(d);var f=e.offsetWidth===42;d.removeChild(e),g.removeChild(d);return f},r.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},r.canvastext=function(){return!!e.canvas&&!!C(b.createElement("canvas").getContext("2d").fillText,"function")},r.webgl=function(){return!!a.WebGLRenderingContext},r.touch=function(){return e.touch},r.geolocation=function(){return!!navigator.geolocation},r.postmessage=function(){return!!a.postMessage},r.websqldatabase=function(){var b=!!a.openDatabase;return b},r.indexedDB=function(){for(var b=-1,c=p.length;++b<c;)if(a[p[b].toLowerCase()+"IndexedDB"])return!0;return!!a.indexedDB},r.hashchange=function(){return w("hashchange",a)&&(b.documentMode===c||b.documentMode>7)},r.history=function(){return!!a.history&&!!history.pushState},r.draganddrop=function(){return w("dragstart")&&w("drop")},r.websockets=function(){for(var b=-1,c=p.length;++b<c;)if(a[p[b]+"WebSocket"])return!0;return"WebSocket"in a},r.rgba=function(){A("background-color:rgba(150,255,150,.5)");return D(k.backgroundColor,"rgba")},r.hsla=function(){A("background-color:hsla(120,40%,100%,.5)");return D(k.backgroundColor,"rgba")||D(k.backgroundColor,"hsla")},r.multiplebgs=function(){A("background:url(https://),url(https://),red url(https://)");return/(url\s*\(.*?){3}/.test(k.background)},r.backgroundsize=function(){return F("backgroundSize")},r.borderimage=function(){return F("borderImage")},r.borderradius=function(){return F("borderRadius")},r.boxshadow=function(){return F("boxShadow")},r.textshadow=function(){return b.createElement("div").style.textShadow===""},r.opacity=function(){B("opacity:.55");return/^0.55$/.test(k.opacity)},r.cssanimations=function(){return F("animationName")},r.csscolumns=function(){return F("columnCount")},r.cssgradients=function(){var a="background-image:",b="gradient(linear,left top,right bottom,from(#9f9),to(white));",c="linear-gradient(left top,#9f9, white);";A((a+o.join(b+a)+o.join(c+a)).slice(0,-a.length));return D(k.backgroundImage,"gradient")},r.cssreflections=function(){return F("boxReflect")},r.csstransforms=function(){return!!E(["transformProperty","WebkitTransform","MozTransform","OTransform","msTransform"])},r.csstransforms3d=function(){var a=!!E(["perspectiveProperty","WebkitPerspective","MozPerspective","OPerspective","msPerspective"]);a&&"webkitPerspective"in g.style&&(a=e.csstransforms3d);return a},r.csstransitions=function(){return F("transitionProperty")},r.fontface=function(){return e.fontface},r.generatedcontent=function(){return e.generatedcontent},r.video=function(){var a=b.createElement("video"),c=!1;try{if(c=!!a.canPlayType){c=new Boolean(c),c.ogg=a.canPlayType('video/ogg; codecs="theora"');var d='video/mp4; codecs="avc1.42E01E';c.h264=a.canPlayType(d+'"')||a.canPlayType(d+', mp4a.40.2"'),c.webm=a.canPlayType('video/webm; codecs="vp8, vorbis"')}}catch(e){}return c},r.audio=function(){var a=b.createElement("audio"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('audio/ogg; codecs="vorbis"'),c.mp3=a.canPlayType("audio/mpeg;"),c.wav=a.canPlayType('audio/wav; codecs="1"'),c.m4a=a.canPlayType("audio/x-m4a;")||a.canPlayType("audio/aac;")}catch(d){}return c},r.localstorage=function(){try{return!!localStorage.getItem}catch(a){return!1}},r.sessionstorage=function(){try{return!!sessionStorage.getItem}catch(a){return!1}},r.webworkers=function(){return!!a.Worker},r.applicationcache=function(){return!!a.applicationCache},r.svg=function(){return!!b.createElementNS&&!!b.createElementNS(q.svg,"svg").createSVGRect},r.inlinesvg=function(){var a=b.createElement("div");a.innerHTML="<svg/>";return(a.firstChild&&a.firstChild.namespaceURI)==q.svg},r.smil=function(){return!!b.createElementNS&&/SVG/.test(n.call(b.createElementNS(q.svg,"animate")))},r.svgclippaths=function(){return!!b.createElementNS&&/SVG/.test(n.call(b.createElementNS(q.svg,"clipPath")))};for(var I in r)z(r,I)&&(x=I.toLowerCase(),e[x]=r[I](),u.push((e[x]?"":"no-")+x));e.input||H(),A(""),j=l=null,a.attachEvent&&function(){var a=b.createElement("div");a.innerHTML="<elem></elem>";return a.childNodes.length!==1}()&&function(a,b){function s(a){var b=-1;while(++b<g)a.createElement(f[b])}a.iepp=a.iepp||{};var d=a.iepp,e=d.html5elements||"abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",f=e.split("|"),g=f.length,h=new RegExp("(^|\\s)("+e+")","gi"),i=new RegExp("<(/*)("+e+")","gi"),j=/^\s*[\{\}]\s*$/,k=new RegExp("(^|[^\\n]*?\\s)("+e+")([^\\n]*)({[\\n\\w\\W]*?})","gi"),l=b.createDocumentFragment(),m=b.documentElement,n=m.firstChild,o=b.createElement("body"),p=b.createElement("style"),q=/print|all/,r;d.getCSS=function(a,b){if(a+""===c)return"";var e=-1,f=a.length,g,h=[];while(++e<f){g=a[e];if(g.disabled)continue;b=g.media||b,q.test(b)&&h.push(d.getCSS(g.imports,b),g.cssText),b="all"}return h.join("")},d.parseCSS=function(a){var b=[],c;while((c=k.exec(a))!=null)b.push(((j.exec(c[1])?"\n":c[1])+c[2]+c[3]).replace(h,"$1.iepp_$2")+c[4]);return b.join("\n")},d.writeHTML=function(){var a=-1;r=r||b.body;while(++a<g){var c=b.getElementsByTagName(f[a]),d=c.length,e=-1;while(++e<d)c[e].className.indexOf("iepp_")<0&&(c[e].className+=" iepp_"+f[a])}l.appendChild(r),m.appendChild(o),o.className=r.className,o.id=r.id,o.innerHTML=r.innerHTML.replace(i,"<$1font")},d._beforePrint=function(){p.styleSheet.cssText=d.parseCSS(d.getCSS(b.styleSheets,"all")),d.writeHTML()},d.restoreHTML=function(){o.innerHTML="",m.removeChild(o),m.appendChild(r)},d._afterPrint=function(){d.restoreHTML(),p.styleSheet.cssText=""},s(b),s(l);d.disablePP||(n.insertBefore(p,n.firstChild),p.media="print",p.className="iepp-printshim",a.attachEvent("onbeforeprint",d._beforePrint),a.attachEvent("onafterprint",d._afterPrint))}(a,b),e._version=d,e._prefixes=o,e._domPrefixes=p,e.hasEvent=w,e.testProp=function(a){return E([a])},e.testAllProps=F,e.testStyles=v,g.className=g.className.replace(/\bno-js\b/,"")+(f?" js "+u.join(" "):"");return e}(this,this.document),function(a,b,c){function k(a){return!a||a=="loaded"||a=="complete"}function j(){var a=1,b=-1;while(p.length- ++b)if(p[b].s&&!(a=p[b].r))break;a&&g()}function i(a){var c=b.createElement("script"),d;c.src=a.s,c.onreadystatechange=c.onload=function(){!d&&k(c.readyState)&&(d=1,j(),c.onload=c.onreadystatechange=null)},m(function(){d||(d=1,j())},H.errorTimeout),a.e?c.onload():n.parentNode.insertBefore(c,n)}function h(a){var c=b.createElement("link"),d;c.href=a.s,c.rel="stylesheet",c.type="text/css";if(!a.e&&(w||r)){var e=function(a){m(function(){if(!d)try{a.sheet.cssRules.length?(d=1,j()):e(a)}catch(b){b.code==1e3||b.message=="security"||b.message=="denied"?(d=1,m(function(){j()},0)):e(a)}},0)};e(c)}else c.onload=function(){d||(d=1,m(function(){j()},0))},a.e&&c.onload();m(function(){d||(d=1,j())},H.errorTimeout),!a.e&&n.parentNode.insertBefore(c,n)}function g(){var a=p.shift();q=1,a?a.t?m(function(){a.t=="c"?h(a):i(a)},0):(a(),j()):q=0}function f(a,c,d,e,f,h){function i(){!o&&k(l.readyState)&&(r.r=o=1,!q&&j(),l.onload=l.onreadystatechange=null,m(function(){u.removeChild(l)},0))}var l=b.createElement(a),o=0,r={t:d,s:c,e:h};l.src=l.data=c,!s&&(l.style.display="none"),l.width=l.height="0",a!="object"&&(l.type=d),l.onload=l.onreadystatechange=i,a=="img"?l.onerror=i:a=="script"&&(l.onerror=function(){r.e=r.r=1,g()}),p.splice(e,0,r),u.insertBefore(l,s?null:n),m(function(){o||(u.removeChild(l),r.r=r.e=o=1,j())},H.errorTimeout)}function e(a,b,c){var d=b=="c"?z:y;q=0,b=b||"j",C(a)?f(d,a,b,this.i++,l,c):(p.splice(this.i++,0,a),p.length==1&&g());return this}function d(){var a=H;a.loader={load:e,i:0};return a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=r&&!s,u=s?l:n.parentNode,v=a.opera&&o.call(a.opera)=="[object Opera]",w="webkitAppearance"in l.style,x=w&&"async"in b.createElement("script"),y=r?"object":v||x?"img":"script",z=w?"img":y,A=Array.isArray||function(a){return o.call(a)=="[object Array]"},B=function(a){return Object(a)===a},C=function(a){return typeof a=="string"},D=function(a){return o.call(a)=="[object Function]"},E=[],F={},G,H;H=function(a){function f(a){var b=a.split("!"),c=E.length,d=b.pop(),e=b.length,f={url:d,origUrl:d,prefixes:b},g,h;for(h=0;h<e;h++)g=F[b[h]],g&&(f=g(f));for(h=0;h<c;h++)f=E[h](f);return f}function e(a,b,e,g,h){var i=f(a),j=i.autoCallback;if(!i.bypass){b&&(b=D(b)?b:b[a]||b[g]||b[a.split("/").pop().split("?")[0]]);if(i.instead)return i.instead(a,b,e,g,h);e.load(i.url,i.forceCSS||!i.forceJS&&/css$/.test(i.url)?"c":c,i.noexec),(D(b)||D(j))&&e.load(function(){d(),b&&b(i.origUrl,h,g),j&&j(i.origUrl,h,g)})}}function b(a,b){function c(a){if(C(a))e(a,h,b,0,d);else if(B(a))for(i in a)a.hasOwnProperty(i)&&e(a[i],h,b,i,d)}var d=!!a.test,f=d?a.yep:a.nope,g=a.load||a.both,h=a.callback,i;c(f),c(g),a.complete&&b.load(a.complete)}var g,h,i=this.yepnope.loader;if(C(a))e(a,0,i,0);else if(A(a))for(g=0;g<a.length;g++)h=a[g],C(h)?e(h,0,i,0):A(h)?H(h):B(h)&&b(h,i);else B(a)&&b(a,i)},H.addPrefix=function(a,b){F[a]=b},H.addFilter=function(a){E.push(a)},H.errorTimeout=1e4,b.readyState==null&&b.addEventListener&&(b.readyState="loading",b.addEventListener("DOMContentLoaded",G=function(){b.removeEventListener("DOMContentLoaded",G,0),b.readyState="complete"},0)),a.yepnope=d()}(this,this.document),Modernizr.load=function(){yepnope.apply(window,[].slice.call(arguments,0))};
scaffold/tiny/Application.hs.cg view
@@ -1,6 +1,5 @@ {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE CPP #-} {-# OPTIONS_GHC -fno-warn-orphans #-} module Application@@ -11,11 +10,13 @@ import Foundation import Settings import Yesod.Static-import Yesod.Logger (makeLogger, flushLogger, Logger, logLazyText, logString)+import Yesod.Default.Config+import Yesod.Default.Main (defaultDevelApp, defaultRunner)+import Yesod.Default.Handlers (getFaviconR, getRobotsR)+import Yesod.Logger (Logger) import Data.ByteString (ByteString) import Network.Wai (Application) import Data.Dynamic (Dynamic, toDyn)-import Network.Wai.Middleware.Debug (debugHandle) -- Import all relevant handler modules here. import Handler.Root@@ -25,19 +26,11 @@ -- the comments there for more details. mkYesodDispatch "~sitearg~" resources~sitearg~ --- Some default handlers that ship with the Yesod site template. You will--- very rarely need to modify this.-getFaviconR :: Handler ()-getFaviconR = sendFile "image/x-icon" "config/favicon.ico"--getRobotsR :: Handler RepPlain-getRobotsR = return $ RepPlain $ toContent ("User-agent: *" :: ByteString)- -- This function allocates resources (such as a database connection pool), -- performs initialization and creates a WAI application. This is also the -- place to put your migrate statements to have automatic database -- migrations handled by Yesod.-with~sitearg~ :: AppConfig -> Logger -> (Application -> IO a) -> IO a+with~sitearg~ :: AppConfig DefaultEnv -> Logger -> (Application -> IO ()) -> IO () with~sitearg~ conf logger f = do #ifdef PRODUCTION s <- static Settings.staticDir@@ -45,20 +38,8 @@ s <- staticDevel Settings.staticDir #endif let h = ~sitearg~ conf logger s- toWaiApp h >>= f+ defaultRunner f h -- for yesod devel withDevelAppPort :: Dynamic-withDevelAppPort =- toDyn go- where- go :: ((Int, Application) -> IO ()) -> IO ()- go f = do- conf <- Settings.loadConfig Settings.Development- let port = appPort conf- logger <- makeLogger- logString logger $ "Devel application launched, listening on port " ++ show port- with~sitearg~ conf logger $ \app -> f (port, debugHandle (logHandle logger) app)- flushLogger logger- where- logHandle logger msg = logLazyText logger msg >> flushLogger logger+withDevelAppPort = toDyn $ defaultDevelApp with~sitearg~
scaffold/tiny/Foundation.hs.cg view
@@ -1,8 +1,9 @@ {-# LANGUAGE QuasiQuotes, TemplateHaskell, TypeFamilies #-}-{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE OverloadedStrings, MultiParamTypeClasses #-} module Foundation ( ~sitearg~ (..) , ~sitearg~Route (..)+ , ~sitearg~Message (..) , resources~sitearg~ , Handler , Widget@@ -14,29 +15,31 @@ ) where import Yesod.Core+import Yesod.Default.Config+import Yesod.Default.Util (addStaticContentExternal) import Yesod.Static (Static, base64md5, StaticRoute(..)) import Settings.StaticFiles import Yesod.Logger (Logger, logLazyText) import qualified Settings-import System.Directory-import qualified Data.ByteString.Lazy as L-import Settings (hamletFile, cassiusFile, luciusFile, juliusFile, widgetFile)-import Control.Monad (unless)+import Settings (widgetFile) import Control.Monad.Trans.Class (lift) import Control.Monad.IO.Class (liftIO)-import qualified Data.Text as T import Web.ClientSession (getKey)+import Text.Hamlet (hamletFile) -- | The site argument for your application. This can be a good place to -- keep settings and values requiring initialization before your application -- starts running, such as database connections. Every handler will have -- access to the data present here. data ~sitearg~ = ~sitearg~- { settings :: Settings.AppConfig+ { settings :: AppConfig DefaultEnv , getLogger :: Logger , getStatic :: Static -- ^ Settings for static file serving. } +-- Set up i18n messages. See the message folder.+mkMessage "~sitearg~" "messages" "en"+ -- This is where we define all of the routes in our application. For a full -- explanation of the syntax, please see: -- http://docs.yesodweb.com/book/web-routes-quasi/@@ -61,17 +64,24 @@ -- Please see the documentation for the Yesod typeclass. There are a number -- of settings which can be configured by overriding methods here. instance Yesod ~sitearg~ where- approot = Settings.appRoot . settings+ approot = appRoot . settings -- Place the session key file in the config folder encryptKey _ = fmap Just $ getKey "config/client_session_key.aes" defaultLayout widget = do mmsg <- getMessage++ -- We break up the default layout into two components:+ -- default-layout is the contents of the body tag, and+ -- default-layout-wrapper is the entire page. Since the final+ -- value passed to hamletToRepHtml cannot be a widget, this allows+ -- you to use normal widget features in default-layout.+ pc <- widgetToPageContent $ do- widget- addCassius $(cassiusFile "default-layout")- hamletToRepHtml $(hamletFile "default-layout")+ $(widgetFile "normalize")+ $(widgetFile "default-layout")+ hamletToRepHtml $(hamletFile "hamlet/default-layout-wrapper.hamlet") -- This is done to provide an optimization for serving static files from -- a separate domain. Please see the staticroot setting in Settings.hs@@ -86,11 +96,7 @@ -- and names them based on a hash of their content. This allows -- expiration dates to be set far in the future without worry of -- users receiving stale content.- addStaticContent ext' _ content = do- let fn = base64md5 content ++ '.' : T.unpack ext'- let statictmp = Settings.staticDir ++ "/tmp/"- liftIO $ createDirectoryIfMissing True statictmp- let fn' = statictmp ++ fn- exists <- liftIO $ doesFileExist fn'- unless exists $ liftIO $ L.writeFile fn' content- return $ Just $ Right (StaticR $ StaticRoute ["tmp", T.pack fn] [], [])+ addStaticContent = addStaticContentExternal (const $ Left ()) base64md5 Settings.staticDir (StaticR . flip StaticRoute [])++ -- Enable Javascript async loading+ yepnopeJs _ = Just $ Right $ StaticR js_modernizr_js
− scaffold/tiny/Handler/Root.hs.cg
@@ -1,18 +0,0 @@-{-# LANGUAGE TemplateHaskell, QuasiQuotes, OverloadedStrings #-}-module Handler.Root where--import Foundation---- This is a handler function for the GET request method on the RootR--- resource pattern. All of your resource patterns are defined in--- config/routes------ The majority of the code you will write in Yesod lives in these handler--- functions. You can spread them across multiple files if you are so--- inclined, or create a single monolithic file.-getRootR :: Handler RepHtml-getRootR = do- defaultLayout $ do- h2id <- lift newIdent- setTitle "~project~ homepage"- addWidget $(widgetFile "homepage")
scaffold/tiny/Settings.hs.cg view
@@ -7,80 +7,16 @@ -- by overriding methods in the Yesod typeclass. That instance is -- declared in the ~project~.hs file. module Settings- ( hamletFile- , cassiusFile- , juliusFile- , luciusFile- , widgetFile+ ( widgetFile , staticRoot , staticDir- , loadConfig- , AppEnvironment(..)- , AppConfig(..) ) where -import qualified Text.Hamlet as S-import qualified Text.Cassius as S-import qualified Text.Julius as S-import qualified Text.Lucius as S-import qualified Text.Shakespeare.Text as S import Text.Shakespeare.Text (st) import Language.Haskell.TH.Syntax-import Yesod.Widget (addWidget, addCassius, addJulius, addLucius, whamletFile)-import Data.Monoid (mempty)-import System.Directory (doesFileExist)-~settingsTextImport~-import Data.Object-import qualified Data.Object.Yaml as YAML-import Control.Monad (join)--data AppEnvironment = Test- | Development- | Staging- | Production- deriving (Eq, Show, Read, Enum, Bounded)---- | Dynamic per-environment configuration loaded from the YAML file Settings.yaml.--- Use dynamic settings to avoid the need to re-compile the application (between staging and production environments).------ By convention these settings should be overwritten by any command line arguments.--- See config/~sitearg~.hs for command line arguments--- Command line arguments provide some convenience but are also required for hosting situations where a setting is read from the environment (appPort on Heroku).----data AppConfig = AppConfig {- appEnv :: AppEnvironment-- , appPort :: Int-- -- | The base URL for your application. This will usually be different for- -- development and production. Yesod automatically constructs URLs for you,- -- so this value must be accurate to create valid links.- -- Please note that there is no trailing slash.- --- -- You probably want to change this! If your domain name was "yesod.com",- -- you would probably want it to be:- -- > "http://yesod.com"- , appRoot :: Text-} deriving (Show)--loadConfig :: AppEnvironment -> IO AppConfig-loadConfig env = do- allSettings <- (join $ YAML.decodeFile ("config/settings.yml" :: String)) >>= fromMapping- settings <- lookupMapping (show env) allSettings- hostS <- lookupScalar "host" settings- port <- fmap read $ lookupScalar "port" settings- return $ AppConfig {- appEnv = env- , appPort = port- , appRoot = pack $ hostS ++ addPort port- }- where- addPort :: Int -> String-#ifdef PRODUCTION- addPort _ = ""-#else- addPort p = ":" ++ (show p)-#endif+import Yesod.Default.Config+import qualified Yesod.Default.Util+import Data.Text (Text) -- | The location of static files on your system. This is a file system -- path. The default value works properly with your scaffolded site.@@ -100,72 +36,12 @@ -- have to make a corresponding change here. -- -- To see how this value is used, see urlRenderOverride in ~project~.hs-staticRoot :: AppConfig -> Text+staticRoot :: AppConfig DefaultEnv -> Text staticRoot conf = [st|#{appRoot conf}/static|] --- The rest of this file contains settings which rarely need changing by a--- user.---- The following functions are used for calling HTML, CSS,--- Javascript, and plain text templates from your Haskell code. During development,--- the "Debug" versions of these functions are used so that changes to--- the templates are immediately reflected in an already running--- application. When making a production compile, the non-debug version--- is used for increased performance.------ You can see an example of how to call these functions in Handler/Root.hs------ Note: due to polymorphic Hamlet templates, hamletFileDebug is no longer--- used; to get the same auto-loading effect, it is recommended that you--- use the devel server.---- | expects a root folder for each type, e.g: hamlet/ lucius/ julius/-globFile :: String -> String -> FilePath-globFile kind x = kind ++ "/" ++ x ++ "." ++ kind--hamletFile :: FilePath -> Q Exp-hamletFile = S.hamletFile . globFile "hamlet"--cassiusFile :: FilePath -> Q Exp-cassiusFile = -#ifdef PRODUCTION- S.cassiusFile . globFile "cassius"-#else- S.cassiusFileDebug . globFile "cassius"-#endif--luciusFile :: FilePath -> Q Exp-luciusFile = -#ifdef PRODUCTION- S.luciusFile . globFile "lucius"-#else- S.luciusFileDebug . globFile "lucius"-#endif--juliusFile :: FilePath -> Q Exp-juliusFile =-#ifdef PRODUCTION- S.juliusFile . globFile "julius"-#else- S.juliusFileDebug . globFile "julius"-#endif--textFile :: FilePath -> Q Exp-textFile =-#ifdef PRODUCTION- S.textFile . globFile "text"+widgetFile :: String -> Q Exp+#if PRODUCTION+widgetFile = Yesod.Default.Util.widgetFileProduction #else- S.textFileDebug . globFile "text"+widgetFile = Yesod.Default.Util.widgetFileDebug #endif--widgetFile :: FilePath -> Q Exp-widgetFile x = do- let h = whenExists (globFile "hamlet") (whamletFile . globFile "hamlet")- let c = whenExists (globFile "cassius") cassiusFile- let j = whenExists (globFile "julius") juliusFile- let l = whenExists (globFile "lucius") luciusFile- [|addWidget $h >> addCassius $c >> addJulius $j >> addLucius $l|]- where- whenExists tofn f = do- e <- qRunIO $ doesFileExist $ tofn x- if e then f x else [|mempty|]
− scaffold/tiny/hamlet/homepage.hamlet.cg
@@ -1,2 +0,0 @@-<h1>Hello-<h2 ##{h2id}>You do not have Javascript enabled.
scaffold/tiny/project.cabal.cg view
@@ -26,12 +26,13 @@ else Buildable: False exposed-modules: Application- hs-source-dirs: . other-modules: Foundation Settings Settings.StaticFiles Handler.Root + ghc-options: -Wall -threaded -O0+ executable ~project~ if flag(devel) Buildable: False@@ -40,30 +41,20 @@ cpp-options: -DPRODUCTION ghc-options: -Wall -threaded -O2 else- ghc-options: -Wall -threaded+ ghc-options: -Wall -threaded -O0 main-is: main.hs- hs-source-dirs: . - build-depends: base >= 4 && < 5- , yesod-core >= 0.9 && < 0.10- , yesod-static- , clientsession- , wai-extra- , directory- , bytestring- , text+ build-depends: base >= 4 && < 5+ , yesod-core >= 0.9.3 && < 0.10+ , yesod-static >= 0.3.1 && < 0.4+ , yesod-default >= 0.3.1 && < 0.4+ , clientsession >= 0.7.3 && < 0.8+ , bytestring >= 0.9 && < 0.10+ , text >= 0.11 && < 0.12 , template-haskell- , hamlet >= 0.10 && < 0.11- , shakespeare-css >= 0.10 && < 0.11- , shakespeare-js >= 0.10 && < 0.11- , shakespeare-text >= 0.10 && < 0.11- , transformers- , data-object- , data-object-yaml- , wai- , warp- , blaze-builder- , cmdargs- , data-object- , data-object-yaml+ , hamlet >= 0.10 && < 0.11+ , shakespeare-text >= 0.10 && < 0.11+ , wai >= 0.4.2 && < 0.5+ , transformers >= 0.2 && < 0.3+
yesod.cabal view
@@ -1,5 +1,5 @@ name: yesod-version: 0.9.2.2+version: 0.9.3 license: BSD3 license-file: LICENSE author: Michael Snoyman <michael@snoyman.com>@@ -17,8 +17,8 @@ extra-source-files: input/*.cg- scaffold/cassius/default-layout.cassius.cg- scaffold/cassius/homepage.cassius.cg+ scaffold/lucius/default-layout.lucius.cg+ scaffold/lucius/homepage.lucius.cg scaffold/Model.hs.cg scaffold/Foundation.hs.cg scaffold/LICENSE.cg@@ -26,11 +26,9 @@ scaffold/tiny/Foundation.hs.cg scaffold/tiny/project.cabal.cg scaffold/tiny/Application.hs.cg- scaffold/tiny/hamlet/homepage.hamlet.cg- scaffold/tiny/Handler/Root.hs.cg scaffold/tiny/config/routes.cg scaffold/tiny/Settings.hs.cg- scaffold/static/css/normalize.css.cg+ scaffold/lucius/normalize.lucius.cg scaffold/postgresqlConnPool.cg scaffold/sqliteConnPool.cg scaffold/.ghci.cg@@ -39,6 +37,7 @@ scaffold/julius/homepage.julius.cg scaffold/hamlet/homepage.hamlet.cg scaffold/hamlet/default-layout.hamlet.cg+ scaffold/hamlet/default-layout-wrapper.hamlet.cg scaffold/hamlet/boilerplate-layout.hamlet.cg scaffold/deploy/Procfile.cg scaffold/main.hs.cg@@ -52,10 +51,16 @@ scaffold/config/routes.cg scaffold/Settings.hs.cg scaffold/Settings/StaticFiles.hs.cg+ scaffold/messages/en.msg.cg+ scaffold/static/js/modernizr.js.cg flag ghc7 +flag threaded+ default: True+ description: Build with support for multithreaded execution+ library if flag(ghc7) build-depends: base >= 4.3 && < 5@@ -102,7 +107,9 @@ , blaze-builder >= 0.2 && < 0.4 , filepath >= 1.1 && < 1.3 , process- ghc-options: -Wall -threaded+ ghc-options: -Wall+ if flag(threaded)+ ghc-options: -threaded main-is: main.hs other-modules: Scaffolding.CodeGen Scaffolding.Scaffolder