herringbone 0.1.0 → 0.1.1
raw patch · 7 files changed
+72/−56 lines, 7 files
Files
- README.md +0/−42
- Web/Herringbone.hs +3/−0
- Web/Herringbone/Internal/FindAsset.hs +4/−0
- Web/Herringbone/Internal/Precompile.hs +35/−0
- Web/Herringbone/Internal/Types.hs +25/−10
- Web/Herringbone/Internal/Utils.hs +3/−1
- herringbone.cabal +2/−3
− README.md
@@ -1,42 +0,0 @@-herringbone-===========--herringbone is a Haskell library for compiling and serving web assets. It-aims to make it dead simple to create a 'Network.Wai.Middleware' or-'Network.Wai.Application' which deals with all of your static assets, including-preprocessing for languages like Fay, CoffeeScript, Sass, and LESS.--It takes most of its inspiration from the Ruby library, [Sprockets], hence the-name.--Status---------Alpha.--How to use it----------------```haskell-import Web.Herringbone--fay, sass :: PP--hb = Herringbone-hb = herringbone- ( addSourceDir "assets"- . setDestDir "compiled_assets"- . addPreprocessors [fay, sass]- )---- You can now access assets programmatically-asset <- findAsset hb (fromJust . makeLogicalPath $ ["application.js"])---- Or serve them with a Wai application-app = toApplication hb-```--For more information, go and look at the documentation on [Hackage]!--[Sprockets]: https://github.com/sstephenson/sprockets-[Hackage]: http://hackage.haskell.org/package/herringbone
Web/Herringbone.hs view
@@ -42,7 +42,9 @@ fromLogicalPath, toFilePath, Asset(..),+ assetContent, findAsset,+ precompile, -- * Preprocessors PP(..), PPs,@@ -55,3 +57,4 @@ import Web.Herringbone.Internal.Configuration import Web.Herringbone.Internal.Types import Web.Herringbone.Internal.FindAsset+import Web.Herringbone.Internal.Precompile
Web/Herringbone/Internal/FindAsset.hs view
@@ -4,6 +4,10 @@ import Web.Herringbone.Internal.BuildAsset import Web.Herringbone.Internal.Types +-- | The most important function in this library. Attempts to find the asset+-- referenced by the given 'LogicalPath', compiles it if necessary (based on+-- file modification time), and returns it to you as an 'Asset' (or an+-- 'AssetError', if something went wrong). findAsset :: Herringbone -> LogicalPath -> IO (Either AssetError Asset)
+ Web/Herringbone/Internal/Precompile.hs view
@@ -0,0 +1,35 @@+module Web.Herringbone.Internal.Precompile where++import Control.Monad (forM)+import qualified Filesystem.Path.CurrentOS as F+import qualified Data.Text as T++import Web.Herringbone.Internal.Types+import Web.Herringbone.Internal.FindAsset+import Web.Herringbone.Internal.GetBuildMapping (getBuildMapping)++-- | Precompiles all assets, returning a list of the logical paths of assets+-- that failed to compile (if any) together with 'AssetError' values describing+-- what went wrong.+precompile :: Herringbone -> IO [(LogicalPath, AssetError)]+precompile hb = do+ mapping <- getBuildMapping hb+ results <- forM mapping $ \(BuildSpec _ destPath _) -> do+ let path = toLogicalPath destPath+ either invalidPath compile path+ return $ concat results+ where+ toLogicalPath filePath =+ case F.toText filePath of+ Left approximation ->+ Left (unsafeMakeLogicalPath [approximation])+ Right (T.splitOn "/" -> pieces) ->+ Right (unsafeMakeLogicalPath pieces)++ invalidPath path = return [(path, AssetNotFound)]++ compile path = do+ asset <- findAsset hb path+ return $ case asset of+ Right _ -> []+ Left err -> [(path, err)]
Web/Herringbone/Internal/Types.hs view
@@ -13,9 +13,12 @@ import System.IO hiding (FilePath) import qualified Data.ByteString as B import qualified Filesystem.Path.CurrentOS as F+import qualified Filesystem as F import Filesystem.Path.CurrentOS (FilePath) import Prelude hiding (FilePath) +-- | A value describing an error that occurred while trying to produce an+-- 'Asset'. data AssetError = AssetNotFound | AssetCompileError CompileError | AmbiguousSources [FilePath]@@ -29,7 +32,9 @@ , ppReaderSourcePath :: FilePath -- ^ The file path to the source file , ppReaderPPs :: [PP]- -- ^ Preprocessors being invoked.+ -- ^ Preprocessors being invoked. Currently this will only ever have zero+ -- or one elements; in the future, Herringbone may be able to run multiple+ -- preprocessors on a single file. } -- | A monad in which preprocessor actions happen.@@ -64,9 +69,9 @@ -- | A function which performs the compilation. type PPAction =- B.ByteString ->+ B.ByteString -- ^ Input file contents- PPM (Either CompileError B.ByteString)+ -> PPM (Either CompileError B.ByteString) -- ^ Output file contents, or a compile error. -- | A string which should contain information about why an asset failed to@@ -97,9 +102,10 @@ -- | A BuildSpec specifies how an asset should be built. data BuildSpec = BuildSpec- FilePath -- ^ Source path (relative)- FilePath -- ^ Destination path (again, relative)- (Maybe PP) -- ^ Preprocessor to run (if any)+ { bsSourcePath :: FilePath -- ^ Source path (relative)+ , bsDestPath :: FilePath -- ^ Destination path (again, relative)+ , bsPP :: (Maybe PP) -- ^ Preprocessor to run (if any)+ } deriving (Show) -- | A BuildMapping contains the information to build all of the assets@@ -128,15 +134,20 @@ type ConfigBuilder = HerringboneSettings -> HerringboneSettings +-- | The directory where Herringbone will look when searching for assets. hbSourceDir :: Herringbone -> FilePath hbSourceDir = settingsSourceDir . herringboneSettings +-- | The directory to place assets in after compilation. hbDestDir :: Herringbone -> FilePath hbDestDir = settingsDestDir . herringboneSettings +-- | The collection of preprocessors that will be used when preprocessing+-- assets. hbPPs :: Herringbone -> PPs hbPPs = settingsPPs . herringboneSettings +-- | True iff the 'Herringbone' has the verbose setting enabled. hbVerbose :: Herringbone -> Bool hbVerbose = settingsVerbose . herringboneSettings @@ -147,13 +158,14 @@ hFlush stdout -- | All assets in Herringbone are referenced by their logical path. This is--- the path to an asset, relative to any of the source directories.+-- the path to an asset, relative to the source directory. newtype LogicalPath = LogicalPath { fromLogicalPath :: [Text] } deriving (Show, Eq) --- | Create a LogicalPath from a list of Text values. This returns Nothing if--- the path would be unsafe (that is, if it contains \"..\"), to prevent--- directory traversal attacks.+-- | Create a LogicalPath from a list of path segments. For example,+-- @[\"data\", \"dogs.txt\"]@ would map to data/dogs.txt (relative to the+-- source directory). This returns Nothing if the path would be unsafe (that+-- is, if it contains \"..\"), to prevent directory traversal attacks. makeLogicalPath :: [Text] -> Maybe LogicalPath makeLogicalPath xs = if safe xs then Just $ LogicalPath xs else Nothing where@@ -179,6 +191,9 @@ , assetModifiedTime :: UTCTime -- ^ Modification time of the asset's source file. }++assetContent :: Asset -> IO B.ByteString+assetContent = F.readFile . assetFilePath instance Show Asset where show (Asset size sourcePath filePath modifiedTime) =
Web/Herringbone/Internal/Utils.hs view
@@ -26,7 +26,9 @@ let maybes = map (F.stripPrefix root') files return $ catMaybes maybes --- should this go in a utils module?+-- | Partition a list of values based on a monadic predicate, with the list of+-- values satisfying the predicate as the first element of the result pair, and+-- the list of values not satisfying the predicate as the second. partitionM :: Monad m => (a -> m Bool) -> [a] -> m ([a], [a]) partitionM f = foldM g ([], []) where
herringbone.cabal view
@@ -1,5 +1,5 @@ name: herringbone-version: 0.1.0+version: 0.1.1 synopsis: A library for compiling and serving static web assets. description: A library for compiling and serving static web assets. For more information, please see <https://github.com/hdgarrood/herringbone>. license: MIT@@ -9,8 +9,6 @@ category: Web build-type: Simple cabal-version: >=1.10-extra-source-files:- README.md source-repository head type: git@@ -22,6 +20,7 @@ Web.Herringbone.Preprocessor.StdIO Web.Herringbone.Preprocessor.Sass Web.Herringbone.Preprocessor.CoffeeScript+ Web.Herringbone.Internal.Precompile Web.Herringbone.Internal.Types Web.Herringbone.Internal.Configuration Web.Herringbone.Internal.GetBuildMapping