diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,23 @@
 # Revision history for BBCode
 
-## 0.1.0.1 -- 2023-09-12
+## 0.2.0.1 -- 2023-12-31
+
+### Changes
+
+- Update cabal index
+- Regenerate bounds for packages
+- Update nixpkgs version
+
+### Fixed
+
+- When pretty-printing, wrap code's and pre's body in newlines
+- Improve parsing of spoiler's and quote's arguments
+
+### Dev
+
+- Improve candidate publishing script
+
+## 0.1.0.2 -- 2023-09-12
 
 ### Added
 
diff --git a/bbcode.cabal b/bbcode.cabal
--- a/bbcode.cabal
+++ b/bbcode.cabal
@@ -1,6 +1,6 @@
 cabal-version:   3.0
 name:            bbcode
-version:         0.1.0.2
+version:         0.2.0.1
 synopsis:        Library for parsing, constructing, and printing BBCode
 description:
   This is a set of utilities for: Parsing BBCode into AST(providing
@@ -23,7 +23,7 @@
   location: https://gitlab.com/repetitivesin/BBCode.git
 
 common c
-  build-depends:      base ^>=4.16.4.0
+  build-depends:      base
   ghc-options:        -Wall
   default-extensions:
     ApplicativeDo
@@ -33,13 +33,13 @@
     ViewPatterns
 
   build-depends:
-    , base          ^>=4.16.4.0
-    , containers    >=0.6.5     && <0.7
-    , lens          >=5.2.2     && <5.3
-    , megaparsec    >=9.4.1     && <9.5
-    , mtl           >=2.2.2     && <2.3
-    , text          >=1.2.5     && <1.3
-    , transformers  >=0.5.6     && <0.6
+    base >= 4.17.2 && < 4.18,
+    containers >= 0.6.7 && < 0.7,
+    lens >= 5.2.3 && < 5.3,
+    transformers >= 0.5.6 && < 0.6,
+    mtl >= 2.2.2 && < 2.3,
+    text >= 2.0.2 && < 2.1,
+    megaparsec >= 9.6.1 && < 9.7,
 
 library
   import:           c
diff --git a/lib/Text/BBCode.hs b/lib/Text/BBCode.hs
--- a/lib/Text/BBCode.hs
+++ b/lib/Text/BBCode.hs
@@ -1,4 +1,5 @@
 {-# OPTIONS_HADDOCK show-extensions #-}
+
 {-|
 Module      : Text.BBCode
 Description : Main module exporting builder interface and types
@@ -6,19 +7,44 @@
 Stability   : experimental
 Portability : GHC
 
-Here is a longer description of this module, containing some
-commentary with @some markup@.
+Usually you only need to import that module, which reexports most of the functionality.
+
+If you need 'lens' definitions for types, import "Text.BBCode.Lens"
+
+If you need interface to parsing, see "Text.BBCode.Parser"
 -}
 module Text.BBCode
-  ( -- Builder
+  ( -- * Builder
+
+    -- | Functions for constructing AST in a more elegant way than directly using type constructors.
+    --
+    -- This wrappers are usually no more than partially applied data
+    -- constructors. An exception to that is 'list' and 'listFlavor' functions,
+    -- which adds 'listEl' before each element. This is implementation detail
+    -- and shouldn't bother you unless you work with AST directly
+
+    -- ** Void elements
+
+    -- | Void elements' data constructors only specify the type of the
+    -- element(e.g. 'HR', 'Clear', @...@),
+    -- such element don't have any content unlike other types of elements.
+    --
+    -- see 'ElVoid'
     nl
-  , text
-  , doc
-  , docNL
   , hr
   , br
   , clear
   , listEl
+
+    -- ** Simple elements
+
+    -- | Simple elements have contents, usually 'BBCode'. 'text' is not actually a
+    -- simple element builder and included here just for convenience
+    --
+    -- see 'ElSimple'
+  , text
+  , doc
+  , docNL
   , bold
   , italic
   , underline
@@ -33,6 +59,13 @@
   , quote
   , spoiler
   , list
+
+    -- ** Elements with an argument
+
+    -- | Apart from having contents, following elements also have argument. It
+    -- can indicate position, color, or something else.
+    --
+    -- see 'ElArg'
   , boxAlign
   , imageAlign
   , quoteNamed
@@ -43,17 +76,31 @@
   , size
   , align
   , font
-  -- Types
+
+    -- * Types
   , BBCode (..)
   , El (..)
   , IsArgument (..)
-  , AlignPosition (..)
   , ListFlavor (..)
+
+    -- ** Alignment and position
+
+    -- | There are three different position types because 'align', 'image',
+    -- 'boxAlign' all have different sets of valid positions. You can notice
+    -- that all these types have different number of valid positions.
+  , AlignPosition (..)
   , ImagePosition (..)
   , BoxPosition (..)
-  -- Pretty
+
+    -- * Pretty-printer
   , pretty
-  -- Parser
+
+    -- * Parser
+
+    -- | A small part of "Text.BBCode.Parser". Dedicated module has an interface
+    -- to parsing specific elements as well as different parser runners.
+    --
+    -- These should be sufficient for parsing whole document.
   , bbcode
   , runParserMaybeEnv
   )
diff --git a/lib/Text/BBCode/Internal/Builder.hs b/lib/Text/BBCode/Internal/Builder.hs
--- a/lib/Text/BBCode/Internal/Builder.hs
+++ b/lib/Text/BBCode/Internal/Builder.hs
@@ -22,7 +22,7 @@
 doc = ElDocument
 {-# INLINE doc #-}
 
--- | Intersperse('intersperse') list with 'nl' and wrap it in 'ElDocument'
+-- | 'intersperse' list with 'nl' and wrap it in 'ElDocument'
 docNL :: [BBCode] -> BBCode
 docNL = doc . intersperse nl
 
diff --git a/lib/Text/BBCode/Internal/Parser.hs b/lib/Text/BBCode/Internal/Parser.hs
--- a/lib/Text/BBCode/Internal/Parser.hs
+++ b/lib/Text/BBCode/Internal/Parser.hs
@@ -53,7 +53,6 @@
 import Text.BBCode.Internal.Helper hiding (closing, opening, openingArg, surround, wrap, wrapArg)
 import Text.Megaparsec
 import Text.Megaparsec.Char
-import Text.Megaparsec.Char.Lexer (charLiteral)
 
 {-| Parser with reader transformer inside.
 
@@ -303,19 +302,46 @@
     ElText <$> takeWhile1P (Just "URL") (/= '[')
 {-# INLINEABLE imageAlign #-}
 
+{-| Can give cryptic error message if quote is ill-formed.
+
+>>>> parseTestEnv quoteNamed "[quote=\"QQ\"\"a][/quote]"
+1:24:
+  |
+1 | [quote="QQ""a][/quote]
+  |                       ^
+unexpected end of input
+expecting quote author in quotes(e.g. [quote="Dan"])
+
+Issue here is letter \'a\' before closing bracket
+-}
 quoteNamed :: Parser BBCode
 quoteNamed = elArg Quote arg bbcode
   where
+    go :: Parser Text = do
+      text <- takeWhileP (Just "\"]") (/= '"')
+      end <- lookAhead . optional $ string "\"]"
+      if isNothing end
+        then (text <>) <$> liftA2 (<>) (hidden $ string "\"") go
+        else pure text
     arg =
-      fmap T.pack . label "quote author in quotes(e.g. [quote=\"Dan\"])" $
-        char '"' *> manyTill charLiteral (char '"')
+      label "quote author in quotes(e.g. [quote=\"Dan\"])" $
+        try $
+          char '"' *> go <* string "\"]"
 
+-- | See 'quoteNamed'
 spoilerNamed :: Parser BBCode
 spoilerNamed = elArg Spoiler arg bbcode
   where
+    go :: Parser Text = do
+      text <- takeWhileP (Just "\"]") (/= '"')
+      end <- lookAhead . optional $ string "\"]"
+      if isNothing end
+        then (text <>) <$> liftA2 (<>) (hidden $ string "\"") go
+        else pure text
     arg =
-      fmap T.pack . label "spoiler name in quotes (e.g. [spoiler=\"The ending is\"])" $
-        char '"' *> manyTill charLiteral (char '"')
+      label "spoiler name in quotes (e.g. [spoiler=\"The ending is\"])" $
+        try $
+          char '"' *> go <* string "\"]"
 
 listFlavor :: Parser BBCode
 listFlavor =
diff --git a/lib/Text/BBCode/Internal/Pretty.hs b/lib/Text/BBCode/Internal/Pretty.hs
--- a/lib/Text/BBCode/Internal/Pretty.hs
+++ b/lib/Text/BBCode/Internal/Pretty.hs
@@ -12,9 +12,12 @@
 
 {- | Serialize BBCode AST
 
-Should be reversible by parsing, but it is not guaranteed
+Parsing @'pretty' x@ should give you @x@, but currently that rarely works mostly
+because of whitespaces. Whitespaces are appended when prettifying, but not
+stripped when parsing. This leads to redundant whitespaces in parsed AST
 
-Can cause error at runtime if unrepresentable element is passed, e.g.
+Can cause error at runtime if unrepresentable element is passed
+
 >>> pretty $ ElSimple HR "abc"
 Prelude.undefined
 -}
@@ -35,8 +38,14 @@
 pretty (ElSimple Indent bb) = wrap Indent $ pretty bb
 pretty (ElSimple NFO bb) = wrap NFO $ pretty bb
 pretty (ElSimple Oneline bb) = wrap Oneline $ pretty bb
-pretty (ElSimple Code bb) = wrap Code $ pretty bb
-pretty (ElSimple Preformatted bb) = wrap Preformatted $ pretty bb
+pretty (ElSimple Code bb) =
+  wrap Code
+    . surround "\n"
+    $ pretty bb
+pretty (ElSimple Preformatted bb) =
+  wrap Preformatted
+    . surround "\n"
+    $ pretty bb
 
 pretty (ElSimple Box bb) = wrap Box $ pretty bb
 pretty (ElSimple Image bb) = wrap Image $ pretty bb
@@ -51,9 +60,14 @@
 
 pretty (ElArg Box arg bb) = wrapArg Box arg $ pretty bb
 pretty (ElArg Image arg bb) = wrapArg Image arg $ pretty bb
--- BUG:/NOT? if arg contains double quote " then parser won't be able to parse it
-pretty (ElArg Quote arg bb) = wrapArg Quote (mconcat ["\"", arg, "\""]) $ pretty bb
-pretty (ElArg Spoiler arg bb) = wrapArg Spoiler (mconcat ["\"", arg, "\""]) $ pretty bb
+pretty (ElArg Quote arg bb) =
+  wrapArg Quote (mconcat ["\"", arg, "\""])
+    . surround "\n"
+    $ pretty bb
+pretty (ElArg Spoiler arg bb) =
+  wrapArg Spoiler (mconcat ["\"", arg, "\""])
+    . surround "\n"
+    $ pretty bb
 pretty (ElArg List arg (ElDocument bb)) =
   wrapArg List arg
     . (<> "\n")
