diff --git a/language-bash.cabal b/language-bash.cabal
--- a/language-bash.cabal
+++ b/language-bash.cabal
@@ -1,6 +1,6 @@
 cabal-version:      2.2
 name:               language-bash
-version:            0.11.0
+version:            0.11.1
 category:           Language
 license:            BSD-3-Clause
 license-file:       LICENSE
@@ -20,7 +20,6 @@
 extra-source-files:
   README.md
   tests/pretty/*.golden
-  tests/pretty/*.out
   tests/pretty/*.sh
 
 source-repository head
@@ -58,7 +57,7 @@
     prettyprinter >= 1.7 && < 2.0,
     transformers  >= 0.2 && < 0.7
 
-  ghc-options: -Wall -Wno-deriving-typeable
+  ghc-options: -Wall -Wno-unused-imports -Wno-deriving-typeable
 
 test-suite tests
   default-language: Haskell2010
diff --git a/src/Language/Bash/Parse/Word.hs b/src/Language/Bash/Parse/Word.hs
--- a/src/Language/Bash/Parse/Word.hs
+++ b/src/Language/Bash/Parse/Word.hs
@@ -48,7 +48,7 @@
 upTo1 :: Alternative f => Int -> f a -> f [a]
 upTo1 n p = (:) <$> p <*> upTo (n - 1) p
 
--- | Parse a span until a delimeter.
+-- | Parse a span until a delimiter.
 spans
     :: Stream s m Char
     => [Char]              -- ^ Delimiters
diff --git a/src/Language/Bash/Syntax.hs b/src/Language/Bash/Syntax.hs
--- a/src/Language/Bash/Syntax.hs
+++ b/src/Language/Bash/Syntax.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE DeriveDataTypeable, FlexibleInstances, OverloadedStrings, RecordWildCards, DeriveGeneric #-}
+{-# LANGUAGE DeriveDataTypeable, FlexibleInstances, GeneralizedNewtypeDeriving, OverloadedStrings, RecordWildCards, DeriveGeneric #-}
 -- | Shell script types.
 module Language.Bash.Syntax
     (
@@ -87,9 +87,14 @@
 prettyHeredocs [] = mempty
 prettyHeredocs rs = mconcat $ intersperse hardline $ map prettyHeredoc rs
     where
-        prettyHeredoc Heredoc{..} = pretty hereDocument <> pretty heredocDelim
+        prettyHeredoc Heredoc{..} = pretty (ensureTrailingNewline hereDocument) <> pretty heredocDelim
         prettyHeredoc _ = mempty
 
+        ensureTrailingNewline [] = []
+        ensureTrailingNewline xs
+            | last xs == Char '\n' = xs
+            | otherwise = xs ++ [Char '\n']
+
 -- | Indent by 4 columns.
 indent' :: Doc ann -> Doc ann
 indent' = indent 4
@@ -315,7 +320,7 @@
 
 -- | A compound list of statements.
 newtype List = List [Statement]
-    deriving (Data, Eq, Read, Show, Typeable, Generic)
+    deriving (Data, Eq, Monoid, Read, Semigroup, Show, Typeable, Generic)
 
 instance Pretty List where
     pretty (List as) = pretty as
diff --git a/tests/Tests.hs b/tests/Tests.hs
--- a/tests/Tests.hs
+++ b/tests/Tests.hs
@@ -188,6 +188,32 @@
                   heredocDelim = "EOF",
                   heredocDelimQuoted = False,
                   hereDocument = stringToWord "comment\n"}])
+  , testGroup "Issue #23 regression tests"
+    [ testCase "Empty document" $ do
+          let list = wrapCommand $ Command
+                  (SimpleCommand [] [stringToWord "command"])
+                  [ Heredoc
+                      { heredocOp = Here
+                      , heredocDelim = "EOF"
+                      , heredocDelimQuoted = False
+                      , hereDocument = []
+                      }
+                  ]
+              expected = "command <<EOF;\nEOF"
+          expected @=? prettyText list
+    , testCase "Non-empty document" $ do
+          let list = wrapCommand $ Command
+                  (SimpleCommand [] [stringToWord "command"])
+                  [ Heredoc
+                      { heredocOp = Here
+                      , heredocDelim = "EOF"
+                      , heredocDelimQuoted = False
+                      , hereDocument = stringToWord "here document"
+                      }
+                  ]
+              expected = "command <<EOF;\nhere document\nEOF"
+          expected @=? prettyText list
+    ]
   ]
 
 failingtests :: TestTree
diff --git a/tests/pretty/conditionals-simple.out b/tests/pretty/conditionals-simple.out
deleted file mode 100644
--- a/tests/pretty/conditionals-simple.out
+++ /dev/null
@@ -1,35 +0,0 @@
-if true; then
-    true;
-fi;
-if true; then
-    true;
-else
-    if false; then
-        false;
-    fi;
-fi;
-if true; then
-    true;
-else
-    false;
-fi;
-if true; then
-    true;
-else
-    if false; then
-        false;
-    else
-        false;
-    fi;
-fi;
-case x in
-    x)
-        true;
-        ;;
-esac;
-select x; do
-    true;
-done;
-select x in y z; do
-    true;
-done;
diff --git a/tests/pretty/heredoc-composed.out b/tests/pretty/heredoc-composed.out
deleted file mode 100644
--- a/tests/pretty/heredoc-composed.out
+++ /dev/null
@@ -1,30 +0,0 @@
-cat <<EOF1 |
-Here doc 1
-EOF1
-cat <<EOF2;
-Here doc 2
-EOF2
-cat <<EOF1 &&
-Here doc 1
-EOF1
-cat <<EOF2;
-Here doc 2
-EOF2
-cat <<EOF1 ||
-Here doc 1
-EOF1
-cat <<EOF2;
-Here doc 2
-EOF2
-cat <<EOF1 |
-Here doc 1
-EOF1
-for x in true; do
-    true;
-done;
-cat <<EOF1 |
-Here doc 1
-EOF1
-while true; do
-    true;
-done;
diff --git a/tests/pretty/heredoc-in-condition.out b/tests/pretty/heredoc-in-condition.out
deleted file mode 100644
--- a/tests/pretty/heredoc-in-condition.out
+++ /dev/null
@@ -1,18 +0,0 @@
-if true <<EOF;
-here doc
-EOF
-then
-    true;
-fi;
-until true <<EOF;
-here doc
-EOF
-do
-    true;
-done;
-while true <<EOF;
-here doc
-EOF
-do
-    true;
-done;
diff --git a/tests/pretty/heredoc-nested.out b/tests/pretty/heredoc-nested.out
deleted file mode 100644
--- a/tests/pretty/heredoc-nested.out
+++ /dev/null
@@ -1,26 +0,0 @@
-for x in true; do
-    cat <<EOF;
-here doc
-EOF
-done;
-for x in true; do
-    for y in true; do
-        cat <<EOF;
-here doc
-EOF
-        true;
-    done;
-done;
-while true; do
-    cat <<EOF;
-here doc
-EOF
-done;
-while true; do
-    while true; do
-        cat <<EOF;
-here doc
-EOF
-        true;
-    done;
-done;
diff --git a/tests/pretty/heredoc.out b/tests/pretty/heredoc.out
deleted file mode 100644
--- a/tests/pretty/heredoc.out
+++ /dev/null
@@ -1,11 +0,0 @@
-cat <<EOF;
-Hello world!
-EOF
-cat <<EOF1 <<EOF2;
-Here doc 1
-EOF1
-Here doc 2
-EOF2
-cat <<EOF >/dev/null;
-Hello world!
-EOF
diff --git a/tests/pretty/loops-nested.out b/tests/pretty/loops-nested.out
deleted file mode 100644
--- a/tests/pretty/loops-nested.out
+++ /dev/null
@@ -1,15 +0,0 @@
-for x in true; do
-    for y in true; do
-        true;
-    done;
-done;
-until true; do
-    until true; do
-        true;
-    done;
-done;
-while true; do
-    while true; do
-        true;
-    done;
-done;
diff --git a/tests/pretty/loops-simple.out b/tests/pretty/loops-simple.out
deleted file mode 100644
--- a/tests/pretty/loops-simple.out
+++ /dev/null
@@ -1,9 +0,0 @@
-for x in true; do
-    true;
-done;
-until true; do
-    true;
-done;
-while true; do
-    true;
-done;
diff --git a/tests/pretty/simple.out b/tests/pretty/simple.out
deleted file mode 100644
--- a/tests/pretty/simple.out
+++ /dev/null
@@ -1,14 +0,0 @@
-declare foo;
-declare foo=bar;
-declare foo1=bar1 foo2=bar2;
-declare -i foo;
-declare -a foo;
-declare -r foo;
-cmd;
-cmd1 | cmd2;
-time cmd1 | cmd2;
-time -p cmd1 | cmd2;
-! cmd1 | cmd2;
-time -p ! cmd1 | cmd2;
-cmd1 && cmd2;
-cmd1 || cmd2;
