diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,51 @@
 All notable changes to this project will be documented in this file.
 This project adheres to [Semantic Versioning](http://semver.org/).
 
+## [0.8.0] - 2018-11-25
+### Changed
+- Fix invalid usage of `sass_make_import` and fix `SassImport`. This is a
+  breaking change. Fixes [#12](https://github.com/jakubfijalkowski/hsass/issues/12).
+
+## [0.7.0] - 2018-04-02
+### Changed
+- This library uses UTF-8 to encode/decode all `CString`s (paths included!)
+
+## [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 !)
+
+### Added
+- `SassIporter` now takes path to the file that is being imported into (thanks
+  @h-3-0)
+
+## [0.4.2] - 2017-08-28
+### Added
+- Introduce `defaultSassOptions` as default options (thanks @chris-martin !)
+
+## [0.4.1] - 2017-03-19
+### Fixed
+- Bump `hlibsass` version to 0.1.5.2 (fixes build problem on Cabal 1.24 & Stack
+  1.4)
+
+## [0.4.0] - 2015-12-19
+### Added
+- Support for combining `SassValues` (new in hlibsass 0.1.5)
+
+### Changed
+- Requires hlibsass version 0.1.5
+- `SassValue` derives `Show`
+
 ## [0.3.0] - 2015-07-10
 ### Added
 - Support for a `ByteString` result (thanks to [Andy
@@ -33,3 +78,10 @@
 
 [0.2.0]: https://github.com/jakubfijalkowski/hsass/compare/v0.1.0...v0.2.0
 [0.3.0]: https://github.com/jakubfijalkowski/hsass/compare/v0.2.0...v0.3.0
+[0.4.0]: https://github.com/jakubfijalkowski/hsass/compare/v0.3.0...v0.4.0
+[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
+[0.7.0]: https://github.com/jakubfijalkowski/hsass/compare/v0.6.0...v0.7.0
+[0.8.0]: https://github.com/jakubfijalkowski/hsass/compare/v0.7.0...v0.8.0
diff --git a/Text/Sass.hs b/Text/Sass.hs
--- a/Text/Sass.hs
+++ b/Text/Sass.hs
@@ -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
@@ -141,16 +146,15 @@
 -- documentation for more information.
 
 -- $headers_and_importers
--- Importers are functions that override default behaviour of @import statements
--- 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 a 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 a file.
+-- Headers allow you to insert arbitrary sass at the beginning of the file being
+-- compiled.
 --
--- Let's say that we want to inject a path to currently compiled file. We may
--- write the following header:
+-- Let's say that we want to inject a path to the currently compiled file. We
+-- may write the following header:
 --
 -- > header src = return [makeSourceImport $ "$file: " ++ src ++ ";"]
 --
@@ -158,10 +162,10 @@
 -- the current file (first argument of the function).
 -- Then, we must define header signature and override options:
 --
--- > headerSig = SassImporter 1 header
+-- > headerSig = SassHeader 1 header
 -- > opts = def { sassHeaders = Just [headerSig], sassInputPath = Just "path" }
 --
--- We set 'sassInputPath', because we will be compiling string and it won't be
+-- We set 'sassInputPath', because we will be compiling a string and it won't be
 -- set automatically.
 -- Now, executing
 --
@@ -171,15 +175,26 @@
 --
 -- > "foo { prop: path; }"
 --
--- 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'.
+-- Importers are defined and act similarly, but they take two arguments. The
+-- first argument is the path to the file being imported, and the second
+-- argument is the path to the importing file. For example
 --
--- Additionally, importers support priorities - if two importers return source
--- for some file, the one with higher priority wins. For example
+-- > importer imp src = return
+-- >     [makeSourceImport $ "/* imported " ++ imp ++ " into " ++ src ++ " */"]
+-- > sassImporter = Just [SassImporter 1 importer]
+-- > opts = def { sassImporters = sassImporter, sassInputPath = Just "file" }
+-- > compileString "@import \"relative/path\"" opts
 --
--- > importer1 src = return [makeSourceImport $ "$file: " ++ src ++ "1;"]
--- > importer2 src = return [makeSourceImport $ "$file: " ++ src ++ "2;"]
+-- Gives
+--
+-- > "/* imported relative/path into file */"
+--
+-- The first argument to 'SassHeader' or 'SassImporter' is its priority - if two
+-- importers return source for some file, the one with higher priority wins. For
+-- example
+--
+-- > importer1 imp _ = return [makeSourceImport $ "$file: " ++ imp ++ "1;"]
+-- > importer2 imp _ = return [makeSourceImport $ "$file: " ++ imp ++ "2;"]
 -- > importerSigs = [SassImporter 0.5 importer1, SassImporter 1 importer2]
 -- > opts = def { sassImporters = Just importerSigs }
 -- > compileString "@import \"file\";\nfoo { prop: $file; }" opts
diff --git a/Text/Sass/Compilation.hs b/Text/Sass/Compilation.hs
--- a/Text/Sass/Compilation.hs
+++ b/Text/Sass/Compilation.hs
@@ -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,12 +30,17 @@
   , 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
@@ -78,7 +85,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 +99,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'
+        !result' <- peekUTF8CString 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.
@@ -118,12 +140,12 @@
 loadFromError get conv err = withForeignPtr ptr $ get >=> conv
     where ptr = errorContext err
 
--- | Equivalent of @'loadFromError' 'get' 'peekCString' 'err'@.
+-- | Equivalent of @'loadFromError' 'get' 'peekUTF8CString 'err'@.
 loadStringFromError
     :: (Ptr Lib.SassContext -> IO CString) -- ^ Accessor function.
     -> SassError -- ^ Pointer to context.
     -> IO String -- ^ Result.
-loadStringFromError get = loadFromError get peekCString
+loadStringFromError get = loadFromError get peekUTF8CString
 
 -- | Equivalent of @'loadFromError' 'get' 'fromInteger' 'err'@.
 loadIntFromError :: (Integral a)
@@ -165,7 +187,7 @@
 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)
+    forM (arrayRange $ fromIntegral len) (peekElemOff lst >=> peekUTF8CString)
 
 -- | Loads a source map if it was generated by libsass.
 resultSourcemap :: SassExtendedResult a -> IO (Maybe String)
@@ -173,7 +195,7 @@
     cstr <- Lib.sass_context_get_source_map_string ctx
     if cstr == nullPtr
         then return Nothing
-        else Just <$> peekCString cstr
+        else Just <$> peekUTF8CString cstr
 
 -- | Common code for 'compileFile' and 'compileString'.
 compileInternal :: (SassResult b)
@@ -195,7 +217,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.
@@ -203,7 +225,7 @@
             => FilePath -- ^ Path to the file.
             -> SassOptions -- ^ Compilation options.
             -> IO (Either SassError a) -- ^ Error or output string.
-compileFile path opts = withCString path $ \cpath ->
+compileFile path opts = withUTF8CString path $ \cpath ->
     compileInternal cpath opts
         Lib.sass_make_file_context
         Lib.sass_compile_file_context
@@ -215,7 +237,19 @@
               -> SassOptions -- ^ Compilation options.
               -> IO (Either SassError a) -- ^ Error or output string.
 compileString str opts = do
-    cdata <- newCString str
+    cdata <- newUTF8CString 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 <- newCStringFromBS str
     compileInternal cdata opts
         Lib.sass_make_data_context
         Lib.sass_compile_data_context
diff --git a/Text/Sass/Functions.hs b/Text/Sass/Functions.hs
--- a/Text/Sass/Functions.hs
+++ b/Text/Sass/Functions.hs
@@ -8,6 +8,8 @@
   , SassImport (..)
   , SassImporterType
   , SassImporter (..)
+  , SassHeaderType
+  , SassHeader (..)
   , makeSourceImport
   , makePathImport
   ) where
@@ -30,25 +32,30 @@
 -- | Represents a sass import - a sass content with additional metadata.
 --
 -- Even though this ADT has four fields, you may just provide either
--- 'importPath' and 'importBase' and leave loading to the library, or provide
--- 'importSource' and do not provide 'importPath' nor 'importBase'.
+-- 'importPath' and 'importAbsolutePath' and leave loading to the library, or
+-- provide 'importSource' and do not provide 'importAbsolutePath'.
 -- Nevertheless, you are free to provide all of the fields.
 data SassImport = SassImport {
-    importPath      :: Maybe FilePath, -- ^ Path to the import, relative to base.
-    importBase      :: Maybe FilePath, -- ^ Base path.
-    importSource    :: Maybe String,   -- ^ Import's source.
-    importSourceMap :: Maybe String    -- ^ Source map of the import.
+    -- | Path to the import, as requested by the import statement.
+    importPath         :: Maybe FilePath 
+    -- | Absolute path to the file.
+  , importAbsolutePath :: Maybe FilePath 
+    -- | Import's source.
+  , importSource       :: Maybe String
+    -- | Source map of the import.
+  , importSourceMap    :: Maybe String
 }
 
--- | Type of the function that acts like importer/header.
+-- | Type of the function that acts like an importer.
 --
--- You may return empty list in order to tell libsass to handle the import by
--- itself or not insert any header.
+-- You may return the empty list in order to tell libsass to handle the import by
+-- itself.
 type SassImporterType =
-       String
-       -- ^ Path to the import that needs to be loaded or file that is being
-       -- processed when used as a header.
-    -> IO [SassImport] -- ^ Imports.
+     String
+     -- ^ Path to the import that needs to be loaded.
+  -> String
+     -- ^ Absolute path to the importing file.
+  -> IO [SassImport] -- ^ Imports.
 
 -- | Description of the importer.
 data SassImporter = SassImporter {
@@ -56,12 +63,23 @@
   , importerFunction :: SassImporterType -- ^ Main function.
 }
 
+-- | Type of the function that acts like a header.
+type SassHeaderType =
+       String -- ^ Absolute path to the file being processed.
+    -> IO [SassImport] -- ^ Imports.
+
+-- | Description of the header.
+data SassHeader = SassHeader {
+    headerPriority :: Double -- ^ Priority of the header.
+  , headerFunction :: SassHeaderType -- ^ Main function.
+}
+
 -- | 'makeSourceImport' @s@ is equivalent to 'SassImport'
 -- @Nothing Nothing (Just s) Nothing@.
 makeSourceImport :: String -> SassImport
 makeSourceImport s = SassImport Nothing Nothing (Just s) Nothing
 
--- | 'makePathImport' @p b@ is equivalent to 'SassImport'
--- @(Just p) (Just b) Nothing Nothing@.
-makePathImport :: String -> String -> SassImport
-makePathImport p b = SassImport (Just p) (Just b) Nothing Nothing
+-- | 'makePathImport' @p@ is equivalent to 'SassImport'
+-- @(Just p) (Just p) Nothing Nothing@.
+makePathImport :: String -> SassImport
+makePathImport p = SassImport (Just p) (Just p) Nothing Nothing
diff --git a/Text/Sass/Functions/Internal.hs b/Text/Sass/Functions/Internal.hs
--- a/Text/Sass/Functions/Internal.hs
+++ b/Text/Sass/Functions/Internal.hs
@@ -1,13 +1,10 @@
-{-# LANGUAGE LambdaCase #-}
 module Text.Sass.Functions.Internal
   (
     -- * Functions
     wrapFunction
   , makeNativeFunction
-  , clearNativeFunction
   , freeNativeFunction
   , makeNativeFunctionList
-  , clearNativeFunctionList
   , freeNativeFunctionList
     -- * Imports and headers
   , wrapImporter
@@ -21,10 +18,10 @@
   , freeNativeImporterList
   ) where
 
-import qualified Bindings.Libsass          as Lib
+import qualified Bindings.Libsass           as Lib
 import           Foreign
-import           Foreign.C
 import           Text.Sass.Functions
+import           Text.Sass.Marshal.Internal
 import           Text.Sass.Utils
 import           Text.Sass.Values.Internal
 
@@ -35,27 +32,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'
+    sig <- newUTF8CString 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,28 +52,29 @@
 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
-wrapImporter fn url _ _ = peekCString url >>= fn >>= \case
-    [] -> return nullPtr
-    xs -> makeNativeImportList xs
+wrapImporter fn url _ compiler = do
+    lastImport <- Lib.sass_compiler_get_last_import compiler
+    absPath <- Lib.sass_import_get_abs_path lastImport >>= peekUTF8CString
+    url' <- peekUTF8CString url
+    importList <- fn url' absPath
+    case importList of
+        [] -> return nullPtr
+        xs -> makeNativeImportList xs
 
 -- | Converts 'SassImport' into native representation.
 makeNativeImport :: SassImport -> IO Lib.SassImportEntry
-makeNativeImport el = do
-    path <- maybeNew newCString $ importPath el
-    base <- maybeNew newCString $ importPath el
-    source <- maybeNew newCString $ importSource el
-    srcmap <- maybeNew newCString $ importSourceMap el
-    Lib.sass_make_import path base source srcmap
+makeNativeImport el =
+    maybeWith withUTF8CString (importPath el) $ \path ->
+        maybeWith withUTF8CString (importAbsolutePath el) $ \absPath -> do
+            source <- maybeNew newUTF8CString $ importSource el
+            srcmap <- maybeNew newUTF8CString $ importSourceMap el
+            Lib.sass_make_import path absPath source srcmap
 
 -- | Frees native representation of 'SassImport'.
 freeNativeImport :: Lib.SassImportEntry -> IO ()
diff --git a/Text/Sass/Internal.hs b/Text/Sass/Internal.hs
--- a/Text/Sass/Internal.hs
+++ b/Text/Sass/Internal.hs
@@ -5,6 +5,7 @@
   ) where
 
 import           Text.Sass.Functions.Internal as I
+import           Text.Sass.Marshal.Internal   as I
 import           Text.Sass.Options.Internal   as I
 import           Text.Sass.Utils              as I
 import           Text.Sass.Values.Internal    as I
diff --git a/Text/Sass/Marshal/Internal.hs b/Text/Sass/Marshal/Internal.hs
new file mode 100644
--- /dev/null
+++ b/Text/Sass/Marshal/Internal.hs
@@ -0,0 +1,43 @@
+-- | Helper functions used by Compilation module.
+module Text.Sass.Marshal.Internal
+  (
+    peekUTF8CString,
+    newUTF8CString,
+    withUTF8CString,
+    newCStringFromBS
+  ) where
+
+import           Data.ByteString          (ByteString)
+import qualified Data.ByteString.Internal as BI
+import           Foreign
+import           Foreign.C
+import           Foreign.Marshal.Alloc    (mallocBytes)
+
+import qualified GHC.Foreign              as GHC
+import qualified GHC.IO.Encoding          as E
+
+-- | Marshal a NUL terminated C string (UTF-8 encoded) into Haskell string.
+-- It is equivalent to 'peekCString' but with different encoding.
+peekUTF8CString :: CString -> IO String
+peekUTF8CString = GHC.peekCString E.utf8
+
+-- | Marshal a Haskell string into a NUL terminated C string (UTF-8 encoded).
+-- It is equivalent to 'newCString' but with different encoding.
+newUTF8CString :: String -> IO CString
+newUTF8CString = GHC.newCString E.utf8
+
+-- | Marshal a Haskell string into a C string (i.e., character array)
+-- in temporary storage, with explicit length information.
+-- It is equivalent to 'withCString' but with different encoding.
+withUTF8CString :: String -> (CString -> IO a) -> IO a
+withUTF8CString = GHC.withCString E.utf8
+
+-- | Copies 'ByteString' to newly allocated 'CString'. The result must be
+-- explicitly freed using 'free' or 'finalizerFree'.
+newCStringFromBS :: ByteString -> IO CString
+newCStringFromBS (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
diff --git a/Text/Sass/Options.hs b/Text/Sass/Options.hs
--- a/Text/Sass/Options.hs
+++ b/Text/Sass/Options.hs
@@ -2,6 +2,7 @@
 module Text.Sass.Options
   (
     SassOptions (..)
+  , defaultSassOptions
   , Lib.SassOutputStyle (..)
   ) where
 
@@ -9,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
@@ -50,29 +53,44 @@
     -- | List of user-supplied functions that provide "headers" for sass files.
     -- Header is injected at the beginning of a file which name is passed as
     -- the first argument of importer.
-  , sassHeaders           :: Maybe [SassImporter]
+  , 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':
+--
+-- * 'sassPrecision' = 5
+-- * 'sassOutputStyle' = 'Lib.SassStyleNested'
+-- * 'sassIndent' = two spaces
+-- * 'sassLinefeed' = @"\\n"@
+-- * All other fields default to 'False' or 'Nothing'.
+defaultSassOptions :: SassOptions
+defaultSassOptions = SassOptions
+  { sassPrecision         = 5
+  , sassOutputStyle       = Lib.SassStyleNested
+  , sassSourceComments    = False
+  , sassSourceMapEmbed    = False
+  , sassSourceMapContents = False
+  , sassOmitSourceMapUrl  = False
+  , sassIsIndentedSyntax  = False
+  , sassIndent            = "  "
+  , sassLinefeed          = "\n"
+  , sassInputPath         = Nothing
+  , sassOutputPath        = Nothing
+  , sassPluginPaths       = Nothing
+  , sassIncludePaths      = Nothing
+  , sassSourceMapFile     = Nothing
+  , sassSourceMapRoot     = Nothing
+  , sassFunctions         = Nothing
+  , sassHeaders           = Nothing
+  , sassImporters         = Nothing
+  , sassStripEncodingInfo = False
+  }
+
+-- | 'def' = 'defaultSassOptions'
 instance Default SassOptions where
-    def = SassOptions {
-        sassPrecision         = 5
-      , sassOutputStyle       = Lib.SassStyleNested
-      , sassSourceComments    = False
-      , sassSourceMapEmbed    = False
-      , sassSourceMapContents = False
-      , sassOmitSourceMapUrl  = False
-      , sassIsIndentedSyntax  = False
-      , sassIndent            = "  "
-      , sassLinefeed          = "\n"
-      , sassInputPath         = Nothing
-      , sassOutputPath        = Nothing
-      , sassPluginPaths       = Nothing
-      , sassIncludePaths      = Nothing
-      , sassSourceMapFile     = Nothing
-      , sassSourceMapRoot     = Nothing
-      , sassFunctions         = Nothing
-      , sassHeaders           = Nothing
-      , sassImporters         = Nothing
-    }
+    def = defaultSassOptions
diff --git a/Text/Sass/Options/Internal.hs b/Text/Sass/Options/Internal.hs
--- a/Text/Sass/Options/Internal.hs
+++ b/Text/Sass/Options/Internal.hs
@@ -14,8 +14,9 @@
 #endif
 import           Control.Monad                ((>=>))
 import           Foreign
-import           Foreign.C
+import           Text.Sass.Functions
 import           Text.Sass.Functions.Internal
+import           Text.Sass.Marshal.Internal
 import           Text.Sass.Options
 import           Text.Sass.Utils
 
@@ -30,27 +31,31 @@
     Lib.sass_option_set_source_map_contents ptr (sassSourceMapContents opt)
     Lib.sass_option_set_omit_source_map_url ptr (sassOmitSourceMapUrl opt)
     Lib.sass_option_set_is_indented_syntax_src ptr (sassIsIndentedSyntax opt)
-    withCString (sassIndent opt) (Lib.sass_option_set_indent ptr)
-    withCString (sassLinefeed opt) (Lib.sass_option_set_linefeed ptr)
-    withOptionalCString (sassInputPath opt)
+    withUTF8CString (sassIndent opt) (Lib.sass_option_set_indent ptr)
+    withUTF8CString (sassLinefeed opt) (Lib.sass_option_set_linefeed ptr)
+    withOptionalUTF8CString (sassInputPath opt)
         (Lib.sass_option_set_input_path ptr)
-    withOptionalCString (sassOutputPath opt)
+    withOptionalUTF8CString (sassOutputPath opt)
         (Lib.sass_option_set_output_path ptr)
-    withOptionalCString (concatPaths <$> sassPluginPaths opt)
+    withOptionalUTF8CString (concatPaths <$> sassPluginPaths opt)
         (Lib.sass_option_set_plugin_path ptr)
-    withOptionalCString (concatPaths <$> sassIncludePaths opt)
+    withOptionalUTF8CString (concatPaths <$> sassIncludePaths opt)
         (Lib.sass_option_set_include_path ptr)
-    withOptionalCString (sassSourceMapFile opt)
+    withOptionalUTF8CString (sassSourceMapFile opt)
         (Lib.sass_option_set_source_map_file ptr)
-    withOptionalCString (sassSourceMapRoot opt)
+    withOptionalUTF8CString (sassSourceMapRoot opt)
         (Lib.sass_option_set_source_map_root ptr)
     maybe (return ())
-        (makeNativeImporterList >=> Lib.sass_option_set_c_headers ptr)
+        (makeNativeImporterList . fmap fromHeader
+         >=> Lib.sass_option_set_c_headers ptr)
         (sassHeaders opt)
     maybe (return ())
         (makeNativeImporterList >=> Lib.sass_option_set_c_importers ptr)
         (sassImporters opt)
+    where
+      fromHeader (SassHeader p f) = SassImporter p (\filename _ -> f filename)
 
+
 -- | Copies 'sassFunctions' to native object, executes action, clears leftovers
 -- (see documentation of 'makeNativeFunction') and returns action result.
 withFunctions :: SassOptions -- ^ Options.
@@ -64,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
diff --git a/Text/Sass/Utils.hs b/Text/Sass/Utils.hs
--- a/Text/Sass/Utils.hs
+++ b/Text/Sass/Utils.hs
@@ -4,7 +4,7 @@
 module Text.Sass.Utils
   (
     -- * Interoperation with C API
-    withOptionalCString
+    withOptionalUTF8CString
   , listEntryNotNull
   , loopCList
   , copyToCList
@@ -23,6 +23,8 @@
 import           Foreign.C
 import           System.FilePath                  (searchPathSeparator)
 
+import           Text.Sass.Marshal.Internal
+
 -- Fix for transformers-0.3.0.0 (used by lts-2.17 in stack).
 #if !MIN_VERSION_transformers(0,4,0)
 modify' :: (Monad m) => (s -> s) -> StateT s m ()
@@ -31,11 +33,11 @@
     put $! f s
 #endif
 
--- | 'withOptionalCString' @str action@, if @str@ is 'Nothing', @action@ is not
+-- | 'withOptionalCString' @str action@, if @str@ is @Nothing@, @action@ is not
 -- invoked, otherwise behaves like 'withCString'.
-withOptionalCString :: Maybe String -> (CString -> IO ()) -> IO ()
-withOptionalCString (Just str) action = withCString str action
-withOptionalCString Nothing _ = return ()
+withOptionalUTF8CString :: Maybe String -> (CString -> IO ()) -> IO ()
+withOptionalUTF8CString (Just str) action = withUTF8CString str action
+withOptionalUTF8CString Nothing _         = return ()
 
 -- | Checks if the pointer in state points to non-null location.
 listEntryNotNull :: (Monad m, MonadIO m) => StateT (Ptr (Ptr a)) m Bool
diff --git a/Text/Sass/Values.hs b/Text/Sass/Values.hs
--- a/Text/Sass/Values.hs
+++ b/Text/Sass/Values.hs
@@ -28,4 +28,4 @@
                 | SassNull -- ^ Null value.
                 | SassWarning String -- ^ Warning with message.
                 | SassError String -- ^ Error with message.
-                deriving (Eq)
+                deriving (Eq, Show)
diff --git a/Text/Sass/Values/Internal.hs b/Text/Sass/Values/Internal.hs
--- a/Text/Sass/Values/Internal.hs
+++ b/Text/Sass/Values/Internal.hs
@@ -9,32 +9,32 @@
   , makeValueForeignPtr
   ) where
 
-import qualified Bindings.Libsass    as Lib
+import qualified Bindings.Libsass           as Lib
 #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.Marshal.Internal
 import           Text.Sass.Utils
 import           Text.Sass.Values
 
 -- | Converts a 'SassValue' to native type.
 toNativeValue :: SassValue -> IO (Ptr Lib.SassValue)
 toNativeValue (SassBool val) = Lib.sass_make_boolean val
-toNativeValue (SassNumber val unit) = withCString unit $
+toNativeValue (SassNumber val unit) = withUTF8CString unit $
     Lib.sass_make_number (realToFrac val)
 toNativeValue (SassColor r g b a) = Lib.sass_make_color r' g' b' a'
     where r' = realToFrac r
           g' = realToFrac g
           b' = realToFrac b
           a' = realToFrac a
-toNativeValue (SassString str) = withCString str Lib.sass_make_string
+toNativeValue (SassString str) = withUTF8CString str Lib.sass_make_string
 toNativeValue SassNull = Lib.sass_make_null
-toNativeValue (SassWarning str) = withCString str Lib.sass_make_warning
-toNativeValue (SassError str) = withCString str Lib.sass_make_error
+toNativeValue (SassWarning str) = withUTF8CString str Lib.sass_make_warning
+toNativeValue (SassError str) = withUTF8CString 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'
 
@@ -60,7 +60,7 @@
     SassBool <$> Lib.sass_boolean_get_value ptr
 fromNativeValue' Lib.SassNumber ptr = do
     val <- Lib.sass_number_get_value ptr
-    unit <- Lib.sass_number_get_unit ptr >>= peekCString
+    unit <- Lib.sass_number_get_unit ptr >>= peekUTF8CString
     return $ SassNumber (realToFrac val) unit
 fromNativeValue' Lib.SassColor ptr = do
     r <- realToFrac <$> Lib.sass_color_get_r ptr
@@ -69,12 +69,12 @@
     a <- realToFrac <$> Lib.sass_color_get_a ptr
     return $ SassColor r g b a
 fromNativeValue' Lib.SassString ptr =
-    SassString <$> (Lib.sass_string_get_value ptr >>= peekCString)
+    SassString <$> (Lib.sass_string_get_value ptr >>= peekUTF8CString)
 fromNativeValue' Lib.SassNull _ = return SassNull
 fromNativeValue' Lib.SassWarning ptr =
-    SassWarning <$> (Lib.sass_warning_get_message ptr >>= peekCString)
+    SassWarning <$> (Lib.sass_warning_get_message ptr >>= peekUTF8CString)
 fromNativeValue' Lib.SassError ptr =
-    SassError <$> (Lib.sass_error_get_message ptr >>= peekCString)
+    SassError <$> (Lib.sass_error_get_message ptr >>= peekUTF8CString)
 fromNativeValue' Lib.SassList ptr = do
     len <- Lib.sass_list_get_length ptr
     sep <- fromIntegral <$> Lib.sass_list_get_separator ptr
diff --git a/Text/Sass/Values/Utils.hs b/Text/Sass/Values/Utils.hs
new file mode 100644
--- /dev/null
+++ b/Text/Sass/Values/Utils.hs
@@ -0,0 +1,31 @@
+{-# LANGUAGE BangPatterns #-}
+-- | Provides utility functions for working with 'SassValues'
+module Text.Sass.Values.Utils
+  (
+    combineSassValues
+  , Lib.SassOp (..)
+  ) where
+
+import qualified Bindings.Libsass as Lib
+
+import System.IO.Unsafe
+
+import Text.Sass.Values
+import Text.Sass.Values.Internal
+
+-- | Combines two 'SassValue's using specified operator.
+-- |
+-- | Uses 'Lib.sass_value_op'.
+combineSassValues :: Lib.SassOp -- ^ Operator.
+                  -> SassValue  -- ^ First value.
+                  -> SassValue  -- ^ Second value.
+                  -> SassValue  -- ^ Resulting value.
+combineSassValues op val1 val2 = unsafePerformIO $ do
+    native1 <- toNativeValue val1
+    native2 <- toNativeValue val2
+    combined <- Lib.sass_value_op (fromIntegral $ fromEnum op) native1 native2
+    !result <- fromNativeValue combined
+    deleteNativeValue native1
+    deleteNativeValue native2
+    deleteNativeValue combined
+    return result
diff --git a/hsass.cabal b/hsass.cabal
--- a/hsass.cabal
+++ b/hsass.cabal
@@ -1,5 +1,5 @@
 name:                hsass
-version:             0.3.0
+version:             0.8.0
 license:             MIT
 license-file:        LICENSE
 author:              Jakub Fijałkowski <fiolek94@gmail.com>
@@ -42,12 +42,14 @@
     , Text.Sass.Values
     , Text.Sass.Internal
     , Text.Sass.Functions.Internal
+    , Text.Sass.Marshal.Internal
     , Text.Sass.Options.Internal
     , Text.Sass.Values.Internal
+    , Text.Sass.Values.Utils
     , Text.Sass.Utils
   build-depends:
       base               >= 4.7 && < 5
-    , hlibsass           >= 0.1.1
+    , hlibsass           >= 0.1.7.0
     , bytestring         >= 0.10.0
     , data-default-class
     , filepath           >= 1.0
@@ -61,6 +63,13 @@
 test-suite test
   hs-source-dirs:      test
   main-is:             Spec.hs
+  other-modules:
+      Text.Sass.CompilationSpec
+    , Text.Sass.FunctionsSpec
+    , Text.Sass.TestingUtils
+    , Text.Sass.TutorialSpec
+    , Text.Sass.ValuesSpec
+    , Text.Sass.EncodingSpec
   type:                exitcode-stdio-1.0
   ghc-options:         -Wall
   build-depends:
@@ -69,6 +78,7 @@
     , hspec              >= 2.1.5
     , hspec-discover     >= 2.1.5
     , temporary          >= 1.1
+    , text               >= 1.2
     , hsass
     , data-default-class
   default-language:    Haskell2010
diff --git a/test/Text/Sass/CompilationSpec.hs b/test/Text/Sass/CompilationSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Text/Sass/CompilationSpec.hs
@@ -0,0 +1,155 @@
+module Text.Sass.CompilationSpec where
+
+import           System.IO
+import           System.IO.Temp
+import           Test.Hspec
+import           Text.Sass
+
+import           Data.ByteString.Char8  (pack)
+import           Data.Either            (isLeft, isRight)
+import           Data.Maybe             (isJust)
+import           Text.Sass.TestingUtils
+
+main :: IO ()
+main = hspec spec
+
+importerFunc :: String -> String -> IO [SassImport]
+importerFunc _ _ = return [makeSourceImport "a { margin: 1px; }"]
+
+importers :: [SassImporter]
+importers = [SassImporter 1 importerFunc]
+
+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" $
+        compileString "foo { margin: 21px * 2; }" def `shouldReturn`
+            Right "foo {\n  margin: 42px; }\n"
+
+    it "should compile simple source as a bytestring" $
+        compileString "foo { margin: 21px * 2; }" def `shouldReturn`
+            Right (pack "foo {\n  margin: 42px; }\n")
+
+    it "should respect options" $ do
+        let opts = def { sassOutputStyle = SassStyleCompressed }
+        compileString "foo { margin: 21px * 2; }" opts `shouldReturn`
+            Right "foo{margin:42px}\n"
+
+    it "should compile file" $
+        withSystemTempFile "styles.sass" $ \p h -> do
+            hPutStr h "foo { margin: 21px * 2; }"
+            hClose h
+            compileFile p def `shouldReturn` Right "foo {\n  margin: 42px; }\n"
+
+    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
+        res `shouldSatisfy` isRight
+        let Right res' = res
+        resultString res' `shouldBe` "foo {\n  margin: 42px; }\n"
+
+    it "should compile simple source as a bytestring" $ do
+        res <- compileString "foo { margin: 21px * 2; }" def
+        res `shouldSatisfy` isRight
+        let Right res' = res
+        resultString res' `shouldBe` (pack "foo {\n  margin: 42px; }\n")
+
+    it "should report correct includes when available" $ do
+        let opts = def { sassImporters = Just importers }
+        Right res <- compileString "@import '_abc';" opts :: ExtendedResult
+        resultIncludes res `shouldReturn` [ "_abc" ]
+
+    it "should report no includes when unavailable" $ do
+        Right res <- compileString "foo { margin: 1px; }" def :: ExtendedResult
+        resultIncludes res `shouldReturn` [ ]
+
+    it "should retrieve source map if available" $ do
+        let opts = def { sassSourceMapFile = Just "abc.css" }
+        Right res <- compileString "foo { margin: 1px; }" opts :: ExtendedResult
+        m <- resultSourcemap res
+        m `shouldSatisfy` isJust
+        let Just m' = m
+        m' `shouldSatisfy` (not . null)
+
+    it "should return Nothing is source map if not available" $ do
+        Right res <- compileString "foo { margin: 1px; }" def :: ExtendedResult
+        resultSourcemap res `shouldReturn` Nothing
+
+errorReportingSpec = do
+    it "string compilation should report error on invalid code" $
+        (compileString "inv mark" def :: StringResult)
+            `returnShouldSatisfy` isLeft
+
+    it "file compilation should report error on invalid code" $
+        withSystemTempFile "styles.sass" $ \p h -> do
+            hPutStr h "!@# !@##  ## #"
+            hClose h
+            (compileFile p def :: StringResult) `returnShouldSatisfy` isLeft
+
+    it "should contain line" $ do
+        (Left r) <- compileString "invalid mark" def :: StringResult
+        errorLine r `shouldReturn` 1
+
+    it "should contain column" $ do
+        (Left r) <- compileString "body { !! }" def :: StringResult
+        errorColumn r `shouldReturn` 7
+
+    it "should contain description" $ do
+        (Left r) <- compileString "body { !! }" def :: StringResult
+        errorText r `returnShouldSatisfy` (not . null)
+
+    it "should contain message" $ do
+        (Left r) <- compileString "body { !! }" def :: StringResult
+        errorMessage r `returnShouldSatisfy` (not . null)
+
+    it "should contain Json description" $ do
+        (Left r) <- compileString "body { !! }" def :: StringResult
+        errorJson r `returnShouldSatisfy` (not . null)
+
+    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")
+
diff --git a/test/Text/Sass/EncodingSpec.hs b/test/Text/Sass/EncodingSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Text/Sass/EncodingSpec.hs
@@ -0,0 +1,136 @@
+module Text.Sass.EncodingSpec where
+
+import           Control.Concurrent.MVar
+import qualified Data.ByteString           as BS
+import qualified Data.Text                 as T
+import qualified Data.Text.Encoding        as TE
+import           GHC.IO.Encoding           (setFileSystemEncoding, utf8)
+import           System.IO
+import           System.IO.Temp
+import           Test.Hspec
+import           Text.Sass
+import qualified Text.Sass.Values.Internal as VI
+
+opts :: SassOptions
+opts = def { sassStripEncodingInfo = True }
+
+testString :: String
+testString =  "Zażółcić gęślą jaźń"
+
+testInput :: String
+testInput = "a { content: '" ++ testString ++ "'; }"
+
+expectedResult :: Either a String
+expectedResult = Right $ "a {\n  content: '" ++ testString ++ "'; }\n"
+
+main :: IO ()
+main = hspec spec
+
+testValue :: SassValue -> Expectation
+testValue v =
+    (VI.toNativeValue v >>= VI.fromNativeValue) `shouldReturn` v
+
+storeFunc :: MVar String -> SassValue -> IO SassValue
+storeFunc m (SassList [SassString s] _) = do
+    putMVar m s
+    return $ SassString s
+storeFunc _ _ = fail "Unknown value"
+
+storeFuncSig :: MVar String -> SassFunction
+storeFuncSig = SassFunction "store($s)" . storeFunc
+
+returnFunc :: SassValue -> IO SassValue
+returnFunc _ = return $ SassString $ "'" ++ testString ++ "'"
+
+returnFuncSig :: SassFunction
+returnFuncSig = SassFunction "ret()" returnFunc
+
+nonUTFNameSig :: SassFunction
+nonUTFNameSig = SassFunction "zażółcić()" returnFunc
+
+importFunction :: FilePath -> String -> String -> IO [SassImport]
+importFunction _ "src"  _ = return [makeSourceImport testInput]
+importFunction p "path" _ = return [makePathImport p]
+importFunction _ _ _      = fail "Unknown import"
+
+importers :: FilePath -> [SassImporter]
+importers p = [SassImporter 1 $ importFunction p]
+
+withNonASCIIContentFile :: (String -> IO a) -> IO a
+withNonASCIIContentFile f =
+    withSystemTempFile "styles.scss" $ \p h -> do
+        BS.hPutStr h (TE.encodeUtf8 $ T.pack testInput)
+        hClose h
+        f p
+
+withNonASCIIPathFile :: (String -> IO a) -> IO a
+withNonASCIIPathFile f = do
+    setFileSystemEncoding utf8
+    res <- withSystemTempFile "pl-zażółcić.scss" $ \p h -> do
+        BS.hPutStr h (TE.encodeUtf8 $ T.pack testInput)
+        hClose h
+        f p
+    return res
+
+spec :: Spec
+spec = do
+    it "should preserve UTF-8 encoding when compiling Strings" $
+        compileString testInput opts `shouldReturn` expectedResult
+
+    it "should preserve UTF-8 encoding when compiling files" $
+        withNonASCIIContentFile $ \p ->
+            compileFile p opts `shouldReturn` expectedResult
+
+    it "should correctly encode UTF-8 chars in source paths" $
+        withNonASCIIPathFile $ \p ->
+            compileFile p opts `shouldReturn` expectedResult
+
+    it "should correctly encode UTF-8 chars in included files path" $
+        withNonASCIIPathFile $ \p ->
+            withSystemTempFile "styles.scss" $ \impP impH -> do
+                let cnt = "@import \"" ++ p ++ "\";"
+                BS.hPutStr impH $ TE.encodeUtf8 $ T.pack cnt
+                hClose impH
+
+                Right res <- compileFile impP opts :: ExtendedResult
+                includes <- resultIncludes res
+                includes `shouldSatisfy` elem p
+
+    it "should correctly encode/decode UTF-8 SassStrings" $
+        testValue $ SassString testString
+
+    it "should correctly encode/decode UTF-8 units in SassNumbers" $
+        testValue $ SassNumber 1 testString
+
+    it "should correctly encode/decode UTF-8 SassWarnings" $
+        testValue $ SassWarning testString
+
+    it "should correctly encode/decode UTF-8 SassErrors" $
+        testValue $ SassError testString
+
+    it "should correctly encode/decode list of UTF-8 SassStrings" $
+        testValue $ SassList [SassString "Zażółcić", SassString "gęślą"] SassSeparatorComma
+
+    it "should correctly UTF-8 decode function arguments" $ do
+        arg <- newEmptyMVar
+        let fopts = opts { sassFunctions = Just [ storeFuncSig arg ] }
+        _ <- compileString ("a {foo: store('" ++ testString ++ "');}") fopts :: StringResult
+        tryTakeMVar arg `shouldReturn` Just testString
+
+    it "should correctly UTF-8 encode function return value" $ do
+        let fopts = opts { sassFunctions = Just [ returnFuncSig ] }
+        compileString "a {content: ret(); }" fopts `shouldReturn` expectedResult
+
+    it "should correctly UTF-8 encode function names" $ do
+        let fopts = opts { sassFunctions = Just [ nonUTFNameSig ] }
+        compileString "a {content: zażółcić(); }" fopts
+            `shouldReturn` expectedResult
+
+    it "should correctly encode UTF-8 string from importer" $
+        let iopts = opts { sassImporters = Just $ importers "" }
+         in compileString "@import 'src';" iopts `shouldReturn` expectedResult
+
+    it "should correctly encode UTF-8 path from importer" $
+        withNonASCIIPathFile $ \p ->
+            let iopts = opts { sassImporters = Just $ importers p }
+            in compileString "@import 'path';" iopts `shouldReturn` expectedResult
diff --git a/test/Text/Sass/FunctionsSpec.hs b/test/Text/Sass/FunctionsSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Text/Sass/FunctionsSpec.hs
@@ -0,0 +1,74 @@
+module Text.Sass.FunctionsSpec where
+
+import           Test.Hspec
+import           Text.Sass  hiding (headerFunction)
+
+fooFunction :: SassValue -> IO SassValue
+fooFunction _ = return $ SassNumber 1 "px"
+
+barFunction :: SassValue -> IO SassValue
+barFunction (SassList [SassString "a"] _) = return $ SassNumber 1 "px"
+barFunction _ = return $ SassError "invalid arguments"
+
+functions :: [SassFunction]
+functions =
+  [ SassFunction "foo()"   fooFunction
+  , SassFunction "bar($n)" barFunction
+  ]
+
+inclContent :: String
+inclContent = "a {\n  margin: 1px; }\n"
+
+altInclContent :: String
+altInclContent = "b {\n  margin: 5px; }\n"
+
+headerFunction :: String -> IO [SassImport]
+headerFunction src = return [makeSourceImport $ src ++ "{\n  margin: 1px; }\n"]
+
+headers :: [SassHeader]
+headers = [SassHeader 1 headerFunction]
+
+importFunction :: String -> String -> IO [SassImport]
+importFunction "_imp" _ = return [makeSourceImport inclContent]
+importFunction _      _ = return [makeSourceImport altInclContent]
+
+importers :: [SassImporter]
+importers = [SassImporter 1 importFunction]
+
+main :: IO ()
+main = hspec spec
+
+spec :: Spec
+spec = do
+    it "should call simple function" $ do
+        let opts = def { sassFunctions = Just functions }
+        compileString "a { margin: foo(); }" opts `shouldReturn`
+            Right "a {\n  margin: 1px; }\n"
+
+    it "should correctly pass arguments to function" $ do
+        let opts = def { sassFunctions = Just functions }
+        compileString "a { margin: bar('a'); }" opts `shouldReturn`
+            Right "a {\n  margin: 1px; }\n"
+
+    it "should correctly inject header" $ do
+        let opts = def { sassHeaders = Just headers, sassInputPath = Just "path" }
+        compileString "a { margin : 1px; }" opts `shouldReturn`
+            Right ("path {\n  margin: 1px; }\n\na {\n  margin: 1px; }\n")
+
+    it "should not apply header to imports" $ do
+        let opts = def {
+            sassHeaders = Just headers
+          , sassImporters = Just importers
+          , sassInputPath = Just "path"
+        }
+        compileString "@import '_imp';" opts `shouldReturn`
+            Right ("path {\n  margin: 1px; }\n\n" ++ inclContent)
+
+    it "should call importers" $ do
+        let opts = def { sassImporters = Just importers }
+        compileString "@import '_imp';" opts `shouldReturn` Right inclContent
+
+    it "should pass import name to importers" $ do
+        let opts = def { sassImporters = Just importers }
+        compileString "@import 'other';" opts `shouldReturn` Right altInclContent
+
diff --git a/test/Text/Sass/TestingUtils.hs b/test/Text/Sass/TestingUtils.hs
new file mode 100644
--- /dev/null
+++ b/test/Text/Sass/TestingUtils.hs
@@ -0,0 +1,8 @@
+module Text.Sass.TestingUtils where
+
+import           Test.Hspec
+
+-- | @a `returnShouldSatisfy` p@ asserts that the action @a@ returns value that
+--   satisfies predicate @p@.
+returnShouldSatisfy :: (Show a, Eq a) => IO a -> (a -> Bool) -> Expectation
+v `returnShouldSatisfy` p = v >>= (`shouldSatisfy` p)
diff --git a/test/Text/Sass/TutorialSpec.hs b/test/Text/Sass/TutorialSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Text/Sass/TutorialSpec.hs
@@ -0,0 +1,93 @@
+module Text.Sass.TutorialSpec where
+
+import           Control.Concurrent.MVar
+import           Test.Hspec
+import           Text.Sass
+
+max3 :: SassValue -> IO SassValue
+max3 (SassList (SassNumber a _:SassNumber b _:SassNumber c _:_) _) =
+    return $ SassNumber (max a $ max b c) "px"
+max3 _ = return $ SassError "invalid arguments"
+
+max3sig :: SassFunction
+max3sig = SassFunction "max3($a, $b, $c)" max3
+
+warn :: MVar String -> SassValue -> IO SassValue
+warn m (SassList (SassString s:_) _) = do
+    putMVar m s
+    return $ SassString "warn!"
+warn _ _ = return $ SassString "invalid arguments"
+
+warnSig :: MVar String -> SassFunction
+warnSig = SassFunction "@warn" . warn
+
+header :: String -> IO [SassImport]
+header src = return [makeSourceImport $ "$file: " ++ src ++ ";"]
+
+headerSig :: SassHeader
+headerSig = SassHeader 1 header
+
+importer :: String -> String -> IO [SassImport]
+importer imp src = return
+    [makeSourceImport $ "/* imported " ++ imp ++ " into " ++ src ++ " */"]
+
+sassImporter :: Maybe [SassImporter]
+sassImporter = Just [SassImporter 1 importer]
+
+importer1 :: String -> String -> IO [SassImport]
+importer1 imp _ = return [makeSourceImport $ "$file: " ++ imp ++ "1;"]
+
+importer2 :: String -> String -> IO [SassImport]
+importer2 imp _ = return [makeSourceImport $ "$file: " ++ imp ++ "2;"]
+
+importerSigs :: [SassImporter]
+importerSigs = [SassImporter 0.5 importer1, SassImporter 1 importer2]
+
+main :: IO ()
+main = hspec spec
+
+spec :: Spec
+spec = do
+    describe "max3" $ do
+        it "should return max value" $ do
+            let vals = SassList [SassNumber 1 "", SassNumber 2 "",
+                                 SassNumber 3 ""] SassSeparatorSpace
+            SassNumber v _ <- max3 vals
+            v `shouldBe` 3
+
+        it "should return error on invalid aruments" $ do
+            let vals = SassList [SassString "", SassString "",
+                                 SassNumber 3 ""] SassSeparatorSpace
+            SassError e <- max3 vals
+            e `shouldBe` "invalid arguments"
+
+        it "should be usable by compile" $ do
+            let opts = def { sassFunctions = Just [max3sig] }
+            compileString "foo { margin: max3(1px, 2px, 3px); }" opts
+                `shouldReturn` Right "foo {\n  margin: 3px; }\n"
+
+    describe "warn" $
+        it "should call warn on @warn statement" $ do
+            msg <- newEmptyMVar
+            let opts = def { sassFunctions = Just [warnSig msg] }
+            _ <- compileString "@warn \"message\";" opts :: StringResult
+            tryTakeMVar msg `shouldReturn` Just "message"
+
+    describe "Headers" $
+        it "should inject header into file" $ do
+            let opts = def {
+                sassHeaders = Just [headerSig]
+              , sassInputPath = Just "path"
+            }
+            compileString "foo { prop: $file; }" opts `shouldReturn`
+                Right "foo {\n  prop: path; }\n"
+
+    describe "Importers" $ do
+        it "should provide the importer with the correct arguments" $ do
+            let opts = def { sassImporters = sassImporter, sassInputPath = Just "file" }
+            compileString "@import \"relative/path\"" opts
+                `shouldReturn` Right "/* imported relative/path into file */\n"
+        it "should inject import with higher priority" $ do
+            let opts = def { sassImporters = Just importerSigs }
+            compileString "@import \"file\";\nfoo { prop: $file; }" opts
+                `shouldReturn` Right "foo {\n  prop: file2; }\n"
diff --git a/test/Text/Sass/ValuesSpec.hs b/test/Text/Sass/ValuesSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/Text/Sass/ValuesSpec.hs
@@ -0,0 +1,95 @@
+{-# LANGUAGE StandaloneDeriving #-}
+module Text.Sass.ValuesSpec where
+
+import           Test.Hspec
+import           Text.Sass
+import           Text.Sass.Values.Utils
+
+optsWithVal :: SassValue -> SassOptions
+optsWithVal v = def {
+    sassFunctions = Just [SassFunction "foo()" (\_ -> return v)]
+}
+
+testSerialize :: SassValue -> String -> Expectation
+testSerialize v e =
+    let opts = optsWithVal v
+    in compileString "foo { prop: foo(); }" opts `shouldReturn`
+        Right ("foo {\n  prop: " ++ e ++ "; }\n")
+
+fooFunction :: SassValue -> SassValue -> IO SassValue
+fooFunction e (SassList [a] _) = return $ if e == a
+    then a
+    else SassNull
+fooFunction _ _ = error "fooFunction: invalid arguments"
+
+optsWithArg :: SassValue -> SassOptions
+optsWithArg a = def {
+    sassFunctions = Just [SassFunction "foo($a)" (fooFunction a)]
+}
+
+testDeserialize :: SassValue -> String -> Expectation
+testDeserialize a e =
+    let opts = optsWithArg a
+    in compileString ("foo { prop: foo(" ++ e ++ "); }") opts `shouldReturn`
+        Right ("foo {\n  prop: " ++ e ++ "; }\n")
+
+main :: IO ()
+main = hspec spec
+
+spec :: Spec
+spec = do
+    it "should serialize boolean true" $
+        testSerialize (SassBool True) "true"
+
+    it "should serialize boolean false" $
+        testSerialize (SassBool False) "false"
+
+    it "should serialize number" $
+        testSerialize (SassNumber 1 "px") "1px"
+
+    it "should serialize color" $
+        testSerialize (SassColor 1 2 3 0.5) "rgba(1, 2, 3, 0.5)"
+
+    it "should serialize string" $
+        testSerialize (SassString "abcd") "abcd"
+
+    it "should serialize list" $
+        testSerialize
+            (SassList [SassNumber 1 "px", SassNumber 2 "px"]
+             SassSeparatorComma)
+            "1px, 2px"
+
+    it "should serialize map" $ do
+        let sassMap = (SassMap [ (SassString "a", SassString "b")
+                       , (SassNumber 1 "", SassBool True)])
+        let opts = optsWithVal sassMap
+        result <- compileString "@each $key, $val in foo() { #{$key} { val: #{$val} } }" opts
+        result `shouldBe` Right "a {\n  val: b; }\n\n1 {\n  val: true; }\n"
+
+    it "should deserialize boolean true" $
+        testDeserialize (SassBool True) "true"
+
+    it "should deserialize boolean false" $
+        testDeserialize (SassBool False) "false"
+
+    it "should deserialize number" $
+        testDeserialize (SassNumber 1 "px") "1px"
+
+    it "should deserialize color" $
+        testDeserialize (SassColor 1 2 3 0.5) "rgba(1, 2, 3, 0.5)"
+
+    it "should deserialize string" $
+        testDeserialize (SassString "abcd") "abcd"
+
+    it "should deserialize list" $
+        testDeserialize
+            (SassList [SassNumber 1 "px", SassNumber 2 "px"] SassSeparatorSpace)
+            "1px 2px"
+
+    it "should deserialize map" $
+        pendingWith "Libsass does not allow maps in CSS any more"
+
+    it "should correctly combine two SassValues" $ do
+        let val1 = SassNumber 1.0 ""
+            val2 = SassNumber 2.0 ""
+        combineSassValues SassAdd val1 val2 `shouldBe` SassNumber 3.0 ""
