packages feed

happstack-yui 7351.2.0 → 7351.3.0

raw patch · 3 files changed

+152/−29 lines, 3 filesdep +directorydep +mtl

Dependencies added: directory, mtl

Files

happstack-yui.cabal view
@@ -1,5 +1,5 @@ Name          : happstack-yui-Version       : 7351.2.0+Version       : 7351.3.0 Category      : Web, Happstack Synopsis      : Utilities for using YUI3 with Happstack. Homepage      : https://github.com/dag/happstack-yui@@ -12,10 +12,11 @@ Description :   Bundles YUI 3.5.1 and includes a \"combo handler\" for use in   Happstack which concatenates YUI modules server-side to send in a single-  HTTP request.  The YUI bundle is embedded in the library with Template-  Haskell which means the files are served directly from memory, and also-  that you can compile and deploy a single executable without having to-  worry about deploying the YUI files as well.+  HTTP request.  The YUI bundle can be embedded in compiled code with+  Template Haskell (install with @-fembed@) which means the files are+  served directly from memory, and also that you can compile and deploy a+  single executable without having to worry about deploying the YUI files+  as well.   .   The benefits of using this over the Yahoo! CDN is that you can work   offline and that you can host YUI yourself without sacrificing the@@ -26,10 +27,11 @@   means \"Happstack 7, YUI 3.5.1\".  The second part is the major version   of this package itself, as defined by the Package Versioning Policy.   .-  In a future release, the plan is to add more utilities than just a-  bundled YUI, for example a combo handler for YUI modules written using-  JMacro, a bridge between HSX and YUI Node objects and tools for working-  with the YUI CSS modules.+  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.   .   For an example application, see:   <https://github.com/dag/happstack-yui/blob/master/demo/happstack-yui-demo.hs>@@ -2829,6 +2831,10 @@ bundle/yui-log/yui-log-min.js } +Flag embed+  Description : Embed the YUI bundle in compiled code.+  Default     : False+ Source-Repository head   Type     : git   Location : git://github.com/dag/happstack-yui.git@@ -2837,7 +2843,6 @@   HS-Source-Dirs   : src   Default-Language : Haskell2010   GHC-Options      : -Wall-  CPP-Options      : -DYUI_VERSION=3.5.1 -DYUI_VERSION_STR="3.5.1"   Exposed-Modules  :     Happstack.Server.YUI   Other-Modules    :@@ -2847,13 +2852,29 @@     boomerang             == 1.3.*,     bytestring            == 0.9.*,     containers            >= 0.4 && < 0.6,-    file-embed            == 0.0.*,     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.*++  if !flag(embed)+    CPP-Options   :+      -DYUI_VERSION=3.5.1+      -DYUI_VERSION_STR="3.5.1"+    Other-Modules :+      Paths_happstack_yui+    Build-Depends :+      directory == 1.1.*+  else+    CPP-Options   :+      -DYUI_VERSION=3.5.1+      -DYUI_VERSION_STR="3.5.1"+      -DEMBED+    Build-Depends :+      file-embed == 0.0.*
src/Happstack/Server/YUI.hs view
@@ -1,27 +1,35 @@ {-# LANGUAGE CPP, OverloadedStrings, TemplateHaskell, QuasiQuotes #-}  module Happstack.Server.YUI-  ( implYUISite-  , bundle+  ( -- * Combo Handler+    implYUISite+    -- * CSS utilities+  , gridUnit+  , fontSize+    -- * Bundle utilities+  , isYUIFile+  , readYUIFile   ) where  import Prelude hiding ((.))  import qualified Data.ByteString as B-import qualified Data.Map        as Map import qualified Data.Text       as T  import Control.Category             (Category((.)))-import Control.Monad                (liftM, void, mzero)+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  (bundle)+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)@@ -98,32 +106,96 @@     void compressedResponseFilter     case url of       BundleURL paths ->-        do let filepath = intercalate "/" paths-           mime <- guessContentTypeM mimeTypes filepath+        do let name = intercalate "/" paths+           exists <- liftIO $ isYUIFile name+           guard exists+           mime <- guessContentTypeM mimeTypes name            setHeaderM "Content-Type" mime-           maybe mzero (ok . toResponse) $ Map.lookup filepath bundle+           bytes <- liftIO $ readYUIFile name+           ok . toResponse $ bytes       ComboHandlerURL ->         do qs <- liftM (map fst) lookPairs-           if null qs || any (`Map.notMember` bundle) qs+           exists <- liftIO $ mapM isYUIFile qs+           if null qs || any (== False) exists              then badRequest $ toResponse ()              else do mime <- guessContentTypeM mimeTypes $ head qs                      setHeaderM "Content-Type" mime-                     ok $ toResponse $ B.concat $ map (bundle Map.!) qs+                     bytes <- liftIO $ mapM readYUIFile qs+                     ok $ toResponse $ B.concat bytes       CSSComboURL ->         do qs <- liftM (map (css . fst)) lookPairs-           if null qs || any (`Map.notMember` bundle) qs+           exists <- liftIO $ mapM isYUIFile qs+           if null qs || any (== False) exists              then badRequest $ toResponse ()              else do setHeaderM "Content-Type" "text/css"-                     ok $ toResponse $ B.concat $ map (bundle Map.!) qs+                     bytes <- liftIO $ mapM readYUIFile qs+                     ok $ toResponse $ B.concat bytes       ConfigURL ->         do config <- mkConfig            ok $ toResponse config       SeedURL ->         do config <- mkConfig+           seed <- liftIO $ readYUIFile "yui/yui-min.js"            setHeaderM "Content-Type" "application/javascript"            ok $ toResponse $ seed `B.append` (encode . render) config   where-    seed   = bundle Map.! "yui/yui-min.js"     render = renderStyle (style { mode = OneLineMode }) . renderJs     encode = encodeUtf8 . T.pack     css fn = "css" ++ fn ++ "/css" ++ fn ++ "-min.css"++-- | 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.+-- This helper function handles that for you, though:+--+-- >>> gridUnit 6 24+-- "yui3-u-1-4"+--+-- The intention is for this function to be used in templates to create+-- values for class attributes, for example with HSP:+--+-- ><div class=(gridUnit 6 24)>+-- >  <% 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+             ]++-- | Converts a pixel size to a percentage suitable for use+-- with the CSS fonts module:+--+-- >>> fontSize 16+-- "123.1%"+--+-- Useful in generated stylesheets, for example with HSP:+--+-- ><style>+-- >  h1 { font-size: <% fontSize 26 %> }+-- ></style>+fontSize :: Integer -> T.Text+fontSize 10 = "77%"+fontSize 11 = "85%"+fontSize 12 = "93%"+fontSize 13 = "100%"+fontSize 14 = "108%"+fontSize 15 = "116%"+fontSize 16 = "123.1%"+fontSize 17 = "131%"+fontSize 18 = "138.5%"+fontSize 19 = "146.5%"+fontSize 20 = "153.9%"+fontSize 21 = "161.6%"+fontSize 22 = "167%"+fontSize 23 = "174%"+fontSize 24 = "182%"+fontSize 25 = "189%"+fontSize 26 = "197%"+fontSize px =+    T.pack . printf "%.1f%%" $ percentage+  where+    percentage :: Double+    percentage = fromIntegral px * (100 / 13)
src/Happstack/Server/YUI/Bundle.hs view
@@ -1,11 +1,41 @@-{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE CPP, TemplateHaskell #-} -module Happstack.Server.YUI.Bundle where+module Happstack.Server.YUI.Bundle+  ( isYUIFile+  , readYUIFile+  ) where  import Data.ByteString (ByteString)-import Data.FileEmbed  (embedDir)-import Data.Map        (Map, fromList) --- | Maps the filenames of the bundled YUI build to their contents.+#if EMBED+import Data.FileEmbed            (embedDir)+import Data.Map                  (Map, (!), fromList, member)+#else+import Paths_happstack_yui       (getDataFileName)+import System.Directory          (doesFileExist)+import qualified Data.ByteString as B+#endif++#if EMBED bundle :: Map FilePath ByteString bundle = fromList $(embedDir "bundle")+#endif++-- | Tells if a file is included in the YUI bundle.+--+-- >>> isYUIFile "yui/yui-min.js"+-- True+isYUIFile :: FilePath -> IO Bool+#if EMBED+isYUIFile name = return $ member name bundle+#else+isYUIFile name = getDataFileName ("bundle/" ++ name) >>= doesFileExist+#endif++-- | Reads the contents of a file included in the YUI bundle.+readYUIFile :: FilePath -> IO ByteString+#if EMBED+readYUIFile name = return $ bundle ! name+#else+readYUIFile name = getDataFileName ("bundle/" ++ name) >>= B.readFile+#endif