diff --git a/README b/README
--- a/README
+++ b/README
@@ -28,7 +28,7 @@
 style, given a collection of references.
 
 Natively [citeproc-hs] can read [JSON][^1] and [MODS][^2] XML
-formattted bibliographic databases.
+formatted bibliographic databases.
 
 [bibutils] can be used to convert Bibtex and other bibliographic
 databases to [MODS] collections, which can be thus read by
@@ -54,11 +54,7 @@
 
 To get the darcs source run:
 
-        darcs get http://code.haskell.org/citeproc-hs/
-
-**NOTE**: <http://code.haskell.org> is presently down. The darcs
-  repository may be accessed at:
-  <http://gorgias.mine.nu/repos/citeproc-hs/>
+        darcs get http://gorgias.mine.nu/repos/citeproc-hs/
 
 Installation
 ------------
@@ -133,7 +129,7 @@
 
 <http://hackage.haskell.org/package/citeproc-hs>
 
-### Some notes about name parsing
+### Name parsing
 
 The [MODS] parser has been optimized for bibtex input, especially for
 parsing names with affixes , dropping and non-dropping particles.
@@ -159,6 +155,20 @@
 
 <http://citationstyles.org/downloads/specification.html#name-particles>
 
+### Date parsing
+
+The [MODS] parser, which is used to read all bibliograhic databases
+supported by [bibutils], tries to parse dates, including seasons
+(expressed in English). An example of supported formats:
+
+    2010-01-31   (January 31, 2010)
+
+    2004-05      (May, 2004)
+
+    2001         (the year only)
+
+    Summer, 2001 (the season)
+
 ### Running the test-suite
 
 To run the test suite, you first need to grab it with [mercurial] by
@@ -178,11 +188,15 @@
 
         runhaskell test/test.hs
 
-
 You may also specify a test group:
 
         runhaskell test/test.hs date
 
+or a single test in a group:
+
+        runhaskell test/test.hs date IgnoreNonexistentSort
+
+
 To increase the debug messages edit *test/test.hs* and increase the
 *Int* parameter of *runTS*:
 
@@ -191,21 +205,17 @@
 Known Issues
 ------------
 
-[citeproc-hs] is in an early stage of development and the [CSL]
-implementation is not complete.
-
-Most of [CSL]-1.0 features are implemented. Some missing features are
-meaningless in [pandoc], the main target of [citeproc-hs] at the
-present time. Specifically the [display] attribute has not been
-implemented yet.
+The [CSL] implementation is mostly but not entirely complete. Some of
+the missing features are meaningless in [pandoc], the main target of
+[citeproc-hs] at the present time. Specifically the [display]
+attribute has not been implemented yet.
 
-The [citeproc-hs]-0.3.2 release passes 411 out of 537 tests of the
+The [citeproc-hs]-0.3.4 release passes 483 out of 654 tests of the
 [citeproc-test] suite. The test-suite has been developed along with
 [citeproc-js], and the failure of some of those tests is not
-meaningful for [citeproc-hs]. The major missing bits are related to
-multi-language names.
+meaningful for [citeproc-hs].
 
-The [MODS] parser needs some refinement too.
+The [MODS] parser may need some refinement.
 
 Bug Reports
 -----------
diff --git a/citeproc-hs.cabal b/citeproc-hs.cabal
--- a/citeproc-hs.cabal
+++ b/citeproc-hs.cabal
@@ -1,5 +1,5 @@
 name:               citeproc-hs
-version:            0.3.3
+version:            0.3.4
 homepage:           http://gorgias.mine.nu/repos/citeproc-hs/
 synopsis:           A Citation Style Language implementation in Haskell
 
@@ -101,7 +101,7 @@
     ghc-prof-options: -prof -auto-all
     hs-source-dirs:   src
     build-depends:    containers, directory, mtl, xml, json, utf8-string,
-                      bytestring, filepath, pandoc-types >= 1.8 && < 1.9
+                      bytestring, filepath, pandoc-types >= 1.8 && < 1.10
 
     if flag(bibutils)
        build-depends:   hs-bibutils >= 0.3
diff --git a/src/Text/CSL.hs b/src/Text/CSL.hs
--- a/src/Text/CSL.hs
+++ b/src/Text/CSL.hs
@@ -32,6 +32,7 @@
     , readModsCollectionFile
     , readJsonInput
     , readJsonInputString
+    , readJsonAbbrevFile
 
     -- ** Reference Representation
     , Reference (..)
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
@@ -16,8 +16,7 @@
 module Text.CSL.Eval
     ( evalLayout
     , evalSorting
-    , rtfParser
-    , last'
+    , last', split, trim
     , module Text.CSL.Eval.Common
     , module Text.CSL.Eval.Output
     ) where
@@ -26,6 +25,7 @@
 import Control.Applicative ( (<$>) )
 import Control.Monad.State
 import Data.Char
+import qualified Data.Map as M
 import Data.Maybe
 
 import Text.CSL.Eval.Common
@@ -36,15 +36,14 @@
 import Text.CSL.Reference
 import Text.CSL.Style
 import Text.Pandoc.Definition
-import Text.ParserCombinators.Parsec hiding ( State (..) )
 
 -- | Produce the output with a 'Layout', the 'EvalMode', a 'Bool'
 -- 'True' if the evaluation happens for disambiguation purposes, the
--- 'Locale', the 'MacrpMap', the position of the cite and the
+-- 'Locale', the 'MacroMap', the position of the cite and the
 -- 'Reference'.
 evalLayout :: Layout   -> EvalMode -> Bool -> [Locale] -> [MacroMap]
-           -> [Option] -> Reference -> [Output]
-evalLayout (Layout _ _ es) em b l m o r
+           -> [Option] -> [Abbrev] -> Reference -> [Output]
+evalLayout (Layout _ _ es) em b l m o a r
     = cleanOutput evalOut
     where
       evalOut = case evalState job initSt of
@@ -62,15 +61,16 @@
                  EvalSorting c -> c
                  EvalBiblio  s -> emptyCite { citePosition = s }
       initSt = EvalState (mkRefMap r) (Env cit (localeTermMap locale) m
-                         (localeDate locale) o []) [] em b False [] [] False [] [] []
+                         (localeDate locale) o [] a) [] em b False [] [] False [] [] []
 
-evalSorting :: EvalMode -> [Locale] -> [MacroMap] -> [Option] -> [Sort] -> Reference -> [Sorting]
-evalSorting m l ms opts ss r
+evalSorting :: EvalMode -> [Locale] -> [MacroMap] -> [Option] ->
+               [Sort] -> [Abbrev] -> Reference -> [Sorting]
+evalSorting m l ms opts ss as r
     = map (format . sorting) ss
     where
       render       = renderPlainStrict . formatOutputList
       format (s,e) = applaySort s . render $ uncurry eval e
-      eval     o e = evalLayout (Layout emptyFormatting [] [e]) m False l ms o r
+      eval     o e = evalLayout (Layout emptyFormatting [] [e]) m False l ms o as r
       applaySort c s
           | Ascending {} <- c = Ascending  s
           | otherwise         = Descending s
@@ -108,12 +108,18 @@
                                     ifEmpty (evalNames False s n d)
                                             (withNames s el $ evalElements sub)
                                             (appendOutput fm)
-    | Substitute (e:els)    <- el = ifEmpty (consuming $ evalElement e)
+    | Substitute (e:els)    <- el = ifEmpty (consuming $ substituteWith e)
                                             (getFirst els) id
     | ShortNames   s fm d   <- el = head <$> gets (names . env) >>= \(Names _ ns fm' d' _) ->
                                     appendOutput fm' <$> evalNames False s (updateNameParts d fm ns) d'
     | otherwise                   = return []
     where
+      substituteWith e = head <$> gets (names . env) >>= \(Names _ ns fm d _) -> do
+                           case e of
+                             Names rs [Name NotSet _ [] [] []] fm' d' []
+                                 -> evalElement $ Names rs ns (mergeFM fm' fm) (d' `betterThen` d) []
+                             _   -> evalElement e
+
       updateNameParts d fm (Name f fm' nf d' np : xs) = Name f (mergeFM fm' fm) nf (d `betterThen` d') np : xs
       updateNameParts d fm                   (x : xs) = x : updateNameParts d fm xs
       updateNameParts _ _                         []  = []
@@ -140,14 +146,16 @@
                                     (getFirst xs)
 
       getMacro         s = maybe [] id . lookup s <$> gets (macros . env)
-      getVariable f fm s = case s of
+      getVariable f fm s = case (map toLower s) of
                              "year-suffix" -> getStringVar "ref-id" >>= \k  ->
                                               return . return $ OYearSuf [] k [] fm
                              "page"        -> getStringVar "page" >>= formatRange fm
                              "title"       -> formatTitle f fm
                              "locator"     -> getLocVar >>= formatRange fm . snd
-                             _             -> gets (options . env) >>= \opts ->
-                                              getVar [] (getFormattedValue opts f fm) s >>= \r ->
+                             "url"         -> getStringVar "url" >>= \k ->
+                                              if null k then return [] else return [OUrl k fm]
+                             _             -> gets (env >>> options &&& abbrevs) >>= \(opts,as) ->
+                                              getVar [] (getFormattedValue opts as f fm s) s >>= \r ->
                                               consumeVariable s >> return r
 
 evalIfThen :: IfThen -> [IfThen] -> [Element] -> State EvalState [Output]
@@ -178,7 +186,6 @@
 
       chkType         t = let chk = (==) (formatVariable t) . show . fromMaybe NoType . fromValue
                           in  getVar False chk "ref-type"
-      numericVars       = ["edition", "volume", "number-of-volumes", "number", "issue", "citation-number"]
       chkNumeric      v = do val <- getStringVar v
                              return (v `elem` numericVars && or (map isDigit val))
       chkDate         v = getDateVar v >>= return . not . null . filter ((/=) [] . circa)
@@ -195,9 +202,9 @@
                                           b == "ibid-with-locator-c" then True  else False
           | otherwise                = isIbid b
 
-getFormattedValue :: [Option] -> Form -> Formatting -> Value -> [Output]
-getFormattedValue o f fm val
-    | Just v <- fromValue val :: Maybe String    = rtfParser fm v
+getFormattedValue :: [Option] -> [Abbrev] -> Form -> Formatting -> String -> Value -> [Output]
+getFormattedValue o as f fm s val
+    | Just v <- fromValue val :: Maybe String    = rtfParser fm . getAbbr $ value v
     | Just v <- fromValue val :: Maybe Int       = output  fm (if v == 0 then [] else show v)
     | Just v <- fromValue val :: Maybe CNum      = if v == 0 then [] else [OCitNum (unCNum v) fm]
     | Just v <- fromValue val :: Maybe [RefDate] = formatDate (EvalSorting emptyCite) [] [] sortDate v
@@ -205,83 +212,31 @@
                                                               fm nameOpts []) v
     | otherwise                                  = []
     where
+      value     = if stripPeriods fm then filter (/= '.') else id
+      getAbbr v = if f /= Short then v else
+                  case lookup "default" as of
+                    Nothing -> v
+                    Just x  -> case lookup s x of
+                                 Nothing -> v
+                                 Just x' -> case M.lookup v x' of
+                                              Nothing  -> v
+                                              Just x'' -> x''
       nameOpts = ("name-as-sort-order","all") : o
       sortDate = [ DatePart "year"  "numeric-leading-zeros" "" emptyFormatting
                  , DatePart "month" "numeric-leading-zeros" "" emptyFormatting
                  , DatePart "day"   "numeric-leading-zeros" "" emptyFormatting]
 
-rtfTags :: [(String, (String,Formatting))]
-rtfTags =
-    [("b"                      , ("b"   , ef {fontWeight    = "bold"      }))
-    ,("i"                      , ("i"   , ef {fontStyle     = "italic"    }))
-    ,("sc"                     , ("sc"  , ef {fontVariant   = "small-caps"}))
-    ,("sup"                    , ("sup" , ef {verticalAlign = "sub"       }))
-    ,("sub"                    , ("sub" , ef {verticalAlign = "sub"       }))
-    ,("span class=\"nocase\""  , ("span", ef {noCase        = True        }))
-    ,("span class=\"nodecor\"" , ("span", ef {noDecor       = True        }))
-    ]
-    where
-      ef = emptyFormatting
-
-rtfParser :: Formatting -> String -> [Output]
-rtfParser _ [] = []
-rtfParser fm s
-    = either (const [OStr s fm]) (return . flip Output fm . concat) $
-      parse (manyTill parser eof) "" s
-    where
-      parser = parseText <|> parseMarkup
-
-      parseText = do
-        let amper = string "&" >> notFollowedBy (char '#') >>
-                    return [OStr "&" emptyFormatting]
-        x  <- many $ noneOf "<'\"`“‘&"
-        xs <- parseQuotes <|> parseMarkup <|> amper
-        r  <- manyTill anyChar eof
-        return (OStr x emptyFormatting : xs ++
-                [Output (rtfParser emptyFormatting r) emptyFormatting])
-
-      parseMarkup = do
-        let tillTag = many $ noneOf "<"
-        m   <- string "<" >> manyTill anyChar (try $ string ">")
-        res <- case lookup m rtfTags of
-                 Just tf -> do let ot = "<"  ++ fst tf ++ ">"
-                                   ct = "</" ++ fst tf ++ ">"
-                                   parseGreedy = do a <- tillTag
-                                                    _ <- string ct
-                                                    return a
-                               x <- manyTill anyChar $ try $ string ct
-                               y <- try parseGreedy <|> (string ot >> pzero) <|> return []
-                               let r = if null y then x else x ++ ct ++ y
-                               return [Output (rtfParser emptyFormatting r) (snd tf)]
-                 Nothing -> do r <- tillTag
-                               return [OStr ("<" ++ m ++ ">" ++ r) emptyFormatting]
-        return [Output res emptyFormatting]
-
-      parseQuotes = choice [parseQ "'" "'"
-                           ,parseQ "\"" "\""
-                           ,parseQ "``" "''"
-                           ,parseQ "`" "'"
-                           ,parseQ "“" "”"
-                           ,parseQ "‘" "’"
-                           ,parseQ "&#39;" "&#39;"
-                           ,parseQ "&#34;" "&#34;"
-                           ,parseQ "&quot;" "&quot;"
-                           ,parseQ "&apos;" "&apos;"
-                           ]
-      parseQ a b = try $ do
-        q <- string a >> manyTill anyChar (try $ string b)
-        return [Output (rtfParser emptyFormatting q) (emptyFormatting {quotes = True})]
-
 formatTitle :: Form -> Formatting -> State EvalState [Output]
 formatTitle f fm
-    | Short <- f = getIt "short-title" "title"
-    | otherwise  = getIt "title" "short-title"
+    | Short <- f = getIt "title-short" "title"
+    | otherwise  = getIt "title" "title-short"
     where
       getIt x fb = do
         o <- gets (options . env)
-        r <- getVar [] (getFormattedValue o f fm) x
+        a <- gets (abbrevs . env)
+        r <- getVar [] (getFormattedValue o a f fm x) x
         case r of
-          [] -> getVar [] (getFormattedValue o f fm) fb
+          [] -> getVar [] (getFormattedValue o a f fm x) fb
           _  -> return r
 
 formatNumber :: NumericForm -> Formatting -> String -> State EvalState [Output]
@@ -309,18 +264,18 @@
 formatRange fm p = do
   ops <- gets (options . env)
   let opt = getOptionVal "page-range-format" ops
-      splitRange = second (dropWhile (== '-')) . break (== '-')
+      splitRange = break (== '-') >>> trim *** trim . dropWhile (== '-')
       pages = map splitRange . split (== ',') $ p
       format a b = if b /= []
-                   then flip Output emptyFormatting [ OStr a emptyFormatting, OPan [EnDash]
+                   then flip Output emptyFormatting [ OStr a emptyFormatting, OPan [Str "\x2013"]
                                                     , OStr b emptyFormatting]
                    else flip Output emptyFormatting [ OStr a emptyFormatting]
       result = case opt of
                  "expanded" -> map (uncurry format . uncurry expandedRange) pages
                  "chicago"  -> map (uncurry format . uncurry chicagoRange ) pages
                  "minimal"  -> map (uncurry format . uncurry minimalRange ) pages
-                 _          -> [OStr p emptyFormatting]
-  return [flip Output fm $ addDelim ", " result]
+                 _          -> map (uncurry format                        ) pages
+  return [flip OLoc fm $ addDelim ", " result]
 
 expandedRange :: String -> String -> (String, String)
 expandedRange sa [] = (sa,[])
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
@@ -49,6 +49,7 @@
       , dates   :: [Element]
       , options :: [Option]
       , names   :: [Element]
+      , abbrevs :: [Abbrev]
       } deriving ( Show )
 
 data EvalMode
@@ -128,6 +129,7 @@
 withRefMap :: (ReferenceMap -> a) -> State EvalState a
 withRefMap f = return . f =<< gets ref
 
+-- | Convert variable to lower case, translating underscores ("_") to dashes ("-")
 formatVariable :: String -> String
 formatVariable = foldr f []
     where f x xs = if x == '_' then '-' : xs else toLower x : xs
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
@@ -26,7 +26,7 @@
 import Text.CSL.Parser ( toRead )
 import Text.CSL.Reference
 import Text.CSL.Style
-import Text.Pandoc.Definition ( Inline (Str,EnDash) )
+import Text.Pandoc.Definition ( Inline (Str) )
 
 evalDate :: Element -> State EvalState [Output]
 evalDate (Date s f fm dl dp dp') = do
@@ -100,20 +100,20 @@
       addZero n = if length n == 1 then '0' : n else n
       addZeros  = reverse . take 5 . flip (++) (repeat '0') . reverse
       formatDatePart False (RefDate y m e d _ _) (DatePart n f _ fm)
-          | "year"  <- n, y /= [] = return $ OYear (formatYear  f y) k fm
-          | "month" <- n, m /= [] = output fm      (formatMonth f m)
-          | "day"   <- n, d /= [] = output fm      (formatDay   f d)
+          | "year"  <- n, y /= [] = return $ OYear (formatYear  f    y) k fm
+          | "month" <- n, m /= [] = output fm      (formatMonth f fm m)
+          | "day"   <- n, d /= [] = output fm      (formatDay   f    d)
           | "month" <- n, m == []
                         , e /= [] = output fm $ term f ("season-0" ++ e)
 
       formatDatePart True (RefDate y m e d _ _) (DatePart n f rd fm)
           | "year"  <- n, y /= [] = OYear (formatYear  f y) k (fm {suffix = []}) : formatDelim
-          | "month" <- n, m /= [] = output (fm {suffix = []}) (formatMonth f m) ++ formatDelim
-          | "day"   <- n, d /= [] = output (fm {suffix = []}) (formatDay   f d) ++ formatDelim
+          | "month" <- n, m /= [] = output (fm {suffix = []}) (formatMonth f fm m) ++ formatDelim
+          | "day"   <- n, d /= [] = output (fm {suffix = []}) (formatDay   f    d) ++ formatDelim
           | "month" <- n, m == []
                         , e /= [] = output (fm {suffix = []}) (term f $ "season-0" ++ e) ++ formatDelim
           where
-            formatDelim = if rd == "-" then [OPan [EnDash]] else [OPan [Str rd]]
+            formatDelim = if rd == "-" then [OPan [Str "\x2013"]] else [OPan [Str rd]]
 
       formatDatePart _ (RefDate _ _ _ _ o _) (DatePart n _ _ fm)
           | "year"  <- n, o /= [] = output fm o
@@ -131,12 +131,13 @@
           | otherwise    = y
           where
             iy = readNum y
-      formatMonth f m
-          | "short"   <- f = getMonth fst
+      formatMonth f fm m
+          | "short"   <- f = getMonth $ period . fst
           | "long"    <- f = getMonth fst
           | "numeric" <- f = m
           | otherwise      = addZero m
           where
+            period     = if stripPeriods fm then filter (/= '.') else id
             getMonth g = maybe m g $ lookup ("month-" ++ addZero m, read $ toRead f) tm
       formatDay f d
           | "numeric-leading-zeros" <- f = addZero d
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
@@ -17,7 +17,7 @@
 
 import Control.Applicative ( (<$>) )
 import Control.Monad.State
-import Data.Char  ( toUpper, isLower, isSpace )
+import Data.Char  ( toUpper, isLower, isUpper, isSpace )
 import Data.List  ( nub )
 import Data.Maybe ( isJust )
 
@@ -69,7 +69,7 @@
       agents p s a = concatMapM (formatNames (hasEtAl nl) d p s a) nl
       delim    ops = if d == [] then getOptionVal "names-delimiter" ops else d
       resetEtal    = modify (\s -> s { etal = [] })
-      count  num x = if hasCount nl && num /= []
+      count  num x = if hasCount nl && num /= [] -- FIXME!! le zero!!
                      then [OContrib [] [] [ONum (length num) emptyFormatting] [] []]
                      else x
       hasCount     = or . query hasCount'
@@ -172,19 +172,21 @@
         if isWithLastName o
            then case () of
                   _ | (length as - i) == 1 -> et_al o b t fm d i -- is that correct? FIXME later
-                    | (length as - i) >  1 -> return $ [ODel d, OPan [Ellipses], OSpace] ++ ln
+                    | (length as - i) >  1 -> return $ [ODel d, OPan [Str "\x2026"], OSpace] ++ ln
                     | otherwise            -> return []
            else et_al o b t fm d i
       et_al o b t fm d i
           = when' (gets mode >>= return . not . isSorting) $
             if b || length as <= i
             then return []
-            else case getOptionVal "delimiter-precedes-et-al" o of
-                   "never"  -> return . (++) [OSpace] . output fm =<< getTerm False Long t
-                   "always" -> return . (++) [ODel d] . output fm =<< getTerm False Long t
-                   _        -> if i > 1
-                               then return . (++) [ODel d] . output fm =<< getTerm False Long t
-                               else return . (++) [OSpace] . output fm =<< getTerm False Long t
+            else do x <- getTerm False Long t
+                    when' (return $ x /= []) $
+                          case getOptionVal "delimiter-precedes-et-al" o of
+                            "never"  -> return . (++) [OSpace] $ output fm x
+                            "always" -> return . (++) [ODel d] $ output fm x
+                            _        -> if i > 1
+                                        then return . (++) [ODel d] $ output fm x
+                                        else return . (++) [OSpace] $ output fm x
 
 -- | The first 'Bool' is 'True' if we are evaluating the bibliography.
 -- The 'String' is the cite position. The function also returns the
@@ -223,23 +225,18 @@
                             else getOptionVal' "et-al-use-first" "et-al-subsequent-min"
                     in if null u then 1 else read u
 
-isPlural :: Plural -> Int -> Bool
-isPlural p l
-    = case p of
-        Always     -> True
-        Never      -> False
-        Contextual -> l > 1
-
 -- | Generate the 'Agent's names applying et-al options, with all
 -- possible permutations to disambiguate colliding citations. The
 -- 'Bool' indicate whether we are formatting the first name or not.
 formatName :: EvalMode -> Bool -> Form -> Formatting -> [Option] -> [NamePart] -> Agent -> [Output]
 formatName m b f fm ops np n
-    | Short     <- f = return $ OName (show n)  shortName       disambdata fm
-    | otherwise      = return $ OName (show n) (longName given) disambdata fm
+    | literal n /= [] = return $ OName (show n)  institution     []         fm
+    | Short      <- f = return $ OName (show n)  shortName       disambdata fm
+    | otherwise       = return $ OName (show n) (longName given) disambdata fm
     where
+      institution = [OStr (literal n) $ form "family"]
       when_ c o = if c /= [] then o else []
-      addAffixes s sf ns = [Output ((OStr s (form sf) { prefix = [], suffix = [] }) : ns) $
+      addAffixes s sf ns = [Output ((oStr' s (form sf) { prefix = [], suffix = [] }) ++ ns) $
                                    emptyFormatting { prefix = prefix (form sf)
                                                    , suffix = suffix (form sf)}]
 
@@ -251,13 +248,17 @@
       hyphen    = if getOptionVal "initialize-with-hyphen" ops == "false"
                   then getOptionVal "initialize-with" ops
                   else filter (not . isSpace) $ getOptionVal "initialize-with" ops  ++ "-"
-      initial x = if isJust (lookup "initialize-with" ops)
+      isInit  x = length x == 1 && or (map isUpper x)
+      initial x = if isJust (lookup "initialize-with" ops) &&
+                     getOptionVal "initialize" ops /= "false"
                   then if not . and . map isLower $ x
                        then addIn x $ getOptionVal "initialize-with" ops
                        else " " ++ case x of
                                      _:'\'':[] -> x
                                      _         -> x ++ " "
-                  else " " ++ x
+                  else " " ++ if isJust (lookup "initialize-with" ops) && isInit x
+                              then addIn x $ getOptionVal "initialize-with" ops
+                              else x
       addIn x i = if hasHyphen x
                   then head (       takeWhile (/= '-') x) : hyphen ++
                        head (tail $ dropWhile (/= '-') x) : i
@@ -278,26 +279,27 @@
       givenLong = when_ (givenName  n) . unwords' $ givenName n
       family    = familyName n
 
-      shortName = [OStr (nonDroppingPart n <+> family) (form "family")]
+      shortName = oStr' (nonDroppingPart n <+> family) (form "family")
       longName g = if isSorting m
                    then let firstPart = case getOptionVal "demote-non-dropping-particle" ops of
                                            "never" -> nonDroppingPart n <+> family  <+> droppingPart n
                                            _       -> family  <+> droppingPart n <+> nonDroppingPart n
-                        in [OStr firstPart (form "family")] <++> [OStr g (form "given")] ++ suffCom
+                        in [OStr firstPart (form "family")] <++> oStr' g (form "given") ++ suffCom
                    else if (b && getOptionVal "name-as-sort-order" ops == "first") ||
                            getOptionVal "name-as-sort-order" ops == "all"
                         then let (fam,par) = case getOptionVal "demote-non-dropping-particle" ops of
                                                "never"     -> (nonDroppingPart n <+> family, droppingPart n)
                                                "sort-only" -> (nonDroppingPart n <+> family, droppingPart n)
                                                _           -> (family, droppingPart n <+> nonDroppingPart n)
-                             in OStr fam (form "family") : sortSep g par ++ suffCom
+                             in oStr' fam (form "family") ++ sortSep g par ++ suffCom
                           else oStr' g (form "given") <++>
                                addAffixes (droppingPart n <+> nonDroppingPart n <+> family) "family" suff
 
       disWithGiven = getOptionVal "disambiguate-add-givenname" ops == "true"
-      initialize   = not . null . getOptionVal "initialize-with" $ ops
+      initialize   = isJust . lookup "initialize-with" $ ops
       isLong       = f /= Short && initialize
-      givenRule    = getOptionVal "givenname-disambiguation-rule" ops
+      givenRule    = let gr = getOptionVal "givenname-disambiguation-rule" ops
+                     in if null gr then "by-cite" else gr
       disambdata   = case () of
                        _ | "all-names-with-initials"    <- givenRule
                          , disWithGiven, Short <- f, initialize    -> [longName given]
@@ -323,19 +325,21 @@
 formatLabel f fm p s
     | "locator" <- s = when' (gets (citeLocator . cite . env) >>= return . (/=) []) $ do
                        (l,v) <- getLocVar
-                       format l ('-' `elem` v)
-    | "page"    <- s = when' (isVarSet s) $ do
-                       v <- getStringVar s
-                       format  s ('-' `elem` v)
+                       form (\fm' -> return . flip OLoc emptyFormatting . output fm') id l ('-' `elem` v)
+    | "page"    <- s = checkPlural
+    | "volume"  <- s = checkPlural
     | "ibid"    <- s = format' s p
     | otherwise      = format  s p
     where
-      format      = form id
+      checkPlural = when' (isVarSet s) $ do
+                      v <- getStringVar s
+                      format  s ('-' `elem` v)
+      format      = form output id
       format' t b = gets (citePosition . cite . env) >>= \po ->
                     if po == "ibid-with-locator-c" || po == "ibid-c"
-                    then form capital t b
-                    else form id t b
-      form  g t b = return . output fm =<< g . period <$> getTerm (b && p) f t
+                    then form output capital t b
+                    else format t b
+      form o g t b = return . o fm =<< g . period <$> getTerm (b && p) f t
       period      = if stripPeriods fm then filter (/= '.') else id
       capital   x = toUpper (head x) : (tail x)
 
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
@@ -17,6 +17,7 @@
 
 import Text.CSL.Output.Plain
 import Text.CSL.Style
+import Text.ParserCombinators.Parsec hiding ( State (..) )
 
 output :: Formatting -> String -> [Output]
 output fm s
@@ -38,6 +39,7 @@
           | ONull       <- o     = flatten os
           | Output [] _ <- o     = flatten os
           | OStr []   _ <- o     = flatten os
+          | OUrl []   _ <- o     = flatten os
           | Output xs f <- o
           , f == emptyFormatting = flatten xs ++ flatten os
           | otherwise            = o : flatten os
@@ -66,9 +68,72 @@
 
 oStr' :: String -> Formatting -> [Output]
 oStr' [] _ = []
-oStr' s  f = [OStr s f]
+oStr' s  f = rtfParser f s
 
 (<++>) :: [Output] -> [Output] -> [Output]
 [] <++> o  = o
 o  <++> [] = o
 o1 <++> o2 = o1 ++ [OSpace] ++ o2
+
+rtfTags :: [(String, (String,Formatting))]
+rtfTags =
+    [("b"                      , ("b"   , ef {fontWeight    = "bold"      }))
+    ,("i"                      , ("i"   , ef {fontStyle     = "italic"    }))
+    ,("sc"                     , ("sc"  , ef {fontVariant   = "small-caps"}))
+    ,("sup"                    , ("sup" , ef {verticalAlign = "sup"       }))
+    ,("sub"                    , ("sub" , ef {verticalAlign = "sub"       }))
+    ,("span class=\"nocase\""  , ("span", ef {noCase        = True        }))
+    ,("span class=\"nodecor\"" , ("span", ef {noDecor       = True        }))
+    ]
+    where
+      ef = emptyFormatting
+
+rtfParser :: Formatting -> String -> [Output]
+rtfParser _ [] = []
+rtfParser fm s
+    = either (const [OStr s fm]) (return . flip Output fm . concat) $
+      parse (manyTill parser eof) "" s
+    where
+      parser = parseText <|> parseMarkup
+
+      parseText = do
+        let amper = string "&" >> notFollowedBy (char '#') >>
+                    return [OStr "&" emptyFormatting]
+            apos  = string "'" >> return [OStr "’" emptyFormatting]
+        x  <- many $ noneOf "<'\"`“‘&"
+        xs <- parseQuotes <|> parseMarkup <|> amper <|> apos
+        r  <- manyTill anyChar eof
+        return (OStr x emptyFormatting : xs ++
+                [Output (rtfParser emptyFormatting r) emptyFormatting])
+
+      parseMarkup = do
+        let tillTag = many $ noneOf "<"
+        m   <- string "<" >> manyTill anyChar (try $ string ">")
+        res <- case lookup m rtfTags of
+                 Just tf -> do let ot = "<"  ++ fst tf ++ ">"
+                                   ct = "</" ++ fst tf ++ ">"
+                                   parseGreedy = do a <- tillTag
+                                                    _ <- string ct
+                                                    return a
+                               x <- manyTill anyChar $ try $ string ct
+                               y <- try parseGreedy <|> (string ot >> pzero) <|> return []
+                               let r = if null y then x else x ++ ct ++ y
+                               return [Output (rtfParser emptyFormatting r) (snd tf)]
+                 Nothing -> do r <- tillTag
+                               return [OStr ("<" ++ m ++ ">" ++ r) emptyFormatting]
+        return [Output res emptyFormatting]
+
+      parseQuotes = choice [parseQ "'" "'"
+                           ,parseQ "\"" "\""
+                           ,parseQ "``" "''"
+                           ,parseQ "`" "'"
+                           ,parseQ "“" "”"
+                           ,parseQ "‘" "’"
+                           ,parseQ "&#39;" "&#39;"
+                           ,parseQ "&#34;" "&#34;"
+                           ,parseQ "&quot;" "&quot;"
+                           ,parseQ "&apos;" "&apos;"
+                           ]
+      parseQ a b = try $ do
+        q <- string a >> manyTill anyChar (try $ string b)
+        return [Output (rtfParser emptyFormatting q) (emptyFormatting {quotes = True})]
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
@@ -23,9 +23,10 @@
 import Text.CSL.Reference
 import Text.CSL.Input.Json
 import Text.CSL.Input.MODS
+import Text.JSON.Generic
 
 #ifdef USE_BIBUTILS
-import Control.Exception ( bracket )
+import Control.Exception ( bracket, catch )
 import Control.Monad.Trans ( liftIO )
 import System.FilePath ( (</>), (<.>) )
 import System.IO.Error ( isAlreadyExistsError )
@@ -44,6 +45,7 @@
     = case getExt f of
         ".mods"    -> readBiblioFile' f mods_in
         ".bib"     -> readBiblioFile' f biblatex_in
+        ".bibtex"  -> readBiblioFile' f bibtex_in
         ".ris"     -> readBiblioFile' f ris_in
         ".enl"     -> readBiblioFile' f endnote_in
         ".xml"     -> readBiblioFile' f endnotexml_in
@@ -51,20 +53,23 @@
         ".medline" -> readBiblioFile' f medline_in
         ".copac"   -> readBiblioFile' f copac_in
         ".json"    -> readJsonInput f
+        ".native"  -> readFile f >>= return . decodeJSON
         _          -> error $ "citeproc: the format of the bibliographic database could not be recognized\n" ++
                               "using the file extension."
 
 #else
 readBiblioFile f
-    | ".mods" <- getExt f = readModsCollectionFile f
-    | ".json" <- getExt f = readJsonInput f
-    | otherwise           = error $ "citeproc: Bibliography format not supported.\n" ++
-                                    "citeproc-hs was not compiled with bibutils support."
+    | ".mods"   <- getExt f = readModsCollectionFile f
+    | ".json"   <- getExt f = readJsonInput f
+    | ".native" <- getExt f = readFile f >>= return . decodeJSON
+    | otherwise             = error $ "citeproc: Bibliography format not supported.\n" ++
+                                      "citeproc-hs was not compiled with bibutils support."
 #endif
 
 data BibFormat
     = Mods
     | Json
+    | Native
 #ifdef USE_BIBUTILS
     | Bibtex
     | BibLatex
@@ -80,6 +85,7 @@
 readBiblioString b s
     | Mods      <- b = return $ readXmlString xpModsCollection s
     | Json      <- b = return $ readJsonInputString s
+    | Native    <- b = return $ decodeJSON s
 #ifdef USE_BIBUTILS
     | Bibtex    <- b = go bibtex_in
     | BibLatex  <- b = go biblatex_in
@@ -128,10 +134,10 @@
 createTempDir num baseName = do
   sysTempDir <- getTemporaryDirectory
   let dirName = sysTempDir </> baseName <.> show num
-  liftIO $ catch (createDirectory dirName >> return dirName) $
+  liftIO $ Control.Exception.catch (createDirectory dirName >> return dirName) $
       \e -> if isAlreadyExistsError e
-               then createTempDir (num + 1) baseName
-               else ioError e
+            then createTempDir (num + 1) baseName
+            else ioError e
 #endif
 
 getExt :: String -> String
diff --git a/src/Text/CSL/Input/Json.hs b/src/Text/CSL/Input/Json.hs
--- a/src/Text/CSL/Input/Json.hs
+++ b/src/Text/CSL/Input/Json.hs
@@ -20,6 +20,7 @@
 import Data.Generics
 import Data.Char (toLower, toUpper)
 import Data.List
+import qualified Data.Map as M
 import Data.Ratio
 
 import Text.JSON.Generic
@@ -50,6 +51,15 @@
   let rmCom = unlines . filter (\x -> not (" *" `isPrefixOf` x || "/*" `isPrefixOf` x)) . lines
   in  either error id . runGetJSON readJSTopType . rmCom
 
+readJsonAbbrevFile :: FilePath -> IO [Abbrev]
+readJsonAbbrevFile f = readJsonAbbrev `fmap` readJsonFile f
+
+readJsonAbbrev :: JSValue -> [Abbrev]
+readJsonAbbrev
+    = mapSndObj (mapSndObj (M.fromList . mapSndObj fromJString))
+    where
+      mapSndObj f = map (second f) . fromObj
+
 readJsonCitations :: JSValue -> [Cite]
 readJsonCitations jv
     | JSArray (JSObject o:_) <- jv
@@ -91,8 +101,9 @@
     | "non-dropping-particle" <- s = ("nonDroppingPart", j)
     | "comma-suffix"          <- s = ("commaSuffix", toJSBool j)
     | "id"                    <- s = ("refId"      , toString j)
+    | "shortTitle"            <- s = ("titleShort" , j)
     | isRefDate s
-    , JSObject js <- j = (s            , JSArray (editDate $ fromJSObject js))
+    , JSObject js <- j = (camel s      , JSArray (editDate $ fromJSObject js))
     | "family"    <- s = ("familyName" , j)
     | "suffix"    <- s = ("nameSuffix" , j)
     | "edition"   <- s = ("edition"    , toString j)
@@ -111,7 +122,7 @@
       camel x
           | '-':y:ys <- x = toUpper y : camel ys
           | '_':y:ys <- x = toUpper y : camel ys
-          |     y:ys <- x =         y : camel ys
+          |     y:ys <- x = toLower y : camel ys
           | otherwise     = []
 
       format (x:xs) = toUpper x : xs
@@ -212,6 +223,11 @@
 fromObj :: JSValue -> [(String, JSValue)]
 fromObj (JSObject o) = fromJSObject o
 fromObj _            = []
+
+fromJString :: JSValue -> String
+fromJString j
+    | JSString x <- j = fromJSString x
+    | otherwise       = []
 
 defaultJson :: [(String, JSValue)]
 defaultJson = fromObj (toJSON emptyReference) ++ fromObj emptyRefDate ++
diff --git a/src/Text/CSL/Input/MODS.hs b/src/Text/CSL/Input/MODS.hs
--- a/src/Text/CSL/Input/MODS.hs
+++ b/src/Text/CSL/Input/MODS.hs
@@ -16,16 +16,14 @@
 
 module Text.CSL.Input.MODS where
 
-import Text.CSL.Output.Plain ( (<+>) )
-import Text.CSL.Reference
+import Text.CSL.Eval ( split )
+import Text.CSL.Output.Plain ( (<+>), tail' )
 import Text.CSL.Pickle
+import Text.CSL.Reference
 import Text.CSL.Style ( betterThen )
 
 import Data.Char ( isDigit, isLower )
-
-#ifdef USE_HXT
-import Text.XML.HXT.Arrow.Pickle.Xml
-#endif
+import qualified Data.Map as M
 
 -- | Read a file with a single MODS record.
 readModsFile :: FilePath -> IO Reference
@@ -47,11 +45,11 @@
                 , (ck,ty,ti,i,d)
                 ,((au,ed,tr),(re,it,pu'),(co,ce))
                 ,((di',pg,vl,is),(nu,sc,ch))
-                , (di,pu,pp)
-                , ((ac,uri),no)
+                , (di,ac,pu,pp)
+                , ((ac',uri),no)
                  ) ->
                ref { refId            = ck `betterThen` take 10 (concat $ words ti)
-                   , refType          = if refType ref /= NoType then refType ref else ty
+                   , refType          = if ty == NoType then refType ref else ty
                    , title            = ti
                    , author           = au
                    , editor           = ed `betterThen` editor           ref
@@ -64,10 +62,10 @@
                    , containerAuthor  = containerAuthor  ref
                    , url              = uri
                    , note             = no
-                   , accessed         = ac
                    , isbn             = i
                    , doi              = d
                    , issued           = issued        ref `betterThen` di `betterThen` di'
+                   , accessed         = accessed      ref `betterThen` ac `betterThen` ac'
                    , page             = page          ref `betterThen` pg
                    , volume           = volume        ref `betterThen` vl
                    , issue            = issue         ref `betterThen` is
@@ -85,26 +83,27 @@
                       ,(composer  r, collectionEditor r))
                      ,((issued    r, page  r, volume r, issue r)
                       ,(number    r, section   r, chapterNumber r))
-                     , (issued    r, emptyAgents, publisherPlace r)
+                     , (issued    r, accessed r, emptyAgents, publisherPlace r)
                      ,((accessed  r, url r), note r)
                      )) $
       xp6Tuple (xpDefault emptyReference xpRelatedItem)
                (xp5Tuple  xpCiteKey xpRefType xpTitle xpIsbn xpDoi)
-                xpAgents xpPart xpOrigin
-                (xpPair xpUrl xpNote)
+                xpAgents xpPart xpOrigin (xpPair xpUrl xpNote)
 
 xpCiteKey :: PU String
 xpCiteKey
     = xpDefault [] $
-      xpChoice (xpAttr  "ID"         xpText)
-               (xpIElem "identifier" xpText)
+      xpChoice (xpAttr "ID" xpText)
+               (xpElemWithAttrValue "identifier" "type" "citekey" xpText)
                 xpLift
 
-xpOrigin :: PU ([RefDate],[Agent],String)
+xpOrigin :: PU ([RefDate],[RefDate],[Agent],String)
 xpOrigin
-    = xpDefault ([],[],[]) . xpIElem "originInfo" $
-      xpTriple (xpDefault [] $ xpWrap (readDate,show) $
+    = xpDefault ([],[],[],[]) . xpIElem "originInfo" $
+      xp4Tuple (xpDefault [] $ xpWrap (readDate,show) $
                 xpIElem "dateIssued" xpText0)
+               (xpDefault [] $ xpWrap (readDate,show) $
+                xpIElem "dateCaptured" xpText0)
                (xpDefault [] $ xpList $ xpWrap (\s -> Agent [] [] [] s [] [] False, show) $
                 xpIElem "publisher" xpText0)
                (xpDefault [] $ xpIElem "place" $ xpIElem "placeTerm" xpText0)
@@ -112,26 +111,7 @@
 xpRefType :: PU RefType
 xpRefType
     = xpDefault NoType $
-      xpWrap (readType, const []) xpGenre
-      where
-        readType [] = NoType
-        readType (t:_)
-            | "conference publication" <- t = PaperConference
-            | "periodical"             <- t = ArticleJournal
-            | otherwise                     = Book
-
-xpRefType' :: PU RefType
-xpRefType'
-    = xpDefault NoType $
-      xpWrap (readTypeIn, const []) xpGenre
-      where
-        readTypeIn  [] = NoType
-        readTypeIn t
-            | "book"                   `elem` t = Chapter
-            | "conference publication" `elem` t = PaperConference
-            | "academic journal"       `elem` t = ArticleJournal
-            | "collection"             `elem` t = Chapter
-            | otherwise                         = ArticleJournal
+      xpWrap (readRefType, const []) xpGenre
 
 xpGenre :: PU [String]
 xpGenre
@@ -146,7 +126,7 @@
       xpWrap ( \( (ty,ct)
                 ,((ca,ed,tr),(re,it,pu'),(co,ce))
                 ,((di,pg,vl,is),(nu,sc,ch))
-                , (di',pu,pp)
+                , (di',ac,pu,pp)
                 ) ->
                emptyReference { refType          = ty
                               , containerAuthor  = ca
@@ -160,6 +140,7 @@
                               , composer         = co
                               , collectionEditor = ce
                               , issued           = di `betterThen` di'
+                              , accessed         = ac
                               , page             = pg
                               , volume           = vl
                               , issue            = is
@@ -173,9 +154,9 @@
                       ,(composer        r, collectionEditor r))
                      ,((issued  r, page  r, volume r, issue r)
                       ,(number  r, section   r, chapterNumber r))
-                     , (issued  r, emptyAgents, publisherPlace r)
+                     , (issued  r, accessed  r,emptyAgents, publisherPlace r)
                      )) $
-      xp4Tuple (xpPair  xpRefType' xpTitle)
+      xp4Tuple (xpPair  xpRefType xpTitle)
                 xpAgents xpPart xpOrigin
 
 -- FIXME: join title and subtitle correctly: usare Title per shortTitle.
@@ -314,9 +295,47 @@
 xpNote = xpDefault [] $ xpIElem "note" xpText
 
 readDate :: String -> [RefDate]
-readDate s = if takeWhile isDigit s /= []
-             then return $ RefDate (takeWhile isDigit s) [] [] [] [] []
-             else []
+readDate s = (parseDate         $ takeWhile (/= '/') s) ++
+             (parseDate . tail' $ dropWhile (/= '/') s)
 
+-- | Possible formats: "YYYY", "YYYY-MM", "YYYY-MM-DD".
+parseDate :: String -> [RefDate]
+parseDate s = case split (== '-') (unwords $ words s) of
+                [y,m,d] -> [RefDate y m [] d  [] []]
+                [y,m]   -> [RefDate y m [] [] [] []]
+                [y]     -> if and (map isDigit y)
+                           then [RefDate y  [] [] [] [] []]
+                           else [RefDate [] [] [] [] y  []]
+                _       -> []
+
 emptyAgents :: [Agent]
 emptyAgents  = []
+
+readRefType :: [String] -> RefType
+readRefType [] = NoType
+readRefType (t:_) =
+  case M.lookup t genreTypeMapping of
+    Just x  -> x
+    Nothing -> ArticleJournal       -- Reasonable default (?)
+
+-- The string constants come from http://www.loc.gov/standards/valuelist/marcgt.html, which are used in the
+-- "<genre></genre>" element (http://www.loc.gov/standards/mods/userguide/genre.html)
+genreTypeMapping ::  M.Map String RefType
+genreTypeMapping = M.fromList
+  [ ( "book",                       Book )
+  , ( "periodical",                 ArticleJournal )
+  , ( "newspaper",                  ArticleNewspaper )
+  , ( "encyclopedia",               EntryEncyclopedia )
+  , ( "conference publication",     PaperConference )
+  , ( "academic journal",           ArticleJournal )
+  , ( "collection",                 Chapter )
+  , ( "legal case and case notes",  LegalCase )
+  , ( "legislation",                Legislation )
+  , ( "motion picutre",             MotionPicture )
+  , ( "patent",                     Patent )
+  , ( "review",                     Review )
+  , ( "thesis",                     Thesis )
+  , ( "web page",                   Webpage )
+  , ( "webpage",                    Webpage )
+  , ( "web site",                   Webpage )
+  ]
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
@@ -26,6 +26,7 @@
     ) where
 
 import Data.Char ( toUpper, toLower, isPunctuation )
+import Data.Maybe ( fromMaybe )
 
 import Text.CSL.Style
 import Text.CSL.Output.Plain
@@ -35,19 +36,22 @@
 -- the native 'Pandoc' formats (i.e. immediately readable by pandoc).
 renderPandoc :: Style -> [FormattedOutput] -> [Inline]
 renderPandoc s
-    = proc' (clean s $ isPunctuationInQuote s) . concatMap (flipFlop . render s)
+    = proc (convertQuoted s) . proc' (clean s $ isPunctuationInQuote s) .
+      concatMap (flipFlop . render s)
 
 -- | Same as 'renderPandoc', but the output is wrapped in a pandoc
 -- paragraph block.
 renderPandoc' :: Style -> [FormattedOutput] -> Block
 renderPandoc' s
-    = Para . proc' (clean s $ isPunctuationInQuote s) . concatMap (flipFlop . render s)
+    = Para . proc (convertQuoted s) . proc' (clean s $ isPunctuationInQuote s) .
+      concatMap (flipFlop . render s)
 
 -- | For the testsuite: we use 'Link' and 'Strikeout' to store
 -- "nocase" and "nodecor" rich text formatting classes.
 renderPandoc_ :: Style -> [FormattedOutput] -> [Inline]
 renderPandoc_ s
-    = proc (clean' s $ isPunctuationInQuote s) . concatMap (flipFlop . render s)
+    = proc (convertQuoted s) . proc (clean' s $ isPunctuationInQuote s) .
+      concatMap (flipFlop . render s)
 
 render :: Style -> FormattedOutput -> [Inline]
 render _ (FPan i) = i
@@ -56,14 +60,16 @@
     | FS str fm    <- fo = toPandoc fm $ toStr str
     | FN str fm    <- fo = toPandoc fm $ toStr $ rmZeros str
     | FO     fm xs <- fo = toPandoc fm $ rest xs
+    | FUrl u fm    <- fo = toPandoc fm [Link (toStr u) (u,u)]
     | otherwise = []
     where
       addSuffix f i
           | suffix f /= []
-          , elem (head $ suffix f) ",.:?!"
-          , [head $ suffix f] == lastInline i = i ++ toStr (tail $ suffix f)
-          | suffix f /= []                    = i ++ toStr (       suffix f)
-          | otherwise                         = i
+          , elem (head $ suffix f) ".?!"
+          , lastInline i /= []
+          , last (lastInline i)`elem` ".?!" = i ++ toStr (tail $ suffix f)
+          | suffix f /= []                  = i ++ toStr (       suffix f)
+          | otherwise                       = i
 
       toPandoc f i = addSuffix f $ toStr (prefix f) ++
                      (format f . quote f . proc cleanStrict $ i)
@@ -72,7 +78,6 @@
       quote    f i = if i /= [] && quotes f
                      then [Quoted DoubleQuote . valign f $ i]
                      else valign f i
-
       setCase f i
           | Str     s <- i = Str $ f s
           | otherwise      = i
@@ -121,9 +126,15 @@
 toStr = toStr' . entityToChar
     where
       toStr' s
+          |'«':' ':xs <- s = toStr' ("«\8239" ++ xs)
+          |' ':'»':xs <- s = toStr' ("\8239»" ++ xs)
+          |' ':';':xs <- s = toStr' ("\8239;" ++ xs)
+          |' ':':':xs <- s = toStr' ("\8239:" ++ xs)
+          |' ':'!':xs <- s = toStr' ("\8239!" ++ xs)
+          |' ':'?':xs <- s = toStr' ("\8239?" ++ xs)
           |' ':xs <- s = Space   : toStr' xs
           | x :xs <- s = Str [x] : toStr' xs
-          | otherwise   = []
+          | otherwise  = []
 
 cleanStrict :: [Inline] -> [Inline]
 cleanStrict []  = []
@@ -142,8 +153,8 @@
     | SmallCaps   x <- i = split (isLink  "nodecor" ) (return . SmallCaps  ) x ++ clean s b is
     | Emph        x <- i = split (isLink' "emph"    ) (return . Emph       ) x ++ clean s b is
     | Strong      x <- i = split (isLink' "strong"  ) (return . Strong     ) x ++ clean s b is
-    | Link      x _ <- i = clean' s b (x ++ clean s b is)
-    | otherwise          = clean' s b (i :  clean s b is)
+    | Link      x t <- i = clean' s b (Link x t : clean s b is)
+    | otherwise          = clean' s b (i        : clean s b is)
     where
       unwrap f ls
           | Link x _ : _ <- ls = clean' s b x
@@ -219,6 +230,21 @@
 endWithPunct, startWithPunct :: [Inline] -> Bool
 endWithPunct   = and . map (`elem` ".,;:!?") . lastInline
 startWithPunct = and . map (`elem` ".,;:!?") . headInline
+
+convertQuoted :: Style -> [Inline] -> [Inline]
+convertQuoted s = proc convertQuoted'
+    where
+      locale = let l = styleLocale s in case l of [x] -> x; _   -> Locale [] [] [] [] []
+      getQuote  x y = entityToChar . fst . fromMaybe (x,[]) . lookup (y,Long) . localeTermMap $ locale
+      doubleQuotesO = getQuote "\"" "open-quote"
+      doubleQuotesC = getQuote "\"" "close-quote"
+      singleQuotesO = getQuote "'"  "open-inner-quote"
+      singleQuotesC = getQuote "'"  "close-inner-quote"
+      convertQuoted' o
+          | (Quoted DoubleQuote t:xs) <- o = Str doubleQuotesO : t ++ Str doubleQuotesC : convertQuoted' xs
+          | (Quoted SingleQuote t:xs) <- o = Str singleQuotesO : t ++ Str singleQuotesC : convertQuoted' xs
+          | (x                   :xs) <- o = x : convertQuoted' xs
+          | otherwise                      = []
 
 headInline :: [Inline] -> String
 headInline [] = []
diff --git a/src/Text/CSL/Output/Plain.hs b/src/Text/CSL/Output/Plain.hs
--- a/src/Text/CSL/Output/Plain.hs
+++ b/src/Text/CSL/Output/Plain.hs
@@ -89,8 +89,13 @@
     | x      :xs <- s = x : entityToChar xs
     | otherwise       = []
     where
-      parseEntity  = chr . read . takeWhile isDigit &&&
+      parseEntity  = chr . readNum . takeWhile (/= ';') &&&
                      entityToChar . tail' . dropWhile (/= ';')
+      readNum ('x': n) = readNum $ "0x" ++ n
+      readNum       n  = case readsPrec 1 n of
+                           [(x,[])] -> x
+                           _        -> error $ "Invalid character entity:" ++ n
+
 
 head' :: [a] -> [a]
 head' = foldr (\x _ -> [x]) []
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
@@ -257,8 +257,8 @@
 
 xpStyle :: PU Style
 xpStyle
-    = xpWrap ( \ ((v,sc,si,sl,l),(o,m,c,b))   -> Style v sc si sl l o m c b
-             , \ (Style v sc si sl l o m c b) -> ((v,sc,si,sl,l),(o,m,c,b))) $
+    = xpWrap ( \ ((v,sc,si,sl,l),(o,m,c,b))   -> Style v sc si sl l [] o m c b
+             , \ (Style v sc si sl l _ o m c b) -> ((v,sc,si,sl,l),(o,m,c,b))) $
       xpIElem "style" $
       xpPair (xp5Tuple (xpAttrText "version")
                        (xpAttrText "class")
@@ -321,16 +321,18 @@
 
 xpNameFormat :: PU [Option]
 xpNameFormat
-    = xpWrap (\(a,b,c,d,e) ->
+    = xpWrap (\(a,b,c,d,e,f) ->
                   catMaybes [ checkOpt "and"                     a
                             , checkOpt "delimiter-precedes-last" b
                             , checkOpt "sort-separator"          c
-                            , checkOpt "initialize-with"         d
-                            , checkOpt "name-as-sort-order"      e
-                            ] , const (Nothing, Nothing, Nothing, Nothing, Nothing)) $
-      xp5Tuple (getOpt "and")
+                            , checkOpt "initialize"              d
+                            , checkOpt "initialize-with"         e
+                            , checkOpt "name-as-sort-order"      f
+                            ] , const (Nothing, Nothing, Nothing, Nothing, Nothing, Nothing)) $
+      xp6Tuple (getOpt "and")
                (getOpt "delimiter-precedes-last")
                (getOpt "sort-separator")
+               (getOpt "initialize")
                (getOpt "initialize-with")
                (getOpt "name-as-sort-order")
 
diff --git a/src/Text/CSL/Pickle.hs b/src/Text/CSL/Pickle.hs
--- a/src/Text/CSL/Pickle.hs
+++ b/src/Text/CSL/Pickle.hs
@@ -351,7 +351,7 @@
 	    return (Just res, st)
 
 xpElemWithAttrValue :: String -> String -> String -> PU a -> PU a
-xpElemWithAttrValue n a v = xpElem n . xpAddFixedAttr a v
+xpElemWithAttrValue n a v = xpIElem n . xpAddFixedAttr a v
 
 xpAttrFixed	:: String -> String -> PU ()
 xpAttrFixed name val
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
@@ -17,10 +17,11 @@
 module Text.CSL.Proc where
 
 import Control.Arrow ( (&&&), (>>>), second )
+import Data.Char ( toLower )
 import Data.List
 import Data.Ord  ( comparing )
 
-import Text.CSL.Eval
+import Text.CSL.Eval hiding ( trim )
 import Text.CSL.Output.Plain
 import Text.CSL.Parser
 import Text.CSL.Proc.Collapse
@@ -81,12 +82,12 @@
 -- according to the 'Style' and assign the citation number to each
 -- 'Reference'.
 procRefs :: Style -> [Reference] -> [Reference]
-procRefs (Style {biblio = mb, csMacros = ms , styleLocale = l, csOptions = opts}) rs
+procRefs (Style {biblio = mb, csMacros = ms , styleLocale = l, styleAbbrevs = as, csOptions = opts}) rs
     = maybe rs process mb
     where
       opts'   b = mergeOptions (bibOptions b) opts
       citNum  x = x { citationNumber = maybe 0 ((+) 1 . fromIntegral) . elemIndex x $ rs }
-      sort_   b = evalSorting (EvalSorting emptyCite {citePosition = "first"})l ms (opts' b) (bibSort b)
+      sort_   b = evalSorting (EvalSorting emptyCite {citePosition = "first"})l ms (opts' b) (bibSort b) as
       process b = sortItems . map (citNum &&& sort_ b) $ rs
 
 sortItems :: Show a => [(a,[Sorting])] -> [a]
@@ -106,12 +107,14 @@
 -- | With a 'Style' and a sorted list of 'Reference's produce the
 -- evaluated output for the bibliography.
 procBiblio :: BibOpts -> Style -> [Reference] -> [[Output]]
-procBiblio bos (Style {biblio = mb, csMacros = ms , styleLocale = l, csOptions = opts}) rs
+procBiblio bos (Style {biblio = mb, csMacros = ms , styleLocale = l,
+                       styleAbbrevs = as, csOptions = opts}) rs
     = maybe [] process mb
     where
       render  b = map (format b) . chkAut [] . filterRefs bos $ rs
       process b = flip map (render b) $ uncurry formatBiblioLayout (layFormat &&& layDelim $ bibLayout b)
-      format  b (p,r) = evalLayout (bibLayout b) (EvalBiblio p) False l ms (mergeOptions (bibOptions b) opts) r
+      format  b (p,r) = evalLayout (bibLayout b) (EvalBiblio p) False l ms
+                                   (mergeOptions (bibOptions b) opts) as r
       chkAut _ []     = []
       chkAut a (x:xs) = if author x `elem` a
                         then ("subsequent",x) : chkAut             a  xs
@@ -143,22 +146,25 @@
                               | Just v' <- (fromValue x :: Maybe [RefDate]) -> v == [] && v' == [] || v == show v'
                        _                                                    -> False
 
--- | Given the CSL 'Style' and the list of 'Reference's coupled with
--- their position, generate a 'CitationGroup'. The citations are
--- sorted according to the 'Style'.
+-- | Given the CSL 'Style' and the list of 'Cite's coupled with their
+-- 'Reference's, generate a 'CitationGroup'. The citations are sorted
+-- according to the 'Style'.
 procGroup :: Style -> [(Cite, Reference)] -> CitationGroup
-procGroup (Style {citation = ct, csMacros = ms , styleLocale = l, csOptions = opts}) cr
-    = CG authInTxt (layFormat $ citLayout ct) (layDelim $ citLayout ct) result
+procGroup (Style {citation = ct, csMacros = ms , styleLocale = l,
+                  styleAbbrevs = as, csOptions = opts}) cr
+    = CG authIn (layFormat $ citLayout ct) (layDelim $ citLayout ct) (authIn ++ co)
     where
-      authInTxt    = case cr of
+      (co, authIn) = case cr of
                        (c:_) -> if authorInText (fst c)
-                                then foldr (\x _ -> [x]) [] $
-                                     filter ((==) (citeId $ fst c) . citeId . fst) result
-                                else []
-                       _     -> []
+                                then (,) (filter (eqCites (/=) c) $ result
+                                         ) . foldr (\x _ -> [x]) [] .
+                                          filter (eqCites (==) c) $ result
+                                else (,) result []
+                       _     -> (,) result []
+      eqCites eq c = fst >>> citeId &&& citeHash >>> eq (citeId &&& citeHash $ fst c)
       opts'        = mergeOptions (citOptions ct) opts
-      format (c,r) = (,) c $ evalLayout (citLayout ct) (EvalCite c) False l ms opts' r
-      sort_  (c,r) = evalSorting (EvalSorting c) l ms opts' (citSort ct) r
+      format (c,r) = (,) c $ evalLayout (citLayout ct) (EvalCite c) False l ms opts' as r
+      sort_  (c,r) = evalSorting (EvalSorting c) l ms opts' (citSort ct) as r
       process      = map (second (flip Output emptyFormatting) . format &&& sort_)
       result       = sortItems $ process cr
 
@@ -167,35 +173,20 @@
 
 formatCitLayout :: Style -> CitationGroup -> [FormattedOutput]
 formatCitLayout s (CG co f d cs)
-    | [a] <- co = formatAuth a : formatCits (setAsSupAu . citeHash . fst $ a) cs
+    | [a] <- co = formatAuth a : formatCits (fst >>> citeId &&& citeHash >>> setAsSupAu $ a) cs
     | otherwise = formatCits id cs
     where
       formatAuth   = formatOutput . localMod
       formatCits g = formatOutputList . appendOutput formatting . addAffixes f .
-                     addDelim d . map (fst &&& localMod >>> uncurry format) . g
-      formatting   = if co /= []
-                     then emptyFormatting
-                     else unsetAffixes f
+                     addDelim d . map (fst &&& localMod >>> uncurry addCiteAffixes) . g
+      formatting   = unsetAffixes f
       localMod     = if cs /= []
                      then uncurry $ localModifiers s (co /= [])
                      else snd
-      setAsSupAu h = map $ \(c,o) -> if citeHash c == h
+      setAsSupAu h = map $ \(c,o) -> if (citeId c, citeHash c) == h
                                      then flip (,) o c { authorInText   = False
                                                        , suppressAuthor = True }
                                      else flip (,) o c
-      format c x = if isNumStyle [x]
-                   then x
-                   else flip Output emptyFormatting $
-                             addCiteAff citePrefix True  c ++ [x] ++
-                             addCiteAff citeSuffix False c
-      addCiteAff g x c =
-          case g c of
-            PlainText  []    -> []
-            PlainText  p | x -> [Output (rtfParser emptyFormatting p) emptyFormatting, OSpace]
-            PlainText  p     -> [OSpace, Output (rtfParser emptyFormatting p) emptyFormatting]
-            PandocText []    -> []
-            PandocText p | x -> [OPan p, OSpace]
-            PandocText p     -> [OPan p]
 
 addAffixes :: Formatting -> [Output] -> [Output]
 addAffixes f os
@@ -238,6 +229,8 @@
           | otherwise        = [True]
       trim [] = []
       trim (o:os)
+          | Output ot f <- o, p <- prefix f,  p /= []
+          , isPunct p         = trim $ Output ot f { prefix = []} : os
           | Output ot f <- o  = if or (query hasOutput ot)
                                 then Output (trim ot) f : os
                                 else Output       ot  f : trim os
@@ -259,29 +252,39 @@
           | OContrib _ "authorsub"
                   _ _ _ <- o = o
           | Output ot f <- o = Output (cleanOutput $ map contribOnly ot) f
+          | OStr    x _ <- o
+          , "ibid" <- filter (/= '.')
+             (map toLower x) = o
           | otherwise        = ONull
+      rmCitNum o
+          | OCitNum {} <- o = ONull
+          | otherwise       = o
       rmContrib [] = []
       rmContrib o
-          | b, isNumStyle o = []
-      rmContrib (o:os)
-          | Output ot f <- o = Output (rmContrib ot) f : rmContrib os
+          | b, isNumStyle o = proc rmCitNum o
+          | otherwise       = rmContrib' o
+      rmContrib' [] = []
+      rmContrib' (o:os)
+          | Output ot f <- o = Output (rmContrib' ot) f : rmContrib' os
+          | ODel _ <- o
+          , OContrib _ "author"
+                     _ _ _ : xs <- os = rmContrib' xs
+          | ODel _ <- o
+          , OContrib _ "authorsub"
+                     _ _ _ : xs <- os = rmContrib' xs
+          | OContrib _ "author" _ _ _ <- o
+          , ODel _ : xs <- os =     rmContrib' xs
+          | OContrib _ "authorsub" _ _ _ <- o
+          , ODel _ : xs <- os =     rmContrib' xs
           | OContrib _ "author"
-                  _ _ _ <- o =        rmContrib os
+                  _ _ _ <- o =     rmContrib' os
           | OContrib _ "authorsub"
-                  _ _ _ <- o =        rmContrib os
-          | otherwise        = o :    rmContrib os
+                  _ _ _ <- o =     rmContrib' os
+          | OStr x _ <- o
+          , "ibid" <- filter (/= '.') (map toLower x) = rmContrib' os
+
+          | otherwise        = o : rmContrib' os
       getRefTerm :: TermMap -> String
       getRefTerm t
           | (("reference", Long), (x,_)) <- t = capitalize x
           | otherwise                         = []
-
-isNumStyle :: [Output] -> Bool
-isNumStyle = null . query authorOrDate
-    where
-      authorOrDate o
-          | OContrib {} <- o = ['a']
-          | OYear    {} <- o = ['a']
-          | OYearSuf {} <- o = ['a']
-          | OStr     {} <- o = ['a']
-          | OPan     {} <- o = ['a']
-          | otherwise        = []
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
@@ -16,13 +16,14 @@
 
 module Text.CSL.Proc.Collapse where
 
-import Control.Arrow ( (&&&), (>>>) )
+import Control.Arrow ( (&&&), (>>>), second )
 import Data.Char
 import Data.List ( groupBy )
 
 import Text.CSL.Eval
 import Text.CSL.Proc.Disamb
 import Text.CSL.Style
+import Text.Pandoc.Definition ( Inline (Str) )
 
 -- | Collapse citations according to the style options.
 collapseCitGroups :: Style -> [CitationGroup] -> [CitationGroup]
@@ -42,23 +43,31 @@
     = map snd . filter ((==) "collapse" . fst) . citOptions . citation
 
 collapseNumber :: CitationGroup -> CitationGroup
-collapseNumber = mapCitationGroup process
+collapseNumber cg
+    | CG [a] f d os <- cg = mapCitationGroup process . CG [a] f d $ tail' os
+    | otherwise           = mapCitationGroup process cg
     where
+      tail' x = if length x > 1 then tail x else x
+      hasLocator = or . query hasLocator'
+      hasLocator' o
+          | OLoc _ _ <- o = [True]
+          | otherwise     = [False]
       citNum o
           | OCitNum i f <- o = [(i,f)]
           | otherwise        = []
-      numOf   = foldr (\x _ -> x) (0,emptyFormatting) . query citNum
-      newNum  = map numOf >>> (map fst >>> groupConsec) &&& map snd >>> uncurry zip
-      process xs = flip concatMap (newNum xs) $
+      numOf  = foldr (\x _ -> x) (0,emptyFormatting) . query citNum
+      newNum = map numOf >>> (map fst >>> groupConsec) &&& map snd >>> uncurry zip
+      process xs = if  hasLocator xs then xs else
+                   flip concatMap (newNum xs) $
                    \(x,f) -> if length x > 2
                              then return $ Output [ OCitNum (head x) f
-                                                  , ODel "-"
+                                                  , OPan [Str "\x2013"]
                                                   , OCitNum (last x) f
                                                   ] emptyFormatting
                              else map (flip OCitNum f) x
 
 collapseYear :: Style -> String -> CitationGroup -> CitationGroup
-collapseYear s ranged (CG cs f d os) = CG cs f [] [(emptyCite, process $ map snd os)]
+collapseYear s ranged (CG cs f d os) = CG cs f [] (process os)
     where
       styleYSD    = getOptionVal "year-suffix-delimiter"    . citOptions . citation $ s
       yearSufDel  = styleYSD `betterThen` (layDelim . citLayout . citation $ s)
@@ -67,31 +76,46 @@
 
       format []     = []
       format (x:xs) = x : map getYearAndSuf xs
-      getYearAndSuf x = case  query getOYear x of
+      getYearAndSuf x = case query getOYear x of
                           [] -> noOutputError
                           x' -> Output x' emptyFormatting
       getOYear o
-          | OYear    {} <- o = [o]
-          | OYearSuf {} <- o = [o]
-          | OPan     {} <- o = [o]
-          | otherwise        = []
+          | OYear    {} : _ <- o = [head o]
+          | OYearSuf {} : _ <- o = [head o]
+          | OPan     {} : _ <- o = [head o]
+          | OLoc     {} : _ <- o = [head o]
+          | ODel _ : OLoc {} : _ <- o = [head o]
+          | otherwise = []
 
       isRanged = case ranged of
                    "year-suffix-ranged" -> True
                    _                    -> False
-      collapsYS xs = if length xs < 2 || null ranged
-                     then xs
-                     else collapseYearSuf isRanged yearSufDel xs
-      addDelimiter []     = []
-      addDelimiter (x:[]) = [addDelim d x]
-      addDelimiter (x:xs) = if length x > 1
-                            then (addDelim d x ++ [ODel afterColDel]) : addDelimiter xs
-                            else (addDelim d x ++ [ODel d          ]) : addDelimiter xs
-      namesOf = map (fst . snd) . getNamesYear True
-      process = flip Output emptyFormatting . concat . addDelimiter .
-                map (collapsYS . format) . groupBy (\a b -> namesOf a == namesOf b)
 
-collapseYearSuf :: Bool -> String -> [Output] -> [Output]
+      collapseRange = if null ranged then map (uncurry addCiteAffixes)
+                      else collapseYearSuf isRanged yearSufDel
+
+      rmAffixes x = x {citePrefix = emptyAffix, citeSuffix = emptyAffix}
+      collapsYS a = case a of
+                      []  -> (emptyCite, ONull)
+                      [x] -> rmAffixes . fst &&& uncurry addCiteAffixes $ x
+                      _   -> (,) (rmAffixes $ fst $ head a) . flip Output emptyFormatting .
+                             addDelim d . collapseRange .
+                             uncurry zip . second format . unzip $ a
+
+      doCollapse []     = []
+      doCollapse (x:[]) = [collapsYS x]
+      doCollapse (x:xs) = let (a,b) = collapsYS x
+                          in if length x > 1
+                             then (a, Output (b : [ODel afterColDel]) emptyFormatting) : doCollapse xs
+                             else (a, Output (b : [ODel d          ]) emptyFormatting) : doCollapse xs
+
+      contribsQ o
+          | OContrib _ _ c _ _ <- o = [c]
+          | otherwise               = []
+      namesOf = query contribsQ
+      process = doCollapse . groupBy (\a b -> namesOf (snd a) == namesOf (snd b))
+
+collapseYearSuf :: Bool -> String -> [(Cite,Output)] -> [Output]
 collapseYearSuf ranged ysd = process
     where
       yearOf  = concat . query getYear
@@ -100,13 +124,25 @@
           | otherwise        = []
 
       processYS = if ranged then collapseYearSufRanged else id
-      process = map (flip Output emptyFormatting . getYS) .
-                groupBy (\a b -> yearOf a == yearOf b)
+      process = map (flip Output emptyFormatting . getYS) . groupBy comp
 
+      checkAffix (PlainText  []) = True
+      checkAffix (PandocText []) = True
+      checkAffix _               = False
+
+      comp a b = yearOf (snd a) == yearOf (snd b) &&
+                 checkAffix (citePrefix $ fst a) &&
+                 checkAffix (citeSuffix $ fst a) &&
+                 checkAffix (citePrefix $ fst b) &&
+                 checkAffix (citeSuffix $ fst b) &&
+                 null (citeLocator $ fst a) &&
+                 null (citeLocator $ fst b)
+
       getYS []     = []
+      getYS (x:[]) = return $ uncurry addCiteAffixes x
       getYS (x:xs) = if ranged
-                     then proc rmOYearSuf x : addDelim ysd (processYS $ x : query rmOYear xs)
-                     else addDelim ysd  $ x : (processYS $ query rmOYear xs)
+                     then proc rmOYearSuf (snd x) : addDelim ysd (processYS $ (snd x) : query rmOYear (map snd xs))
+                     else addDelim ysd  $ (snd x) : (processYS $ query rmOYear (map snd xs))
       rmOYearSuf o
           | OYearSuf {} <- o = ONull
           | otherwise        = o
@@ -125,10 +161,40 @@
       process xs = flip concatMap (newSuf xs) $
                    \(x,f) -> if length x > 2
                              then return $ Output [ OStr [chr $ head x] f
-                                                  , ODel "-"
+                                                  , OPan [Str "\x2013"]
                                                   , OStr [chr $ last x] f
                                                   ] emptyFormatting
                              else map (\y -> if y == 0 then ONull else flip OStr f . return . chr $ y) x
+
+addCiteAffixes :: Cite -> Output -> Output
+addCiteAffixes = format
+    where
+      format c x = if isNumStyle [x]
+                   then x
+                   else flip Output emptyFormatting $
+                             addCiteAff citePrefix True  c ++ [x] ++
+                             addCiteAff citeSuffix False c
+      addCiteAff g x c =
+          case g c of
+            PlainText  []    -> []
+            PlainText  p | x -> [Output (rtfParser emptyFormatting p) emptyFormatting, OSpace]
+            PlainText  p     -> [Output (rtfParser emptyFormatting p) emptyFormatting]
+            PandocText []    -> []
+            PandocText p | x -> [OPan p, OSpace]
+            PandocText p     -> [OPan p]
+
+isNumStyle :: [Output] -> Bool
+isNumStyle = null . query authorOrDate . proc rmLocator
+    where
+      rmLocator o
+          | OLoc     {} <- o = ONull
+          | otherwise        = o
+      authorOrDate o
+          | OContrib {} <- o = ['a']
+          | OYear    {} <- o = ['a']
+          | OYearSuf {} <- o = ['a']
+          | OStr     {} <- o = ['a']
+          | otherwise        = []
 
 -- | Group consecutive integers:
 --
diff --git a/src/Text/CSL/Proc/Disamb.hs b/src/Text/CSL/Proc/Disamb.hs
--- a/src/Text/CSL/Proc/Disamb.hs
+++ b/src/Text/CSL/Proc/Disamb.hs
@@ -20,8 +20,8 @@
 
 import Control.Arrow ( (&&&), (>>>), second )
 import Data.Char ( chr )
-import Data.List ( elemIndex, find, findIndex, sortBy, mapAccumL
-                 , nub, groupBy, isPrefixOf )
+import Data.List ( elemIndex, elemIndices, find, findIndex, sortBy, mapAccumL
+                 , nub, nubBy, groupBy, isPrefixOf )
 import Data.Maybe
 import Data.Ord ( comparing )
 
@@ -47,23 +47,29 @@
       -- name data of name duplicates
       nameDupls = getDuplNameData groups
       -- citation data of ambiguous cites
-      duplics   = getDuplCiteData hasNamesOpt $ addGName groups
+      duplics   = getDuplCiteData hasNamesOpt hasYSuffOpt groups
 
       -- check the options set in the style
-      --isByCite = getOptionVal "givenname-disambiguation-rule" (citOptions . citation $ s) == "by-cite"
-      disOpts  = getCitDisambOptions s
+      isByCite = let gno = getOptionVal "givenname-disambiguation-rule" (citOptions $ citation s)
+                 in  gno == "by-cite" || gno == []
+      disOpts     = getCitDisambOptions s
       hasNamesOpt = "disambiguate-add-names"       `elem` disOpts
       hasGNameOpt = "disambiguate-add-givenname"   `elem` disOpts
       hasYSuffOpt = "disambiguate-add-year-suffix" `elem` disOpts
+      givenNames = if hasGNameOpt
+                   then if isByCite then ByCite else AllNames
+                   else NoGiven
 
-      withNames = flip map duplics $ same . proc rmNameHash . proc rmGivenNames .
+      clean     = if hasGNameOpt then id else proc rmNameHash . proc rmGivenNames
+      withNames = flip map duplics $ same . clean .
                   map (if hasNamesOpt then disambData else return . disambYS)
 
-      needNames = filter_ (not . snd) $ zip (map disambAddNames duplics) withNames
-      needYSuff = filter_        snd  $ zip (map disambAddLast  duplics) withNames
+      needNames = filter_ (not . snd) $ zip duplics withNames
+      needYSuff = filter_        snd  $ zip duplics withNames
 
       newNames :: [CiteData]
-      newNames  = when_ hasNamesOpt $ needNames ++ needYSuff
+      newNames  = when_ (hasNamesOpt || hasGNameOpt) $ disambAddNames givenNames $ needNames ++
+                  if hasYSuffOpt && givenNames == NoGiven then [] else needYSuff
 
       newGName :: [NameData]
       newGName  = when_ hasGNameOpt $ concatMap disambAddGivenNames nameDupls
@@ -76,38 +82,44 @@
                     then map (uncurry $ reEvaluate s reEval) $ zip refs groups
                     else groups
 
-      addGName  = proc (updateOutput []       newGName)
-      addNames  = proc (updateOutput newNames newGName)
-
       withYearS = if hasYSuffOpt
                   then map (mapCitationGroup $ setYearSuffCollision hasNamesOpt needYSuff) $ reEvaluated
                   else rmYearSuff $ reEvaluated
 
       yearSuffs = when_ hasYSuffOpt . generateYearSuffix bibs . query getYearSuffixes $ withYearS
 
+      addNames  = proc (updateContrib givenNames newNames newGName)
       processed = if hasYSuffOpt
                   then proc (updateYearSuffixes yearSuffs) .
                        addNames $ withYearS
                   else addNames $ withYearS
 
-      citOutput = if disOpts /= [] then processed else groups
+      citOutput = if disOpts /= [] then processed else reEvaluated
 
 mapDisambData :: (Output -> Output) -> CiteData -> CiteData
-mapDisambData f (CD k c ys d r y) = CD k c ys (proc f d) r y
+mapDisambData f (CD k c ys d r s y) = CD k c ys (proc f d) r s y
 
 mapCitationGroup :: ([Output] -> [Output]) -> CitationGroup ->  CitationGroup
 mapCitationGroup f (CG cs fm d os) = CG cs fm d (zip (map fst os) . f $ map snd os)
 
-disambAddNames :: [CiteData] -> [CiteData]
-disambAddNames needName = addLNames
-    where
-      disSolved = zip needName (disambiguate $ map disambData needName)
-      addLNames = map (\(c,n) -> c { disambed = if null n then collision c else head n }) disSolved
+data GiveNameDisambiguation
+    = NoGiven
+    | ByCite
+    | AllNames
+    deriving (Show, Eq)
 
-disambAddLast :: [CiteData] -> [CiteData]
-disambAddLast = map last_
+disambAddNames :: GiveNameDisambiguation -> [CiteData] -> [CiteData]
+disambAddNames b needName = addLNames
     where
-      last_ c = c { disambed   = if disambData c /= [] then last $ disambData c else collision  c }
+      clean     = if b == NoGiven then proc rmNameHash . proc rmGivenNames else id
+      disSolved = zip needName' . disambiguate . map disambData $ needName'
+      needName' = nub' needName []
+      addLNames = map (\(c,n) -> c { disambed = if null n then collision c else head n }) disSolved
+      nub' []     r = r
+      nub' (x:xs) r = case elemIndex (disambData $ clean x) (map (disambData . clean) r) of
+                         Nothing -> nub' xs (x:r)
+                         Just i  -> let y = r !! i
+                                    in nub' xs (y {sameAs = key x : sameAs y} : filter (/= y) r)
 
 disambAddGivenNames :: [NameData] -> [NameData]
 disambAddGivenNames needName = addGName
@@ -115,17 +127,23 @@
       disSolved = zip needName (disambiguate $ map nameDisambData needName)
       addGName = map (\(c,n) -> c { nameDataSolved = if null n then nameCollision c else head n }) disSolved
 
--- | Given the list of 'CiteData' with the disambiguated field set
--- update the evaluated citations by setting the contributor list
--- accordingly.
-updateOutput :: [CiteData] -> [NameData] -> Output -> Output
-updateOutput c n o
-    | OContrib k r x  _ d <- o = case elemIndex (CD k (clean x) [] [] [] []) c of
-                                   Just i -> OContrib k r (disambed $ c !! i) [] d
-                                   _      -> o
+updateContrib :: GiveNameDisambiguation -> [CiteData] -> [NameData] -> Output -> Output
+updateContrib g c n o
+    | OContrib k r s d dd <- o = case filter (key &&& sameAs >>> uncurry (:) >>> elem k) c of
+                                  x:_ | clean (disambData x) == clean (d:dd) ->
+                                          OContrib k r (map processGNames $ disambed x) [] dd
+                                  _ | null c, AllNames <- g -> OContrib k r (map processGNames s) d dd
+                                    | otherwise             -> o
+    | otherwise = o
+    where
+      clean         = if g == NoGiven then proc rmNameHash . proc rmGivenNames else id
+      processGNames = if g /= NoGiven then updateOName n else id
+
+updateOName :: [NameData] -> Output -> Output
+updateOName n o
     | OName _ _ [] _ <- o = o
     | OName k x _  f <- o = case elemIndex (ND k (clean x) [] []) n of
-                              Just i -> OName k (nameDataSolved $ n !! i) [] f
+                              Just i -> OName [] (nameDataSolved $ n !! i) [] f
                               _      -> o
     | otherwise           = o
     where
@@ -135,11 +153,12 @@
 -- field set to 'True' (for matching the @\"disambiguate\"@
 -- condition).
 reEvaluate :: Style -> [CiteData] -> [(Cite, Reference)] -> CitationGroup -> CitationGroup
-reEvaluate (Style {citation = ct, csMacros = ms , styleLocale = lo}) l cr (CG a f d os)
+reEvaluate (Style {citation = ct, csMacros = ms , styleLocale = lo,
+                   styleAbbrevs = as}) l cr (CG a f d os)
     = CG a f d . flip concatMap (zip cr os) $
       \((c,r),out) -> if refId r `elem` map key l
                       then return . second (flip Output emptyFormatting) $
-                           (,) c $ evalLayout (citLayout ct) (EvalCite c) True lo ms (citOptions ct) r
+                           (,) c $ evalLayout (citLayout ct) (EvalCite c) True lo ms (citOptions ct) as r
                       else [out]
 
 -- | Check if the 'Style' has any conditional for disambiguation. In
@@ -159,28 +178,46 @@
       filter (isPrefixOf "disambiguate" . fst) . citOptions . citation
 
 -- | Group citation data (with possible alternative names) of
--- citations which have a duplicate (same 'collision' and same
--- 'citYear'). If the first 'Bool' is 'False', then we need to
--- retrieve data for year suffix disambiguation.
-getDuplCiteData :: Bool -> [CitationGroup] -> [[CiteData]]
-getDuplCiteData b g
+-- citations which have a duplicate (same 'collision', and same
+-- 'citYear' if year suffix disambiiguation is used). If the first
+-- 'Bool' is 'False', then we need to retrieve data for year suffix
+-- disambiguation. The second 'Bool' is 'True' when comparing both
+-- year and contributors' names for finding duplicates (when the
+-- year-suffix option is set).
+getDuplCiteData :: Bool -> Bool -> [CitationGroup] -> [[CiteData]]
+getDuplCiteData b1 b2 g
     = groupBy (\x y -> collide x == collide y) . sortBy (comparing collide) $ duplicates
     where
-      whatToGet  = if b then collision else disambYS
-      collide    = proc rmNameHash . proc rmGivenNames . whatToGet
-      citeData   = nub $ concatMap (mapGroupOutput $ getCiteData) g
-      duplicates = filter (collide &&& citYear >>> flip elem (getDuplNamesYear b g)) citeData
+      whatToGet  = if b1 then collision else disambYS
+      collide    = proc rmExtras . proc rmNameHash . proc rmGivenNames . whatToGet
+      citeData   = nubBy (\a b -> collide a == collide b && key a == key b) $
+                   concatMap (mapGroupOutput $ getCiteData) g
+      findDupl f = filter (flip (>) 1 . length . flip elemIndices (map f citeData) . f) citeData
+      duplicates = if b2 then findDupl (collide &&& citYear)
+                         else findDupl  collide
+rmExtras :: [Output] -> [Output]
+rmExtras os
+    | Output         x f : xs <- os = if null (rmExtras x)
+                                      then rmExtras xs
+                                      else Output (rmExtras x) f : rmExtras xs
+    | OContrib _ _ x _ _ : xs <- os = OContrib [] [] x [] [] : rmExtras xs
+    | OYear        y _ f : xs <- os = OYear y [] f : rmExtras xs
+    | ODel             _ : xs <- os = rmExtras xs
+    | OLoc           _ _ : xs <- os = rmExtras xs
+    | x                  : xs <- os = x : rmExtras xs
+    | otherwise                     = []
 
 -- | For an evaluated citation get its 'CiteData'. The disambiguated
--- citation and the year fields are empty.
+-- citation and the year fields are empty. Only the first list of
+-- contributors' disambiguation data are collected for disambiguation
+-- purposes.
 getCiteData :: Output -> [CiteData]
-getCiteData
-    = contribs &&& years >>>
-      zipData
+getCiteData out
+    = (contribs &&& years >>> zipData) out
     where
       contribs x = if query contribsQ x /= []
                    then query contribsQ x
-                   else [CD [] [] [] [] [] []]
+                   else [CD [] [] [] [] [] [] []]
       yearsQ  = query getYears
       years o = if yearsQ o /= [] then yearsQ o else [([],[])]
       zipData = uncurry . zipWith $ \c y -> if key c /= []
@@ -188,45 +225,8 @@
                                             else c {key     = fst y
                                                    ,citYear = snd y}
       contribsQ o
-          | OContrib k _ c d dd <- o = [CD k c d dd [] []]
+          | OContrib k _ _ d dd <- o = [CD k [out] d (d:dd) [] [] []]
           | otherwise                = []
-
--- | The contributors diambiguation data, the list of names and
--- give-names, and the citation year ('OYear').
-type NamesYear = ([Output],String)
-
--- | Get the contributors list ('OContrib') and the year occurring in
--- more then one citation.
-getDuplNamesYear :: Bool -> [CitationGroup] -> [NamesYear]
-getDuplNamesYear b
-    = nub . catMaybes . snd . mapAccumL dupl [] . getData
-    where
-      getData  = nub . concatMap (mapGroupOutput $ getNamesYear b)
-      dupl a c = if snd c `elem` a
-                 then (a,Just $ snd c) else (snd c:a,Nothing)
-
--- | Get the list of citation keys coupled with their 'NamesYear' in
--- the evaluated 'Output'. If the 'Bool' is 'False' then the function
--- retrieves the names used in citations not occuring for the first
--- time.
-getNamesYear :: Bool -> Output -> [(String,NamesYear)]
-getNamesYear b
-    = proc rmNameHash    >>>
-      proc rmGivenNames  >>>
-      contribs &&& years >>>
-      zipData
-    where
-      contribs x = if query contribsQ x /= []
-                   then query contribsQ x
-                   else [([],[])]
-      yearsQ  = query getYears
-      years o = if yearsQ o /= [] then yearsQ o else [([],[])]
-      zipData = uncurry . zipWith $ \(k,c) y -> if k /= []
-                                                then (,) k       (c, snd y)
-                                                else (,) (fst y) (c, snd y)
-      contribsQ o
-          | OContrib k _ c d _ <- o = [(k,if b then c else d)]
-          | otherwise               = []
 
 getYears :: Output -> [(String,String)]
 getYears o
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
@@ -128,64 +128,65 @@
 -- | The 'Reference' record.
 data Reference =
     Reference
-    { refId              :: String
-    , refType            :: RefType
+    { refId               :: String
+    , refType             :: RefType
 
-    , author             :: [Agent]
-    , editor             :: [Agent]
-    , translator         :: [Agent]
-    , recipient          :: [Agent]
-    , interviewer        :: [Agent]
-    , composer           :: [Agent]
-    , originalAuthor     :: [Agent]
-    , containerAuthor    :: [Agent]
-    , collectionEditor   :: [Agent]
-    , editorialDirector  :: [Agent]
+    , author              :: [Agent]
+    , editor              :: [Agent]
+    , translator          :: [Agent]
+    , recipient           :: [Agent]
+    , interviewer         :: [Agent]
+    , composer            :: [Agent]
+    , originalAuthor      :: [Agent]
+    , containerAuthor     :: [Agent]
+    , collectionEditor    :: [Agent]
+    , editorialDirector   :: [Agent]
 
-    , issued             :: [RefDate]
-    , eventDate          :: [RefDate]
-    , accessed           :: [RefDate]
-    , container          :: [RefDate]
-    , originalDate       :: [RefDate]
+    , issued              :: [RefDate]
+    , eventDate           :: [RefDate]
+    , accessed            :: [RefDate]
+    , container           :: [RefDate]
+    , originalDate        :: [RefDate]
 
-    , title              :: String
-    , shortTitle         :: String
-    , containerTitle     :: String
-    , collectionTitle    :: String
-    , collectionNumber   :: String --Int
-    , originalTitle      :: String
-    , publisher          :: String
-    , originalPublisher  :: String
-    , publisherPlace     :: String
-    , authority          :: String
-    , archive            :: String
-    , archivePlace       :: String
-    , archiveLocation    :: String
-    , event              :: String
-    , eventPlace         :: String
-    , page               :: String
-    , pageFirst          :: String
-    , numberOfPages      :: String
-    , version            :: String
-    , volume             :: String
-    , numberOfVolumes    :: String --Int
-    , issue              :: String
-    , chapterNumber      :: String
-    , medium             :: String
-    , status             :: String
-    , edition            :: String
-    , section            :: String
-    , genre              :: String
-    , note               :: String
-    , annote             :: String
-    , abstract           :: String
-    , keyword            :: String
-    , number             :: String
-    , references         :: String
-    , url                :: String
-    , doi                :: String
-    , isbn               :: String
-    , categories         :: [String]
+    , title               :: String
+    , titleShort          :: String
+    , containerTitle      :: String
+    , collectionTitle     :: String
+    , containerTitleShort :: String
+    , collectionNumber    :: String --Int
+    , originalTitle       :: String
+    , publisher           :: String
+    , originalPublisher   :: String
+    , publisherPlace      :: String
+    , authority           :: String
+    , archive             :: String
+    , archivePlace        :: String
+    , archiveLocation     :: String
+    , event               :: String
+    , eventPlace          :: String
+    , page                :: String
+    , pageFirst           :: String
+    , numberOfPages       :: String
+    , version             :: String
+    , volume              :: String
+    , numberOfVolumes     :: String --Int
+    , issue               :: String
+    , chapterNumber       :: String
+    , medium              :: String
+    , status              :: String
+    , edition             :: String
+    , section             :: String
+    , genre               :: String
+    , note                :: String
+    , annote              :: String
+    , abstract            :: String
+    , keyword             :: String
+    , number              :: String
+    , references          :: String
+    , url                 :: String
+    , doi                 :: String
+    , isbn                :: String
+    , categories          :: [String]
 
     , citationNumber           :: CNum
     , firstReferenceNoteNumber :: Int
@@ -216,8 +217,9 @@
     , originalDate        = []
 
     , title               = []
-    , shortTitle          = []
+    , titleShort          = []
     , containerTitle      = []
+    , containerTitleShort = []
     , collectionTitle     = []
 
     , collectionNumber    = []
@@ -259,6 +261,10 @@
     , firstReferenceNoteNumber = 0
     , citationLabel            = []
     }
+
+numericVars :: [String]
+numericVars = [ "edition", "volume", "number-of-volumes", "number", "issue", "citation-number"
+              , "chapter-number", "collection-number", "number-of-pages"]
 
 parseLocator :: String -> (String, String)
 parseLocator s
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
@@ -18,6 +18,7 @@
 import Data.List ( nubBy, isPrefixOf )
 import Data.Generics ( Typeable, Data, everywhere
                      , everywhere', everything, mkT, mkQ)
+import qualified Data.Map as M
 import Text.JSON
 import Text.Pandoc.Definition ( Inline )
 
@@ -29,6 +30,7 @@
       , styleInfo          ::  Maybe CSInfo
       , styleDefaultLocale ::  String
       , styleLocale        :: [Locale]
+      , styleAbbrevs       :: [Abbrev]
       , csOptions          :: [Option]
       , csMacros           :: [MacroMap]
       , citation           ::  Citation
@@ -63,6 +65,9 @@
       newDate    x = nubBy (\(Date _ a _ _ _ _)
                              (Date _ b _ _ _ _) -> a == b) (concatMap localeDate x ++ localeDate l)
 
+type Abbrev
+    = (String, [(String, M.Map String String)])
+
 type TermMap
     = ((String,Form),(String,String))
 
@@ -222,6 +227,13 @@
     = NamePart String Formatting
       deriving ( Show, Eq, Typeable, Data )
 
+isPlural :: Plural -> Int -> Bool
+isPlural p l
+    = case p of
+        Always     -> True
+        Never      -> False
+        Contextual -> l > 1
+
 isName :: Name -> Bool
 isName x = case x of Name {} -> True; _ -> False
 
@@ -294,12 +306,13 @@
 -- | The formatted output, produced after post-processing the
 -- evaluated citations.
 data FormattedOutput
-    = FO          Formatting [FormattedOutput]
-    | FN   String Formatting
-    | FS   String Formatting
-    | FDel String
-    | FPan [Inline]
-    | FNull
+    = FO          Formatting [FormattedOutput]          -- ^ List of 'FormatOutput' items
+    | FN   String Formatting                            -- ^ Formatted number
+    | FS   String Formatting                            -- ^ Formatted string
+    | FUrl String Formatting                            -- ^ Formatted uniform resource locator (URL)
+    | FDel String                                       -- ^ Delimeter string
+    | FPan [Inline]                                     -- ^ Pandoc inline elements
+    | FNull                                             -- ^ Null formatting item
       deriving ( Eq, Show )
 
 -- | The 'Output' generated by the evaluation of a style. Must be
@@ -318,6 +331,8 @@
     | OContrib String    String   [Output] [Output] [[Output]] -- ^ The citation key, the role (author, editor, etc.), the contributor(s),
                                                         -- the output needed for year suf. disambiguation, and everything used for
                                                         -- name disambiguation.
+    | OUrl    String              Formatting            -- ^ A uniform resource locator (URL)
+    | OLoc    [Output]            Formatting            -- ^ The citation's locator
     | Output  [Output]            Formatting            -- ^ Some nested 'Output'
       deriving ( Eq, Ord, Show, Typeable, Data )
 
@@ -357,9 +372,10 @@
 emptyCite :: Cite
 emptyCite  = Cite [] emptyAffix emptyAffix [] [] [] [] False False False 0
 
--- | A citation group: a list of evaluated citations, the 'Formatting'
--- to be applied to them, and the 'Delimiter' between individual
--- citations.
+-- | A citation group: the first list has a single member when the
+-- citation group starts with an "author-in-text" cite, the
+-- 'Formatting' to be applied, the 'Delimiter' between individual
+-- citations and the list of evaluated citations.
 data CitationGroup = CG [(Cite, Output)] Formatting Delimiter [(Cite, Output)] deriving ( Show, Eq, Typeable, Data )
 
 data BiblioData
@@ -369,11 +385,12 @@
       } deriving ( Show )
 
 -- | A record with all the data to produce the 'FormattedOutput' of a
--- citation: the citation key, the part of the citation that may be
--- colliding with other citations (the list of contributors for the
--- same year), the data to disambiguate it (all possible contributors
--- and all possible given names), and the disambiguated citation and
--- its year.
+-- citation: the citation key, the part of the formatted citation that
+-- may be colliding with other citations, the form of the citation
+-- when a year suffix is used for disambiguation , the data to
+-- disambiguate it (all possible contributors and all possible given
+-- names), and, after processing, the disambiguated citation and its
+-- year, initially empty.
 data CiteData
     = CD
       { key        ::   String
@@ -381,12 +398,13 @@
       , disambYS   ::  [Output]
       , disambData :: [[Output]]
       , disambed   ::  [Output]
+      , sameAs     ::  [String]
       , citYear    ::   String
       } deriving ( Show, Typeable, Data )
 
 instance Eq CiteData where
-    (==) (CD ka ca _ _ _ _)
-         (CD kb cb _ _ _ _) = ka == kb && ca == cb
+    (==) (CD ka ca _ _ _ _ _)
+         (CD kb cb _ _ _ _ _) = ka == kb && ca == cb
 
 data NameData
     = ND
@@ -421,7 +439,7 @@
 formatOutput :: Output -> FormattedOutput
 formatOutput o
     | OSpace             <- o = FDel " "
-    | OPan     i          <- o = FPan i
+    | OPan     i         <- o = FPan i
     | ODel     []        <- o = FNull
     | ODel     s         <- o = FDel s
     | OStr     []      _ <- o = FNull
@@ -430,8 +448,10 @@
     | OYearSuf s _ _   f <- o = FS s         f
     | ONum     i       f <- o = FS (show  i) f
     | OCitNum  i       f <- o = FN (add00 i) f
+    | OUrl     s       f <- o = FUrl s       f
     | OName  _ s _     f <- o = FO f               (format  s)
     | OContrib _ _ s _ _ <- o = FO emptyFormatting (format  s)
+    | OLoc     os      f <- o = FO f               (format os)
     | Output   os      f <- o = FO f               (format os)
     | otherwise               = FNull
     where
@@ -465,12 +485,6 @@
 rmNameHash o
     | OName _ s ss f <- o = OName [] s ss f
     | otherwise           = o
-
--- | Removes all contributors' names.
-rmContribs :: Output -> Output
-rmContribs o
-    | OContrib s r _ _ _ <- o = OContrib s r [] [] []
-    | otherwise               = o
 
 -- | Add, with 'proc', a give name to the family name. Needed for
 -- disambiguation.
diff --git a/src/Text/CSL/Test.hs b/src/Text/CSL/Test.hs
--- a/src/Text/CSL/Test.hs
+++ b/src/Text/CSL/Test.hs
@@ -47,7 +47,7 @@
 import qualified Data.ByteString.UTF8 as BS ( toString )
 import Text.CSL.Parser ( localeFiles )
 #else
-import Foreign
+import System.IO.Unsafe
 import Data.IORef
 import Paths_citeproc_hs ( getDataFileName )
 import Text.CSL.Parser ( readLocaleFile )
@@ -59,6 +59,7 @@
       { testMode      :: String
       , testInput     :: [Reference]
       , testCSL       :: Style
+      , testAbbrevs   :: [Abbrev]
       , testResult    :: String
       , testBibSect   :: BibOpts
       , testCitItems  :: Maybe Citations
@@ -66,7 +67,7 @@
       } deriving ( Show )
 
 toTest :: JSValue -> Test
-toTest ob = Test mode input style result bibsection cites cites'
+toTest ob = Test mode input style abbrevs result bibsection cites cites'
     where
       getObj f = case procJSObject f ob of
                    JSObject o -> fromJSObject o
@@ -82,6 +83,10 @@
       mode   = look "mode"
       result = look "result"
 
+      abbrevs  = case lookup "abbreviations" object of
+                   Just o -> readJsonAbbrev o
+                   _      -> []
+
       bibsection = case lookup "bibsection" objectI of
                      Just (JSObject o) -> getBibOpts $ fromJSObject o
                      _                 -> Select [] []
@@ -125,7 +130,7 @@
 readTestFile :: FilePath -> IO JSValue
 readTestFile f = do
   s <- readFile f
-  let fields = ["CSL","RESULT","MODE","INPUT","CITATION-ITEMS","CITATIONS","BIBSECTION","BIBENTRIES"]
+  let fields = ["CSL","RESULT","MODE","INPUT","CITATION-ITEMS","CITATIONS","BIBSECTION","BIBENTRIES", "ABBREVIATIONS"]
       format = map (toLower . \x -> if x == '-' then '_' else x)
   return . toJson . zip (map format fields) . map (fieldsParser s) $ fields
 
@@ -165,8 +170,6 @@
     | Superscript is <- i = "<sup>" ++ pandocToHTML is ++ "</sup>" ++ pandocToHTML xs
     | Subscript   is <- i = "<sub>" ++ pandocToHTML is ++ "</sub>" ++ pandocToHTML xs
     | Space          <- i = " " ++ pandocToHTML xs
-    | EnDash         <- i = "–" ++ pandocToHTML xs
-    | Ellipses       <- i = "…" ++ pandocToHTML xs
     | Quoted    t is <- i = case t of
                               DoubleQuote -> "“" ++ pandocToHTML is ++ "”" ++ pandocToHTML xs
                               SingleQuote -> "‘" ++ pandocToHTML is ++ "’" ++ pandocToHTML xs
@@ -196,7 +199,7 @@
 
 #ifndef EMBED_DATA_FILES
 localeCache :: IORef [(String, Locale)]
-localeCache = unsafePerformIO $ newIORef []
+localeCache = System.IO.Unsafe.unsafePerformIO $ newIORef []
 
 getCachedLocale :: String -> IO [Locale]
 getCachedLocale n = maybe [] return `fmap` lookup n `fmap` readIORef localeCache
@@ -230,7 +233,8 @@
 #endif
   let opts   = procOpts { bibOpts = testBibSect t}
       style' = testCSL t
-      style  = style' {styleLocale = mergeLocales (styleDefaultLocale style') ls $ styleLocale style'}
+      style  = style' {styleLocale = mergeLocales (styleDefaultLocale style') ls $ styleLocale style'
+                      ,styleAbbrevs = testAbbrevs t}
       cites  = case (testCitations t, testCitItems t) of
                  (Just cs, _      ) -> cs
                  (_,       Just cs) -> cs
diff --git a/test/test.hs b/test/test.hs
--- a/test/test.hs
+++ b/test/test.hs
@@ -1,10 +1,18 @@
 import System.Environment
+import Text.CSL.Eval (split)
 import Text.CSL.Test
 
 -- a dir with a final slash
-testDir = "citeproc-test/processor-tests/machines/"
+testDir  = "citeproc-test/processor-tests/machines/"
+testDirH = "citeproc-test/processor-tests/humans/"
 
 main :: IO ()
 main = do
   args <- getArgs
-  runTS args 0 testDir
+  case args of
+    [x,y,z] -> if z == "txt"
+               then test_ 2 (testDirH ++ x ++ "_" ++ y ++ ".txt" ) >> return ()
+               else test' 2 (testDir  ++ x ++ "_" ++ y ++ ".json") >> return ()
+    [x,y]   ->      test' 2 (testDir  ++ x ++ "_" ++ y ++ ".json") >> return ()
+    [x]     -> runTS (split (== ',') x) 0 testDir
+    x       -> runTS                 x  0 testDir
