happstack-yui 7351.3.0 → 7351.4.0
raw patch · 2 files changed
+150/−85 lines, 2 filesdep +hspdep +interpolatedstring-perl6dep +web-routes-th
Dependencies added: hsp, interpolatedstring-perl6, web-routes-th
Files
- happstack-yui.cabal +23/−19
- src/Happstack/Server/YUI.hs +127/−66
happstack-yui.cabal view
@@ -1,5 +1,5 @@ Name : happstack-yui-Version : 7351.3.0+Version : 7351.4.0 Category : Web, Happstack Synopsis : Utilities for using YUI3 with Happstack. Homepage : https://github.com/dag/happstack-yui@@ -28,10 +28,11 @@ of this package itself, as defined by the Package Versioning Policy. . The package also includes some utilities for working with the YUI CSS- modules. In a future release, the plan is to add more utilities, for- example a combo handler for YUI modules written using JMacro, a bridge- between HSX and YUI Node objects and tools for making it easier to work- with modules like Uploader and Pjax.+ modules and for using HSX to create YUI Node objects with JMacro. In a+ future release, the plan is to add more utilities, for example a combo+ handler for YUI modules written using JMacro, tools for making it+ easier to work with modules like Uploader and Pjax and a quasi-quoter for+ compile-time syntax checked YQL queries. . For an example application, see: <https://github.com/dag/happstack-yui/blob/master/demo/happstack-yui-demo.hs>@@ -2848,20 +2849,23 @@ Other-Modules : Happstack.Server.YUI.Bundle Build-Depends :- base >= 4.3 && < 4.6,- boomerang == 1.3.*,- bytestring == 0.9.*,- containers >= 0.4 && < 0.6,- happstack-jmacro == 7.0.*,- happstack-server == 7.0.*,- jmacro == 0.5.*,- mtl >= 2.0 && < 2.2,- pretty == 1.1.*,- template-haskell >= 2.5 && < 2.8,- text == 0.11.*,- web-routes == 0.27.*,- web-routes-boomerang == 0.26.*,- web-routes-happstack == 0.23.*+ base >= 4.3 && < 4.6,+ boomerang == 1.3.*,+ bytestring == 0.9.*,+ containers >= 0.4 && < 0.6,+ happstack-jmacro == 7.0.*,+ happstack-server == 7.0.*,+ hsp == 0.7.*,+ interpolatedstring-perl6 == 0.9.*,+ jmacro == 0.5.*,+ mtl >= 2.0 && < 2.2,+ pretty == 1.1.*,+ template-haskell >= 2.5 && < 2.8,+ text == 0.11.*,+ web-routes == 0.27.*,+ web-routes-boomerang == 0.26.*,+ web-routes-happstack == 0.23.*,+ web-routes-th == 0.21.* if !flag(embed) CPP-Options :
src/Happstack/Server/YUI.hs view
@@ -3,9 +3,15 @@ module Happstack.Server.YUI ( -- * Combo Handler implYUISite+ , YUISitemap(..)+ , sitemap+ , route+ , showCSSComboURL -- * CSS utilities , gridUnit , fontSize+ -- * JS utilities+ , createNode -- * Bundle utilities , isYUIFile , readYUIFile@@ -15,92 +21,113 @@ import qualified Data.ByteString as B import qualified Data.Text as T+import qualified Web.Routes as WR -import Control.Category (Category((.)))-import Control.Monad (guard, liftM, void)-import Control.Monad.Trans (liftIO)-import Data.List (intercalate)-import Data.Ratio ((%), numerator,denominator)-import Data.Text.Encoding (encodeUtf8)-import Happstack.Server (ServerPartT, Response, neverExpires, setHeaderM, badRequest, ok, toResponse, guessContentTypeM, mimeTypes, lookPairs)-import Happstack.Server.Compression (compressedResponseFilter)-import Happstack.Server.JMacro ()-import Happstack.Server.YUI.Bundle (isYUIFile, readYUIFile)-import Language.Javascript.JMacro (JStat(BlockStat), jmacro, renderJs, jhFromList, toJExpr)-import Text.Boomerang.TH (derivePrinterParsers)-import Text.PrettyPrint (Style(mode), Mode(OneLineMode), renderStyle, style)-import Text.Printf (printf)-import Web.Routes (Site, RouteT, showURL)-import Web.Routes.Boomerang (Router, (<>), (</>), rList, anyString, eos, boomerangSiteRouteT)-import Web.Routes.Happstack (implSite)+import Control.Category (Category((.)))+import Control.Monad (guard, liftM, void)+import Control.Monad.Trans (liftIO)+import Data.List (intercalate)+import Data.Ratio ((%), numerator,denominator)+import Data.Text.Encoding (encodeUtf8)+import Happstack.Server (Happstack, Response, neverExpires, setHeaderM, badRequest, ok, toResponse, guessContentTypeM, mimeTypes, lookPairs)+import Happstack.Server.Compression (compressedResponseFilter)+import Happstack.Server.JMacro ()+import Happstack.Server.YUI.Bundle (isYUIFile, readYUIFile)+import HSP (XML, renderAsHTML)+import Language.Javascript.JMacro (JStat(BlockStat), JExpr, jmacro, jmacroE, renderJs, jhFromList, toJExpr)+import Text.Boomerang.TH (derivePrinterParsers)+import Text.InterpolatedString.Perl6 (qq)+import Text.PrettyPrint (Style(mode), Mode(OneLineMode), renderStyle, style)+import Text.Printf (printf)+import Web.Routes (Site, RouteT)+import Web.Routes.Boomerang (Router, (<>), (</>), rList, anyString, eos, boomerangSiteRouteT)+import Web.Routes.Happstack (implSite)+import Web.Routes.TH (derivePathInfo) #if !MIN_VERSION_template_haskell(2,7,0) import Language.Javascript.JMacro (JStat(..), JExpr(..), JVal(..), Ident(..)) #endif -data Sitemap- = ComboHandlerURL+-- | The @web-routes@ sitemap for the handler that serves up the YUI+-- bundle. You can embed this in your own sitemap, something like:+--+-- >data Sitemap = YUI YUISitemap | Home+--+-- The version number of the bundled YUI release is included in the routes+-- for sake of cache-busting: the routes all respond with far-future+-- expiration dates.+--+-- A 'WR.PathInfo' instance is provided in case you're using @web-routes@+-- without @boomerang@. This isn't recommended for production, however,+-- since the YUI version number is not included in this case.+data YUISitemap+ = SeedURL+ -- ^ [@\/YUI_VERSION\/@]+ -- The YUI seed file plus the configuration for using our own+ -- combo loader.+ | ComboURL+ -- ^ [@\/YUI_VERSION\/combo@]+ -- The combo loader. | BundleURL [String]+ -- ^ [@\/YUI_VERSION\/bundle\/\<filename\>@]+ -- Get an individual file without combo loading. | ConfigURL+ -- ^ [@\/YUI_VERSION\/config@]+ -- The code for configuring YUI to use our own combo loader. Not needed+ -- if you use the seed file mentioned above. | CSSComboURL- | SeedURL+ -- ^ [@\/YUI_VERSION\/css@]+ -- A specialized combo loader for CSS modules, for use in @\<link\/\>@+ -- tags. Simply list the CSS modules in the query string by name rather+ -- than file path, for example+ -- @\"\/YUI_VERSION\/css?reset&base&fonts&grids\"@. Order matters;+ -- you'll usually want reset first if you use it. -derivePrinterParsers ''Sitemap+derivePathInfo ''YUISitemap -sitemap :: Router Sitemap+derivePrinterParsers ''YUISitemap++-- | A @boomerang@ 'Router' for 'YUISitemap'. If you embed the+-- @YUISitemap@ in your own, you can also embed this router in your own:+--+-- >import qualified Happstack.Server.YUI as Y+-- >sitemap = (rYUI . (lit "yui" </> Y.sitemap)) <> rHome+sitemap :: Router YUISitemap sitemap = YUI_VERSION_STR </>- ( rComboHandlerURL . "combo"+ ( rComboURL . "combo" <> rCSSComboURL . "css" <> rBundleURL . "bundle" </> rList (anyString . eos) <> rConfigURL . "config" <> rSeedURL ) -site :: Site Sitemap (ServerPartT IO Response)+site :: Happstack m => Site YUISitemap (m Response) site = boomerangSiteRouteT route sitemap --- | Mounts a handler for serving YUI.------ The handler responds to these routes:------ [@\/YUI_VERSION\/@]--- The YUI seed file plus the configuration for using our own--- combo loader.------ [@\/YUI_VERSION\/combo@]--- The combo loader.------ [@\/YUI_VERSION\/css@]--- A specialized combo loader for CSS modules, for use in @\<link\/\>@--- tags. Simply list the CSS modules in the query string by name rather--- than file path, for example--- @\"\/YUI_VERSION\/css?reset&base&fonts&grids\"@. Order matters;--- you'll usually want reset first if you use it.------ [@\/YUI_VERSION\/bundle\/\<filename\>@]--- Get an individual file without combo loading.------ [@\/YUI_VERSION\/config@]--- The code for configuring YUI to use our own combo loader. Not needed--- if you use the seed file mentioned above.------ The version number of the bundled YUI release is included in the routes--- for sake of cache-busting: the routes all respond with far-future--- expiration dates.-implYUISite :: T.Text -- ^ The URL of your application, e.g. @\"http:\/\/localhost:8000\"@.+-- | Mounts a handler for serving YUI. You can use this if you're not+-- using @web-routes@ in your own application. See 'YUISitemap' for the+-- routes the mounted handler responds to.+implYUISite :: Happstack m+ => T.Text -- ^ The URL of your application, e.g. @\"http:\/\/localhost:8000\"@. -> T.Text -- ^ The path under which to mount the YUI handler, e.g. @\"/yui\"@.- -> ServerPartT IO Response+ -> m Response implYUISite domain approot = implSite domain approot site -mkConfig :: RouteT Sitemap (ServerPartT IO) JStat+mkConfig :: Happstack m => RouteT YUISitemap m JStat mkConfig = do- comboURL <- showURL ComboHandlerURL+ comboURL <- WR.showURL ComboURL return [jmacro| YUI.applyConfig { comboBase: `((T.unpack comboURL) ++ "?")`, root: "" } |] -route :: Sitemap -> RouteT Sitemap (ServerPartT IO) Response+-- | Routes a 'YUISitemap' to its handler. If you embed @YUISitemap@ in+-- your own sitemap, you can use 'WR.nestURL' in your own routing function+-- to dispatch to this one:+--+-- >import qualified Happstack.Server.YUI as Y+-- >route (YUI url) = nestURL YUI (Y.route url)+route :: Happstack m => YUISitemap -> RouteT YUISitemap m Response route url = do neverExpires void compressedResponseFilter@@ -113,10 +140,10 @@ setHeaderM "Content-Type" mime bytes <- liftIO $ readYUIFile name ok . toResponse $ bytes- ComboHandlerURL ->+ ComboURL -> do qs <- liftM (map fst) lookPairs exists <- liftIO $ mapM isYUIFile qs- if null qs || any (== False) exists+ if null qs || any not exists then badRequest $ toResponse () else do mime <- guessContentTypeM mimeTypes $ head qs setHeaderM "Content-Type" mime@@ -125,7 +152,7 @@ CSSComboURL -> do qs <- liftM (map (css . fst)) lookPairs exists <- liftIO $ mapM isYUIFile qs- if null qs || any (== False) exists+ if null qs || any not exists then badRequest $ toResponse () else do setHeaderM "Content-Type" "text/css" bytes <- liftIO $ mapM readYUIFile qs@@ -143,6 +170,22 @@ encode = encodeUtf8 . T.pack css fn = "css" ++ fn ++ "/css" ++ fn ++ "-min.css" +-- | Helper for building a URL to 'CSSComboURL'.+--+-- >do cssURL <- showCSSComboURL YUI ["reset", "base", "fonts", "grids"]+-- > unXMLGenT+-- > <html>+-- > <head>+-- > <link href=cssURL rel="stylesheet"/>+-- > </head>+-- > </html>+showCSSComboURL :: WR.MonadRoute m+ => (YUISitemap -> WR.URL m) -- ^ Constructor for 'YUISitemap' inside your own sitemap.+ -> [T.Text] -- ^ Names of CSS modules to include, in order.+ -> m T.Text+showCSSComboURL yui ms =+ WR.showURLParams (yui CSSComboURL) [(m,Nothing) | m <- ms]+ -- | Gets the class name for the grid unit of the ratio of the two argument -- integers. YUI doesn't define redundant classes like \"6\/24\" because -- that is the same as 1\/4 and presumably for sake of a smaller CSS file.@@ -150,6 +193,8 @@ -- -- >>> gridUnit 6 24 -- "yui3-u-1-4"+-- >>> gridUnit 24 24+-- "yui3-u-1" -- -- The intention is for this function to be used in templates to create -- values for class attributes, for example with HSP:@@ -158,12 +203,13 @@ -- > <% someContent %> -- ></div> gridUnit :: Integer -> Integer -> T.Text-gridUnit n d =- T.concat [ "yui3-u-"- , T.pack . show . numerator $ n % d- , "-"- , T.pack . show . denominator $ n % d- ]+gridUnit n d+ | num == 0 = "yui3-u"+ | (num,den) == (1,1) = "yui3-u-1"+ | otherwise = [qq|yui3-u-$num-$den|]+ where+ num = numerator $ n % d+ den = denominator $ n % d -- | Converts a pixel size to a percentage suitable for use -- with the CSS fonts module:@@ -199,3 +245,18 @@ where percentage :: Double percentage = fromIntegral px * (100 / 13)++-- | Creates a YUI Node object from XML created using HSP, for use with+-- JMacro. This generates less code than using the @hsx-jmacro@ package to+-- achieve the same effect, since it goes straight to YUI without directly+-- using the DOM itself. The first argument is the YUI object that gets+-- passed to the function you give to @YUI().use()@. Such variables are+-- available in antiquotation splices with JMacro:+--+-- @+--do html \<- unXMLGenT \<p>Hello, World!\</p>+-- ok [jmacro| YUI().use \"node\" \\y ->+-- y.one(\"body\").append(`(y ``createNode`` html`)) |]+-- @+createNode :: JExpr -> XML -> JExpr+createNode y xml = [jmacroE| `(y)`.Node.create(`(renderAsHTML xml)`) |]