hsass 0.5.0 → 0.6.0
raw patch · 11 files changed
+144/−45 lines, 11 filesdep ~hlibsassPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: hlibsass
API changes (from Hackage documentation)
- Text.Sass.Functions.Internal: clearNativeFunction :: SassFunctionEntry -> IO ()
- Text.Sass.Functions.Internal: clearNativeFunctionList :: SassFunctionList -> IO ()
+ Text.Sass.Compilation: compileByteString :: SassResult a => ByteString -> SassOptions -> IO (Either SassError a)
+ Text.Sass.Compilation.Internal: newCString :: ByteString -> IO CString
+ Text.Sass.Options: [sassStripEncodingInfo] :: SassOptions -> Bool
- Text.Sass.Options: SassOptions :: Int -> SassOutputStyle -> Bool -> Bool -> Bool -> Bool -> Bool -> String -> String -> Maybe FilePath -> Maybe FilePath -> Maybe [FilePath] -> Maybe [FilePath] -> Maybe FilePath -> Maybe String -> Maybe [SassFunction] -> Maybe [SassHeader] -> Maybe [SassImporter] -> SassOptions
+ Text.Sass.Options: SassOptions :: Int -> SassOutputStyle -> Bool -> Bool -> Bool -> Bool -> Bool -> String -> String -> Maybe FilePath -> Maybe FilePath -> Maybe [FilePath] -> Maybe [FilePath] -> Maybe FilePath -> Maybe String -> Maybe [SassFunction] -> Maybe [SassHeader] -> Maybe [SassImporter] -> Bool -> SassOptions
Files
- CHANGELOG.md +13/−1
- Text/Sass.hs +5/−0
- Text/Sass/Compilation.hs +49/−14
- Text/Sass/Compilation/Internal.hs +21/−0
- Text/Sass/Functions/Internal.hs +3/−19
- Text/Sass/Internal.hs +5/−4
- Text/Sass/Options.hs +7/−1
- Text/Sass/Options/Internal.hs +2/−1
- Text/Sass/Values/Internal.hs +1/−1
- hsass.cabal +3/−2
- test/Text/Sass/CompilationSpec.hs +35/−2
CHANGELOG.md view
@@ -2,9 +2,20 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [0.6.0] - 2018-03-24+### Changed+- Switched to `hLibsass` 0.1.7.0 and `libsass` 3.5.2++### Added+- `compileByteString` for `ByteString`-only compilation+- option to strip BOM/@charset with `sassStripEncodingInfo` option (thanks @h-3-0 !)++### Removed+- `clearNativeFunction` and `clearNativeFunctionList` are not needed anymore+ ## [0.5.0] - 2017-11-01 ### Changed-- Split `SassImporter` into `SassImporter` and `SassHeader` (thanks @h-3-0)+- Split `SassImporter` into `SassImporter` and `SassHeader` (thanks @h-3-0 !) ### Added - `SassIporter` now takes path to the file that is being imported into (thanks@@ -62,3 +73,4 @@ [0.4.1]: https://github.com/jakubfijalkowski/hsass/compare/v0.4.0...v0.4.1 [0.4.2]: https://github.com/jakubfijalkowski/hsass/compare/v0.4.1...v0.4.2 [0.5.0]: https://github.com/jakubfijalkowski/hsass/compare/v0.4.2...v0.5.0+[0.6.0]: https://github.com/jakubfijalkowski/hsass/compare/v0.5.0...v0.6.0
Text/Sass.hs view
@@ -70,6 +70,11 @@ -- If you want access to the extended result, you have to use 'resultString', -- 'resultIncludes' and 'resultSourcemap' on the result to extract desirable -- information.+--+-- Note that if the compiled output contains non-ASCII characters, by default it+-- will be prefixed with either a @\@charset@ rule indicating UTF-8 encoding or+-- a byte-order mark (depending on the output style). If this is inconvenient,+-- you can suppress it by enabling 'sassStripEncodingInfo'. -- $options -- 'SassOptions' wraps <http://libsass.org libsass> context options. It does not
Text/Sass/Compilation.hs view
@@ -2,12 +2,14 @@ {-# LANGUAGE BangPatterns #-} {-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE PatternGuards #-} {-# LANGUAGE TypeSynonymInstances #-} module Text.Sass.Compilation ( -- * Compilation compileFile , compileString+ , compileByteString -- * Results , SassExtendedResult , StringResult@@ -28,15 +30,21 @@ , errorColumn ) where -import qualified Bindings.Libsass as Lib-import Data.ByteString (ByteString, packCString)+import qualified Bindings.Libsass as Lib+import Data.ByteString (ByteString)+import qualified Data.ByteString as B+import qualified Data.ByteString.Char8 as B.C8+import qualified Data.ByteString.Unsafe as B+import Data.List (stripPrefix)+import Data.Maybe (fromMaybe) #if !MIN_VERSION_base(4,8,0)-import Control.Applicative ((<$>))+import Control.Applicative ((<$>)) #endif-import Control.Monad (forM, (>=>))+import Control.Monad (forM, (>=>)) import Foreign import Foreign.C-import Text.Sass.Internal+import qualified Text.Sass.Compilation.Internal as CI+import Text.Sass.Internal hiding (newCString) import Text.Sass.Options -- | Represents compilation error.@@ -78,7 +86,7 @@ -- 'SassResult'). 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+ toSassResult :: Bool -> ForeignPtr Lib.SassContext -> IO a instance Show SassError where show (SassError s _) =@@ -92,22 +100,37 @@ -- | Only compiled code. instance SassResult String where- toSassResult ptr = withForeignPtr ptr $ \ctx -> do+ toSassResult stripEncoding ptr = withForeignPtr ptr $ \ctx -> do result <- Lib.sass_context_get_output_string ctx !result' <- peekCString result- return result'+ return $ if stripEncoding then strip result' else result'+ where+ strip s+ | Just stripped <- stripPrefix "@charset \"UTF-8\";\n" s = stripped+ | Just stripped <- stripPrefix "\65279" s = stripped+ | otherwise = s -- | Only compiled code (UTF-8 encoding). instance SassResult ByteString where- toSassResult ptr = withForeignPtr ptr $ \ctx -> do+ toSassResult stripEncoding ptr = withForeignPtr ptr $ \ctx -> do result <- Lib.sass_context_get_output_string ctx- !result' <- packCString result- return result'+ !result' <- B.packCString result+ return $ if stripEncoding then strip result' else result'+ where+ strip s+ | Just stripped <- stripCharset s = stripped+ | Just stripped <- stripBom s = stripped+ | otherwise = s+ stripCharset = stripPrefixBS (B.C8.pack "@charset \"UTF-8\";\n")+ stripBom = stripPrefixBS (B.C8.pack "\239\187\191")+ stripPrefixBS bs1 bs2+ | bs1 `B.C8.isPrefixOf` bs2 = Just (B.unsafeDrop (B.length bs1) bs2)+ | otherwise = Nothing -- | Compiled code with includes and a source map. instance (SassResult a) => SassResult (SassExtendedResult a) where- toSassResult ptr = do- str <- toSassResult ptr+ toSassResult stripEncoding ptr = do+ str <- toSassResult stripEncoding ptr return $ SassExtendedResult str ptr -- | Loads specified property from a context and converts it to desired type.@@ -195,7 +218,7 @@ then return $ Left $ SassError (fromIntegral status) fptr else do- result <- toSassResult fptr+ result <- toSassResult (sassStripEncodingInfo opts) fptr return $ Right result -- | Compiles a file using specified options.@@ -216,6 +239,18 @@ -> 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.p_sass_delete_data_context++-- | Compiles raw Sass content using specified options.+compileByteString :: SassResult a+ => ByteString -- ^ String to compile.+ -> SassOptions -- ^ Compilation options.+ -> IO (Either SassError a) -- ^ Error or output string.+compileByteString str opts = do+ cdata <- CI.newCString str compileInternal cdata opts Lib.sass_make_data_context Lib.sass_compile_data_context
+ Text/Sass/Compilation/Internal.hs view
@@ -0,0 +1,21 @@+-- | Helper functions used by Compilation module.+module Text.Sass.Compilation.Internal+ (+ newCString+ ) where++import Data.ByteString (ByteString)+import qualified Data.ByteString.Internal as BI+import Foreign+import Foreign.C hiding (newCString)+import Foreign.Marshal.Alloc (mallocBytes)++-- | Copies 'ByteString' to newly allocated 'CString'. The result must be+-- | explicitly freed using 'free' or 'finalizerFree'.+newCString :: ByteString -> IO CString+newCString (BI.PS fp o l) = do+ buf <- mallocBytes (l + 1)+ withForeignPtr fp $ \p -> do+ BI.memcpy buf (p `plusPtr` o) (fromIntegral l)+ pokeByteOff buf l (0::Word8)+ return $ castPtr buf
Text/Sass/Functions/Internal.hs view
@@ -4,10 +4,8 @@ -- * Functions wrapFunction , makeNativeFunction- , clearNativeFunction , freeNativeFunction , makeNativeFunctionList- , clearNativeFunctionList , freeNativeFunctionList -- * Imports and headers , wrapImporter@@ -35,27 +33,17 @@ -- | Converts 'SassFunction' into native representation. ----- Freeing native representation is not a pleasant process - libsass frees--- the 'Lib.SassFunctionEntry', but does not free signature. Because of that,--- special care must be taken in order to properly deallocate the object. -- If you don't want to pass the resulting object to Sass_Options,--- call both 'clearNativeFunction' and then 'freeNativeFunction'. Otherwise,--- you should call 'clearNativeFunction' BEFORE you deallocate context.+-- call 'freeNativeFunction'. makeNativeFunction :: SassFunction -> IO Lib.SassFunctionEntry makeNativeFunction (SassFunction sig' fn) = do sig <- newCString sig' wrapped <- Lib.mkSassFunctionFn $ wrapFunction fn Lib.sass_make_function sig wrapped nullPtr --- | Releases the signature of a function entry.-clearNativeFunction :: Lib.SassFunctionEntry -> IO ()-clearNativeFunction entry = do- sig <- Lib.sass_function_get_signature entry- free sig- -- | Deallocates the object, but does not deallocate signature. freeNativeFunction :: Lib.SassFunctionEntry -> IO ()-freeNativeFunction = free+freeNativeFunction = Lib.sass_delete_function -- | Converts list of 'SassFunction's into native representation. --@@ -65,13 +53,9 @@ makeNativeFunctionList = copyToCList Lib.sass_make_function_list makeNativeFunction pokeElemOff --- | Releases signatures of entries in the list.-clearNativeFunctionList :: Lib.SassFunctionList -> IO ()-clearNativeFunctionList = loopCList clearNativeFunction- -- | Frees the list and entries, without releasing signatures. freeNativeFunctionList :: Lib.SassFunctionList -> IO ()-freeNativeFunctionList = loopCList freeNativeFunction+freeNativeFunctionList = Lib.sass_delete_function_list -- | Wraps function of type 'SassImporterType'. wrapImporter :: SassImporterType -> Lib.SassImporterFnType
Text/Sass/Internal.hs view
@@ -4,7 +4,8 @@ module I ) where -import Text.Sass.Functions.Internal as I-import Text.Sass.Options.Internal as I-import Text.Sass.Utils as I-import Text.Sass.Values.Internal as I+import Text.Sass.Compilation.Internal as I+import Text.Sass.Functions.Internal as I+import Text.Sass.Options.Internal as I+import Text.Sass.Utils as I+import Text.Sass.Values.Internal as I
Text/Sass/Options.hs view
@@ -10,7 +10,9 @@ import Data.Default.Class import Text.Sass.Functions --- | Describes options used by libsass during compilation.+-- | Describes compilation options. With the exception of+-- 'sassStripEncodingInfo', these correspond to the compilation options of+-- libsass. data SassOptions = SassOptions { -- | Precision of fractional numbers. sassPrecision :: Int@@ -54,6 +56,9 @@ , sassHeaders :: Maybe [SassHeader] -- | List of user-supplied functions that resolve @import directives. , sassImporters :: Maybe [SassImporter]+ -- | Remove @\@charset \"UTF-8\";\\n@ or byte-order mark from CSS output,+ -- if present.+ , sassStripEncodingInfo :: Bool } -- | The default 'SassOptions':@@ -83,6 +88,7 @@ , sassFunctions = Nothing , sassHeaders = Nothing , sassImporters = Nothing+ , sassStripEncodingInfo = False } -- | 'def' = 'defaultSassOptions'
Text/Sass/Options/Internal.hs view
@@ -69,5 +69,6 @@ nativeFnList <- makeNativeFunctionList lst Lib.sass_option_set_c_functions ptr nativeFnList !result <- action- clearNativeFunctionList nativeFnList+ Lib.sass_option_set_c_functions ptr nullPtr+ freeNativeFunctionList nativeFnList return result
Text/Sass/Values/Internal.hs view
@@ -34,7 +34,7 @@ toNativeValue (SassWarning str) = withCString str Lib.sass_make_warning toNativeValue (SassError str) = withCString str Lib.sass_make_error toNativeValue (SassList lst sep') =- copyToCList (`Lib.sass_make_list` sep) toNativeValue+ copyToCList (\size -> Lib.sass_make_list size sep False) toNativeValue Lib.sass_list_set_value lst where sep = fromIntegral $ fromEnum sep'
hsass.cabal view
@@ -1,5 +1,5 @@ name: hsass-version: 0.5.0+version: 0.6.0 license: MIT license-file: LICENSE author: Jakub Fijałkowski <fiolek94@gmail.com>@@ -41,6 +41,7 @@ , Text.Sass.Options , Text.Sass.Values , Text.Sass.Internal+ , Text.Sass.Compilation.Internal , Text.Sass.Functions.Internal , Text.Sass.Options.Internal , Text.Sass.Values.Internal@@ -48,7 +49,7 @@ , Text.Sass.Utils build-depends: base >= 4.7 && < 5- , hlibsass >= 0.1.5.2+ , hlibsass >= 0.1.7.0 , bytestring >= 0.10.0 , data-default-class , filepath >= 1.0
test/Text/Sass/CompilationSpec.hs view
@@ -19,11 +19,12 @@ importers :: [SassImporter] importers = [SassImporter 1 importerFunc] -extendedResultSpec, compilationSpec, errorReportingSpec, spec :: Spec+extendedResultSpec, compilationSpec, errorReportingSpec, stripEncodingInfoSpec, spec :: Spec spec = do describe "Compilation" compilationSpec describe "Extended compilation" extendedResultSpec describe "Error reporting" errorReportingSpec+ describe "Stripping encoding information" stripEncodingInfoSpec compilationSpec = do it "should compile simple source" $@@ -45,13 +46,17 @@ hClose h compileFile p def `shouldReturn` Right "foo {\n margin: 42px; }\n" - it "compile file should respect options" $ do+ it "should respect options when compiling file" $ do let opts = def { sassOutputStyle = SassStyleCompressed } withSystemTempFile "styles.sass" $ \p h -> do hPutStr h "foo { margin: 21px * 2; }" hClose h compileFile p opts `shouldReturn` Right "foo{margin:42px}\n" + it "should compile bytestring correctly" $+ compileByteString (pack "foo { margin: 21px * 2; }") def `shouldReturn`+ Right (pack "foo {\n margin: 42px; }\n")+ extendedResultSpec = do it "should compile simple source" $ do res <- compileString "foo { margin: 21px * 2; }" def@@ -120,3 +125,31 @@ it "should contain file path" $ do (Left r) <- compileString "body { !! }" def :: StringResult errorFile r `returnShouldSatisfy` (not . null)++stripEncodingInfoSpec = do+ describe "from strings" $ do+ it "should strip '@charset \"UTF-8\";\\n'" $ do+ let opts = def { sassStripEncodingInfo = True }+ compileString "h1:before { content: '\9660'; }" opts `shouldReturn`+ Right "h1:before {\n content: '\9660'; }\n"++ it "should strip byte-order mark" $ do+ let opts = def { sassOutputStyle = SassStyleCompressed+ , sassStripEncodingInfo = True+ }+ compileString "h1:before { content: '\9660'; }" opts `shouldReturn`+ Right "h1:before{content:'\9660'}\n"++ describe "from bytestrings" $ do+ it "should strip '@charset \"UTF-8\";\\n'" $ do+ let opts = def { sassStripEncodingInfo = True }+ compileString "h1:before { content: '\9660'; }" opts `shouldReturn`+ Right (pack "h1:before {\n content: '\226\150\188'; }\n")++ it "should strip byte-order mark" $ do+ let opts = def { sassOutputStyle = SassStyleCompressed+ , sassStripEncodingInfo = True+ }+ compileString "h1:before { content: '\9660'; }" opts `shouldReturn`+ Right (pack "h1:before{content:'\226\150\188'}\n")+