diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,6 +1,10 @@
 pandoc-citeproc
 ===============
 
+[![CI
+tests](https://github.com/jgm/pandoc-citeproc/workflows/CI%20tests/badge.svg)](https://github.com/jgm/pandoc-citeproc/actions)
+
+
 This package provides a library and executable to facilitate the use of
 citeproc with pandoc 1.12 and greater.  (Earlier versions of pandoc have
 integrated citeproc support.)
diff --git a/changelog b/changelog
--- a/changelog
+++ b/changelog
@@ -1,3 +1,19 @@
+pandoc-citeproc (0.16.4)
+
+  * Simplify compat since we now require pandoc >= 2.8.
+  * Update man page.  Clarify that `reference-section-title` doesn't have any
+    effect when an explicit Div is used (#424).
+  * Qualify fail with Prelude to fix compiler warnings.
+  * Disable `raw_attribute` extension when writing Markdown.
+    This way we avoid e.g. `<i>{=html}` in the CSL export.
+  * Use pandoc-types 1.20.  Note that this change removes
+    the ability to compile pandoc-citeproc with
+    older versions of pandoc (< 2.8).
+  * Incorporate the switch to Text in the dependencies (Christian
+    Despres).  The changes to the structure of the code are fairly minimal.
+    None of the types have changed, requiring a reasonable amount of
+    packing, unpacking, and view patterns.
+
 pandoc-citeproc (0.16.3.1)
 
   * Fix how LANG is set for bibtex conversion.
diff --git a/compat/Text/CSL/Compat/Pandoc.hs b/compat/Text/CSL/Compat/Pandoc.hs
--- a/compat/Text/CSL/Compat/Pandoc.hs
+++ b/compat/Text/CSL/Compat/Pandoc.hs
@@ -20,12 +20,9 @@
 import Data.ByteString as B
 import Text.Pandoc (Pandoc, ReaderOptions(..), def, WrapOption(..),
         WriterOptions(..))
-#if MIN_VERSION_pandoc(1,19,0)
 import Text.Pandoc (Extension(..), pandocExtensions)
-#endif
 import qualified Text.Pandoc as Pandoc
 import qualified Text.Pandoc.Process
-#if MIN_VERSION_pandoc(2,0,0)
 import qualified Data.Text as T
 import Text.Pandoc.MIME (MimeType)
 import Text.Pandoc.Error (PandocError)
@@ -33,18 +30,10 @@
 import qualified Text.Pandoc.Class (fetchItem)
 import Control.Monad.Except (runExceptT, lift)
 import Text.Pandoc.Extensions (extensionsFromList, disableExtension)
-#else
-import Data.Set as Set
-import System.IO (stderr)
-import qualified Text.Pandoc.Shared (fetchItem)
 
-type MimeType = String
-#endif
-
 readHtml, readLaTeX, readMarkdown, readNative :: String -> Pandoc
 writeMarkdown, writePlain, writeNative, writeHtmlString :: Pandoc -> String
 
-#if MIN_VERSION_pandoc(2,0,0)
 readHtml = either mempty id . runPure . Pandoc.readHtml
    def{ readerExtensions = extensionsFromList [Ext_native_divs,
                            Ext_native_spans, Ext_raw_html, Ext_smart] } .
@@ -63,6 +52,7 @@
 writeMarkdown = either mempty T.unpack . runPure . Pandoc.writeMarkdown
    def{ writerExtensions = disableExtension Ext_smart $
                            disableExtension Ext_bracketed_spans $
+                           disableExtension Ext_raw_attribute $
                            pandocExtensions,
         writerWrapText = WrapNone }
 
@@ -75,53 +65,15 @@
        [Ext_native_divs, Ext_native_spans, Ext_raw_html],
        writerWrapText = WrapPreserve }
 
-#else
-readHtml = either mempty id . Pandoc.readHtml
-   def{ readerSmart = True, readerParseRaw = True }
-
-readMarkdown = either mempty id . Pandoc.readMarkdown
-   def{ readerSmart = True, readerStandalone = True}
-
-readLaTeX = either mempty id . Pandoc.readLaTeX
-   def{ readerSmart = True, readerParseRaw = True }
-
-readNative = either mempty id . Pandoc.readNative
-
-writeMarkdown = Pandoc.writeMarkdown def{
-    writerWrapText = WrapNone
-  , writerColumns = 72
-#if MIN_VERSION_pandoc(1,19,0)
-  , writerExtensions = Set.delete Ext_bracketed_spans pandocExtensions
-#endif
-  }
-
-writePlain = Pandoc.writePlain def
-
-writeNative = Pandoc.writeNative def{ writerTemplate = Just mempty }
-
-writeHtmlString = Pandoc.writeHtmlString def
-#endif
-
 pipeProcess :: Maybe [(String, String)] -> FilePath -> [String]
             -> BL.ByteString -> IO (ExitCode,BL.ByteString)
-#if MIN_VERSION_pandoc(2,0,0)
 pipeProcess = Text.Pandoc.Process.pipeProcess
-#else
-pipeProcess e f a b = do
-  (ec, out, err) <- Text.Pandoc.Process.pipeProcess e f a b
-  BL.hPutStr stderr err
-  return (ec, out)
-#endif
 
 fetchItem :: String
           -> IO (Either E.SomeException (B.ByteString, Maybe MimeType))
-#if MIN_VERSION_pandoc(2,0,0)
 fetchItem s = do
-  res <- runIO $ runExceptT $ lift $ Text.Pandoc.Class.fetchItem s
+  res <- runIO $ runExceptT $ lift $ Text.Pandoc.Class.fetchItem $ T.pack s
   return $ case res of
        Left e          -> Left (E.toException e)
        Right (Left (e :: PandocError))  -> Left (E.toException e)
        Right (Right r) -> Right r
-#else
-fetchItem = Text.Pandoc.Shared.fetchItem Nothing
-#endif
diff --git a/man/man1/pandoc-citeproc.1 b/man/man1/pandoc-citeproc.1
--- a/man/man1/pandoc-citeproc.1
+++ b/man/man1/pandoc-citeproc.1
@@ -1,7 +1,7 @@
 .\"t
-.\" Automatically generated by Pandoc 2.7.1
+.\" Automatically generated by Pandoc 2.8
 .\"
-.TH "pandoc-citeproc" "1" "2019-03-26" "pandoc-citeproc 0.16.1.3" ""
+.TH "pandoc-citeproc" "1" "2019-11-19" "pandoc-citeproc 0.16.3.1" ""
 .hy
 .SH NAME
 .PP
@@ -24,8 +24,11 @@
 If no such Div exists, one will be created and appended to the end of
 the document (unless the \f[C]suppress-bibliography\f[R] metadata field
 is set to a true value).
+If the CSL style species hanging indent, the class
+\f[C]hanging-indent\f[R] will be added to this Div.
 If you wish the bibliography to have a section header, put the section
-header at the end of your document.
+header at the end of your document (or at the beginning of the Div with
+id \f[C]refs\f[R], if there is one).
 (See the \f[C]pandoc\f[R] (1) man page under \[lq]Citations\[rq] for
 details on how to encode citations in pandoc\[cq]s markdown.)
 .PP
@@ -44,7 +47,7 @@
 \f[C]--metadata-file\f[R], and
 \f[C]Extension: yaml_metadata_block\f[R].)
 .TP
-.B \f[C]bibliography\f[R]
+\f[B]\f[CB]bibliography\f[B]\f[R]
 A path, or YAML list of paths, of bibliography files to use.
 These may be in any of the formats supported by bibutils.
 .RS
@@ -124,7 +127,7 @@
 BibLaTeX files, but you can use \f[C].bibtex\f[R] to force BibTeX.
 .RE
 .TP
-.B \f[C]references\f[R]
+\f[B]\f[CB]references\f[B]\f[R]
 A YAML list of references.
 Each reference is a YAML object.
 The format is essentially CSL JSON format.
@@ -153,7 +156,7 @@
 Simple tex math will also be parsed and rendered appropriately.
 .RE
 .TP
-.B \f[C]csl\f[R] or \f[C]citation-style\f[R]
+\f[B]\f[CB]csl\f[B]\f[R] or \f[B]\f[CB]citation-style\f[B]\f[R]
 Path or URL of a CSL style file.
 If the file is not found relative to the working directory,
 pandoc-citeproc will look in the \f[C]$HOME/.csl\f[R] directory (or
@@ -164,12 +167,12 @@
 use \f[C]chicago-author-date.csl\f[R], looking first in
 \f[C]$HOME/.csl\f[R] and then in its own data files.
 .TP
-.B \f[C]link-citations\f[R]
+\f[B]\f[CB]link-citations\f[B]\f[R]
 If this has a true value, citations in author-date and numerical styles
 will be hyperlinked to their corresponding bibliography entries.
 The default is not to add hyperlinks.
 .TP
-.B \f[C]citation-abbreviations\f[R]
+\f[B]\f[CB]citation-abbreviations\f[B]\f[R]
 Path to a CSL abbreviations JSON file.
 If the file is not found relative to the working directory,
 pandoc-citeproc will look in the \f[C]$HOME/.csl\f[R] directory (or
@@ -198,7 +201,7 @@
 .fi
 .RE
 .TP
-.B \f[C]lang\f[R]
+\f[B]\f[CB]lang\f[B]\f[R]
 Locale to use in formatting citations.
 If this is not set, the locale is taken from the
 \f[C]default-locale\f[R] attribute of the CSL file.
@@ -208,20 +211,22 @@
 instead of \f[C]lang\f[R], but this \f[C]lang\f[R] should be used going
 forward.)
 .TP
-.B \f[C]suppress-bibliography\f[R]
+\f[B]\f[CB]suppress-bibliography\f[B]\f[R]
 If this has a true value, the bibliography will be left off.
 Otherwise a bibliography will be inserted into each Div element with id
 \f[C]refs\f[R].
 If there is no such Div, one will be created at the end of the document.
 .TP
-.B \f[C]reference-section-title\f[R]
+\f[B]\f[CB]reference-section-title\f[B]\f[R]
 If this has a value, a section header with this title will be added
 before the bibliography.
 If \f[C]reference-section-title\f[R] is not specified and the document
 ends with a section header, this final header will be treated as the
 bibliography header.
+Note: \f[C]reference-section-title\f[R] has no effect when the
+bibliography is placed explicitly using a Div with id \f[C]refs\f[R].
 .TP
-.B \f[C]notes-after-punctuation\f[R]
+\f[B]\f[CB]notes-after-punctuation\f[B]\f[R]
 If true (the default), pandoc will put footnote citations after
 following punctuation.
 For example, if the source contains \f[C]blah blah [\[at]jones99].\f[R],
@@ -270,42 +275,42 @@
 CSL implementations.
 .SH OPTIONS
 .TP
-.B \f[C]-y, --bib2yaml\f[R]
+\f[B]\f[CB]-y, --bib2yaml\f[B]\f[R]
 Convert bibliography to YAML suitable for inclusion in pandoc metadata.
 .TP
-.B \f[C]-j, --bib2json\f[R]
+\f[B]\f[CB]-j, --bib2json\f[B]\f[R]
 Convert bibliography to CSL JSON suitable for import into Zotero.
 .TP
-.B \f[C]-f\f[R] \f[I]FORMAT\f[R], \f[C]--format=\f[R]\f[I]FORMAT\f[R]
+\f[B]\f[CB]-f\f[B]\f[R] \f[I]FORMAT\f[R], \f[B]\f[CB]--format=\f[B]\f[R]\f[I]FORMAT\f[R]
 Specify format of bibliography to be converted.
 Legal values are \f[C]biblatex\f[R], \f[C]bibtex\f[R], \f[C]ris\f[R],
 \f[C]endnote\f[R], \f[C]endnotexml\f[R], \f[C]isi\f[R],
 \f[C]medline\f[R], \f[C]copac\f[R], \f[C]mods\f[R], \f[C]nbib\f[R], and
 \f[C]json\f[R].
 .TP
-.B \f[C]-c\f[R] \f[I]NUMBER\f[R], \f[C]--columns=\f[R]\f[I]NUMBER\f[R]
+\f[B]\f[CB]-c\f[B]\f[R] \f[I]NUMBER\f[R], \f[B]\f[CB]--columns=\f[B]\f[R]\f[I]NUMBER\f[R]
 Specify column to which to wrap YAML output produced using
 \f[C]--bib2yaml\f[R].
 Default is 80.
 To disable wrapping, set 0.
 .TP
-.B \f[C]-h, --help\f[R]
+\f[B]\f[CB]-h, --help\f[B]\f[R]
 Print usage information.
 .TP
-.B \f[C]--man\f[R]
+\f[B]\f[CB]--man\f[B]\f[R]
 Print the man page in groff man format.
 To get a plain text version,
 \f[C]pandoc-citeproc --man | groff -mman -Tutf8\f[R].
 To get an HTML version,
 \f[C]pandoc-citeproc --man | groff -mman -Thtml\f[R].
 .TP
-.B \f[C]--license\f[R]
+\f[B]\f[CB]--license\f[B]\f[R]
 Print the license.
 .TP
-.B \f[C]-q, --quiet\f[R]
+\f[B]\f[CB]-q, --quiet\f[B]\f[R]
 Silence all warnings.
 .TP
-.B \f[C]-V, --version\f[R]
+\f[B]\f[CB]-V, --version\f[B]\f[R]
 Print version.
 .SH NOTES
 .SS General
diff --git a/pandoc-citeproc.cabal b/pandoc-citeproc.cabal
--- a/pandoc-citeproc.cabal
+++ b/pandoc-citeproc.cabal
@@ -1,5 +1,5 @@
 name:               pandoc-citeproc
-version:            0.16.3.1
+version:            0.16.4
 cabal-version:      1.12
 synopsis:           Supports using pandoc with citeproc
 
@@ -19,7 +19,7 @@
 
 homepage:           https://github.com/jgm/pandoc-citeproc
 category:           Text
-tested-with:        GHC == 8.0.1, GHC == 8.2.2, GHC == 8.4.3
+tested-with:        GHC == 8.0.1, GHC == 8.2.2, GHC == 8.4.3, GHC == 8.6.3
 license:            BSD3
 license-file:       LICENSE
 author:             John MacFarlane, Andrea Rossato
@@ -110,8 +110,8 @@
                       mtl,
                       bytestring, filepath,
                       network < 3.2,
-                      pandoc-types >= 1.17.3 && < 1.18,
-                      pandoc >= 1.16 && < 2.9,
+                      pandoc-types >= 1.20 && < 1.21,
+                      pandoc >= 2.8 && < 2.9,
                       tagsoup,
                       aeson >= 0.7 && < 1.5,
                       text,
@@ -160,8 +160,8 @@
     ghc-prof-options: -fprof-auto-exported -rtsopts
     build-depends:    base >= 4 && < 5,
                       pandoc-citeproc,
-                      pandoc-types >= 1.17.3 && < 1.18,
-                      pandoc >= 1.16 && < 2.9,
+                      pandoc-types >= 1.20 && < 1.21,
+                      pandoc >= 2.8 && < 2.9,
                       aeson,
                       aeson-pretty >= 0.8,
                       yaml >= 0.11,
@@ -201,8 +201,8 @@
                   directory,
                   text,
                   mtl,
-                  pandoc-types >= 1.17.3 && < 1.18,
-                  pandoc >= 1.16 && < 2.9,
+                  pandoc-types >= 1.20 && < 1.21,
+                  pandoc >= 2.8 && < 2.9,
                   filepath,
                   bytestring,
                   process,
@@ -231,9 +231,9 @@
                   aeson,
                   directory,
                   text,
-                  pandoc-types >= 1.17.3 && < 1.18,
+                  pandoc-types >= 1.20 && < 1.21,
                   mtl,
-                  pandoc >= 1.16 && < 2.9,
+                  pandoc >= 2.8 && < 2.9,
                   filepath,
                   containers,
                   bytestring,
diff --git a/pandoc-citeproc.hs b/pandoc-citeproc.hs
--- a/pandoc-citeproc.hs
+++ b/pandoc-citeproc.hs
@@ -1,5 +1,6 @@
 {-# LANGUAGE CPP                 #-}
 {-# LANGUAGE NoImplicitPrelude   #-}
+{-# LANGUAGE OverloadedStrings   #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 module Main where
 import           Prelude
@@ -135,7 +136,7 @@
 
 findWarnings :: Inline -> [String]
 findWarnings (Span (_,["citeproc-not-found"],[("data-reference-id",ref)]) _) =
-  ["pandoc-citeproc: reference " ++ ref ++ " not found" | ref /= "*"]
+  ["pandoc-citeproc: reference " ++ T.unpack ref ++ " not found" | ref /= "*"]
 findWarnings (Span (_,["citeproc-no-output"],_) _) =
   ["pandoc-citeproc: reference with no printed form"]
 findWarnings _ = []
diff --git a/src/Text/CSL/Eval.hs b/src/Text/CSL/Eval.hs
--- a/src/Text/CSL/Eval.hs
+++ b/src/Text/CSL/Eval.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE FlexibleContexts    #-}
 {-# LANGUAGE PatternGuards       #-}
 {-# LANGUAGE LambdaCase          #-}
@@ -98,6 +99,7 @@
           | Ascending {} <- c = Ascending  s
           | otherwise         = Descending s
 
+      unsetOpts :: (String, String) -> (String, String)
       unsetOpts ("et-al-min"                 ,_) = ("et-al-min"           ,"")
       unsetOpts ("et-al-use-first"           ,_) = ("et-al-use-first"     ,"")
       unsetOpts ("et-al-subsequent-min"      ,_) = ("et-al-subsequent-min","")
@@ -226,7 +228,7 @@
              case map toLower s of
                "first-reference-note-number"
                              -> do refid <- getStringVar "ref-id"
-                                   return [Output [OPan [Span ("",["first-reference-note-number"],[("refid",refid)]) [Str "0"]]] fm]
+                                   return [Output [OPan [Span ("",["first-reference-note-number"],[("refid",T.pack refid)]) [Str "0"]]] fm]
 
                "year-suffix" -> getStringVar "ref-id" >>= \k  ->
                                 return . return $ OYearSuf [] k [] fm
@@ -239,7 +241,7 @@
                "page"        -> getStringVar "page" >>= formatRange fm
                "locator"     -> getLocVar >>= formatRange fm . snd
                "url"         -> getStringVar "url" >>= \k ->
-                                if null k then return [] else return [Output [OPan [Link nullAttr [Str k] (escapeURI k,"")]] fm]
+                                if null k then return [] else return [Output [OPan [Link nullAttr [Str $ T.pack k] (escapeURI $ T.pack k,"")]] fm]
                "doi"         -> do d <- getStringVar "doi"
                                    let (prefixPart, linkPart) = T.breakOn (T.pack "http") (T.pack (prefix fm))
                                    let u = if T.null linkPart
@@ -247,20 +249,20 @@
                                               else T.unpack linkPart ++ d
                                    if null d
                                       then return []
-                                      else return [Output [OPan [Link nullAttr [Str (T.unpack linkPart ++ d)] (escapeURI u, "")]]
+                                      else return [Output [OPan [Link nullAttr [Str (linkPart <> T.pack d)] (escapeURI $ T.pack u, "")]]
                                             fm{ prefix = T.unpack prefixPart, suffix = suffix fm }]
                "isbn"        -> getStringVar "isbn" >>= \d ->
                                 if null d
                                    then return []
-                                   else return [Output [OPan [Link nullAttr [Str d] ("https://worldcat.org/isbn/" ++ escapeURI d, "")]] fm]
+                                   else return [Output [OPan [Link nullAttr [Str $ T.pack d] ("https://worldcat.org/isbn/" <> escapeURI (T.pack d), "")]] fm]
                "pmid"        -> getStringVar "pmid" >>= \d ->
                                 if null d
                                    then return []
-                                   else return [Output [OPan [Link nullAttr [Str d] ("https://www.ncbi.nlm.nih.gov/pubmed/" ++ escapeURI d, "")]] fm]
+                                   else return [Output [OPan [Link nullAttr [Str $ T.pack d] ("https://www.ncbi.nlm.nih.gov/pubmed/" <> escapeURI (T.pack d), "")]] fm]
                "pmcid"       -> getStringVar "pmcid" >>= \d ->
                                 if null d
                                    then return []
-                                   else return [Output [OPan [Link nullAttr [Str d] ("https://www.ncbi.nlm.nih.gov/pmc/articles/" ++ escapeURI d, "")]] fm]
+                                   else return [Output [OPan [Link nullAttr [Str $ T.pack d] ("https://www.ncbi.nlm.nih.gov/pmc/articles/" <> escapeURI (T.pack d), "")]] fm]
                _ -> do (opts, as) <- gets (env >>> options &&& abbrevs)
                        r <- getVar []
                               (getFormattedValue opts as f fm s) s
@@ -315,7 +317,7 @@
     | Just (Formatted v) <- fromValue val :: Maybe Formatted =
        case v of
           [] -> []
-          _  -> case maybe v (unFormatted . fromString) $ getAbbr (stringify v) of
+          _  -> case maybe v (unFormatted . fromString) $ getAbbr (T.unpack $ stringify v) of
                   [] -> []
                   ys -> [Output [(if s == "status"
                                      then OStatus
@@ -341,7 +343,7 @@
     | otherwise                                  = []
     where
       value     = if stripPeriods fm then filter (/= '.') else id
-      value' (Str x) = Str (value x)
+      value' (Str x) = Str $ T.pack $ value $ T.unpack x
       value' x       = x
       getAbbr v = if f == Short
                   then case getAbbreviation as s v of
@@ -379,7 +381,7 @@
       checkRange'   ts   = if v == "page" then checkRange ts else id
       process       ts   = checkRange' ts . printNumStr . map (renderNumber ts) .
                            breakNumericString . words
-      renderNumber  ts x = if isTransNumber x then format ts x else x
+      renderNumber  ts x = if isTransNumber x then format ts (T.pack x) else x
 
       format tm = case f of
                     Ordinal     -> maybe "" (ordinal     tm v) . safeRead
@@ -387,7 +389,7 @@
                     Roman       -> maybe ""
                                    (\x -> if x < 6000 then roman x else show x) .
                                    safeRead
-                    _           -> maybe "" show . (safeRead :: String -> Maybe Int)
+                    _           -> maybe "" show . (safeRead :: T.Text -> Maybe Int)
 
       roman :: Int -> String
       roman     = concat . reverse . zipWith (!!) romanList .
@@ -424,10 +426,10 @@
 
 isTransNumber, isSpecialChar,isNumber :: String -> Bool
 isTransNumber = all isDigit
-isSpecialChar = all (`elem` "&-,.\x2013")
+isSpecialChar = all (`elem` ("&-,.\x2013" :: String))
 isNumber   cs = case [c | c <- cs
                         , not (isLetter c)
-                        , c `notElem` "&-.,\x2013"] of
+                        , c `notElem` ("&-.,\x2013" :: String)] of
                      [] -> False
                      xs -> all isDigit xs
 
@@ -435,10 +437,10 @@
 breakNumericString [] = []
 breakNumericString (x:xs)
     | isTransNumber x = x : breakNumericString xs
-    | otherwise       = let (a,b) = break (`elem` "&-\x2013,") x
+    | otherwise       = let (a,b) = break (`elem` ("&-\x2013," :: String)) x
                             (c,d) = if null b
                                        then ("","")
-                                       else span (`elem` "&-\x2013,") b
+                                       else span (`elem` ("&-\x2013," :: String)) b
                         in filter (/= []) $  a : c : breakNumericString (d : xs)
 
 formatRange :: Formatting -> String -> State EvalState [Output]
@@ -473,7 +475,7 @@
 expandedRange (sa, []) = (sa,[])
 expandedRange (sa, sb)
   | length sb < length sa =
-      case (safeRead sa, safeRead sb) of
+      case (safeRead (T.pack sa), safeRead (T.pack sb)) of
            -- check to make sure we have regular numbers
            (Just (_ :: Int), Just (_ :: Int)) ->
              (sa, take (length sa - length sb) sa ++ sb)
@@ -503,7 +505,7 @@
 --         1496-1504
 chicagoRange :: (String, String) -> (String, String)
 chicagoRange (sa, sb)
-    = case (safeRead sa :: Maybe Int) of
+    = case (safeRead (T.pack sa) :: Maybe Int) of
           Just n | n < 100 -> expandedRange (sa, sb)
                  | n `mod` 100 == 0 -> expandedRange (sa, sb)
                  | n >= 1000 -> let (sa', sb') = minimalRange 1 (sa, sb)
diff --git a/src/Text/CSL/Eval/Common.hs b/src/Text/CSL/Eval/Common.hs
--- a/src/Text/CSL/Eval/Common.hs
+++ b/src/Text/CSL/Eval/Common.hs
@@ -26,6 +26,7 @@
 import           Data.List           (elemIndex)
 import qualified Data.Map            as M
 import           Data.Maybe
+import qualified Data.Text           as T
 
 import           Text.CSL.Reference
 import           Text.CSL.Style
@@ -125,7 +126,7 @@
   -- but need a String.  This is currently needed for "page".  It's a bit
   -- hackish; we should probably change the type in Reference for
   -- page to String.
-  case fromValue val `mplus` ((stringify . unFormatted) `fmap` fromValue val)
+  case fromValue val `mplus` ((T.unpack . stringify . unFormatted) `fmap` fromValue val)
        `mplus` (unLiteral `fmap` fromValue val) of
        Just v   -> v
        Nothing  -> Debug.Trace.trace ("Expecting string value, got " ++
diff --git a/src/Text/CSL/Eval/Date.hs b/src/Text/CSL/Eval/Date.hs
--- a/src/Text/CSL/Eval/Date.hs
+++ b/src/Text/CSL/Eval/Date.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE PatternGuards #-}
 -----------------------------------------------------------------------------
 -- |
@@ -23,6 +24,7 @@
 import           Data.List
 import           Data.List.Split
 import           Data.Maybe (fromMaybe, isNothing)
+import qualified Data.Text              as T
 
 import           Text.CSL.Exception
 import           Text.CSL.Eval.Common
@@ -144,7 +146,7 @@
         | null (concat o1 ++ concat o2) = []
         | otherwise = o1 ++ (case dpRangeDelim <$> last' xs of
                               ["-"] -> [[OPan [Str "\x2013"]]]
-                              [s]   -> [[OPan [Str s]]]
+                              [s]   -> [[OPan [Str $ T.pack s]]]
                               _     -> []) ++ o2
 
       formatYear f y
diff --git a/src/Text/CSL/Eval/Names.hs b/src/Text/CSL/Eval/Names.hs
--- a/src/Text/CSL/Eval/Names.hs
+++ b/src/Text/CSL/Eval/Names.hs
@@ -1,4 +1,6 @@
 {-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE ViewPatterns      #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE PatternGuards    #-}
 -----------------------------------------------------------------------------
@@ -23,6 +25,7 @@
 import           Data.List              (intersperse, nub)
 import           Data.List.Split        (wordsBy)
 import           Data.Maybe             (isJust)
+import qualified Data.Text              as T
 
 import           Text.CSL.Eval.Common
 import           Text.CSL.Eval.Output
@@ -261,25 +264,25 @@
                   if getOptionVal "initialize-with-hyphen" ops == "false"
                   then new ++ accum
                   else trimsp new ++ [Str "-"] ++ accum
-      isInit [Str [c]] = isUpper c
+      isInit [Str (T.unpack -> [c])] = isUpper c
       isInit _         = False
       initial (Formatted x) =
                   case lookup "initialize-with" ops of
                        Just iw
                          | getOptionVal "initialize" ops == "false"
-                         , isInit x  -> addIn x $ B.toList $ B.text iw
+                         , isInit x  -> addIn x $ B.toList $ B.text $ T.pack iw
                          | getOptionVal "initialize" ops /= "false"
-                         , not (all isLower $ query (:[]) x) -> addIn x $ B.toList $ B.text iw
+                         , not (all isLower $ query (:[]) x) -> addIn x $ B.toList $ B.text $ T.pack iw
                        Nothing
                          | isInit x  -> addIn x [Space] -- default
                        _ -> Space : x ++ [Space]
-      addIn x i = foldr (hyphenate . (\z -> Str (headInline z) : i)) []
+      addIn x i = foldr (hyphenate . (\z -> Str (T.pack $ headInline z) : i)) []
                      $ wordsBy (== Str "-")
                      $ splitStrWhen (=='-') x
 
       sortSep g s = when_ g $ separator ++ addAffixes (g <+> s) "given" mempty
       separator   = if isByzantineFamily
-                       then [OPan (B.toList (B.text
+                       then [OPan (B.toList (B.text $ T.pack
                               (getOptionValWithDefault "sort-separator" ", " ops)))]
                        else []
       suff      = if commaSuffix n && nameSuffix n /= mempty
@@ -320,7 +323,7 @@
                       (c >= '\x021a' && c <= '\x021b') ||
                       (c >= '\x202a' && c <= '\x202e')
 
-      isByzantineFamily = any isByzantine (stringify family)
+      isByzantineFamily = T.any isByzantine (stringify family)
       shortName = oPan' (unFormatted $ nondropping <+> family) (form "family")
 
       longName g
diff --git a/src/Text/CSL/Eval/Output.hs b/src/Text/CSL/Eval/Output.hs
--- a/src/Text/CSL/Eval/Output.hs
+++ b/src/Text/CSL/Eval/Output.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE PatternGuards #-}
 -----------------------------------------------------------------------------
 -- |
@@ -17,9 +18,9 @@
 module Text.CSL.Eval.Output where
 
 import Prelude
-import           Data.Char              (toLower, toUpper)
 import           Data.Maybe             (mapMaybe)
 import           Data.String            (fromString)
+import qualified Data.Text              as T
 import           Text.CSL.Output.Pandoc (lastInline)
 import           Text.CSL.Style
 import           Text.CSL.Util          (capitalize, isPunct, titlecase,
@@ -45,10 +46,10 @@
   format <- many1 letter
   _ <- string "}}"
   contents <- manyTill anyChar (try (string ("{{/" ++ format ++ "}}")))
-  return $ RawInline (Format format) contents
+  return $ RawInline (Format $ T.pack format) $ T.pack contents
 
 pString :: Parsec String () Inline
-pString = Str <$> (many1 (noneOf " \t\n\r{}") <|> count 1 (oneOf "{}"))
+pString = Str . T.pack <$> (many1 (noneOf " \t\n\r{}") <|> count 1 (oneOf "{}"))
 
 pSpace :: Parsec String () Inline
 pSpace = Space <$ many1 (oneOf " \t\n\r")
@@ -143,7 +144,7 @@
                                      [Strong [Str "???"]]]
       OErr (ReferenceNotFound r)
                           -> Formatted [Span ("",["citeproc-not-found"],
-                                            [("data-reference-id",r)])
+                                            [("data-reference-id",T.pack r)])
                                      [Strong [Str "???"]]]
       OLabel   []      _  -> Formatted []
       OLabel   s       f  -> addFormatting f $ formatString s
@@ -169,7 +170,7 @@
   addDisplay . addLink . addSuffix . pref . quote . font . text_case . strip_periods
   where addLink i = case hyperlink f of
                          ""  -> i
-                         url -> Formatted [Link nullAttr (unFormatted i) (url, "")]
+                         url -> Formatted [Link nullAttr (unFormatted i) (T.pack url, "")]
         pref i = case prefix f of
                       "" -> i
                       x  -> formatString x <> i
@@ -181,7 +182,7 @@
           | otherwise             = i <> formatString (suffix f)
 
         strip_periods (Formatted ils) = Formatted (walk removePeriod ils)
-        removePeriod (Str xs) | stripPeriods f = Str (filter (/='.') xs)
+        removePeriod (Str xs) | stripPeriods f = Str (T.filter (/='.') xs)
         removePeriod x        = x
 
         quote (Formatted [])  = Formatted []
@@ -227,16 +228,16 @@
                    "title"            -> titlecase ils
                    "capitalize-first"
                      -> case i of
-                             Str cs -> Str (capitalize cs) : is'
+                             Str cs -> Str (T.pack $ capitalize $ T.unpack cs) : is'
                              _ -> unTitlecase [i] ++ is'
                    "sentence"         -> unTitlecase ils
                    _                  -> ils
 
-        lowercaseStr (Str xs) = Str $ map toLower xs
+        lowercaseStr (Str xs) = Str $ T.toLower xs
         lowercaseStr x        = x
-        uppercaseStr (Str xs) = Str $ map toUpper xs
+        uppercaseStr (Str xs) = Str $ T.toUpper xs
         uppercaseStr x        = x
-        capitalizeStr (Str xs) = Str $ capitalize xs
+        capitalizeStr (Str xs) = Str $ T.pack $ capitalize $ T.unpack xs
         capitalizeStr x        = x
 
         valign [] = []
diff --git a/src/Text/CSL/Input/Bibtex.hs b/src/Text/CSL/Input/Bibtex.hs
--- a/src/Text/CSL/Input/Bibtex.hs
+++ b/src/Text/CSL/Input/Bibtex.hs
@@ -1,4 +1,6 @@
 {-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE ViewPatterns      #-}
+{-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# OPTIONS_GHC -fno-warn-unused-do-bind #-}
@@ -33,6 +35,7 @@
 import           Data.List.Split        (splitOn, splitWhen, wordsBy)
 import qualified Data.Map               as Map
 import           Data.Maybe
+import qualified Data.Text              as T
 import           System.Environment     (getEnvironment)
 import           Text.CSL.Compat.Pandoc (readLaTeX)
 import           Text.CSL.Exception     (CiteprocException (ErrorReadingBib, ErrorReadingBibFile))
@@ -60,7 +63,7 @@
 adjustSpans lang (RawInline (Format "latex") s)
   | s == "\\hyphen" || s == "\\hyphen " = [Str "-"]
   | otherwise = Walk.walk (concatMap (adjustSpans lang))
-                $ parseRawLaTeX lang s
+                $ parseRawLaTeX lang (T.unpack s)
 adjustSpans _ x = [x]
 
 parseRawLaTeX :: Lang -> String -> [Inline]
@@ -81,7 +84,7 @@
          -- ... both should be nestable & should work in year fields
          f "autocap"    ils    = ils  -- TODO: should work in year fields
          f "textnormal" ils    = [Span ("",["nodecor"],[]) ils]
-         f "bibstring" [Str s] = [Str $ resolveKey' lang s]
+         f "bibstring" [Str s] = [Str $ T.pack $ resolveKey' lang $ T.unpack s]
          f _            ils    = [Span nullAttr ils]
 parseRawLaTeX _ _ = []
 
@@ -199,7 +202,7 @@
   resolveAlias . map toLower <$> many1 (letter <|> digit <|> oneOf "-_:+")
 
 isBibtexKeyChar :: Char -> Bool
-isBibtexKeyChar c = isAlphaNum c || c `elem` ".:;?!`'()/*@_+=-[]*&"
+isBibtexKeyChar c = isAlphaNum c || c `elem` (".:;?!`'()/*@_+=-[]*&" :: String)
 
 bibItem :: BibParser Item
 bibItem = do
@@ -377,7 +380,7 @@
 
 resolveKey :: Lang -> Formatted -> Formatted
 resolveKey lang (Formatted ils) = Formatted (Walk.walk go ils)
-  where go (Str s) = Str $ resolveKey' lang s
+  where go (Str s) = Str $ T.pack $ resolveKey' lang $ T.unpack s
         go x       = x
 
 -- biblatex localization keys, from files at
@@ -877,7 +880,7 @@
          "oct" -> Just 10
          "nov" -> Just 11
          "dec" -> Just 12
-         _     -> safeRead s
+         _     -> safeRead $ T.pack s
 
 data BibState = BibState{
            untitlecase    :: Bool
@@ -887,7 +890,7 @@
 type Bib = RWST Item () BibState Maybe
 
 notFound :: String -> Bib a
-notFound f = fail $ f ++ " not found"
+notFound f = Prelude.fail $ f ++ " not found"
 
 getField :: String -> Bib Formatted
 getField f = do
@@ -951,20 +954,20 @@
   year' <- fixLeadingDash <$> getRawField (prefix ++ "year") <|> return ""
   month' <- (parseMonth
               <$> getRawField (prefix ++ "month")) <|> return Nothing
-  day' <- (safeRead <$> getRawField (prefix ++ "day")) <|> return Nothing
+  day' <- (safeRead . T.pack <$> getRawField (prefix ++ "day")) <|> return Nothing
   endyear' <- (fixLeadingDash <$> getRawField (prefix ++ "endyear"))
             <|> return ""
   endmonth' <- (parseMonth <$> getRawField (prefix ++ "endmonth"))
             <|> return Nothing
-  endday' <- (safeRead <$> getRawField (prefix ++ "endday")) <|> return Nothing
-  let start' = RefDate { year   = safeRead year'
+  endday' <- (safeRead . T.pack <$> getRawField (prefix ++ "endday")) <|> return Nothing
+  let start' = RefDate { year   = safeRead $ T.pack year'
                        , month  = month'
                        , season = Nothing
                        , day    = day'
                        , other  = Literal $ if isNumber year' then "" else year'
                        , circa  = False
                        }
-  let end' = RefDate { year     = safeRead endyear'
+  let end' = RefDate { year     = safeRead $ T.pack endyear'
                        , month  = endmonth'
                        , day    = endday'
                        , season = Nothing
@@ -1040,7 +1043,7 @@
           , parseNames      = False
           }
  -- extended BibLaTeX name format - see #266
-toAuthor _ ils@(Str ys:_) | '=' `elem` ys = do
+toAuthor _ ils@(Str ys:_) | T.any (== '=') ys = do
   let commaParts = splitWhen (== Str ",")
                    $ splitStrWhen (\c -> c == ',' || c == '=' || c == '\160')
                    $ ils
@@ -1114,7 +1117,7 @@
           }
 
 isCapitalized :: [Inline] -> Bool
-isCapitalized (Str (c:cs) : rest)
+isCapitalized (Str (T.uncons -> Just (c,cs)) : rest)
   | isUpper c = True
   | isDigit c = isCapitalized (Str cs : rest)
   | otherwise = False
@@ -1220,9 +1223,9 @@
         go accum s  = case reverse accum of
                            []    -> s
                            (Str x:_)
-                             | not (null x) && last x `elem` "!?.,:;"
+                             | not (T.null x) && T.last x `elem` ("!?.,:;" :: String)
                                           -> accum ++ (Space : s)
-                           _     -> accum ++ (Str [sep] : Space : s)
+                           _     -> accum ++ (Str (T.singleton sep) : Space : s)
 
 type Options = [(String, String)]
 
@@ -1278,7 +1281,7 @@
        "inproceedings"   -> (PaperConference,mempty)
        "manual"          -> (Book,mempty)
        "mastersthesis"   -> (Thesis, if reftype' == mempty
-                                        then Formatted [Str $ resolveKey' lang "mathesis"]
+                                        then Formatted [Str $ T.pack $ resolveKey' lang "mathesis"]
                                         else reftype')
        "misc"            -> (NoType,mempty)
        "mvbook"          -> (Book,mempty)
@@ -1292,7 +1295,7 @@
          | st == "newspaper" -> (ArticleNewspaper,mempty)
          | otherwise         -> (ArticleJournal,mempty)
        "phdthesis"       -> (Thesis, if reftype' == mempty
-                                        then Formatted [Str $ resolveKey' lang "phdthesis"]
+                                        then Formatted [Str $ T.pack $ resolveKey' lang "phdthesis"]
                                         else reftype')
        "proceedings"     -> (Book,mempty)
        "reference"       -> (Book,mempty)
@@ -1415,9 +1418,9 @@
                         <|> getPeriodicalTitle "shortjournal"
                         <|> return mempty
   -- change numerical series title to e.g. 'series 3'
-  let fixSeriesTitle (Formatted [Str xs]) | all isDigit xs =
-         Formatted [Str (ordinalize locale xs),
-                    Space, Str (resolveKey' lang "ser.")]
+  let fixSeriesTitle (Formatted [Str xs]) | T.all isDigit xs =
+         Formatted [Str (T.pack $ ordinalize locale $ T.unpack xs),
+                    Space, Str (T.pack $ resolveKey' lang "ser.")]
       fixSeriesTitle x = x
   seriesTitle' <- (fixSeriesTitle . resolveKey lang) <$>
                       getTitle "series" <|> return mempty
@@ -1535,12 +1538,12 @@
                          _ -> return mempty
                  )
 
-  let convertEnDash (Str s) = Str (map (\c -> if c == '–' then '-' else c) s)
+  let convertEnDash (Str s) = Str (T.map (\c -> if c == '–' then '-' else c) s)
       convertEnDash x       = x
 
   let takeDigits (Str xs : _) =
-         case takeWhile isDigit xs of
-              [] -> []
+         case T.takeWhile isDigit xs of
+              "" -> []
               ds -> [Str ds]
       takeDigits x             = x
 
diff --git a/src/Text/CSL/Input/Bibutils.hs b/src/Text/CSL/Input/Bibutils.hs
--- a/src/Text/CSL/Input/Bibutils.hs
+++ b/src/Text/CSL/Input/Bibutils.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE CPP                      #-}
 {-# LANGUAGE ScopedTypeVariables      #-}
 {-# LANGUAGE PatternGuards            #-}
@@ -221,7 +222,7 @@
          -- references:
          -- ...
          case fromJSON (metaValueToJSON v) of
-               Success "" -> Right []
+               Success ("" :: String) -> Right []
                _          -> Left s
        Success x            -> Right x
 
diff --git a/src/Text/CSL/Output/Pandoc.hs b/src/Text/CSL/Output/Pandoc.hs
--- a/src/Text/CSL/Output/Pandoc.hs
+++ b/src/Text/CSL/Output/Pandoc.hs
@@ -1,4 +1,6 @@
 {-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE ViewPatterns      #-}
 
 {-# LANGUAGE PatternGuards      #-}
 -----------------------------------------------------------------------------
@@ -28,6 +30,7 @@
 
 import Prelude
 import           Data.Maybe             (fromMaybe)
+import qualified Data.Text              as T
 import           Text.CSL.Style
 import           Text.CSL.Util          (headInline, initInline, lastInline,
                                          proc, proc', tailFirstInlineStr,
@@ -46,26 +49,27 @@
   dropWhile (== LineBreak) . reverse . dropWhile (== LineBreak) . reverse
 
 renderPandoc' :: Style -> (Formatted, String) -> Block
-renderPandoc' sty (form, citId) = Div ("ref-" ++ citId, [], []) [Para $ renderPandoc sty form]
+renderPandoc' sty (form, citId) = Div (T.pack $ "ref-" <> citId, [], []) [Para $ renderPandoc sty form]
 
 clean' :: Style -> [Inline] -> [Inline]
 clean' _   []  = []
 clean' sty (i:is) =
   case i:is of
       (Str "" : rest) -> clean' sty rest
-      (Str xs : Str ys : rest) -> clean' sty $ Str (xs ++ ys) : rest
-      (Link a1 lab1 ('#':r1, "") : Str "\8211" : Link a2 lab2 ('#':r2, "") : rest)
+      (Str xs : Str ys : rest) -> clean' sty $ Str (xs <> ys) : rest
+      (Link a1 lab1 (T.uncons -> Just ('#',r1), "")
+       : Str "\8211" : Link a2 lab2 (T.uncons -> Just ('#',r2), "") : rest)
         | r1 == r2, a1 == a2 ->
-           Link a1 (lab1 ++ [Str "\8211"] ++ lab2) ('#':r1, "") : clean' sty rest
+           Link a1 (lab1 ++ [Str "\8211"] ++ lab2) (T.cons '#' r1, "") : clean' sty rest
       (Span ("",[],[]) inls : _) -> inls ++ clean' sty is
       (Span ("",["csl-inquote"],kvs) inls : _) ->
          let isOuter = lookup "position" kvs == Just "outer"
          in  case headInline is of
-                    [x] -> if x `elem` ".," && isPunctuationInQuote sty
+                    [x] -> if x `elem` (".," :: String) && isPunctuationInQuote sty
                            then if lastInline inls `elem` [".",",",";",":","!","?"]
                                 then quoted isOuter inls ++
                                      clean' sty (tailInline is)
-                                else quoted isOuter (inls ++ [Str [x]]) ++
+                                else quoted isOuter (inls ++ [Str (T.singleton x)]) ++
                                      clean' sty (tailInline is)
                            else quoted isOuter inls ++ clean' sty is
                     _   ->      quoted isOuter inls ++ clean' sty is
@@ -74,12 +78,12 @@
                    then i : clean' sty (tailInline is)
                    else i : clean' sty is
     where
-      isPunct = all (`elem` ".,;:!? ") $ headInline is
+      isPunct = all (`elem` (".,;:!? " :: String)) $ headInline is
       locale  = case styleLocale sty of
                      (x:_) -> x
                      []    -> Locale [] [] [] [] [] -- should not happen
       getQuote s d     = case [term | term <- localeTerms locale, cslTerm term == s] of
-                               (x:_) -> Str (termSingular x)
+                               (x:_) -> Str $ T.pack $ termSingular x
                                _     -> Str d
       openQuoteOuter   = getQuote "open-quote" "“"
       openQuoteInner   = getQuote "open-inner-quote" "‘"
@@ -92,7 +96,7 @@
 convertQuoted s = convertQuoted'
     where
       locale = let l = styleLocale s in case l of [x] -> x; _   -> Locale [] [] [] [] []
-      getQuote  x y = fromEntities . termSingular . fromMaybe newTerm {termSingular = x} .
+      getQuote  x y = fromEntities . T.pack . termSingular . fromMaybe newTerm {termSingular = x} .
                       findTerm y Long . localeTerms $ locale
       doubleQuotesO = getQuote "\"" "open-quote"
       doubleQuotesC = getQuote "\"" "close-quote"
diff --git a/src/Text/CSL/Pandoc.hs b/src/Text/CSL/Pandoc.hs
--- a/src/Text/CSL/Pandoc.hs
+++ b/src/Text/CSL/Pandoc.hs
@@ -1,4 +1,5 @@
-{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE NoImplicitPrelude   #-}
+{-# LANGUAGE ViewPatterns        #-}
 {-# LANGUAGE CPP                 #-}
 {-# LANGUAGE FlexibleInstances   #-}
 {-# LANGUAGE OverloadedStrings   #-}
@@ -15,10 +16,10 @@
 import           Control.Monad.State
 import           Data.Aeson
 import qualified Data.ByteString.Lazy     as L
-import           Data.Char                (isDigit, isPunctuation, isSpace,
-                                           toLower)
+import           Data.Char                (isDigit, isPunctuation, isSpace)
 import qualified Data.Map                 as M
 import qualified Data.Set                 as Set
+import qualified Data.Text                as T
 import           Data.Maybe               (fromMaybe)
 import           System.Directory         (getAppUserDataDirectory)
 import           System.Environment       (getEnv)
@@ -78,9 +79,9 @@
 addFirstNoteNumber :: M.Map String Int -> Inline -> Inline
 addFirstNoteNumber notemap
   s@(Span ("",["first-reference-note-number"],[("refid",refid)]) _)
-  = case M.lookup refid notemap of
+  = case M.lookup (T.unpack refid) notemap of
          Nothing -> s
-         Just n  -> Str (show n)
+         Just n  -> Str $ T.pack (show n)
 addFirstNoteNumber _ -- see below, these spans added by deNote
   (Note [Para (Span ("",["reference-id-list"],_) [] : ils)])
   = Note [Para ils]
@@ -147,9 +148,9 @@
 
 truish :: MetaValue -> Bool
 truish (MetaBool t) = t
-truish (MetaString s) = isYesValue (map toLower s)
-truish (MetaInlines ils) = isYesValue (map toLower (stringify ils))
-truish (MetaBlocks [Plain ils]) = isYesValue (map toLower (stringify ils))
+truish (MetaString s) = isYesValue (T.unpack $ T.toLower s)
+truish (MetaInlines ils) = isYesValue (T.unpack $ T.toLower (stringify ils))
+truish (MetaBlocks [Plain ils]) = isYesValue (T.unpack $ T.toLower (stringify ils))
 truish _ = False
 
 isYesValue :: String -> Bool
@@ -169,7 +170,7 @@
               [] -> cs
               _  -> allcites
         allcites = map (\ref -> Citation{
-                                  citationId = unLiteral (refId ref),
+                                  citationId = T.pack $ unLiteral (refId ref),
                                   citationPrefix = [],
                                   citationSuffix = [],
                                   citationMode = NormalCitation,
@@ -245,19 +246,19 @@
   return $ processCites (tr' "CSL" csl') refs $ Pandoc meta blocks
 
 toPath :: MetaValue -> Maybe String
-toPath (MetaString s) = Just s
+toPath (MetaString s) = Just $ T.unpack s
 -- take last in a list
 toPath (MetaList xs) = case reverse xs of
                              []    -> Nothing
                              (x:_) -> toPath x
-toPath (MetaInlines ils) = Just $ stringify ils
+toPath (MetaInlines ils) = Just $ T.unpack $ stringify ils
 toPath _ = Nothing
 
 getBibRefs :: (String -> Bool) -> MetaValue -> IO [Reference]
 getBibRefs idpred (MetaList xs) = concat `fmap` mapM (getBibRefs idpred) xs
 getBibRefs idpred (MetaInlines xs) = getBibRefs idpred (MetaString $ stringify xs)
 getBibRefs idpred (MetaString s) = do
-  path <- findFile ["."] s >>= maybe (E.throwIO $ CouldNotFindBibFile s) return
+  path <- findFile ["."] (T.unpack s) >>= maybe (E.throwIO $ CouldNotFindBibFile $ T.unpack s) return
   map unescapeRefId `fmap` readBiblioFile idpred path
 getBibRefs _ _ = return []
 
@@ -296,7 +297,7 @@
 getNoteCitationIds (Note [Para (Span ("",["reference-id-list"]
                                       ,[("refids",refids)]) [] : _)])
   -- see deNote below which inserts this special Span
-  = [words refids]
+  = [words $ T.unpack refids]
 getNoteCitationIds (Note _) = [[]]
 getNoteCitationIds _        = []
 
@@ -330,7 +331,7 @@
        then mvPunct moveNotes sty $
              case headInline ys of
                "" -> q : x : tailInline ys
-               w  -> q : Str w : x : tailInline ys
+               w  -> q : Str (T.pack w) : x : tailInline ys
        else q : x : mvPunct moveNotes sty ys
 mvPunct moveNotes sty (Cite cs ils : ys)
    | length ils > 1
@@ -341,7 +342,7 @@
       (init ils ++
          (case headInline ys of
                "" -> []
-               s' | not (endWithPunct False (init ils)) -> [Str s']
+               s' | not (endWithPunct False (init ils)) -> [Str $ T.pack s']
                   | otherwise                           -> [])
        ++ [last ils]) : mvPunct moveNotes sty (tailInline ys)
 mvPunct moveNotes sty (q@(Quoted _ _) : w@(Str _) : x : ys)
@@ -362,7 +363,7 @@
 endWithPunct :: Bool -> [Inline] -> Bool
 endWithPunct _ [] = True
 endWithPunct onlyFinal xs@(_:_) =
-  case reverse (stringify xs) of
+  case reverse (T.unpack $ stringify xs) of
        []                       -> True
        -- covers .), .", etc.:
        (d:c:_) | isPunctuation d
@@ -384,7 +385,7 @@
         -- we insert this to help getNoteCitationIds:
         specialSpan cs =
           Span ("",["reference-id-list"],
-            [("refids", unwords (map citationId cs))]) []
+            [("refids", T.unwords (map citationId cs))]) []
         go' (Str "(" : Cite cs [Note [Para xs]] : Str ")" : ys) =
              Str "(" : Cite cs xs : Str ")" : ys
         go' (x : Cite cs [Note [Para xs]] : ys) | not (isSpacy x) =
@@ -402,7 +403,7 @@
   let xs' = if startWithPunct ys && endWithPunct True xs
                then initInline $ removeLeadingPunct xs
                else removeLeadingPunct xs
-      removeLeadingPunct (Str [c] : s : zs)
+      removeLeadingPunct (Str (T.unpack -> [c]) : s : zs)
           | isSpacy s && (c == ',' || c == '.' || c == ':') = zs
       removeLeadingPunct zs = zs
   in  f xs' ++ ys
@@ -414,7 +415,7 @@
               | otherwise     = []
 
 getCitationIds :: Inline -> Set.Set String
-getCitationIds (Cite cs _) = Set.fromList (map citationId cs)
+getCitationIds (Cite cs _) = Set.map T.unpack $ Set.fromList (map citationId cs)
 getCitationIds _ = mempty
 
 setHashes :: Inline -> State Int Inline
@@ -437,9 +438,9 @@
                          ("","",x:_)
                            | not (isPunct x) -> Space : s
                          _                   -> s
-          isPunct (Str (x:_)) = isPunctuation x
+          isPunct (Str (T.uncons -> Just (x,_))) = isPunctuation x
           isPunct _           = False
-      in   emptyCite { CSL.citeId         = citationId c
+      in   emptyCite { CSL.citeId         = T.unpack $ citationId c
                      , CSL.citePrefix     = Formatted $ citationPrefix c
                      , CSL.citeSuffix     = Formatted s'
                      , CSL.citeLabel      = la
@@ -511,7 +512,7 @@
   (la, _) <- pLocatorLabelDelimited locMap
   -- we only care about balancing {} and [] (because of the outer [] scope);
   -- the rest can be anything
-  let inner = do { t <- anyToken; return (True, stringify t) }
+  let inner = do { t <- anyToken; return (True, T.unpack $ stringify t) }
   gs <- many (pBalancedBraces [('{','}'), ('[',']')] inner)
   _ <- pMatchChar "}" (== '}')
   let lo = concatMap snd gs
@@ -521,7 +522,7 @@
 pLocatorLabelDelimited locMap
   = pLocatorLabel' locMap lim <|> return ("page", True)
     where
-        lim = stringify <$> anyToken
+        lim = T.unpack . stringify <$> anyToken
 
 pLocatorIntegrated :: LocatorMap -> Parsec [Inline] st (String, String)
 pLocatorIntegrated locMap = try $ do
@@ -554,7 +555,7 @@
           -- the pathological case is "p.3"
           t <- anyToken
           ts <- manyTill anyToken (try $ lookAhead lim)
-          let s = acc ++ stringify (t:ts)
+          let s = acc ++ T.unpack (stringify (t:ts))
           case M.lookup (trim s) locMap of
             -- try to find a longer one, or return this one
             Just l -> go s <|> return (l, False)
@@ -563,7 +564,7 @@
 -- hard requirement for a locator to have some real digits in it
 requireDigits :: (Bool, String) -> Parsec [Inline] st String
 requireDigits (_, s) = if not (any isDigit s)
-                          then fail "requireDigits"
+                          then Prelude.fail "requireDigits"
                           else return s
 
 -- soft requirement for a sequence with some roman or arabic parts
@@ -572,7 +573,7 @@
 -- NOT: a, (a)-(b), hello, (some text in brackets)
 requireRomansOrDigits :: (Bool, String) -> Parsec [Inline] st String
 requireRomansOrDigits (d, s) = if not d
-                                  then fail "requireRomansOrDigits"
+                                  then Prelude.fail "requireRomansOrDigits"
                                   else return s
 
 pLocatorWordIntegrated :: Bool -> Parsec [Inline] st (Bool, String)
@@ -582,7 +583,7 @@
               else (stringify <$> pLocatorSep) <|> return ""
   sp <- option "" (pSpace >> return " ")
   (dig, s) <- pBalancedBraces [('(',')'), ('[',']'), ('{','}')] pPageSeq
-  return (dig, punct ++ sp ++ s)
+  return (dig, T.unpack punct ++ sp ++ s)
 
 -- we want to capture:  123, 123A, C22, XVII, 33-44, 22-33; 22-11
 --                      34(1), 34A(A), 34(1)(i)(i), (1)(a)
@@ -621,7 +622,7 @@
           -- .2
           p <- pMatchChar "." (== '.')
           u <- try pPageUnit
-          return (fst u, stringify p ++ snd u)
+          return (fst u, T.unpack (stringify p) ++ snd u)
 
 anyWereDigitLike :: [(Bool, String)] -> (Bool, String)
 anyWereDigitLike as = (any fst as, concatMap snd as)
@@ -635,7 +636,7 @@
           ts <- many1 (notFollowedBy pSpace >>
                        notFollowedBy pLocatorPunct >>
                        anyToken)
-          let s = stringify ts
+          let s = T.unpack $ stringify ts
           -- otherwise look for actual digits or -s
           return (any isDigit s, s)
 
@@ -643,9 +644,9 @@
 pRoman = try $ do
   t <- anyToken
   case t of
-       Str xs -> case parseRomanNumeral xs of
+       Str xs -> case parseRomanNumeral (T.unpack xs) of
                       Nothing -> mzero
-                      Just _  -> return xs
+                      Just _  -> return $ T.unpack xs
        _      -> mzero
 
 isLocatorPunct :: Char -> Bool
@@ -668,7 +669,7 @@
 pMatchChar :: String -> (Char -> Bool) -> Parsec [Inline] st Inline
 pMatchChar msg f = pMatch msg mc
     where
-        mc (Str [c]) = f c
+        mc (Str (T.unpack -> [c])) = f c
         mc _         = False
 
 pSpace :: Parsec [Inline] st Inline
@@ -678,7 +679,7 @@
 pMatch msg condition = try $ do
   t <- anyToken
   if not (condition t)
-     then fail msg
+     then Prelude.fail msg
      else return t
 
 type LocatorMap = M.Map String String
diff --git a/src/Text/CSL/Parser.hs b/src/Text/CSL/Parser.hs
--- a/src/Text/CSL/Parser.hs
+++ b/src/Text/CSL/Parser.hs
@@ -131,7 +131,7 @@
 
 attrWithDefault :: Read a => Text -> a -> Cursor -> a
 attrWithDefault t d cur =
-  fromMaybe d $ safeRead (toRead $ stringAttr t cur)
+  fromMaybe d $ safeRead (T.pack $ toRead $ stringAttr t cur)
 
 stringAttr :: Text -> Cursor -> String
 stringAttr t cur =
diff --git a/src/Text/CSL/Proc.hs b/src/Text/CSL/Proc.hs
--- a/src/Text/CSL/Proc.hs
+++ b/src/Text/CSL/Proc.hs
@@ -2,6 +2,7 @@
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE FlexibleContexts  #-}
 {-# LANGUAGE PatternGuards     #-}
+{-# LANGUAGE ViewPatterns      #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Text.CSL.Proc
@@ -28,6 +29,7 @@
 import           Data.List
 import           Data.Maybe             (mapMaybe)
 import           Data.Ord               (comparing)
+import qualified Data.Text              as T
 import           Text.CSL.Eval
 import           Text.CSL.Proc.Collapse
 import           Text.CSL.Proc.Disamb
@@ -340,7 +342,7 @@
         case ys of
              Formatted []           -> xs
              Formatted (Note _ : _) -> xs <> ys
-             Formatted (Str [c]:_)  | c `elem` (", ;:" :: String) -> xs <> ys
+             Formatted (Str (T.unpack -> [c]):_)  | c `elem` (", ;:" :: String) -> xs <> ys
              _                      -> xs <> Formatted [Space] <> ys
       formatAuth   = formatOutput . localMod
       formatCits   = (if isNote then toNote else id) .
diff --git a/src/Text/CSL/Proc/Collapse.hs b/src/Text/CSL/Proc/Collapse.hs
--- a/src/Text/CSL/Proc/Collapse.hs
+++ b/src/Text/CSL/Proc/Collapse.hs
@@ -1,5 +1,7 @@
 {-# LANGUAGE NoImplicitPrelude #-}
-{-# LANGUAGE PatternGuards #-}
+{-# LANGUAGE ViewPatterns      #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE PatternGuards     #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Text.CSL.Proc.Collapse
@@ -23,6 +25,7 @@
 import           Data.List              (groupBy, sortBy)
 import           Data.Monoid            (Any (..))
 import           Data.Ord               (comparing)
+import qualified Data.Text              as T
 import           Text.CSL.Eval
 import           Text.CSL.Proc.Disamb
 import           Text.CSL.Style         hiding (Any)
@@ -208,11 +211,11 @@
             Formatted  []    -> []
             Formatted ils
               | isprefix  -> case reverse ils of
-                                  (Str zs@(_:_):_) |
-                                    last zs == '\160' -> [OPan ils]
+                                  (Str zs@(T.uncons -> Just (_,_)):_) |
+                                    T.last zs == '\160' -> [OPan ils]
                                   _ -> [OPan ils, OSpace]
               | otherwise -> case ils of
-                                  (Str (z:_):_)
+                                  (Str (T.uncons -> Just (z,_)):_)
                                     | isAlphaNum z ||
                                       z == '(' -> [OSpace, OPan ils]
                                   _            -> [OPan ils]
diff --git a/src/Text/CSL/Reference.hs b/src/Text/CSL/Reference.hs
--- a/src/Text/CSL/Reference.hs
+++ b/src/Text/CSL/Reference.hs
@@ -303,8 +303,8 @@
   = case splitWhen (=='_') xs of
          [x,y] | all isDigit x && all isDigit y &&
                  not (null x) ->
-                 [RefDate (safeRead x) Nothing Nothing Nothing mempty b,
-                  RefDate (safeRead y) Nothing Nothing Nothing mempty b]
+                 [RefDate (safeRead $ T.pack x) Nothing Nothing Nothing mempty b,
+                  RefDate (safeRead $ T.pack y) Nothing Nothing Nothing mempty b]
          _ -> [d]
 handleLiteral d = [d]
 
@@ -360,11 +360,11 @@
   -- found in one of the test cases:
   parseJSON (String "film") = return MotionPicture
   parseJSON (String t) =
-    safeRead (capitalize . camelize . T.unpack $ t) <|>
+    safeRead (T.pack . capitalize . camelize . T.unpack $ t) <|>
     fail ("'" ++ T.unpack t ++ "' is not a valid reference type")
   parseJSON v@(Array _) =
     fmap (capitalize . camelize . inlinesToString) (parseJSON v) >>= \t ->
-      safeRead t <|>
+      safeRead (T.pack t) <|>
        fail ("'" ++ t ++ "' is not a valid reference type")
   parseJSON _ = fail "Could not parse RefType"
 
@@ -1017,18 +1017,18 @@
     extended <- if extyear
                    then P.many P.digit
                    else return []
-    return $ case safeRead (sign ++ rest ++ extended) of
+    return $ case safeRead (T.pack $ sign ++ rest ++ extended) of
                     Just x | x <= 0 -> Just (x - 1)  -- 0 = -1 AD
                     x               -> x
   m' <- P.option Nothing $ Just <$> P.try (P.char '-' >> P.many1 P.digit)
-  (m,s) <- case m' >>= safeRead of
+  (m,s) <- case m' >>= safeRead . T.pack of
                    Just (n::Int)
                           | n >= 1 && n <= 12  -> return (Just n, Nothing)
                           | n >= 13 && n <= 16 -> return (Nothing, pseudoMonthToSeason n)
                           | n >= 21 && n <= 24 -> return (Nothing, pseudoMonthToSeason n)
                    Nothing | isNothing m' -> return (Nothing, Nothing)
                    _ -> fail "Improper month"
-  d <- P.option Nothing $ safeRead <$> P.try (P.char '-' >> P.many1 P.digit)
+  d <- P.option Nothing $ safeRead . T.pack <$> P.try (P.char '-' >> P.many1 P.digit)
   guard $ case d of
            Nothing -> True
            Just (n::Int) | n >= 1 && n <= 31 -> True
@@ -1052,7 +1052,7 @@
   let pmonth = P.try $ do
         xs <- P.many1 P.letter <|> P.many1 P.digit
         if all isDigit xs
-           then case safeRead xs of
+           then case safeRead (T.pack xs) of
                       Just (n::Int) | n >= 1 && n <= 12 -> return (Just n)
                       _ -> fail "Improper month"
            else case elemIndex (map toLower $ take 3 xs) months of
@@ -1068,10 +1068,10 @@
              _       -> fail "Improper season"
   let pday = P.try $ do
         xs <- P.many1 P.digit
-        case safeRead xs of
+        case safeRead (T.pack xs) of
              Just (n::Int) | n >= 1 && n <= 31 -> return (Just n)
              _ -> fail "Improper day"
-  let pyear = safeRead <$> P.many1 P.digit
+  let pyear = safeRead . T.pack <$> P.many1 P.digit
   let sep = P.oneOf [' ','/',','] >> P.spaces
   let rangesep = P.try $ P.spaces >> P.char '-' >> P.spaces
   let refDate = RefDate Nothing Nothing Nothing Nothing mempty False
diff --git a/src/Text/CSL/Style.hs b/src/Text/CSL/Style.hs
--- a/src/Text/CSL/Style.hs
+++ b/src/Text/CSL/Style.hs
@@ -3,6 +3,7 @@
 {-# LANGUAGE DeriveDataTypeable         #-}
 {-# LANGUAGE DeriveGeneric              #-}
 {-# LANGUAGE FlexibleInstances          #-}
+{-# LANGUAGE ViewPatterns               #-}
 
 {-# LANGUAGE MultiParamTypeClasses      #-}
 {-# LANGUAGE OverloadedStrings          #-}
@@ -147,7 +148,7 @@
   -- this is needed for versions of pandoc that don't turn
   -- a span with font-variant:small-caps into a SmallCaps element:
   where handleSmallCapsSpans (Span ("",[],[("style",sty)]) ils)
-            | filter (`notElem` (" \t;" :: String)) sty == "font-variant:small-caps" =
+            | T.filter (`notElem` (" \t;" :: String)) sty == "font-variant:small-caps" =
               SmallCaps ils
         handleSmallCapsSpans x = x
 
@@ -245,7 +246,7 @@
 
 toStr :: String -> [Inline]
 toStr = intercalate [Str "\n"] .
-        map (B.toList . B.text . tweak . fromEntities) .
+        map (B.toList . B.text . T.pack . tweak . T.unpack . fromEntities . T.pack) .
         splitWhen (=='\n')
     where
       tweak ('«':' ':xs) = "«\8239" ++ tweak xs
@@ -898,7 +899,7 @@
   | otherwise = ag
 
 startWithCapital' :: Inline -> Bool
-startWithCapital' (Str (c:_)) = isUpper c && isLetter c
+startWithCapital' (Str (T.uncons -> Just (c,_))) = isUpper c && isLetter c
 startWithCapital' _           = False
 
 startWithCapital :: Formatted -> Bool
diff --git a/src/Text/CSL/Util.hs b/src/Text/CSL/Util.hs
--- a/src/Text/CSL/Util.hs
+++ b/src/Text/CSL/Util.hs
@@ -1,9 +1,12 @@
-{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE NoImplicitPrelude     #-}
+{-# LANGUAGE OverloadedStrings     #-}
+{-# LANGUAGE ViewPatterns          #-}
 {-# LANGUAGE FlexibleContexts      #-}
 {-# LANGUAGE FlexibleInstances     #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE PatternGuards         #-}
 {-# LANGUAGE ScopedTypeVariables   #-}
+{-# LANGUAGE ScopedTypeVariables   #-}
 module Text.CSL.Util
   ( safeRead
   , readNum
@@ -52,7 +55,7 @@
   , isRange
   , addSpaceAfterPeriod
   ) where
-import Prelude
+import           Prelude
 import           Control.Monad.State
 import           Data.Aeson
 import           Data.Aeson.Types    (Parser)
@@ -98,7 +101,7 @@
 sa <^> []         = sa
 sa <^> (s:xs)
   | s `elem` puncts && last sa `elem` puncts = sa ++ xs
-  where puncts = ";:,. "
+  where puncts = ";:,. " :: String
 sa <^> sb         = sa ++ sb
 
 capitalize :: String -> String
@@ -106,7 +109,7 @@
 capitalize (c:cs) = toUpper c : cs
 
 isPunct :: Char -> Bool
-isPunct c = c `elem` ".;?!"
+isPunct c = c `elem` (".;?!" :: String)
 
 camelize :: String -> String
 camelize ('-':y:ys) = toUpper y : camelize ys
@@ -137,7 +140,7 @@
 trim = triml . trimr
 
 triml :: String -> String
-triml = dropWhile (`elem` " \r\n\t")
+triml = dropWhile (`elem` (" \r\n\t" :: String))
 
 trimr :: String -> String
 trimr = reverse . triml . reverse
@@ -148,8 +151,8 @@
 parseBool (Number n) = case fromJSON (Number n) of
                             Success (0 :: Int) -> return False
                             Success _          -> return True
-                            Error e            -> fail $ "Could not read boolean: " ++ e
-parseBool _          = fail "Could not read boolean"
+                            Error e            -> Prelude.fail $ "Could not read boolean: " ++ e
+parseBool _          = Prelude.fail "Could not read boolean"
 
 -- | Parse JSON value as String.
 parseString :: Value -> Parser String
@@ -158,34 +161,34 @@
                             Success (x :: Int) -> return $ show x
                             Error _ -> case fromJSON (Number n) of
                                             Success (x :: Double) -> return $ show x
-                                            Error e -> fail $ "Could not read string: " ++ e
+                                            Error e -> Prelude.fail $ "Could not read string: " ++ e
 parseString (Bool b)   = return $ map toLower $ show b
 parseString v@(Array _)= inlinesToString `fmap` parseJSON v
-parseString v          = fail $ "Could not read as string: " ++ show v
+parseString v          = Prelude.fail $ "Could not read as string: " ++ show v
 
 -- | Parse JSON value as Int.
 parseInt :: Value -> Parser Int
 parseInt (Number n) = case fromJSON (Number n) of
                             Success (x :: Int) -> return x
-                            Error e -> fail $ "Could not read Int: " ++ e
+                            Error e -> Prelude.fail $ "Could not read Int: " ++ e
 parseInt x = parseString x >>= \s ->
-              case safeRead s of
+              case safeRead (T.pack s) of
                    Just n  -> return n
-                   Nothing -> fail "Could not read Int"
+                   Nothing -> Prelude.fail "Could not read Int"
 
 -- | Parse JSON value as Maybe Int.
 parseMaybeInt :: Maybe Value -> Parser (Maybe Int)
 parseMaybeInt Nothing = return Nothing
 parseMaybeInt (Just (Number n)) = case fromJSON (Number n) of
                                        Success (x :: Int) -> return (Just x)
-                                       Error e -> fail $ "Could not read Int: " ++ e
+                                       Error e -> Prelude.fail $ "Could not read Int: " ++ e
 parseMaybeInt (Just x) =
   parseString x >>= \s ->
                    if null s
                       then return Nothing
-                      else case safeRead s of
+                      else case safeRead (T.pack s) of
                                 Just n  -> return (Just n)
-                                Nothing -> fail $ "Could not read as Int: " ++ show s
+                                Nothing -> Prelude.fail $ "Could not read as Int: " ++ show s
 
 mb :: Monad m => (b -> m a) -> (Maybe b -> m (Maybe a))
 mb  = Data.Traversable.mapM
@@ -205,7 +208,7 @@
 
 hasLowercaseWord :: [Inline] -> Bool
 hasLowercaseWord = any startsWithLowercase . splitStrWhen isPunctuation
-  where startsWithLowercase (Str (x:_)) = isLower x
+  where startsWithLowercase (Str (T.uncons -> Just (x,_))) = isLower x
         startsWithLowercase _           = False
 
 splitUpStr :: [Inline] -> [Inline]
@@ -220,7 +223,7 @@
 combineInternalPeriods :: [Inline] -> [Inline]
 combineInternalPeriods [] = []
 combineInternalPeriods (Str xs:Str ".":Str ys:zs) =
-  combineInternalPeriods $ Str (xs ++ "." ++ ys) : zs
+  combineInternalPeriods $ Str (xs <> "." <> ys) : zs
 combineInternalPeriods (x:xs) = x : combineInternalPeriods xs
 
 unTitlecase :: [Inline] -> [Inline]
@@ -229,12 +232,12 @@
           st <- get
           case (w, st) of
                (y, NoBoundary) -> return y
-               (Str (x:xs), LastWordBoundary) | isUpper x ->
-                 return $ Str (map toLower (x:xs))
-               (Str (x:xs), WordBoundary) | isUpper x ->
-                 return $ Str (map toLower (x:xs))
-               (Str (x:xs), SentenceBoundary) | isLower x ->
-                 return $ Str (toUpper x : xs)
+               (Str (T.uncons -> Just (x,xs)), LastWordBoundary) | isUpper x ->
+                 return $ Str (T.toLower (T.cons x xs))
+               (Str (T.uncons -> Just (x,xs)), WordBoundary) | isUpper x ->
+                 return $ Str (T.toLower (T.cons x xs))
+               (Str (T.uncons -> Just (x,xs)), SentenceBoundary) | isLower x ->
+                 return $ Str (T.cons (toUpper x) xs)
                (Span ("",[],[]) xs, _) | hasLowercaseWord xs ->
                  return $ Span ("",["nocase"],[]) xs
                _ -> return w
@@ -264,28 +267,28 @@
 -- and “yet”.
 titlecase :: [Inline] -> [Inline]
 titlecase zs = evalState (caseTransform tc zs) SentenceBoundary
-  where tc (Str (x:xs)) = do
+  where tc (Str (T.unpack -> (x:xs))) = do
           st <- get
           return $ case st of
                         LastWordBoundary ->
                           case (x:xs) of
-                           s | not (isAscii x) -> Str s
-                             | isShortWord s   -> Str s
-                             | all isUpperOrPunct s   -> Str s
-                             | isMixedCase s   -> Str s
-                             | otherwise       -> Str (toUpper x:xs)
+                           s | not (isAscii x) -> Str $ T.pack s
+                             | isShortWord s   -> Str $ T.pack s
+                             | all isUpperOrPunct s   -> Str $ T.pack s
+                             | isMixedCase s   -> Str $ T.pack s
+                             | otherwise       -> Str $ T.pack (toUpper x:xs)
                         WordBoundary ->
                           case (x:xs) of
-                           s | not (isAscii x) -> Str s
-                             | all isUpperOrPunct s   -> Str s
-                             | isShortWord s   -> Str (map toLower s)
-                             | isMixedCase s   -> Str s
-                             | otherwise       -> Str (toUpper x:xs)
+                           s | not (isAscii x) -> Str $ T.pack s
+                             | all isUpperOrPunct s   -> Str $ T.pack s
+                             | isShortWord s   -> Str $ T.pack (map toLower s)
+                             | isMixedCase s   -> Str $ T.pack s
+                             | otherwise       -> Str $ T.pack (toUpper x:xs)
                         SentenceBoundary ->
                            if isMixedCase (x:xs) || all isUpperOrPunct (x:xs)
-                              then Str (x:xs)
-                              else Str (toUpper x : xs)
-                        _ -> Str (x:xs)
+                              then Str $ T.pack (x:xs)
+                              else Str $ T.pack (toUpper x : xs)
+                        _ -> Str $ T.pack (x:xs)
         tc (Span ("",["nocase"],[]) xs) = return $ Span ("",["nocase"],[]) xs
         tc x = return x
         isShortWord  s = map toLower s `Set.member` shortWords
@@ -320,15 +323,15 @@
         go acc LineBreak = do
                put WordBoundary
                return $ Space : acc
-        go acc (Str [c])
-          | c `elem` ".?!:" = do
+        go acc (Str (T.unpack -> [c]))
+          | c `elem` (".?!:" :: String) = do
                put SentenceBoundary
-               return $ Str [c] : acc
-          | c `elem` "-/\x2013\x2014\160" = do
+               return $ Str (T.singleton c) : acc
+          | c `elem` ("-/\x2013\x2014\160" :: String) = do
                put WordBoundary
-               return $ Str [c] : acc
-          | isPunctuation c = return $ Str [c] : acc -- leave state unchanged
-        go acc (Str []) = return acc
+               return $ Str (T.singleton c) : acc
+          | isPunctuation c = return $ Str (T.singleton c) : acc -- leave state unchanged
+        go acc (Str "") = return acc
         go acc (Str xs) = do
                res <- xform (Str xs)
                put NoBoundary
@@ -354,13 +357,13 @@
 
 splitStrWhen :: (Char -> Bool) -> [Inline] -> [Inline]
 splitStrWhen _ [] = []
-splitStrWhen p (Str xs : ys) = go xs ++ splitStrWhen p ys
+splitStrWhen p (Str xs : ys) = go (T.unpack xs) ++ splitStrWhen p ys
   where go [] = []
         go s = case break p s of
                      ([],[])     -> []
-                     (zs,[])     -> [Str zs]
-                     ([],(w:ws)) -> Str [w] : go ws
-                     (zs,(w:ws)) -> Str zs : Str [w] : go ws
+                     (zs,[])     -> [Str $ T.pack zs]
+                     ([],(w:ws)) -> Str (T.singleton w) : go ws
+                     (zs,(w:ws)) -> Str (T.pack zs) : Str (T.singleton w) : go ws
 splitStrWhen p (x : ys) = x : splitStrWhen p ys
 
 -- | A generic processing function.
@@ -395,13 +398,13 @@
           | otherwise     = []
 
 inlinesToString :: [Inline] -> String
-inlinesToString = stringify
+inlinesToString = T.unpack . stringify
 
 headInline :: [Inline] -> String
-headInline = take 1 . stringify
+headInline = take 1 . T.unpack . stringify
 
 lastInline :: [Inline] -> String
-lastInline xs = case stringify xs of
+lastInline xs = case T.unpack $ stringify xs of
                       [] -> []
                       ys -> [last ys]
 
@@ -409,7 +412,7 @@
 initInline [] = []
 initInline [i]
     | Str          s <- i
-    , not (null s)        = return $ Str         (init        s)
+    , not (T.null s)      = return $ Str         (T.init      s)
     | Emph        is <- i = return $ Emph        (initInline is)
     | Strong      is <- i = return $ Strong      (initInline is)
     | Superscript is <- i = return $ Superscript (initInline is)
@@ -437,19 +440,19 @@
 mapHeadInline :: (String -> String) -> [Inline] -> [Inline]
 mapHeadInline _ [] = []
 mapHeadInline f (i:xs)
-    | Str         [] <- i =                      mapHeadInline f xs
-    | Str          s <- i = case f s of
+    | Str         "" <- i =                      mapHeadInline f xs
+    | Str          s <- i = case f (T.unpack s) of
                               "" -> xs
-                              _  -> Str (f                s)   : xs
-    | Emph        is <- i = Emph        (mapHeadInline f is)   : xs
-    | Strong      is <- i = Strong      (mapHeadInline f is)   : xs
-    | Superscript is <- i = Superscript (mapHeadInline f is)   : xs
-    | Subscript   is <- i = Subscript   (mapHeadInline f is)   : xs
-    | Quoted q    is <- i = Quoted q    (mapHeadInline f is)   : xs
-    | SmallCaps   is <- i = SmallCaps   (mapHeadInline f is)   : xs
-    | Strikeout   is <- i = Strikeout   (mapHeadInline f is)   : xs
-    | Link   at is t <- i = Link at     (mapHeadInline f is) t : xs
-    | Span     at is <- i = Span at     (mapHeadInline f is)   : xs
+                              _  -> Str (T.pack $ f $ T.unpack s) : xs
+    | Emph        is <- i = Emph        (mapHeadInline f is)      : xs
+    | Strong      is <- i = Strong      (mapHeadInline f is)      : xs
+    | Superscript is <- i = Superscript (mapHeadInline f is)      : xs
+    | Subscript   is <- i = Subscript   (mapHeadInline f is)      : xs
+    | Quoted q    is <- i = Quoted q    (mapHeadInline f is)      : xs
+    | SmallCaps   is <- i = SmallCaps   (mapHeadInline f is)      : xs
+    | Strikeout   is <- i = Strikeout   (mapHeadInline f is)      : xs
+    | Link   at is t <- i = Link at     (mapHeadInline f is) t    : xs
+    | Span     at is <- i = Span at     (mapHeadInline f is)      : xs
     | otherwise           = i : xs
 
 findFile :: [FilePath] -> FilePath -> IO (Maybe FilePath)
@@ -528,7 +531,7 @@
                 hundreds + nineties + fifties + forties + tens + nines +
                 fives + fours + ones
     if total == 0
-       then fail "not a roman numeral"
+       then Prelude.fail "not a roman numeral"
        else return total
 
 isRange :: String -> Bool
@@ -540,9 +543,9 @@
 addSpaceAfterPeriod = go . splitStrWhen (=='.')
   where
     go [] = []
-    go (Str [c]:Str ".":Str [d]:xs)
+    go (Str (T.unpack -> [c]):Str ".":Str (T.unpack -> [d]):xs)
       | isLetter d
       , isLetter c
       , isUpper c
-      , isUpper d   = Str [c]:Str ".":Space:go (Str [d]:xs)
+      , isUpper d   = Str (T.singleton c):Str ".":Space:go (Str (T.singleton d):xs)
     go (x:xs) = x:go xs
diff --git a/stack.yaml b/stack.yaml
--- a/stack.yaml
+++ b/stack.yaml
@@ -9,18 +9,18 @@
 packages:
 - '.'
 extra-deps:
-- pandoc-types-1.17.6.1
 - HsYAML-0.2.0.0
 - HsYAML-aeson-0.2.0.0
-- texmath-0.11.3
 - haddock-library-1.8.0
 - skylighting-0.8.2.3
 - skylighting-core-0.8.2.3
 - regex-pcre-builtin-0.95.0.8.8.35
-- doctemplates-0.7
+- doctemplates-0.7.1
 - doclayout-0.2.0.1
-- git: https://github.com/jgm/pandoc.git
-  commit: 8f3b3afc70d163afe5e103abec77a4ffafb995bd
+- texmath-0.12
+- pandoc-types-1.20
+- git: 'https://github.com/jgm/pandoc'
+  commit: cac01f45bb2247d152f649eb1ef30f21fbc28867
 
 ghc-options:
    "$locals": -fhide-source-paths
diff --git a/tests/test-citeproc.hs b/tests/test-citeproc.hs
--- a/tests/test-citeproc.hs
+++ b/tests/test-citeproc.hs
@@ -182,7 +182,7 @@
 adjustSpans (Span (id',classes,kvs) ils) =
   [Span (id',classes',kvs') ils]
   where classes' = filter (`notElem` ["csl-no-emph","csl-no-strong","csl-no-smallcaps"]) classes
-        kvs' = if null styles then kvs else (("style", concat styles) : kvs)
+        kvs' = if null styles then kvs else (("style", mconcat styles) : kvs)
         styles = ["font-style:normal;" | "csl-no-emph" `elem` classes]
               ++ ["font-weight:normal;" | "csl-no-strong" `elem` classes]
               ++ ["font-variant:normal;" | "csl-no-smallcaps" `elem` classes]
