hdgarrood / herringbone

Preprocess and serve your web assets.
12 stars 0 forks source link

More flexible preprocessors #22

Open hdgarrood opened 10 years ago

hdgarrood commented 10 years ago

Reasoning is:

Ideas:

data Js = Js
data Hs = Hs

class PPFile a where
    toExt :: a -> Text
    fromExt :: Text -> Maybe a

instance PPFile Js where
    toExt _ = "js"
    fromExt "js" = Just Js
    fromExt _ = Nothing

data PP a b = PP { runPP :: ByteString -> PPM ByteString }

instance Category PP where
    id = PP return
    (PP a) . (PP b) = PP (b >=> a)

Problems: can't really do more than 1 source / destination per PP.

Next attempt:

data PP a b = PP { runPP :: a -> PPM b }

instance Category PP where
    ...

instance Arrow PP where
    ...

sassWithSourceMap :: PP Sass (Css, SourceMap)
minifyCSS :: PP Css Css

cssPipeline :: PP
cssPipeline = sassWithSourceMap >>> first minifyCss

where Sass, Css, SourceMap are probably newtyped ByteString

hdgarrood commented 10 years ago

Or this:

class PPFileType a where
   ext :: a -> Text

newtype Sass = Sass { unSass :: ByteString }

instance PPFileType Sass where
   ext = const "sass"
hdgarrood commented 10 years ago

Actually I think that will cause too much noise and boilerplate for type checking. Maybe this would work better:

newtype FileExtension = FileExtension { unFileExtension :: Text }
newtype PP' a = PP' { runPP :: [(FileExtension, a)] -> PPM [(FileExtension, a)] }
newtype PP = PP { unPP :: PPT ByteString }

instance Monoid a => Monoid PPT a where
    mempty = PP return
    mappend (PP a) (PP b) = PP (b >=> a)

Then a list of pairs Then we can check the correct files have been supplied at runtime with something like this:

withFiles :: [(FileExtension, a -> PPM a)] -> [(FileExtension, a)] -> PPM [(FileExtension, a)]

withFile :: FileExtension -> (a -> PPM a) -> [(FileExtension, a)] -> PPM [(FileExtension, a)]
withFile ext action = withFiles [(ext, (,) <$> pure ext <*> action)]

sassWithSourceMap :: PP
sassWithSourceMap = PP $ PP' $ withFile "sass" $ \fileData -> do
    (css, sourceMap) <- compileSass fileData
    return [("css", css), ("map", sourceMap)]

minifyCss :: PP
minifyCss = PP $ PP' $ withFile "css" $ ???