hsass 0.1.0 → 0.2.0
raw patch · 8 files changed
+171/−88 lines, 8 filesdep ~basePVP ok
version bump matches the API change (PVP)
Dependency ranges changed: base
API changes (from Hackage documentation)
+ Text.Sass.Compilation: data SassExtendedResult
+ Text.Sass.Compilation: errorStatus :: SassError -> Int
+ Text.Sass.Compilation: instance SassResult SassExtendedResult
+ Text.Sass.Compilation: instance SassResult String
+ Text.Sass.Compilation: instance Show SassExtendedResult
+ Text.Sass.Compilation: resultIncludes :: SassExtendedResult -> IO [String]
+ Text.Sass.Compilation: resultSourcemap :: SassExtendedResult -> IO (Maybe String)
+ Text.Sass.Compilation: resultString :: SassExtendedResult -> String
+ Text.Sass.Compilation: type ExtendedResult = IO (Either SassError SassExtendedResult)
+ Text.Sass.Compilation: type StringResult = IO (Either SassError String)
- Text.Sass.Compilation: compileFile :: FilePath -> SassOptions -> IO (Either SassError String)
+ Text.Sass.Compilation: compileFile :: SassResult a => FilePath -> SassOptions -> IO (Either SassError a)
- Text.Sass.Compilation: compileString :: String -> SassOptions -> IO (Either SassError String)
+ Text.Sass.Compilation: compileString :: SassResult a => String -> SassOptions -> IO (Either SassError a)
Files
- CHANGELOG.md +10/−0
- Text/Sass.hs +49/−41
- Text/Sass/Compilation.hs +104/−38
- Text/Sass/Functions/Internal.hs +1/−1
- Text/Sass/Options/Internal.hs +1/−1
- Text/Sass/Utils.hs +1/−2
- Text/Sass/Values/Internal.hs +3/−3
- hsass.cabal +2/−2
CHANGELOG.md view
@@ -2,6 +2,16 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## 0.2.0 - 2015-06-01+### Changed+- Return type of 'compileString' and 'compileFile' is now polymorphic - may+ return both 'String' and 'SassExtendedResult' on success.+- Fixes in documentation (articles, mostly).++### Added+- 'SassExtendedResult' with a compiled string, a list of files included during+ compilation and a source map.+ ## 0.1.0 - 2015-04-11 ### Added - Support for functions, importers, headers and sass values.
Text/Sass.hs view
@@ -5,7 +5,8 @@ -- extension language. It supports basic compilation, functions, importers and -- headers, so it should suffice for most of the work. ----- Code used in this document is testable - see test/Text/Sass/TutorialSpec.hs.+-- Code used in this document is testable - see+-- @test\/Text\/Sass\/TutorialSpec.hs@. module Text.Sass ( -- * Compilation@@ -37,14 +38,18 @@ import Text.Sass.Values -- $compilation--- Compilation of Sass source is very easy - you only have to use 'compileFile'--- or 'compileString' and leave the work to hsass. 'compileFile' takes path to--- the file as first parameter, while 'compileString' takes source code.--- Both functions take 'SassOptions' as second parameter, so if you want to--- customize compilation behaviour, you may use it.+-- Compilation of a Sass source is very easy - you only have to use+-- 'compileFile' or 'compileString' and leave the work to hsass. 'compileFile'+-- a takes path to the file as a first parameter, while 'compileString' takes a+-- source code. Both functions take 'SassOptions' as a second parameter, so if+-- you want to customize compilation behaviour, you may use it. -- -- The result of both functions is 'Either' @Left 'SassError'@, indicating that--- something went wrong, or @Right 'String'@ with resulting code.+-- something went wrong, @Right 'String'@ with resulting code or+-- @Right 'SassExtendedResult'@ with a compiled code, a list of included files+-- and optionally a source map. Compilation functions are polymorphic in their+-- return type (there are no separate functions based on return type), but the+-- compiler should be able to infer the type easily. -- You can examine 'SassError' to gain more knowledge about the error. -- -- 'SassOptions' is instance of 'Default' class, so you may use 'def' function@@ -61,6 +66,10 @@ -- When you want to compile source code instead of file, consider setting -- 'sassIncludePaths' - it will allow to resolve @includes without custom -- importers.+--+-- If you want access to the extended result, you have to use 'resultString',+-- 'resultIncludes' and 'resultSourcemap' on the result to extract desirable+-- information. -- $options -- 'SassOptions' wraps <http://libsass.org libsass> context options. It does not@@ -69,31 +78,30 @@ -- $values -- "Text.Sass.Values" module wraps native values that libsass uses. It provides--- easy way to manage them in pure Haskell code.+-- an easy way to manage them in pure Haskell code. -- $functions_basic -- This is the most advanced stuff in the library (even though it is quite -- simple). It allows you to define functions in Haskell and use them from Sass--- source, provide custom resolution for @import statements and include custom--- headers in files.+-- source, provide custom resolution functions for @import statements and+-- include custom headers in files. -- $functions--- Let's start with explanation of functions. For example, assume that we want to--- use function @max3@, that takes three numbers and returns the largest. In+-- Let's start with explanation of functions. For example, assume that we want+-- to use function @max3@, that takes three numbers and returns the largest. In -- Haskell, we would write it like this: -- -- > max3 :: Int -> Int -> Int -> Int -- > max3 a b c = max a $ max b c -- -- Unfortunately, sass would not be able to use that. We must rewrite this--- function so that it operates on 'SassValue's. If we want to use function+-- function so that it operates on 'SassValue's. If we want to use a function -- in sass, it has to have following signature: -- -- > func :: SassValue -> IO SassValue ----- It takes an argument that is 'SassList' with all of arguments passed in sass--- code and returns computed 'SassValue'. With this in mind, we may write--- following code:+-- It takes an argument that is 'SassList' with all of its arguments and returns+-- computed 'SassValue'. With this in mind, we may write following code: -- -- > max3 (SassList (SassNumber a _:SassNumber b _:SassNumber c _:_) _) = -- > return $ SassNumber (max a $ max b c) "px"@@ -103,14 +111,14 @@ -- -- > max3sig = SassFunction "max3($a, $b, $c)" max3 ----- This description allows compiler to map Haskell function (@max3@) to a form--- that may be used in sass. Signature consists of function name (@max3@),--- opening parenthesis, list of arguments (dollar sign and its name) separated--- by comma and closing parenthesis. It is the same as function definition in--- sass code.+-- This description allows the compiler to map Haskell function (@max3@) to a+-- form that may be used in sass. Signature consists of function name (@max3@),+-- an opening parenthesis, a list of arguments (dollar sign and its name)+-- separated by commas and a closing parenthesis. It is the same as a function+-- definition in sass code. ----- With this code we may tell compiler to use this function. In order to do--- this, we must replace 'sassFunctions' field in 'SassOptions':+-- We can now tell the compiler to use our function. In order to do this, we+-- must replace 'sassFunctions' field in 'SassOptions': -- -- > opts = def { sassFunctions = Just [max3sig] } --@@ -122,7 +130,7 @@ -- -- > "foo { margin: 3px; }" ----- There exist several functions that are special:+-- There exists several functions that are special: -- -- * @*@ - fallback implementation -- * @@warn@ - overload warn statement@@ -133,22 +141,22 @@ -- documentation for more information. -- $headers_and_importers--- Importers are functions that override default behaviour of @import statement--- behaviour. For example, you may implement rewrite rules or even download--- stylesheets from remote server.+-- Importers are functions that override default behaviour of @import statements+-- For example, you may implement rewrite rules or even download stylesheets+-- from remote server. -- -- Headers leverage the same infrastructure as importers - they are just used -- not for @imports, but for every file being loaded. They allow you to inject--- arbitrary sass source in the file.+-- arbitrary sass source in a file. ----- Let's say that we want to inject path to currently compiled file. We may write--- following header:+-- Let's say that we want to inject a path to currently compiled file. We may+-- write the following header: -- -- > header src = return [makeSourceImport $ "$file: " ++ src ++ ";"] ----- It simply returns sass code that defines @$file@ variable set to path to--- current file (first argument of function).--- Then, we must define header signature and options:+-- It simply returns sass code that defines a @$file@ variable set to a path to+-- the current file (first argument of the function).+-- Then, we must define header signature and override options: -- -- > headerSig = SassImporter 1 header -- > opts = def { sassHeaders = Just [headerSig], sassInputPath = Just "path" }@@ -163,11 +171,11 @@ -- -- > "foo { prop: path; }" ----- Importers are defined and act similarly - they just take path to file being--- imported instead of file being processed and are injected using+-- Importers are defined and act similarly - they just take path to the file+-- being imported instead of file being processed and are injected using -- 'sassImporters'. ----- Additionally importers support priorities - if two importers return source+-- Additionally, importers support priorities - if two importers return source -- for some file, the one with higher priority wins. For example -- -- > importer1 src = return [makeSourceImport $ "$file: " ++ src ++ "1;"]@@ -180,8 +188,8 @@ -- -- > "foo { prop: file2; }" ----- Instead of providing source code for imports, you may provide path to file--- and leave loading to library. This is done by settings only 'importPath' and--- 'importBase' in 'SassImport' or using 'makePathImport' instead of--- 'makeSourceImport'. This may be useful to implement just rewrite rules and--- not full loading.+-- Instead of providing source code for imports, you may provide a path to a+-- file and leave loading to the library. This is done by settings only+-- 'importPath' and 'importBase' in 'SassImport' or using 'makePathImport'+-- instead of 'makeSourceImport'. This may be useful to implement just rewrite+-- rules and not full loading.
Text/Sass/Compilation.hs view
@@ -1,12 +1,22 @@ -- | Compilation of sass source or sass files.-{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeSynonymInstances #-} module Text.Sass.Compilation ( -- * Compilation compileFile , compileString+ -- * Results+ , SassExtendedResult+ , StringResult+ , ExtendedResult+ , resultString+ , resultIncludes+ , resultSourcemap -- * Error reporting- , SassError (errorStatus)+ , SassError+ , errorStatus , errorJson , errorText , errorMessage@@ -16,8 +26,9 @@ , errorColumn ) where -import qualified Bindings.Libsass as Lib-import Control.Monad ((>=>))+import qualified Bindings.Libsass as Lib+import Control.Applicative ((<$>))+import Control.Monad (forM, (>=>)) import Foreign import Foreign.C import Text.Sass.Internal@@ -29,6 +40,34 @@ errorContext :: ForeignPtr Lib.SassContext } +-- | Represents extended result - compiled string with a list of includes and+-- a source map.+--+-- Subject to name change in future versions.+data SassExtendedResult = SassExtendedResult {+ resultString :: String, -- ^ Compiled string.+ resultContext :: ForeignPtr Lib.SassContext+}++-- | Result of compilation - 'Either' 'SassError' or a compiled string.+--+-- Subject to name change in future versions.+type StringResult = IO (Either SassError String)++-- | Result of compilation - 'Either' 'SassError' or extended results - a+-- compiled string with a list of included files and a source map.+--+-- Subject to name change in future versions.+type ExtendedResult = IO (Either SassError SassExtendedResult)++-- | Typeclass that allows multiple results from compilation functions.+--+-- Currently, only two types are supported - 'String' and 'SassExtendedResult'.+-- The first provides only a compiled string, the latter one gives access to a+-- list of included files and a source map (if available).+class SassResult a where+ toSassResult :: ForeignPtr Lib.SassContext -> IO a+ instance Show SassError where show (SassError s _) = "SassError: cannot compile provided source, error status: " ++ show s@@ -36,7 +75,23 @@ instance Eq SassError where (SassError s1 _) == (SassError s2 _) = s1 == s2 --- | Loads specified property from context and converts it to desired type.+instance Show SassExtendedResult where+ show _ = "SassExtendedResult"++-- | Only compiled code.+instance SassResult String where+ toSassResult ptr = withForeignPtr ptr $ \ctx -> do+ result <- Lib.sass_context_get_output_string ctx+ !result' <- peekCString result+ return result'++-- | Compiled code with includes and a source map.+instance SassResult SassExtendedResult where+ toSassResult ptr = do+ str <- toSassResult ptr+ return $ SassExtendedResult str ptr++-- | Loads specified property from a context and converts it to desired type. loadFromError :: (Ptr Lib.SassContext -> IO a) -- ^ Accessor function. -> (a -> IO b) -- ^ Conversion method. -> SassError -- ^ Pointer to context.@@ -44,94 +99,105 @@ loadFromError get conv err = withForeignPtr ptr $ get >=> conv where ptr = errorContext err --- | Equivalent to @'loadFromError' 'get' 'peekCString' 'err'@.-loadStringFromError :: (Ptr Lib.SassContext -> IO CString) -- ^ Accessor function.- -> SassError -- ^ Pointer to context.- -> IO String -- ^ Result.+-- | Equivalent of @'loadFromError' 'get' 'peekCString' 'err'@.+loadStringFromError+ :: (Ptr Lib.SassContext -> IO CString) -- ^ Accessor function.+ -> SassError -- ^ Pointer to context.+ -> IO String -- ^ Result. loadStringFromError get = loadFromError get peekCString --- | Equivalent to @'loadFromError' 'get' 'fromInteger' 'err'@.+-- | Equivalent of @'loadFromError' 'get' 'fromInteger' 'err'@. loadIntFromError :: (Integral a) => (Ptr Lib.SassContext -> IO a) -- ^ Accessor function. -> SassError -- ^ Pointer to context. -> IO Int -- ^ Result. loadIntFromError get = loadFromError get (return.fromIntegral) --- | Loads information about error as JSON.+-- | Loads information about an error as JSON. errorJson :: SassError -> IO String errorJson = loadStringFromError Lib.sass_context_get_error_json --- | Loads error text.+-- | Loads an error text. errorText :: SassError -> IO String errorText = loadStringFromError Lib.sass_context_get_error_text --- | Loads user-friendly error message.+-- | Loads a user-friendly error message. errorMessage :: SassError -> IO String errorMessage = loadStringFromError Lib.sass_context_get_error_message --- | Loads file where problem occured.+-- | Loads a filename where problem occured. errorFile :: SassError -> IO String errorFile = loadStringFromError Lib.sass_context_get_error_file --- | Loads error source.+-- | Loads an error source. errorSource :: SassError -> IO String errorSource = loadStringFromError Lib.sass_context_get_error_src --- | Loads line in the file where problem occured.+-- | Loads a line in the file where problem occured. errorLine :: SassError -> IO Int errorLine = loadIntFromError Lib.sass_context_get_error_line --- | Loads line in the file where problem occured.+-- | Loads a line in the file where problem occured. errorColumn :: SassError -> IO Int errorColumn = loadIntFromError Lib.sass_context_get_error_column +-- | Loads a list of files that have been included during compilation.+resultIncludes :: SassExtendedResult -> IO [String]+resultIncludes ex = withForeignPtr (resultContext ex) $ \ctx -> do+ lst <- Lib.sass_context_get_included_files ctx+ len <- Lib.sass_context_get_included_files_size ctx+ forM (arrayRange $ fromIntegral len) (peekElemOff lst >=> peekCString)++-- | Loads a source map if it was generated by libsass.+resultSourcemap :: SassExtendedResult -> IO (Maybe String)+resultSourcemap ex = withForeignPtr (resultContext ex) $ \ctx -> do+ cstr <- Lib.sass_context_get_source_map_string ctx+ if cstr == nullPtr+ then return Nothing+ else Just <$> peekCString cstr+ -- | Common code for 'compileFile' and 'compileString'.-compileInternal :: CString -- ^ String that will be passed to 'make context'.+compileInternal :: (SassResult b)+ => CString -- ^ String that will be passed to 'make context'. -> SassOptions -> (CString -> IO (Ptr a)) -- ^ Make context. -> (Ptr a -> IO CInt) -- ^ Compile context.- -> (Ptr a -> IO ()) -- ^ Delete context. -> FinalizerPtr a -- ^ Context finalizer.- -> IO (Either SassError String)-compileInternal str opts make compile delete finalizer = do+ -> IO (Either SassError b)+compileInternal str opts make compile finalizer = do -- Makes an assumption, that Sass_*_Context inherits from Sass_Context -- and Sass_Options. context <- make str- let context' = castPtr context let opts' = castPtr context copyOptionsToNative opts opts' status <- withFunctions opts opts' $ compile context+ fptr <- castForeignPtr <$> newForeignPtr finalizer context if status /= 0- then do- fptr <- newForeignPtr finalizer context- return $ Left $- SassError (fromIntegral status) (castForeignPtr fptr)+ then return $ Left $+ SassError (fromIntegral status) fptr else do- result <- Lib.sass_context_get_output_string context'- !result' <- peekCString result- delete context- return $ Right result'-+ result <- toSassResult fptr+ return $ Right result --- | Compiles file using specified options.-compileFile :: FilePath -- ^ Path to the file.+-- | Compiles a file using specified options.+compileFile :: SassResult a+ => FilePath -- ^ Path to the file. -> SassOptions -- ^ Compilation options.- -> IO (Either SassError String) -- ^ Error or output string.+ -> IO (Either SassError a) -- ^ Error or output string. compileFile path opts = withCString path $ \cpath -> compileInternal cpath opts Lib.sass_make_file_context Lib.sass_compile_file_context- Lib.sass_delete_file_context Lib.p_sass_delete_file_context -- | Compiles raw Sass content using specified options.-compileString :: String -- ^ String to compile.+compileString :: SassResult a+ => String -- ^ String to compile. -> SassOptions -- ^ Compilation options.- -> IO (Either SassError String) -- ^ Error or output string.+ -> IO (Either SassError a) -- ^ Error or output string. compileString str opts = do cdata <- newCString str compileInternal cdata opts Lib.sass_make_data_context Lib.sass_compile_data_context- Lib.sass_delete_data_context Lib.p_sass_delete_data_context
Text/Sass/Functions/Internal.hs view
@@ -121,4 +121,4 @@ -- Libsass does not provide function to free this kind of objects, but we -- provide it just in case. freeNativeImporterList :: Lib.SassImporterList -> IO ()-freeNativeImporterList lst = (loopCList freeNativeImporter lst) >> free lst+freeNativeImporterList lst = loopCList freeNativeImporter lst >> free lst
Text/Sass/Options/Internal.hs view
@@ -55,7 +55,7 @@ -> IO a -- ^ Action. -> IO a -- ^ Result withFunctions opt ptr action =- case (sassFunctions opt) of+ case sassFunctions opt of Nothing -> action Just lst -> do nativeFnList <- makeNativeFunctionList lst
Text/Sass/Utils.hs view
@@ -1,6 +1,5 @@ -- | Helper functions. This module is internal and should not be used in -- production code.-{-# LANGUAGE ViewPatterns #-} module Text.Sass.Utils ( -- * Interoperation with C API@@ -53,7 +52,7 @@ copyToCList create convert set list = do let len = length list result <- create $ fromIntegral len- zipWithM_ (addToList result) [0..(fromIntegral len) - 1] list+ zipWithM_ (addToList result) [0..fromIntegral len - 1] list return result where addToList lst idx = convert >=> set lst idx
Text/Sass/Values/Internal.hs view
@@ -31,7 +31,7 @@ toNativeValue (SassWarning str) = withCString str Lib.sass_make_warning toNativeValue (SassError str) = withCString str Lib.sass_make_error toNativeValue (SassList lst sep') =- copyToCList (flip Lib.sass_make_list sep) toNativeValue+ copyToCList (`Lib.sass_make_list` sep) toNativeValue Lib.sass_list_set_value lst where sep = fromIntegral $ fromEnum sep' @@ -68,9 +68,9 @@ fromNativeValue' Lib.SassString ptr = SassString <$> (Lib.sass_string_get_value ptr >>= peekCString) fromNativeValue' Lib.SassNull _ = return SassNull-fromNativeValue' Lib.SassWarning ptr = do+fromNativeValue' Lib.SassWarning ptr = SassWarning <$> (Lib.sass_warning_get_message ptr >>= peekCString)-fromNativeValue' Lib.SassError ptr = do+fromNativeValue' Lib.SassError ptr = SassError <$> (Lib.sass_error_get_message ptr >>= peekCString) fromNativeValue' Lib.SassList ptr = do len <- Lib.sass_list_get_length ptr
hsass.cabal view
@@ -1,5 +1,5 @@ name: hsass-version: 0.1.0+version: 0.2.0 license: MIT license-file: LICENSE author: Jakub Fijałkowski <fiolek94@gmail.com>@@ -46,7 +46,7 @@ , Text.Sass.Values.Internal , Text.Sass.Utils build-depends:- base >= 4.7 && <4.8,+ base >= 4.7 && < 5, hlibsass >= 0.1.1, data-default-class, filepath >= 1.0,