diff --git a/INSTALL b/INSTALL
--- a/INSTALL
+++ b/INSTALL
@@ -130,3 +130,31 @@
 [blaze-html]: http://hackage.haskell.org/package/blaze-html
 [Cabal User's Guide]: http://www.haskell.org/cabal/release/latest/doc/users-guide/builders.html#setup-configure-paths
 
+
+Running tests
+-------------
+
+Pandoc comes with an automated test suite integrated to cabal.
+To enable the tests, compile pandoc with the `tests` flag:
+
+    cabal install -ftests
+
+Note: If you obtained the source via git, you should first do
+
+    git submodule update --init templates
+
+to populate the templates subdirectory.  (You can skip this step
+if you obtained the source from a release tarball.)
+
+To run the tests:
+
+    cabal test
+
+If you add a new feature to pandoc, please add tests as well, following
+the pattern of the existing tests. The test suite code is in
+`src/test-pandoc.hs`. If you are adding a new reader or writer, it is
+probably easiest to add some data files to the `tests` directory, and
+modify `src/Tests/Old.hs`. Otherwise, it is better to modify the module
+under the `src/Tests` hierarchy corresponding to the pandoc module you
+are changing.
+
diff --git a/README b/README
--- a/README
+++ b/README
@@ -13,12 +13,13 @@
 Pandoc is a [Haskell] library for converting from one markup format to
 another, and a command-line tool that uses this library. It can read
 [markdown] and (subsets of) [Textile], [reStructuredText], [HTML],
-and [LaTeX]; and it can write plain text, [markdown], [reStructuredText],
-[XHTML], [HTML 5], [LaTeX] (including [beamer] slide shows),
-[ConTeXt], [RTF], [DocBook XML], [OpenDocument XML], [ODT], [Word docx], [GNU
-Texinfo], [MediaWiki markup], [EPUB], [Textile], [groff man] pages, [Emacs
-Org-Mode], [AsciiDoc], and [Slidy], [DZSlides], or [S5] HTML slide shows. It
-can also produce [PDF] output on systems where LaTeX is installed.
+[LaTeX], and [DocBook XML]; and it can write plain text, [markdown],
+[reStructuredText], [XHTML], [HTML 5], [LaTeX] (including [beamer]
+slide shows), [ConTeXt], [RTF], [DocBook XML], [OpenDocument XML],
+[ODT], [Word docx], [GNU Texinfo], [MediaWiki markup], [EPUB],
+[Textile], [groff man] pages, [Emacs Org-Mode], [AsciiDoc], and [Slidy],
+[DZSlides], or [S5] HTML slide shows. It can also produce [PDF] output
+on systems where LaTeX is installed.
 
 Pandoc's enhanced version of markdown includes syntax for footnotes,
 tables, flexible ordered lists, definition lists, delimited code blocks,
@@ -137,10 +138,10 @@
 :   Specify input format.  *FORMAT* can be `native` (native Haskell),
     `json` (JSON version of native AST), `markdown` (markdown),
     `textile` (Textile), `rst` (reStructuredText), `html` (HTML),
-    or `latex` (LaTeX).  If `+lhs` is appended to `markdown`, `rst`,
-    `latex`, the input will be treated as literate Haskell source:
-    see [Literate Haskell support](#literate-haskell-support),
-    below.
+    `docbook` (DocBook XML), or `latex` (LaTeX). If `+lhs` is
+    appended to `markdown`, `rst`, `latex`, the input will be
+    treated as literate Haskell source: see [Literate Haskell
+    support](#literate-haskell-support), below.
 
 `-t` *FORMAT*, `-w` *FORMAT*, `--to=`*FORMAT*, `--write=`*FORMAT*
 :   Specify output format.  *FORMAT* can be `native` (native Haskell),
@@ -212,7 +213,7 @@
     abbreviations, such as "Mr." (Note: This option is significant only when
     the input format is `markdown` or `textile`. It is selected automatically
     when the input format is `textile` or the output format is `latex` or
-    `context`.)
+    `context`, unless `--no-tex-ligatures` is used.)
 
 `--old-dashes`
 :   Selects the pandoc <= 1.8.2.1 behavior for parsing smart dashes: `-` before
@@ -357,6 +358,17 @@
 :   Number section headings in LaTeX, ConTeXt, or HTML output.
     By default, sections are not numbered.
 
+`--no-tex-ligatures`
+:   Do not convert quotation marks, apostrophes, and dashes to
+    the TeX ligatures when writing LaTeX or ConTeXt. Instead, just
+    use literal unicode characters. This is needed for using advanced
+    OpenType features with XeLaTeX and LuaLaTeX. Note: normally
+    `--smart` is selected automatically for LaTeX and ConTeXt
+    output, but it must be specified explicitly if `--no-tex-ligatures`
+    is selected. If you use literal curly quotes, dashes, and ellipses
+    in your source, then you may want to use `--no-tex-ligatures`
+    without `--smart`.
+
 `--listings`
 :   Use listings package for LaTeX code blocks
 
@@ -1632,6 +1644,10 @@
 
     This is a backslash followed by an asterisk: `\*`.
 
+Attributes can be attached to verbatim text, just as with
+[delimited code blocks](#delimited-code-blocks):
+
+    `<$>`{.haskell}
 
 Math
 ----
diff --git a/changelog b/changelog
--- a/changelog
+++ b/changelog
@@ -1,3 +1,84 @@
+pandoc (1.9.3)
+
+  * Fixed bug in `fromEntities`.  The previous version would turn
+    `hi & low you know;` into `hi &`.
+
+  * HTML reader:
+
+    + Don't skip nonbreaking spaces.
+      Previously a paragraph containing just `&nbsp;` would be rendered
+      as an empty paragraph. Thanks to Paul Vorbach for pointing out the bug.
+    + Support `<col>` and `<caption>` in tables. Closes #486.
+
+  * Markdown reader:
+
+    + Don't recognize references inside delimited code blocks.
+    + Allow list items to begin with lists.
+
+  * Added basic docbook reader (John MacFarlane and Mauro Bieg).
+
+  * LaTeX reader:
+
+    + Handle `\bgroup`, `\egroup`, `\begingroup`, `\endgroup`.
+    + Control sequences can't be followed by a letter.
+      This fixes a bug where `\begingroup` was parsed as `\begin`
+      followed by `group`.
+    + Parse 'dimension' arguments to unknown commands.  e.g. `\parindent0pt`
+    + Make `\label` and `\ref` sensitive to `--parse-raw`.
+      If `--parse-raw` is selected, these will be parsed as raw latex
+      inlines, rather than bracketed text.
+    + Don't crash on unknown block commands (like `\vspace{10pt}`)
+      inside `\author`; just skip them.  Closes #505.
+
+  * Textile reader:
+
+    + Implemented literal escapes with `==` and `<notextile>`.  Closes #473.
+    + Added support for LaTeX blocks and inlines (Paul Rivier).
+    + Better conformance to RedCloth inline parsing (Paul Rivier).
+    + Parse '+text+' as emphasized (should be underlined, but this
+      is better than leaving literal plus characters in the output.
+
+  * Docx writer: Fixed multi-paragraph list items.  Previously they each
+    got a list marker.  Closes #457.
+
+  * LaTeX writer:
+
+    + Added `--no-tex-ligatures` option to avoid replacing
+      quotation marks and dashes with TeX ligatures.
+    + Use `fixltx2e` package to provide '\textsubscript'.
+    + Improve spacing around LaTeX block environments:
+      quote, verbatim, itemize, description, enumerate.
+      Closes #502.
+    + Use blue instead of pink for URL links in latex/pdf output.
+
+  * ConTeXt writer: Fixed escaping of `%`.
+    In text, `%` needs to be escaped as `\letterpercent`, not `\%`
+    Inside URLs, `%` needs to be escaped as `\%`
+    Thanks to jmarca and adityam for the fix.  Closes #492.
+
+  * Texinfo writer:  Escape special characters in node titles.
+    This fixes a problem pointed out by Joost Kremers.  Pandoc used
+    to escape an '@' in a chapter title, but not in the corresponding
+    node title, leading to invalid texinfo.
+
+  * Fixed document encoding in texinfo template.
+    Resolves Debian Bug #667816.
+
+  * Markdown writer:
+
+    + Don't force delimited code blocks to be flush left.
+      Fixes bug with delimited code blocks inside lists etc.
+    + Escape `<` and `$`.
+
+  * LaTeX writer: Use `\hyperref[ident]{text}` for internal links.
+    Previously we used `\href{\#ident}{text}`, which didn't work on
+    all systems. Thanks to Dirk Laurie.
+
+  * RST writer: Don't wrap link references.  Closes #487.
+
+  * Updated to use latest versions of blaze-html, mtl.
+
+
 pandoc (1.9.2)
 
   * LaTeX reader:
diff --git a/man/man1/pandoc.1 b/man/man1/pandoc.1
--- a/man/man1/pandoc.1
+++ b/man/man1/pandoc.1
@@ -9,11 +9,11 @@
 Pandoc is a Haskell library for converting from one markup format to
 another, and a command-line tool that uses this library.
 It can read markdown and (subsets of) Textile, reStructuredText, HTML,
-and LaTeX; and it can write plain text, markdown, reStructuredText,
-XHTML, HTML 5, LaTeX (including beamer slide shows), ConTeXt, RTF,
-DocBook XML, OpenDocument XML, ODT, Word docx, GNU Texinfo, MediaWiki
-markup, EPUB, Textile, groff man pages, Emacs Org-Mode, AsciiDoc, and
-Slidy, DZSlides, or S5 HTML slide shows.
+LaTeX, and DocBook XML; and it can write plain text, markdown,
+reStructuredText, XHTML, HTML 5, LaTeX (including beamer slide shows),
+ConTeXt, RTF, DocBook XML, OpenDocument XML, ODT, Word docx, GNU
+Texinfo, MediaWiki markup, EPUB, Textile, groff man pages, Emacs
+Org-Mode, AsciiDoc, and Slidy, DZSlides, or S5 HTML slide shows.
 It can also produce PDF output on systems where LaTeX is installed.
 .PP
 Pandoc\[aq]s enhanced version of markdown includes syntax for footnotes,
@@ -164,7 +164,8 @@
 \f[I]FORMAT\f[] can be \f[C]native\f[] (native Haskell), \f[C]json\f[]
 (JSON version of native AST), \f[C]markdown\f[] (markdown),
 \f[C]textile\f[] (Textile), \f[C]rst\f[] (reStructuredText),
-\f[C]html\f[] (HTML), or \f[C]latex\f[] (LaTeX).
+\f[C]html\f[] (HTML), \f[C]docbook\f[] (DocBook XML), or \f[C]latex\f[]
+(LaTeX).
 If \f[C]+lhs\f[] is appended to \f[C]markdown\f[], \f[C]rst\f[],
 \f[C]latex\f[], the input will be treated as literate Haskell source:
 see Literate Haskell support, below.
@@ -274,7 +275,8 @@
 "Mr." (Note: This option is significant only when the input format is
 \f[C]markdown\f[] or \f[C]textile\f[].
 It is selected automatically when the input format is \f[C]textile\f[]
-or the output format is \f[C]latex\f[] or \f[C]context\f[].)
+or the output format is \f[C]latex\f[] or \f[C]context\f[], unless
+\f[C]--no-tex-ligatures\f[] is used.)
 .RS
 .RE
 .TP
@@ -492,6 +494,21 @@
 .B \f[C]-N\f[], \f[C]--number-sections\f[]
 Number section headings in LaTeX, ConTeXt, or HTML output.
 By default, sections are not numbered.
+.RS
+.RE
+.TP
+.B \f[C]--no-tex-ligatures\f[]
+Do not convert quotation marks, apostrophes, and dashes to the TeX
+ligatures when writing LaTeX or ConTeXt.
+Instead, just use literal unicode characters.
+This is needed for using advanced OpenType features with XeLaTeX and
+LuaLaTeX.
+Note: normally \f[C]--smart\f[] is selected automatically for LaTeX and
+ConTeXt output, but it must be specified explicitly if
+\f[C]--no-tex-ligatures\f[] is selected.
+If you use literal curly quotes, dashes, and ellipses in your source,
+then you may want to use \f[C]--no-tex-ligatures\f[] without
+\f[C]--smart\f[].
 .RS
 .RE
 .TP
diff --git a/man/man5/pandoc_markdown.5 b/man/man5/pandoc_markdown.5
--- a/man/man5/pandoc_markdown.5
+++ b/man/man5/pandoc_markdown.5
@@ -1181,6 +1181,15 @@
 This\ is\ a\ backslash\ followed\ by\ an\ asterisk:\ `\\*`.
 \f[]
 .fi
+.PP
+Attributes can be attached to verbatim text, just as with delimited code
+blocks:
+.IP
+.nf
+\f[C]
+`<$>`{.haskell}
+\f[]
+.fi
 .SH MATH
 .PP
 \f[I]Pandoc extension\f[].
diff --git a/pandoc.cabal b/pandoc.cabal
--- a/pandoc.cabal
+++ b/pandoc.cabal
@@ -1,5 +1,5 @@
 Name:            pandoc
-Version:         1.9.2
+Version:         1.9.3
 Cabal-Version:   >= 1.10
 Build-Type:      Custom
 License:         GPL
@@ -185,6 +185,9 @@
 Flag tests
   Description:   Build test-pandoc.
   Default:       False
+Flag blaze_html_0_5
+  Description:   Use blaze-html 0.5 and blaze-markup 0.5
+  Default:       False
 
 Library
   -- Note: the following is duplicated in all stanzas.
@@ -192,8 +195,7 @@
   -- BEGIN DUPLICATED SECTION
   Build-Depends: containers >= 0.1 && < 0.5,
                  parsec >= 3.1 && < 3.2,
-                 blaze-html >= 0.4.3.0 && < 0.5,
-                 mtl >= 1.1 && < 2.1,
+                 mtl >= 1.1 && < 2.2,
                  network >= 2 && < 2.4,
                  filepath >= 1.1 && < 1.4,
                  process >= 1 && < 1.2,
@@ -216,6 +218,13 @@
                  zlib >= 0.5 && < 0.6,
                  highlighting-kate >= 0.5.0.2 && < 0.6,
                  temporary >= 1.1 && < 1.2
+  if flag(blaze_html_0_5)
+    build-depends:
+                 blaze-html >= 0.5 && < 0.6,
+                 blaze-markup >= 0.5.1 && < 0.6
+  else
+    build-depends:
+                 blaze-html >= 0.4.3.0 && < 0.5
   if impl(ghc >= 6.10)
     Build-depends: base >= 4 && < 5, syb >= 0.1 && < 0.4
   else
@@ -246,6 +255,7 @@
                    Text.Pandoc.Readers.LaTeX,
                    Text.Pandoc.Readers.Markdown,
                    Text.Pandoc.Readers.RST,
+                   Text.Pandoc.Readers.DocBook,
                    Text.Pandoc.Readers.TeXMath,
                    Text.Pandoc.Readers.Textile,
                    Text.Pandoc.Readers.Native,
@@ -290,8 +300,7 @@
   -- BEGIN DUPLICATED SECTION
   Build-Depends: containers >= 0.1 && < 0.5,
                  parsec >= 3.1 && < 3.2,
-                 blaze-html >= 0.4.3.0 && < 0.5,
-                 mtl >= 1.1 && < 2.1,
+                 mtl >= 1.1 && < 2.2,
                  network >= 2 && < 2.4,
                  filepath >= 1.1 && < 1.4,
                  process >= 1 && < 1.2,
@@ -314,6 +323,13 @@
                  zlib >= 0.5 && < 0.6,
                  highlighting-kate >= 0.5.0.2 && < 0.6,
                  temporary >= 1.1 && < 1.2
+  if flag(blaze_html_0_5)
+    build-depends:
+                 blaze-html >= 0.5 && < 0.6,
+                 blaze-markup >= 0.5.1 && < 0.6
+  else
+    build-depends:
+                 blaze-html >= 0.4.3.0 && < 0.5
   if impl(ghc >= 6.10)
     Build-depends: base >= 4 && < 5, syb >= 0.1 && < 0.4
   else
@@ -348,8 +364,7 @@
   -- BEGIN DUPLICATED SECTION
   Build-Depends: containers >= 0.1 && < 0.5,
                  parsec >= 3.1 && < 3.2,
-                 blaze-html >= 0.4.3.0 && < 0.5,
-                 mtl >= 1.1 && < 2.1,
+                 mtl >= 1.1 && < 2.2,
                  network >= 2 && < 2.4,
                  filepath >= 1.1 && < 1.4,
                  process >= 1 && < 1.2,
@@ -372,6 +387,13 @@
                  zlib >= 0.5 && < 0.6,
                  highlighting-kate >= 0.5.0.2 && < 0.6,
                  temporary >= 1.1 && < 1.2
+  if flag(blaze_html_0_5)
+    build-depends:
+                 blaze-html >= 0.5 && < 0.6,
+                 blaze-markup >= 0.5.1 && < 0.6
+  else
+    build-depends:
+                 blaze-html >= 0.4.3.0 && < 0.5
   if impl(ghc >= 6.10)
     Build-depends: base >= 4 && < 5, syb >= 0.1 && < 0.4
   else
diff --git a/src/Tests/Old.hs b/src/Tests/Old.hs
--- a/src/Tests/Old.hs
+++ b/src/Tests/Old.hs
@@ -97,13 +97,18 @@
           , test "reader" ["-r", "textile", "-w", "native", "-s"]
             "textile-reader.textile" "textile-reader.native"
           ]
+        , testGroup "docbook"
+          [ testGroup "writer" $ writerTests "docbook"
+          , test "reader" ["-r", "docbook", "-w", "native", "-s"]
+            "docbook-reader.docbook" "docbook-reader.native"
+          ]
         , testGroup "native"
           [ testGroup "writer" $ writerTests "native"
           , test "reader" ["-r", "native", "-w", "native", "-s"]
             "testsuite.native" "testsuite.native"
           ]
         , testGroup "other writers" $ map (\f -> testGroup f $ writerTests f)
-          [ "docbook", "opendocument" , "context" , "texinfo"
+          [ "opendocument" , "context" , "texinfo"
           , "man" , "plain" , "mediawiki", "rtf", "org", "asciidoc"
           ]
         ]
diff --git a/src/Text/Pandoc.hs b/src/Text/Pandoc.hs
--- a/src/Text/Pandoc.hs
+++ b/src/Text/Pandoc.hs
@@ -69,6 +69,7 @@
                , readLaTeX
                , readHtml
                , readTextile
+               , readDocBook
                , readNative
                -- * Parser state used in readers
                , ParserState (..)
@@ -119,6 +120,7 @@
 import Text.Pandoc.Generic
 import Text.Pandoc.Readers.Markdown
 import Text.Pandoc.Readers.RST
+import Text.Pandoc.Readers.DocBook
 import Text.Pandoc.Readers.LaTeX
 import Text.Pandoc.Readers.HTML
 import Text.Pandoc.Readers.Textile
@@ -162,6 +164,7 @@
           ,("rst"          , readRST)
           ,("rst+lhs"      , \st ->
                              readRST st{ stateLiterateHaskell = True})
+          ,("docbook"      , readDocBook)
           ,("textile"      , readTextile) -- TODO : textile+lhs 
           ,("html"         , readHtml)
           ,("latex"        , readLaTeX)
diff --git a/src/Text/Pandoc/Parsing.hs b/src/Text/Pandoc/Parsing.hs
--- a/src/Text/Pandoc/Parsing.hs
+++ b/src/Text/Pandoc/Parsing.hs
@@ -52,6 +52,7 @@
                              failUnlessLHS,
                              escaped,
                              characterReference,
+                             updateLastStrPos,
                              anyOrderedListMarker,
                              orderedListMarker,
                              charRef,
@@ -785,6 +786,10 @@
   oneOf cs <|> try (do c <- characterReference
                        guard (c `elem` cs)
                        return c)
+
+updateLastStrPos :: GenParser Char ParserState ()
+updateLastStrPos = getPosition >>= \p -> 
+  updateState $ \s -> s{ stateLastStrPos = Just p }
 
 singleQuoteStart :: GenParser Char ParserState ()
 singleQuoteStart = do
diff --git a/src/Text/Pandoc/Readers/DocBook.hs b/src/Text/Pandoc/Readers/DocBook.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Pandoc/Readers/DocBook.hs
@@ -0,0 +1,903 @@
+module Text.Pandoc.Readers.DocBook ( readDocBook ) where
+import Data.Char (toUpper, isDigit)
+import Text.Pandoc.Parsing (ParserState(..))
+import Text.Pandoc.Definition
+import Text.Pandoc.Builder
+import Text.XML.Light
+import Text.HTML.TagSoup.Entity (lookupEntity)
+import Data.Generics
+import Data.Monoid
+import Data.Char (isSpace)
+import Control.Monad.State
+import Control.Applicative ((<$>))
+import Data.List (intersperse)
+
+{-
+
+List of all DocBook tags, with [x] indicating implemented,
+[o] meaning intentionally left unimplemented (pass through):
+
+[o] abbrev - An abbreviation, especially one followed by a period
+[x] abstract - A summary
+[o] accel - A graphical user interface (GUI) keyboard shortcut
+[x] ackno - Acknowledgements in an Article
+[o] acronym - An often pronounceable word made from the initial
+[o] action - A response to a user event
+[o] address - A real-world address, generally a postal address
+[ ] affiliation - The institutional affiliation of an individual
+[ ] alt - Text representation for a graphical element
+[o] anchor - A spot in the document
+[x] answer - An answer to a question posed in a QandASet
+[x] appendix - An appendix in a Book or Article
+[x] appendixinfo - Meta-information for an Appendix
+[o] application - The name of a software program
+[x] area - A region defined for a Callout in a graphic or code example
+[x] areaset - A set of related areas in a graphic or code example
+[x] areaspec - A collection of regions in a graphic or code example
+[ ] arg - An argument in a CmdSynopsis
+[x] article - An article
+[x] articleinfo - Meta-information for an Article
+[ ] artpagenums - The page numbers of an article as published
+[x] attribution - The source of a block quote or epigraph
+[ ] audiodata - Pointer to external audio data
+[ ] audioobject - A wrapper for audio data and its associated meta-information
+[x] author - The name of an individual author
+[ ] authorblurb - A short description or note about an author
+[ ] authorgroup - Wrapper for author information when a document has
+    multiple authors or collabarators
+[x] authorinitials - The initials or other short identifier for an author
+[o] beginpage - The location of a page break in a print version of the document
+[ ] bibliocoverage - The spatial or temporal coverage of a document
+[x] bibliodiv - A section of a Bibliography
+[x] biblioentry - An entry in a Bibliography
+[x] bibliography - A bibliography
+[ ] bibliographyinfo - Meta-information for a Bibliography
+[ ] biblioid - An identifier for a document
+[o] bibliolist - A wrapper for a set of bibliography entries
+[ ] bibliomisc - Untyped bibliographic information
+[x] bibliomixed - An entry in a Bibliography
+[ ] bibliomset - A cooked container for related bibliographic information
+[ ] biblioref - A cross reference to a bibliographic entry
+[ ] bibliorelation - The relationship of a document to another
+[ ] biblioset - A raw container for related bibliographic information
+[ ] bibliosource - The source of a document
+[ ] blockinfo - Meta-information for a block element
+[x] blockquote - A quotation set off from the main text
+[x] book - A book
+[x] bookinfo - Meta-information for a Book
+[x] bridgehead - A free-floating heading
+[ ] callout - A “called out” description of a marked Area
+[ ] calloutlist - A list of Callouts
+[x] caption - A caption
+[x] caution - A note of caution
+[x] chapter - A chapter, as of a book
+[x] chapterinfo - Meta-information for a Chapter
+[ ] citation - An inline bibliographic reference to another published work
+[ ] citebiblioid - A citation of a bibliographic identifier
+[ ] citerefentry - A citation to a reference page
+[ ] citetitle - The title of a cited work
+[ ] city - The name of a city in an address
+[ ] classname - The name of a class, in the object-oriented programming sense
+[ ] classsynopsis - The syntax summary for a class definition
+[ ] classsynopsisinfo - Information supplementing the contents of
+    a ClassSynopsis
+[ ] cmdsynopsis - A syntax summary for a software command
+[ ] co - The location of a callout embedded in text
+[x] code - An inline code fragment
+[x] col - Specifications for a column in an HTML table
+[x] colgroup - A group of columns in an HTML table
+[ ] collab - Identifies a collaborator
+[ ] collabname - The name of a collaborator
+[ ] colophon - Text at the back of a book describing facts about its production
+[x] colspec - Specifications for a column in a table
+[x] command - The name of an executable program or other software command
+[x] computeroutput - Data, generally text, displayed or presented by a computer
+[ ] confdates - The dates of a conference for which a document was written
+[ ] confgroup - A wrapper for document meta-information about a conference
+[ ] confnum - An identifier, frequently numerical, associated with a conference for which a document was written
+[ ] confsponsor - The sponsor of a conference for which a document was written
+[ ] conftitle - The title of a conference for which a document was written
+[x] constant - A programming or system constant
+[ ] constraint - A constraint in an EBNF production
+[ ] constraintdef - The definition of a constraint in an EBNF production
+[ ] constructorsynopsis - A syntax summary for a constructor
+[ ] contractnum - The contract number of a document
+[ ] contractsponsor - The sponsor of a contract
+[ ] contrib - A summary of the contributions made to a document by a
+    credited source
+[ ] copyright - Copyright information about a document
+[ ] coref - A cross reference to a co
+[ ] corpauthor - A corporate author, as opposed to an individual
+[ ] corpcredit - A corporation or organization credited in a document
+[ ] corpname - The name of a corporation
+[ ] country - The name of a country
+[ ] database - The name of a database, or part of a database
+[x] date - The date of publication or revision of a document
+[ ] dedication - A wrapper for the dedication section of a book
+[ ] destructorsynopsis - A syntax summary for a destructor
+[ ] edition - The name or number of an edition of a document
+[ ] editor - The name of the editor of a document
+[x] email - An email address
+[x] emphasis - Emphasized text
+[x] entry - A cell in a table
+[ ] entrytbl - A subtable appearing in place of an Entry in a table
+[ ] envar - A software environment variable
+[x] epigraph - A short inscription at the beginning of a document or component
+    note:  also handle embedded attribution tag
+[ ] equation - A displayed mathematical equation
+[ ] errorcode - An error code
+[ ] errorname - An error name
+[ ] errortext - An error message.
+[ ] errortype - The classification of an error message
+[ ] example - A formal example, with a title
+[ ] exceptionname - The name of an exception
+[ ] fax - A fax number
+[ ] fieldsynopsis - The name of a field in a class definition
+[ ] figure - A formal figure, generally an illustration, with a title
+[x] filename - The name of a file
+[ ] firstname - The first name of a person
+[ ] firstterm - The first occurrence of a term
+[x] footnote - A footnote
+[ ] footnoteref - A cross reference to a footnote (a footnote mark)
+[x] foreignphrase - A word or phrase in a language other than the primary
+    language of the document
+[x] formalpara - A paragraph with a title
+[ ] funcdef - A function (subroutine) name and its return type
+[ ] funcparams - Parameters for a function referenced through a function
+    pointer in a synopsis
+[ ] funcprototype - The prototype of a function
+[ ] funcsynopsis - The syntax summary for a function definition
+[ ] funcsynopsisinfo - Information supplementing the FuncDefs of a FuncSynopsis
+[x] function - The name of a function or subroutine, as in a
+    programming language
+[x] glossary - A glossary
+[x] glossaryinfo - Meta-information for a Glossary
+[x] glossdef - A definition in a GlossEntry
+[x] glossdiv - A division in a Glossary
+[x] glossentry - An entry in a Glossary or GlossList
+[x] glosslist - A wrapper for a set of GlossEntrys
+[x] glosssee - A cross-reference from one GlossEntry to another
+[x] glossseealso - A cross-reference from one GlossEntry to another
+[x] glossterm - A glossary term
+[ ] graphic - A displayed graphical object (not an inline)
+[ ] graphicco - A graphic that contains callout areas
+[ ] group - A group of elements in a CmdSynopsis
+[ ] guibutton - The text on a button in a GUI
+[ ] guiicon - Graphic and/or text appearing as a icon in a GUI
+[ ] guilabel - The text of a label in a GUI
+[ ] guimenu - The name of a menu in a GUI
+[ ] guimenuitem - The name of a terminal menu item in a GUI
+[ ] guisubmenu - The name of a submenu in a GUI
+[ ] hardware - A physical part of a computer system
+[ ] highlights - A summary of the main points of the discussed component
+[ ] holder - The name of the individual or organization that holds a copyright
+[o] honorific - The title of a person
+[ ] html:form - An HTML form
+[ ] imagedata - Pointer to external image data
+[ ] imageobject - A wrapper for image data and its associated meta-information
+[ ] imageobjectco - A wrapper for an image object with callouts
+[x] important - An admonition set off from the text
+[x] index - An index
+[x] indexdiv - A division in an index
+[x] indexentry - An entry in an index
+[x] indexinfo - Meta-information for an Index
+[x] indexterm - A wrapper for terms to be indexed
+[x] info - A wrapper for information about a component or other block. (DocBook v5)
+[ ] informalequation - A displayed mathematical equation without a title
+[ ] informalexample - A displayed example without a title
+[ ] informalfigure - A untitled figure
+[ ] informaltable - A table without a title
+[ ] initializer - The initializer for a FieldSynopsis
+[ ] inlineequation - A mathematical equation or expression occurring inline
+[ ] inlinegraphic - An object containing or pointing to graphical data
+    that will be rendered inline
+[x] inlinemediaobject - An inline media object (video, audio, image, and so on)
+[ ] interface - An element of a GUI
+[ ] interfacename - The name of an interface
+[ ] invpartnumber - An inventory part number
+[ ] isbn - The International Standard Book Number of a document
+[ ] issn - The International Standard Serial Number of a periodical
+[ ] issuenum - The number of an issue of a journal
+[x] itemizedlist - A list in which each entry is marked with a bullet or
+    other dingbat
+[ ] itermset - A set of index terms in the meta-information of a document
+[ ] jobtitle - The title of an individual in an organization
+[ ] keycap - The text printed on a key on a keyboard
+[ ] keycode - The internal, frequently numeric, identifier for a key
+    on a keyboard
+[ ] keycombo - A combination of input actions
+[ ] keysym - The symbolic name of a key on a keyboard
+[ ] keyword - One of a set of keywords describing the content of a document
+[ ] keywordset - A set of keywords describing the content of a document
+[ ] label - A label on a Question or Answer
+[ ] legalnotice - A statement of legal obligations or requirements
+[ ] lhs - The left-hand side of an EBNF production
+[ ] lineage - The portion of a person's name indicating a relationship to
+    ancestors
+[ ] lineannotation - A comment on a line in a verbatim listing
+[x] link - A hypertext link
+[x] listitem - A wrapper for the elements of a list item
+[x] literal - Inline text that is some literal value
+[x] literallayout - A block of text in which line breaks and white space are
+    to be reproduced faithfully
+[ ] lot - A list of the titles of formal objects (as tables or figures) in
+    a document
+[ ] lotentry - An entry in a list of titles
+[ ] manvolnum - A reference volume number
+[x] markup - A string of formatting markup in text that is to be
+    represented literally
+[ ] mathphrase - A mathematical phrase, an expression that can be represented
+    with ordinary text and a small amount of markup
+[ ] medialabel - A name that identifies the physical medium on which some
+    information resides
+[x] mediaobject - A displayed media object (video, audio, image, etc.)
+[ ] mediaobjectco - A media object that contains callouts
+[x] member - An element of a simple list
+[ ] menuchoice - A selection or series of selections from a menu
+[ ] methodname - The name of a method
+[ ] methodparam - Parameters to a method
+[ ] methodsynopsis - A syntax summary for a method
+[ ] mml:math - A MathML equation
+[ ] modespec - Application-specific information necessary for the
+    completion of an OLink
+[ ] modifier - Modifiers in a synopsis
+[ ] mousebutton - The conventional name of a mouse button
+[ ] msg - A message in a message set
+[ ] msgaud - The audience to which a message in a message set is relevant
+[ ] msgentry - A wrapper for an entry in a message set
+[ ] msgexplan - Explanatory material relating to a message in a message set
+[ ] msginfo - Information about a message in a message set
+[ ] msglevel - The level of importance or severity of a message in a message set
+[ ] msgmain - The primary component of a message in a message set
+[ ] msgorig - The origin of a message in a message set
+[ ] msgrel - A related component of a message in a message set
+[ ] msgset - A detailed set of messages, usually error messages
+[ ] msgsub - A subcomponent of a message in a message set
+[ ] msgtext - The actual text of a message component in a message set
+[ ] nonterminal - A non-terminal in an EBNF production
+[x] note - A message set off from the text
+[ ] objectinfo - Meta-information for an object
+[ ] olink - A link that addresses its target indirectly, through an entity
+[ ] ooclass - A class in an object-oriented programming language
+[ ] ooexception - An exception in an object-oriented programming language
+[ ] oointerface - An interface in an object-oriented programming language
+[x] option - An option for a software command
+[x] optional - Optional information
+[x] orderedlist - A list in which each entry is marked with a sequentially
+    incremented label
+[ ] orgdiv - A division of an organization
+[ ] orgname - The name of an organization other than a corporation
+[ ] otheraddr - Uncategorized information in address
+[ ] othercredit - A person or entity, other than an author or editor,
+    credited in a document
+[ ] othername - A component of a persons name that is not a first name,
+    surname, or lineage
+[ ] package - A package
+[ ] pagenums - The numbers of the pages in a book, for use in a bibliographic
+    entry
+[x] para - A paragraph
+[ ] paramdef - Information about a function parameter in a programming language
+[x] parameter - A value or a symbolic reference to a value
+[ ] part - A division in a book
+[ ] partinfo - Meta-information for a Part
+[ ] partintro - An introduction to the contents of a part
+[ ] personblurb - A short description or note about a person
+[ ] personname - The personal name of an individual
+[ ] phone - A telephone number
+[ ] phrase - A span of text
+[ ] pob - A post office box in an address
+[ ] postcode - A postal code in an address
+[x] preface - Introductory matter preceding the first chapter of a book
+[ ] prefaceinfo - Meta-information for a Preface
+[ ] primary - The primary word or phrase under which an index term should be
+    sorted
+[ ] primaryie - A primary term in an index entry, not in the text
+[ ] printhistory - The printing history of a document
+[ ] procedure - A list of operations to be performed in a well-defined sequence
+[ ] production - A production in a set of EBNF productions
+[ ] productionrecap - A cross-reference to an EBNF production
+[ ] productionset - A set of EBNF productions
+[ ] productname - The formal name of a product
+[ ] productnumber - A number assigned to a product
+[x] programlisting - A literal listing of all or part of a program
+[ ] programlistingco - A program listing with associated areas used in callouts
+[x] prompt - A character or string indicating the start of an input field in
+    a computer display
+[ ] property - A unit of data associated with some part of a computer system
+[ ] pubdate - The date of publication of a document
+[ ] publisher - The publisher of a document
+[ ] publishername - The name of the publisher of a document
+[ ] pubsnumber - A number assigned to a publication other than an ISBN or ISSN
+    or inventory part number
+[x] qandadiv - A titled division in a QandASet
+[o] qandaentry - A question/answer set within a QandASet
+[o] qandaset - A question-and-answer set
+[x] question - A question in a QandASet
+[x] quote - An inline quotation
+[ ] refclass - The scope or other indication of applicability of a
+    reference entry
+[ ] refdescriptor - A description of the topic of a reference page
+[ ] refentry - A reference page (originally a UNIX man-style reference page)
+[ ] refentryinfo - Meta-information for a Refentry
+[ ] refentrytitle - The title of a reference page
+[ ] reference - A collection of reference entries
+[ ] referenceinfo - Meta-information for a Reference
+[ ] refmeta - Meta-information for a reference entry
+[ ] refmiscinfo - Meta-information for a reference entry other than the title
+    and volume number
+[ ] refname - The name of (one of) the subject(s) of a reference page
+[ ] refnamediv - The name, purpose, and classification of a reference page
+[ ] refpurpose - A short (one sentence) synopsis of the topic of a reference
+    page
+[x] refsect1 - A major subsection of a reference entry
+[x] refsect1info - Meta-information for a RefSect1
+[x] refsect2 - A subsection of a RefSect1
+[x] refsect2info - Meta-information for a RefSect2
+[x] refsect3 - A subsection of a RefSect2
+[x] refsect3info - Meta-information for a RefSect3
+[x] refsection - A recursive section in a refentry
+[x] refsectioninfo - Meta-information for a refsection
+[ ] refsynopsisdiv - A syntactic synopsis of the subject of the reference page
+[ ] refsynopsisdivinfo - Meta-information for a RefSynopsisDiv
+[ ] releaseinfo - Information about a particular release of a document
+[ ] remark - A remark (or comment) intended for presentation in a draft
+    manuscript
+[ ] replaceable - Content that may or must be replaced by the user
+[ ] returnvalue - The value returned by a function
+[ ] revdescription - A extended description of a revision to a document
+[ ] revhistory - A history of the revisions to a document
+[ ] revision - An entry describing a single revision in the history of the
+    revisions to a document
+[ ] revnumber - A document revision number
+[ ] revremark - A description of a revision to a document
+[ ] rhs - The right-hand side of an EBNF production
+[x] row - A row in a table
+[ ] sbr - An explicit line break in a command synopsis
+[x] screen - Text that a user sees or might see on a computer screen
+[o] screenco - A screen with associated areas used in callouts
+[o] screeninfo - Information about how a screen shot was produced
+[ ] screenshot - A representation of what the user sees or might see on a
+    computer screen
+[ ] secondary - A secondary word or phrase in an index term
+[ ] secondaryie - A secondary term in an index entry, rather than in the text
+[x] sect1 - A top-level section of document
+[x] sect1info - Meta-information for a Sect1
+[x] sect2 - A subsection within a Sect1
+[x] sect2info - Meta-information for a Sect2
+[x] sect3 - A subsection within a Sect2
+[x] sect3info - Meta-information for a Sect3
+[x] sect4 - A subsection within a Sect3
+[x] sect4info - Meta-information for a Sect4
+[x] sect5 - A subsection within a Sect4
+[x] sect5info - Meta-information for a Sect5
+[x] section - A recursive section
+[x] sectioninfo - Meta-information for a recursive section
+[x] see - Part of an index term directing the reader instead to another entry
+    in the index
+[x] seealso - Part of an index term directing the reader also to another entry
+    in the index
+[ ] seealsoie - A See also entry in an index, rather than in the text
+[ ] seeie - A See entry in an index, rather than in the text
+[x] seg - An element of a list item in a segmented list
+[x] seglistitem - A list item in a segmented list
+[x] segmentedlist - A segmented list, a list of sets of elements
+[x] segtitle - The title of an element of a list item in a segmented list
+[ ] seriesvolnums - Numbers of the volumes in a series of books
+[ ] set - A collection of books
+[ ] setindex - An index to a set of books
+[ ] setindexinfo - Meta-information for a SetIndex
+[ ] setinfo - Meta-information for a Set
+[ ] sgmltag - A component of SGML markup
+[ ] shortaffil - A brief description of an affiliation
+[ ] shortcut - A key combination for an action that is also accessible through
+    a menu
+[ ] sidebar - A portion of a document that is isolated from the main
+    narrative flow
+[ ] sidebarinfo - Meta-information for a Sidebar
+[x] simpara - A paragraph that contains only text and inline markup, no block
+    elements
+[x] simplelist - An undecorated list of single words or short phrases
+[ ] simplemsgentry - A wrapper for a simpler entry in a message set
+[ ] simplesect - A section of a document with no subdivisions
+[ ] spanspec - Formatting information for a spanned column in a table
+[ ] state - A state or province in an address
+[ ] step - A unit of action in a procedure
+[ ] stepalternatives - Alternative steps in a procedure
+[ ] street - A street address in an address
+[ ] structfield - A field in a structure (in the programming language sense)
+[ ] structname - The name of a structure (in the programming language sense)
+[ ] subject - One of a group of terms describing the subject matter of a
+    document
+[ ] subjectset - A set of terms describing the subject matter of a document
+[ ] subjectterm - A term in a group of terms describing the subject matter of
+    a document
+[x] subscript - A subscript (as in H2O, the molecular formula for water)
+[ ] substeps - A wrapper for steps that occur within steps in a procedure
+[x] subtitle - The subtitle of a document
+[x] superscript - A superscript (as in x2, the mathematical notation for x
+    multiplied by itself)
+[ ] surname - A family name; in western cultures the last name
+[ ] svg:svg - An SVG graphic
+[x] symbol - A name that is replaced by a value before processing
+[ ] synopfragment - A portion of a CmdSynopsis broken out from the main body
+    of the synopsis
+[ ] synopfragmentref - A reference to a fragment of a command synopsis
+[ ] synopsis - A general-purpose element for representing the syntax of
+    commands or functions
+[ ] systemitem - A system-related item or term
+[ ] table - A formal table in a document
+[ ] task - A task to be completed
+[ ] taskprerequisites - The prerequisites for a task
+[ ] taskrelated - Information related to a task
+[ ] tasksummary - A summary of a task
+[x] tbody - A wrapper for the rows of a table or informal table
+[x] td - A table entry in an HTML table
+[x] term - The word or phrase being defined or described in a variable list
+[ ] termdef - An inline term definition
+[ ] tertiary - A tertiary word or phrase in an index term
+[ ] tertiaryie - A tertiary term in an index entry, rather than in the text
+[ ] textdata - Pointer to external text data
+[ ] textobject - A wrapper for a text description of an object and its
+    associated meta-information
+[ ] tfoot - A table footer consisting of one or more rows
+[x] tgroup - A wrapper for the main content of a table, or part of a table
+[x] th - A table header entry in an HTML table
+[x] thead - A table header consisting of one or more rows
+[x] tip - A suggestion to the user, set off from the text
+[x] title - The text of the title of a section of a document or of a formal
+    block-level element
+[x] titleabbrev - The abbreviation of a Title
+[x] toc - A table of contents
+[x] tocback - An entry in a table of contents for a back matter component
+[x] tocchap - An entry in a table of contents for a component in the body of
+    a document
+[x] tocentry - A component title in a table of contents
+[x] tocfront - An entry in a table of contents for a front matter component
+[x] toclevel1 - A top-level entry within a table of contents entry for a
+    chapter-like component
+[x] toclevel2 - A second-level entry within a table of contents entry for a 
+    chapter-like component
+[x] toclevel3 - A third-level entry within a table of contents entry for a 
+    chapter-like component
+[x] toclevel4 - A fourth-level entry within a table of contents entry for a 
+    chapter-like component
+[x] toclevel5 - A fifth-level entry within a table of contents entry for a 
+    chapter-like component
+[x] tocpart - An entry in a table of contents for a part of a book
+[ ] token - A unit of information
+[x] tr - A row in an HTML table
+[ ] trademark - A trademark
+[ ] type - The classification of a value
+[x] ulink - A link that addresses its target by means of a URL
+    (Uniform Resource Locator)
+[x] uri - A Uniform Resource Identifier
+[x] userinput - Data entered by the user
+[x] varargs - An empty element in a function synopsis indicating a variable
+    number of arguments
+[x] variablelist - A list in which each entry is composed of a set of one or
+    more terms and an associated description
+[x] varlistentry - A wrapper for a set of terms and the associated description
+    in a variable list
+[x] varname - The name of a variable
+[ ] videodata - Pointer to external video data
+[ ] videoobject - A wrapper for video data and its associated meta-information
+[ ] void - An empty element in a function synopsis indicating that the
+    function in question takes no arguments
+[ ] volumenum - The volume number of a document in a set (as of books in a set
+    or articles in a journal)
+[x] warning - An admonition set off from the text
+[x] wordasword - A word meant specifically as a word and not representing
+    anything else
+[ ] xref - A cross reference to another part of the document
+[ ] year - The year of publication of a document
+
+-}
+
+type DB = State DBState
+
+data DBState = DBState{ dbSectionLevel :: Int
+                      , dbQuoteType    :: QuoteType
+                      , dbDocTitle     :: Inlines
+                      , dbDocAuthors   :: [Inlines]
+                      , dbDocDate      :: Inlines
+                      , dbBook         :: Bool
+                      } deriving Show
+
+readDocBook :: ParserState -> String -> Pandoc
+readDocBook _ inp  = setTitle (dbDocTitle st')
+                   $ setAuthors (dbDocAuthors st')
+                   $ setDate (dbDocDate st')
+                   $ doc $ mconcat bs
+  where (bs, st') = runState (mapM parseBlock $ normalizeTree $ parseXML inp)
+                             DBState{ dbSectionLevel = 0
+                                    , dbQuoteType = DoubleQuote
+                                    , dbDocTitle = mempty
+                                    , dbDocAuthors = []
+                                    , dbDocDate = mempty
+                                    , dbBook = False
+                                    }
+
+-- normalize input, consolidating adjacent Text and CRef elements
+normalizeTree :: [Content] -> [Content]
+normalizeTree = everywhere (mkT go)
+  where go :: [Content] -> [Content]
+        go (Text (CData CDataRaw _ _):xs) = xs
+        go (Text (CData CDataText s1 z):Text (CData CDataText s2 _):xs) =
+           Text (CData CDataText (s1 ++ s2) z):xs
+        go (Text (CData CDataText s1 z):CRef r:xs) =
+           Text (CData CDataText (s1 ++ convertEntity r) z):xs
+        go (CRef r:Text (CData CDataText s1 z):xs) =
+             Text (CData CDataText (convertEntity r ++ s1) z):xs
+        go (CRef r1:CRef r2:xs) =
+             Text (CData CDataText (convertEntity r1 ++ convertEntity r2) Nothing):xs
+        go xs = xs
+
+convertEntity :: String -> String
+convertEntity e = maybe (map toUpper e) (:[]) (lookupEntity e)
+
+-- convenience function to get an attribute value, defaulting to ""
+attrValue :: String -> Element -> String
+attrValue attr elt =
+  case lookupAttrBy (\x -> qName x == attr) (elAttribs elt) of
+    Just z  -> z
+    Nothing -> ""
+
+-- convenience function
+named :: String -> Element -> Bool
+named s e = qName (elName e) == s
+
+isBlockElement :: Content -> Bool
+isBlockElement (Elem e) = qName (elName e) `elem` blocktags
+  where blocktags = ["toc","index","para","formalpara","simpara",
+           "ackno","epigraph","blockquote","bibliography","bibliodiv",
+           "biblioentry","glossee","glosseealso","glossary",
+           "glossdiv","glosslist","chapter","appendix","preface",
+           "bridgehead","sect1","sect2","sect3","sect4","sect5","section",
+           "refsect1","refsect2","refsect3","refsection",
+           "important","caution","note","tip","warning","qandadiv",
+           "question","answer","abstract","itemizedlist","orderedlist",
+           "variablelist","article","book","table","informaltable",
+           "screen","programlisting","example"]
+isBlockElement _ = False
+
+-- Trim leading and trailing newline characters
+trimNl :: String -> String
+trimNl = reverse . go . reverse . go
+  where go ('\n':xs) = xs
+        go xs        = xs
+
+-- meld text into beginning of first paragraph of Blocks.
+-- assumes Blocks start with a Para; if not, does nothing.
+addToStart :: Inlines -> Blocks -> Blocks
+addToStart toadd bs =
+  case toList bs of
+    (Para xs : rest) -> para (toadd <> fromList xs) <> fromList rest
+    _                -> bs
+
+-- function that is used by both mediaobject (in parseBlock) 
+-- and inlinemediaobject (in parseInline)
+getImage :: Element -> DB Inlines
+getImage e = do
+  imageUrl <- case filterChild (named "imageobject") e of
+                Nothing  -> return mempty
+                Just z   -> case filterChild (named "imagedata") z of
+                              Nothing -> return mempty
+                              Just i -> return $ attrValue "fileref" i
+  caption <- case filterChild
+                  (\x -> named "caption" x || named "textobject" x) e of
+               Nothing  -> return mempty
+               Just z   -> mconcat <$> (mapM parseInline $ elContent z)
+  return $ image imageUrl "" caption
+
+parseBlock :: Content -> DB Blocks
+parseBlock (Text (CData CDataRaw _ _)) = return mempty -- DOCTYPE
+parseBlock (Text (CData _ s _)) = if all isSpace s
+                                     then return mempty
+                                     else return $ plain $ trimInlines $ text s
+parseBlock (CRef x) = return $ plain $ str $ map toUpper x
+parseBlock (Elem e) =
+  case qName (elName e) of
+        "toc"   -> return mempty -- skip TOC, since in pandoc it's autogenerated
+        "index" -> return mempty -- skip index, since page numbers meaningless
+        "para"  -> parseMixed para (elContent e)
+        "formalpara" -> do
+           tit <- case filterChild (named "title") e of
+                        Just t  -> (<> str "." <> linebreak) <$> emph
+                                      <$> getInlines t
+                        Nothing -> return mempty
+           addToStart tit <$> parseMixed para (elContent e)
+        "simpara"  -> parseMixed para (elContent e)
+        "ackno"  -> parseMixed para (elContent e)
+        "epigraph" -> parseBlockquote
+        "blockquote" -> parseBlockquote
+        "attribution" -> return mempty
+        "titleabbrev" -> return mempty
+        "authorinitials" -> return mempty
+        "title" -> return mempty -- handled by getTitle or sect
+        "bibliography" -> sect 0
+        "bibliodiv" -> sect 1
+        "biblioentry" -> parseMixed para (elContent e)
+        "bibliomixed" -> parseMixed para (elContent e)
+        "glosssee" -> para . (\ils -> text "See " <> ils <> str ".")
+                         <$> getInlines e
+        "glossseealso" -> para . (\ils -> text "See also " <> ils <> str ".")
+                         <$> getInlines e
+        "glossary" -> sect 0
+        "glossdiv" -> definitionList <$>
+                  mapM parseGlossEntry (filterChildren (named "glossentry") e)
+        "glosslist" -> definitionList <$>
+                  mapM parseGlossEntry (filterChildren (named "glossentry") e)
+        "chapter" -> sect 0
+        "appendix" -> sect 0
+        "preface" -> sect 0
+        "bridgehead" -> para . strong <$> getInlines e
+        "sect1" -> sect 1
+        "sect2" -> sect 2
+        "sect3" -> sect 3
+        "sect4" -> sect 4
+        "sect5" -> sect 5
+        "section" -> gets dbSectionLevel >>= sect . (+1)
+        "refsect1" -> sect 1
+        "refsect2" -> sect 2
+        "refsect3" -> sect 3
+        "refsection" -> gets dbSectionLevel >>= sect . (+1)
+        "important" -> blockQuote . (para (strong $ str "Important") <>)
+                        <$> getBlocks e
+        "caution" -> blockQuote . (para (strong $ str "Caution") <>)
+                        <$> getBlocks e
+        "note" -> blockQuote . (para (strong $ str "Note") <>)
+                        <$> getBlocks e
+        "tip" -> blockQuote . (para (strong $ str "Tip") <>)
+                        <$> getBlocks e
+        "warning" -> blockQuote . (para (strong $ str "Warning") <>)
+                        <$> getBlocks e
+        "area" -> return mempty
+        "areaset" -> return mempty
+        "areaspec" -> return mempty
+        "qandadiv" -> gets dbSectionLevel >>= sect . (+1)
+        "question" -> addToStart (strong (str "Q:") <> str " ") <$> getBlocks e
+        "answer" -> addToStart (strong (str "A:") <> str " ") <$> getBlocks e
+        "abstract" -> blockQuote <$> getBlocks e
+        "itemizedlist" -> bulletList <$> listitems
+        "orderedlist" -> do
+          let listStyle = case attrValue "numeration" e of
+                               "arabic"     -> Decimal
+                               "loweralpha" -> LowerAlpha
+                               "upperalpha" -> UpperAlpha
+                               "lowerroman" -> LowerRoman
+                               "upperroman" -> UpperRoman
+                               _            -> Decimal
+          let start = case attrValue "override" <$>
+                            filterElement (named "listitem") e of
+                              Just x@(_:_) | all isDigit x -> read x
+                              _                            -> 1
+          orderedListWith (start,listStyle,DefaultDelim)
+            <$> listitems
+        "variablelist" -> definitionList <$> deflistitems
+        "mediaobject" -> para <$> (getImage e)
+        "caption" -> return mempty
+        "info" -> getTitle >> getAuthors >> getDate >> return mempty
+        "articleinfo" -> getTitle >> getAuthors >> getDate >> return mempty
+        "sectioninfo" -> return mempty  -- keywords & other metadata
+        "refsectioninfo" -> return mempty  -- keywords & other metadata
+        "refsect1info" -> return mempty  -- keywords & other metadata
+        "refsect2info" -> return mempty  -- keywords & other metadata
+        "refsect3info" -> return mempty  -- keywords & other metadata
+        "sect1info" -> return mempty  -- keywords & other metadata
+        "sect2info" -> return mempty  -- keywords & other metadata
+        "sect3info" -> return mempty  -- keywords & other metadata
+        "sect4info" -> return mempty  -- keywords & other metadata
+        "sect5info" -> return mempty  -- keywords & other metadata
+        "chapterinfo" -> return mempty  -- keywords & other metadata
+        "glossaryinfo" -> return mempty  -- keywords & other metadata
+        "appendixinfo" -> return mempty  -- keywords & other metadata
+        "bookinfo" -> getTitle >> getAuthors >> getDate >> return mempty
+        "article" -> modify (\st -> st{ dbBook = False }) >>
+                          getTitle >> getBlocks e
+        "book" -> modify (\st -> st{ dbBook = True }) >> getTitle >> getBlocks e
+        "table" -> parseTable
+        "informaltable" -> parseTable
+        "literallayout" -> codeBlockWithLang
+        "screen" -> codeBlockWithLang
+        "programlisting" -> codeBlockWithLang
+        "?xml"  -> return mempty
+        _       -> getBlocks e
+   where getBlocks e' =  mconcat <$> (mapM parseBlock $ elContent e')
+         parseMixed container conts = do
+           let (ils,rest) = break isBlockElement conts
+           ils' <- (trimInlines . mconcat) <$> mapM parseInline ils
+           let p = if ils' == mempty then mempty else container ils'
+           case rest of
+                 []     -> return p
+                 (r:rs) -> do
+                    b <- parseBlock r
+                    x <- parseMixed container rs
+                    return $ p <> b <> x
+         codeBlockWithLang = do
+           let classes' = case attrValue "language" e of
+                                ""   -> []
+                                x    -> [x]
+           return $ codeBlockWith (attrValue "id" e, classes', [])
+                  $ trimNl $ strContent e
+         parseBlockquote = do
+            attrib <- case filterChild (named "attribution") e of
+                             Nothing  -> return mempty
+                             Just z   -> (para . (str "— " <>) . mconcat)
+                                         <$> (mapM parseInline $ elContent z)
+            contents <- getBlocks e
+            return $ blockQuote (contents <> attrib)
+         listitems = mapM getBlocks $ filterChildren (named "listitem") e
+         deflistitems = mapM parseVarListEntry $ filterChildren
+                     (named "varlistentry") e
+         parseVarListEntry e' = do
+                     let terms = filterChildren (named "term") e'
+                     let items = filterChildren (named "listitem") e'
+                     terms' <- mapM getInlines terms
+                     items' <- mapM getBlocks items
+                     return (mconcat $ intersperse (str "; ") terms', items')
+         parseGlossEntry e' = do
+                     let terms = filterChildren (named "glossterm") e'
+                     let items = filterChildren (named "glossdef") e'
+                     terms' <- mapM getInlines terms
+                     items' <- mapM getBlocks items
+                     return (mconcat $ intersperse (str "; ") terms', items')
+         getTitle = case filterChild (named "title") e of
+                         Just t  -> do
+                            tit <- getInlines t
+                            subtit <-  case filterChild (named "subtitle") e of
+                                            Just s  -> (text ": " <>) <$>
+                                                         getInlines s
+                                            Nothing -> return mempty
+                            modify $ \st -> st{dbDocTitle = tit <> subtit}
+                         Nothing -> return ()
+         getAuthors = do
+                      auths <- mapM getInlines
+                               $ filterChildren (named "author") e
+                      modify $ \st -> st{dbDocAuthors = auths}
+         getDate = case filterChild (named "date") e of
+                         Just t  -> do
+                            dat <- getInlines t
+                            modify $ \st -> st{dbDocDate = dat}
+                         Nothing -> return ()
+         parseTable = do
+                      let isCaption x = named "title" x || named "caption" x
+                      caption <- case filterChild isCaption e of
+                                       Just t  -> getInlines t
+                                       Nothing -> return mempty
+                      let e' = maybe e id $ filterChild (named "tgroup") e
+                      let isColspec x = named "colspec" x || named "col" x
+                      let colspecs = case filterChild (named "colgroup") e' of
+                                           Just c -> filterChildren isColspec c
+                                           _      -> filterChildren isColspec e'
+                      let isRow x = named "row" x || named "tr" x
+                      headrows <- case filterChild (named "thead") e' of
+                                       Just h  -> case filterChild isRow h of
+                                                       Just x  -> parseRow x
+                                                       Nothing -> return []
+                                       Nothing -> return []
+                      bodyrows <- case filterChild (named "tbody") e' of
+                                       Just b  -> mapM parseRow
+                                                  $ filterChildren isRow b
+                                       Nothing -> mapM parseRow
+                                                  $ filterChildren isRow e'
+                      let toAlignment c = case findAttr (unqual "align") c of
+                                                Just "left"   -> AlignLeft
+                                                Just "right"  -> AlignRight
+                                                Just "center" -> AlignCenter
+                                                _             -> AlignDefault
+                      let toWidth c = case findAttr (unqual "colwidth") c of
+                                                Just w -> read $ filter (\x ->
+                                                     (x >= '0' && x <= '9')
+                                                      || x == '.') w
+                                                Nothing -> 0 :: Double
+                      let numrows = maximum $ map length bodyrows
+                      let aligns = case colspecs of
+                                     []  -> replicate numrows AlignDefault
+                                     cs  -> map toAlignment cs
+                      let widths = case colspecs of
+                                     []  -> replicate numrows 0
+                                     cs  -> let ws = map toWidth cs
+                                                tot = sum ws
+                                            in  if all (> 0) ws
+                                                   then map (/ tot) ws
+                                                   else replicate numrows 0
+                      let headrows' = if null headrows
+                                         then replicate numrows mempty
+                                         else headrows
+                      return $ table caption (zip aligns widths)
+                                 headrows' bodyrows
+         isEntry x  = named "entry" x || named "td" x || named "th" x
+         parseRow = mapM (parseMixed plain . elContent) . filterChildren isEntry
+         sect n = do isbook <- gets dbBook
+                     let n' = if isbook || n == 0 then n + 1 else n
+                     headerText <- case filterChild (named "title") e of
+                                      Just t -> getInlines t
+                                      Nothing -> return mempty
+                     modify $ \st -> st{ dbSectionLevel = n }
+                     b <- getBlocks e
+                     modify $ \st -> st{ dbSectionLevel = n - 1 }
+                     return $ header n' headerText <> b
+
+getInlines :: Element -> DB Inlines
+getInlines e' = (trimInlines . mconcat) <$> (mapM parseInline $ elContent e')
+
+parseInline :: Content -> DB Inlines
+parseInline (Text (CData _ s _)) = return $ text s
+parseInline (CRef ref) =
+  return $ maybe (text $ map toUpper ref) (text . (:[])) $ lookupEntity ref
+parseInline (Elem e) =
+  case qName (elName e) of
+        "subscript" -> subscript <$> innerInlines
+        "superscript" -> superscript <$> innerInlines
+        "inlinemediaobject" -> getImage e
+        "quote" -> do
+            qt <- gets dbQuoteType
+            let qt' = if qt == SingleQuote then DoubleQuote else SingleQuote
+            modify $ \st -> st{ dbQuoteType = qt' }
+            contents <- innerInlines
+            modify $ \st -> st{ dbQuoteType = qt }
+            return $ if qt == SingleQuote
+                        then singleQuoted contents
+                        else doubleQuoted contents
+        "simplelist" -> simpleList
+        "segmentedlist" -> segmentedList
+        "code" -> codeWithLang
+        "filename" -> codeWithLang
+        "literal" -> codeWithLang
+        "computeroutput" -> codeWithLang
+        "prompt" -> codeWithLang
+        "parameter" -> codeWithLang
+        "option" -> codeWithLang
+        "optional" -> do x <- getInlines e
+                         return $ str "[" <> x <> str "]"
+        "markup" -> codeWithLang
+        "wordasword" -> emph <$> innerInlines
+        "command" -> codeWithLang
+        "varname" -> codeWithLang
+        "function" -> codeWithLang
+        "type"    -> codeWithLang
+        "symbol"  -> codeWithLang
+        "constant" -> codeWithLang
+        "userinput" -> codeWithLang
+        "varargs" -> return $ code "(...)"
+        "xref" -> return $ str "?" -- so at least you know something is there
+        "email" -> return $ link ("mailto:" ++ strContent e) ""
+                          $ code $ strContent e
+        "uri" -> return $ link (strContent e) "" $ code $ strContent e
+        "ulink" -> link (attrValue "url" e) "" <$> innerInlines
+        "link" -> do
+             ils <- innerInlines
+             let href = case findAttr (QName "href" (Just "http://www.w3.org/1999/xlink") Nothing) e of
+                               Just h -> h
+                               _      -> ('#' : attrValue "linkend" e)
+             let ils' = if ils == mempty then code href else ils
+             return $ link href "" ils'
+        "foreignphrase" -> emph <$> innerInlines
+        "emphasis" -> case attrValue "role" e of
+                             "strong" -> strong <$> innerInlines
+                             "strikethrough" -> strikeout <$> innerInlines
+                             _        -> emph <$> innerInlines
+        "footnote" -> (note . mconcat) <$> (mapM parseBlock $ elContent e)
+        "title" -> return mempty
+        _          -> innerInlines
+   where innerInlines = (trimInlines . mconcat) <$>
+                          (mapM parseInline $ elContent e)
+         codeWithLang = do
+           let classes' = case attrValue "language" e of
+                               "" -> []
+                               l  -> [l]
+           return $ codeWith (attrValue "id" e,classes',[]) $ strContent e
+         simpleList = (mconcat . intersperse (str "," <> space)) <$> mapM getInlines
+                         (filterChildren (named "member") e)
+         segmentedList = do
+           tit <- maybe (return mempty) getInlines $ filterChild (named "title") e
+           segtits <- mapM getInlines $ filterChildren (named "segtitle") e
+           segitems <- mapM (mapM getInlines . filterChildren (named "seg"))
+                          $ filterChildren (named "seglistitem") e
+           let toSeg = mconcat . zipWith (\x y -> strong (x <> str ":") <> space <>
+                                  y <> linebreak) segtits
+           let segs = mconcat $ map toSeg segitems
+           let tit' = if tit == mempty
+                         then mempty
+                         else strong tit <> linebreak
+           return $ linebreak <> tit' <> segs
diff --git a/src/Text/Pandoc/Readers/HTML.hs b/src/Text/Pandoc/Readers/HTML.hs
--- a/src/Text/Pandoc/Readers/HTML.hs
+++ b/src/Text/Pandoc/Readers/HTML.hs
@@ -46,9 +46,15 @@
 import Text.Pandoc.Parsing
 import Data.Maybe ( fromMaybe, isJust )
 import Data.List ( intercalate )
-import Data.Char ( isSpace, isDigit, toLower )
+import Data.Char ( isDigit, toLower )
 import Control.Monad ( liftM, guard, when )
 
+isSpace :: Char -> Bool
+isSpace ' '  = True
+isSpace '\t' = True
+isSpace '\n' = True
+isSpace _    = False
+
 -- | Convert HTML-formatted string to 'Pandoc' document.
 readHtml :: ParserState   -- ^ Parser state
          -> String        -- ^ String to parse (assumes @'\n'@ line endings)
@@ -222,6 +228,8 @@
 pSimpleTable = try $ do
   TagOpen _ _ <- pSatisfy (~== TagOpen "table" [])
   skipMany pBlank
+  caption <- option [] $ pInTags "caption" inline >>~ skipMany pBlank
+  skipMany $ pInTags "col" block >> skipMany pBlank
   head' <- option [] $ pOptInTag "thead" $ pInTags "tr" (pCell "th")
   skipMany pBlank
   rows <- pOptInTag "tbody"
@@ -231,7 +239,7 @@
   let cols = maximum $ map length rows
   let aligns = replicate cols AlignLeft
   let widths = replicate cols 0
-  return [Table [] aligns widths head' rows]
+  return [Table caption aligns widths head' rows]
 
 pCell :: String -> TagParser [TableCell]
 pCell celltype = try $ do
diff --git a/src/Text/Pandoc/Readers/LaTeX.hs b/src/Text/Pandoc/Readers/LaTeX.hs
--- a/src/Text/Pandoc/Readers/LaTeX.hs
+++ b/src/Text/Pandoc/Readers/LaTeX.hs
@@ -82,9 +82,16 @@
   case name of
         ""   -> mzero
         [c] | not (isLetter c) -> string [c]
-        cs   -> string cs <* optional sp
+        cs   -> string cs <* notFollowedBy letter <* optional sp
   return name
 
+dimenarg :: LP String
+dimenarg = try $ do
+  ch  <- option "" $ string "="
+  num <- many1 digit
+  dim <- oneOfStrings ["pt","pc","in","bp","cm","mm","dd","cc","sp"]
+  return $ ch ++ num ++ dim
+
 sp :: LP ()
 sp = skipMany1 $ satisfy (\c -> c == ' ' || c == '\t')
         <|> (try $ newline >>~ lookAhead anyChar >>~ notFollowedBy blankline)
@@ -112,18 +119,28 @@
   newline
   return ()
 
+bgroup :: LP ()
+bgroup = () <$ char '{'
+     <|> () <$ controlSeq "bgroup"
+     <|> () <$ controlSeq "begingroup"
+
+egroup :: LP ()
+egroup = () <$ char '}'
+     <|> () <$ controlSeq "egroup"
+     <|> () <$ controlSeq "endgroup"
+
 grouped :: Monoid a => LP a -> LP a
-grouped parser = try $ char '{' *> (mconcat <$> manyTill parser (char '}'))
+grouped parser = try $ bgroup *> (mconcat <$> manyTill parser egroup)
 
 braced :: LP String
-braced = char '{' *> (concat <$> manyTill
+braced = bgroup *> (concat <$> manyTill
          (  many1 (satisfy (\c -> c /= '\\' && c /= '}' && c /= '{'))
         <|> try (string "\\}")
         <|> try (string "\\{")
         <|> try (string "\\\\")
         <|> ((\x -> "{" ++ x ++ "}") <$> braced)
         <|> count 1 anyChar
-         ) (char '}'))
+         ) egroup)
 
 bracketed :: Monoid a => LP a -> LP a
 bracketed parser = try $ char '[' *> (mconcat <$> manyTill parser (char ']'))
@@ -181,7 +198,7 @@
 
 block :: LP Blocks
 block = (mempty <$ comment)
-    <|> (mempty <$ ((spaceChar <|> blankline) *> spaces))
+    <|> (mempty <$ ((spaceChar <|> newline) *> spaces))
     <|> environment
     <|> mempty <$ macro -- TODO improve macros, make them work everywhere
     <|> blockCommand
@@ -281,7 +298,9 @@
 authors = try $ do
   char '{'
   let oneAuthor = mconcat <$>
-       many1 (notFollowedBy' (controlSeq "and") >> inline)
+       many1 (notFollowedBy' (controlSeq "and") >>
+               (inline <|> mempty <$ blockCommand))
+               -- skip e.g. \vspace{10pt}
   auths <- sepBy oneAuthor (controlSeq "and")
   char '}'
   updateState (\s -> s { stateAuthors = map (normalizeSpaces . toList) auths })
@@ -304,17 +323,20 @@
   parseRaw <- stateParseRaw `fmap` getState
   star <- option "" (string "*")
   let name' = name ++ star
+  let rawargs = withRaw (skipopts *> option "" dimenarg
+                  *> many braced) >>= applyMacros' . snd
+  let raw = if parseRaw
+               then (rawInline "latex" . (('\\':name') ++)) <$> rawargs
+               else mempty <$> rawargs
   case M.lookup name' inlineCommands of
-       Just p      -> p
+       Just p      -> p <|> raw
        Nothing     -> case M.lookup name inlineCommands of
-                           Just p    -> p
-                           Nothing
-                             | parseRaw  ->
-                                (rawInline "latex" . (('\\':name') ++)) <$>
-                                 (withRaw (skipopts *> many braced)
-                                      >>= applyMacros' . snd)
-                             | otherwise -> return mempty
+                           Just p    -> p <|> raw
+                           Nothing   -> raw
 
+unlessParseRaw :: LP ()
+unlessParseRaw = getState >>= guard . not . stateParseRaw
+
 isBlockCommand :: String -> Bool
 isBlockCommand s = maybe False (const True) $ M.lookup s blockCommands
 
@@ -333,8 +355,8 @@
   , ("dots", lit "…")
   , ("mdots", lit "…")
   , ("sim", lit "~")
-  , ("label", inBrackets <$> tok)
-  , ("ref", inBrackets <$> tok)
+  , ("label", unlessParseRaw >> (inBrackets <$> tok))
+  , ("ref", unlessParseRaw >> (inBrackets <$> tok))
   , ("(", mathInline $ manyTill anyChar (try $ string "\\)"))
   , ("[", mathDisplay $ manyTill anyChar (try $ string "\\]"))
   , ("ensuremath", mathInline $ braced)
diff --git a/src/Text/Pandoc/Readers/Markdown.hs b/src/Text/Pandoc/Readers/Markdown.hs
--- a/src/Text/Pandoc/Readers/Markdown.hs
+++ b/src/Text/Pandoc/Readers/Markdown.hs
@@ -183,6 +183,7 @@
   st <- getState
   let firstPassParser = referenceKey
                      <|> (if stateStrict st then pzero else noteBlock)
+                     <|> liftM snd (withRaw codeBlockDelimited)
                      <|> lineClump
   docMinusKeys <- liftM concat $ manyTill firstPassParser eof
   setInput docMinusKeys
@@ -553,7 +554,6 @@
 -- parse a line of a list item (start = parser for beginning of list item)
 listLine :: GenParser Char ParserState [Char]
 listLine = try $ do
-  notFollowedBy' listStart
   notFollowedBy blankline
   notFollowedBy' (do indentSpaces
                      many (spaceChar)
@@ -562,12 +562,14 @@
   return $ concat chunks ++ "\n"
 
 -- parse raw text for one list item, excluding start marker and continuations
-rawListItem :: GenParser Char ParserState a -> GenParser Char ParserState [Char]
+rawListItem :: GenParser Char ParserState a
+            -> GenParser Char ParserState [Char]
 rawListItem start = try $ do
   start
-  result <- many1 listLine
+  first <- listLine
+  rest <- many (notFollowedBy listStart >> listLine)
   blanks <- many blankline
-  return $ concat result ++ blanks
+  return $ concat (first:rest)  ++ blanks
 
 -- continuation of a list item - indented and separated by blankline 
 -- or (in compact lists) endline.
@@ -587,8 +589,9 @@
   result <- manyTill anyChar newline
   return $ result ++ "\n"
 
-listItem :: GenParser Char ParserState a -> GenParser Char ParserState [Block]
-listItem start = try $ do 
+listItem :: GenParser Char ParserState a
+         -> GenParser Char ParserState [Block]
+listItem start = try $ do
   first <- rawListItem start
   continuations <- many listContinuation
   -- parsing with ListItemState forces markers at beginning of lines to
@@ -1023,11 +1026,11 @@
   notFollowedBy digit
   return $ intercalate " " words'
 
--- to avoid performance problems, treat 4 or more _ or * in a row as a literal
--- rather than attempting to parse for emph/strong
+-- to avoid performance problems, treat 4 or more _ or * or ~ or ^ in a row
+-- as a literal rather than attempting to parse for emph/strong/strikeout/super/sub
 fours :: GenParser Char st Inline
 fours = try $ do
-  x <- char '*' <|> char '_'
+  x <- char '*' <|> char '_' <|> char '~' <|> char '^'
   count 2 $ satisfy (==x)
   rest <- many1 (satisfy (==x))
   return $ Str (x:x:x:rest)
diff --git a/src/Text/Pandoc/Readers/Textile.hs b/src/Text/Pandoc/Readers/Textile.hs
--- a/src/Text/Pandoc/Readers/Textile.hs
+++ b/src/Text/Pandoc/Readers/Textile.hs
@@ -18,7 +18,7 @@
 
 {- |
    Module      : Text.Pandoc.Readers.Textile
-   Copyright   : Copyright (C) 2010-2011 Paul Rivier and John MacFarlane
+   Copyright   : Copyright (C) 2010-2012 Paul Rivier and John MacFarlane
    License     : GNU GPL, version 2 or above 
 
    Maintainer  : Paul Rivier <paul*rivier#demotera*com>
@@ -59,10 +59,12 @@
 import Text.Pandoc.Shared 
 import Text.Pandoc.Parsing
 import Text.Pandoc.Readers.HTML ( htmlTag, isInlineTag, isBlockTag )
+import Text.Pandoc.Readers.LaTeX ( rawLaTeXInline, rawLaTeXBlock )
 import Text.ParserCombinators.Parsec
 import Text.HTML.TagSoup.Match
-import Data.Char ( digitToInt, isLetter )
+import Data.Char ( digitToInt, isUpper )
 import Control.Monad ( guard, liftM )
+import Control.Applicative ((<$>), (*>), (<*))
 
 -- | Parse a Textile text and return a Pandoc document.
 readTextile :: ParserState -- ^ Parser state, including options for parser
@@ -72,14 +74,6 @@
   (readWith parseTextile) state{ stateOldDashes = True } (s ++ "\n\n")
 
 
---
--- Constants and data structure definitions
---
-
--- | Special chars border strings parsing
-specialChars :: [Char]
-specialChars = "\\[]<>*#_@~-+^&,.;:!?|\"'%()"
-
 -- | Generate a Pandoc ADT from a textile document
 parseTextile :: GenParser Char ParserState Pandoc
 parseTextile = do
@@ -128,6 +122,7 @@
                , hrule
                , anyList
                , rawHtmlBlock
+               , rawLaTeXBlock'
                , maybeExplicitBlock "table" table
                , maybeExplicitBlock "p" para
                , nullBlock ]
@@ -164,21 +159,16 @@
 header :: GenParser Char ParserState Block
 header = try $ do
   char 'h'
-  level <- oneOf "123456" >>= return . digitToInt
-  optional attributes
-  char '.'
-  whitespace
-  name <- manyTill inline blockBreak
-  return $ Header level (normalizeSpaces name)
+  level <- digitToInt <$> oneOf "123456"
+  optional attributes >> char '.' >> whitespace
+  name <- normalizeSpaces <$> manyTill inline blockBreak
+  return $ Header level name
 
 -- | Blockquote of the form "bq. content"
 blockQuote :: GenParser Char ParserState Block
 blockQuote = try $ do
-  string "bq"
-  optional attributes
-  char '.'
-  whitespace
-  para >>= return . BlockQuote . (:[])
+  string "bq" >> optional attributes >> char '.' >> whitespace
+  BlockQuote . singleton <$> para
 
 -- Horizontal rule
 
@@ -198,10 +188,7 @@
 -- strict in the nesting, sublist must start at exactly "parent depth
 -- plus one"
 anyList :: GenParser Char ParserState Block
-anyList = try $ do
-  l <- anyListAtDepth 1
-  blanklines
-  return l
+anyList = try $ ( (anyListAtDepth 1) <* blanklines )
 
 -- | This allow one type of list to be nested into an other type,
 -- provided correct nesting
@@ -212,20 +199,12 @@
 
 -- | Bullet List of given depth, depth being the number of leading '*'
 bulletListAtDepth :: Int -> GenParser Char ParserState Block
-bulletListAtDepth depth = try $ do
-  items <- many1 (bulletListItemAtDepth depth)
-  return (BulletList items)
+bulletListAtDepth depth = try $ BulletList <$> many1 (bulletListItemAtDepth depth)
 
 -- | Bullet List Item of given depth, depth being the number of
 -- leading '*'
 bulletListItemAtDepth :: Int -> GenParser Char ParserState [Block]
-bulletListItemAtDepth depth = try $ do
-  count depth (char '*')
-  optional attributes
-  whitespace
-  p <- inlines >>= return . Plain
-  sublist <- option [] (anyListAtDepth (depth + 1) >>= return . (:[]))
-  return (p:sublist)
+bulletListItemAtDepth = genericListItemAtDepth '*'
 
 -- | Ordered List of given depth, depth being the number of
 -- leading '#'
@@ -237,19 +216,19 @@
 -- | Ordered List Item of given depth, depth being the number of
 -- leading '#'
 orderedListItemAtDepth :: Int -> GenParser Char ParserState [Block]
-orderedListItemAtDepth depth = try $ do
-  count depth (char '#')
-  optional attributes
-  whitespace
-  p <- inlines >>= return . Plain
-  sublist <- option [] (anyListAtDepth (depth + 1) >>= return . (:[]))
-  return (p:sublist)
+orderedListItemAtDepth = genericListItemAtDepth '#'
 
+-- | Common implementation of list items
+genericListItemAtDepth :: Char -> Int -> GenParser Char ParserState [Block]
+genericListItemAtDepth c depth = try $ do
+  count depth (char c) >> optional attributes >> whitespace
+  p <- inlines
+  sublist <- option [] (singleton <$> anyListAtDepth (depth + 1))
+  return ((Plain p):sublist)
+
 -- | A definition list is a set of consecutive definition items
 definitionList :: GenParser Char ParserState Block  
-definitionList = try $ do
-  items <- many1 definitionListItem
-  return $ DefinitionList items
+definitionList = try $ DefinitionList <$> many1 definitionListItem
   
 -- | A definition list item in textile begins with '- ', followed by
 -- the term defined, then spaces and ":=". The definition follows, on
@@ -277,6 +256,8 @@
 blockBreak = try (newline >> blanklines >> return ()) <|>
               (lookAhead rawHtmlBlock >> return ())
 
+-- raw content
+
 -- | A raw Html Block, optionally followed by blanklines
 rawHtmlBlock :: GenParser Char ParserState Block
 rawHtmlBlock = try $ do
@@ -284,11 +265,16 @@
   optional blanklines
   return $ RawBlock "html" b
 
+-- | Raw block of LaTeX content
+rawLaTeXBlock' :: GenParser Char ParserState Block
+rawLaTeXBlock' = do
+  failIfStrict
+  RawBlock "latex" <$> (rawLaTeXBlock <* spaces)
+
+
 -- | In textile, paragraphs are separated by blank lines.
 para :: GenParser Char ParserState Block
-para = try $ do
-  content <- manyTill inline blockBreak
-  return $ Para $ normalizeSpaces content
+para = try $ Para . normalizeSpaces <$> manyTill inline blockBreak
 
 
 -- Tables
@@ -302,11 +288,7 @@
 
 -- | A table row is made of many table cells
 tableRow :: GenParser Char ParserState [TableCell]
-tableRow = try $ do
-  char '|'
-  cells <- endBy1 tableCell (char '|')
-  newline
-  return cells
+tableRow = try $ ( char '|' *> (endBy1 tableCell (char '|')) <* newline)
 
 -- | Many table rows
 tableRows :: GenParser Char ParserState [[TableCell]]
@@ -314,13 +296,8 @@
 
 -- | Table headers are made of cells separated by a tag "|_."
 tableHeaders :: GenParser Char ParserState [TableCell]
-tableHeaders = try $ do
-  let separator = (try $ string "|_.")
-  separator
-  headers <- sepBy1 tableCell separator
-  char '|'
-  newline
-  return headers
+tableHeaders = let separator = (try $ string "|_.") in
+  try $ ( separator *> (sepBy1 tableCell separator) <* char '|' <* newline )
   
 -- | A table with an optional header. Current implementation can
 -- handle tables with and without header, but will parse cells
@@ -370,17 +347,13 @@
                 , whitespace
                 , endline
                 , code
+                , escapedInline
                 , htmlSpan
                 , rawHtmlInline
+                , rawLaTeXInline'
                 , note
-                , simpleInline (string "??") (Cite [])
-                , simpleInline (string "**") Strong
-                , simpleInline (string "__") Emph
-                , simpleInline (char '*') Strong
-                , simpleInline (char '_') Emph
-                , simpleInline (char '-') Strikeout
-                , simpleInline (char '^') Superscript
-                , simpleInline (char '~') Subscript
+                , try $ (char '[' *> inlineMarkup <* char ']')
+                , inlineMarkup
                 , link
                 , image
                 , mark
@@ -388,6 +361,19 @@
                 , symbol
                 ]
 
+-- | Inline markups
+inlineMarkup :: GenParser Char ParserState Inline
+inlineMarkup = choice [ simpleInline (string "??") (Cite [])
+                      , simpleInline (string "**") Strong
+                      , simpleInline (string "__") Emph
+                      , simpleInline (char '*') Strong
+                      , simpleInline (char '_') Emph
+                      , simpleInline (char '+') Emph  -- approximates underline
+                      , simpleInline (char '-') Strikeout
+                      , simpleInline (char '^') Superscript
+                      , simpleInline (char '~') Subscript
+                      ]
+
 -- | Trademark, registered, copyright
 mark :: GenParser Char st Inline
 mark = try $ char '(' >> (try tm <|> try reg <|> copy)
@@ -413,41 +399,53 @@
 
 note :: GenParser Char ParserState Inline
 note = try $ do
-  char '['
-  ref <- many1 digit
-  char ']'
-  state <- getState
-  let notes = stateNotes state
+  ref <- (char '[' *> many1 digit <* char ']')
+  notes <- stateNotes <$> getState
   case lookup ref notes of
     Nothing   -> fail "note not found"
     Just raw  -> liftM Note $ parseFromString parseBlocks raw
 
+-- | Special chars 
+markupChars :: [Char]
+markupChars = "\\[]*#_@~-+^|%="
+
+-- | Break strings on following chars. Space tab and newline break for
+--  inlines breaking. Open paren breaks for mark. Quote, dash and dot
+--  break for smart punctuation. Punctuation breaks for regular
+--  punctuation. Double quote breaks for named links. > and < break
+--  for inline html.
+stringBreakers :: [Char]
+stringBreakers = " \t\n('-.,:!?;\"<>"
+
+wordBoundaries :: [Char]
+wordBoundaries = markupChars ++ stringBreakers
+
+-- | Parse a hyphened sequence of words
+hyphenedWords :: GenParser Char ParserState String
+hyphenedWords = try $ do
+  hd <- noneOf wordBoundaries
+  tl <- many ( (noneOf wordBoundaries) <|> 
+               try (oneOf markupChars <* lookAhead (noneOf wordBoundaries) ) )
+  let wd = hd:tl
+  option wd $ try $ 
+    (\r -> concat [wd, "-", r]) <$> (char '-' *> hyphenedWords)
+
 -- | Any string
 str :: GenParser Char ParserState Inline
 str = do
-  xs <- many1 (noneOf (specialChars ++ "\t\n "))
-  optional $ try $ do
-    lookAhead (char '(')
-    notFollowedBy' mark
-    getInput >>= setInput . (' ':) -- add space before acronym explanation
-  -- parse a following hyphen if followed by a letter
-  -- (this prevents unwanted interpretation as starting a strikeout section)
-  result <- option xs $ try $ do
-              char '-'
-              next <- lookAhead letter
-              guard $ isLetter (last xs) || isLetter next
-              return $ xs ++ "-"
-  pos <- getPosition
-  updateState $ \s -> s{ stateLastStrPos = Just pos }
-  return $ Str result
+  baseStr <- hyphenedWords
+  -- RedCloth compliance : if parsed word is uppercase and immediatly
+  -- followed by parens, parens content is unconditionally word acronym
+  fullStr <- option baseStr $ try $ do
+    guard $ all isUpper baseStr
+    acro <- enclosed (char '(') (char ')') anyChar
+    return $ concat [baseStr, " (", acro, ")"]
+  updateLastStrPos
+  return $ Str fullStr
 
 -- | Textile allows HTML span infos, we discard them
 htmlSpan :: GenParser Char ParserState Inline
-htmlSpan = try $ do
-  char '%'
-  _ <- attributes
-  content <- manyTill anyChar (char '%')
-  return $ Str content
+htmlSpan = try $ Str <$> ( char '%' *> attributes *> manyTill anyChar (char '%') )
 
 -- | Some number of space chars
 whitespace :: GenParser Char ParserState Inline
@@ -460,8 +458,13 @@
   return LineBreak
 
 rawHtmlInline :: GenParser Char ParserState Inline
-rawHtmlInline = liftM (RawInline "html" . snd)
-                $ htmlTag isInlineTag
+rawHtmlInline = RawInline "html" . snd <$> htmlTag isInlineTag
+                
+-- | Raw LaTeX Inline 
+rawLaTeXInline' :: GenParser Char ParserState Inline
+rawLaTeXInline' = try $ do
+  failIfStrict
+  rawLaTeXInline
 
 -- | Textile standard link syntax is "label":target
 link :: GenParser Char ParserState Inline
@@ -486,24 +489,39 @@
   char '!'
   return $ Image [Str alt] (src, alt)
 
--- | Any special symbol defined in specialChars
+escapedInline :: GenParser Char ParserState Inline
+escapedInline = escapedEqs <|> escapedTag
+
+escapedEqs :: GenParser Char ParserState Inline
+escapedEqs = Str <$> (try $ surrounded (string "==") anyChar)
+
+-- -- | literal text escaped between == ... ==
+-- escapedEqs :: GenParser Char ParserState Inline
+-- escapedEqs = try $ do
+--   string "=="
+--   contents <- manyTill anyChar (try $ string "==")
+--   return $ Str contents
+
+-- | literal text escaped btw <notextile> tags
+escapedTag :: GenParser Char ParserState Inline
+escapedTag = try $ Str <$>
+  enclosed (string "<notextile>") (string "</notextile>") anyChar
+
+-- | Any special symbol defined in wordBoundaries
 symbol :: GenParser Char ParserState Inline
-symbol = do
-  result <- oneOf specialChars
-  return $ Str [result]
+symbol = Str . singleton <$> oneOf wordBoundaries
 
 -- | Inline code
 code :: GenParser Char ParserState Inline
 code = code1 <|> code2
 
 code1 :: GenParser Char ParserState Inline
-code1 = surrounded (char '@') anyChar >>= return . Code nullAttr
+code1 = Code nullAttr <$> surrounded (char '@') anyChar
 
 code2 :: GenParser Char ParserState Inline
 code2 = do
   htmlTag (tagOpen (=="tt") null)
-  result' <- manyTill anyChar (try $ htmlTag $ tagClose (=="tt"))
-  return $ Code nullAttr result'
+  Code nullAttr <$> manyTill anyChar (try $ htmlTag $ tagClose (=="tt"))
 
 -- | Html / CSS attributes
 attributes :: GenParser Char ParserState String
@@ -524,3 +542,7 @@
 simpleInline border construct = surrounded border (inlineWithAttribute) >>=
                                 return . construct . normalizeSpaces
   where inlineWithAttribute = (try $ optional attributes) >> inline
+
+-- | Create a singleton list
+singleton :: a -> [a]
+singleton x = [x]
diff --git a/src/Text/Pandoc/Shared.hs b/src/Text/Pandoc/Shared.hs
--- a/src/Text/Pandoc/Shared.hs
+++ b/src/Text/Pandoc/Shared.hs
@@ -520,6 +520,7 @@
   , writerHighlight        :: Bool       -- ^ Highlight source code
   , writerHighlightStyle   :: Style      -- ^ Style to use for highlighting
   , writerSetextHeaders    :: Bool       -- ^ Use setext headers for levels 1-2 in markdown
+  , writerTeXLigatures     :: Bool       -- ^ Use tex ligatures quotes, dashes in latex
   } deriving Show
 
 {-# DEPRECATED writerXeTeX "writerXeTeX no longer does anything" #-}
@@ -558,6 +559,7 @@
                 , writerHighlight        = False
                 , writerHighlightStyle   = pygments
                 , writerSetextHeaders    = True
+                , writerTeXLigatures     = True
                 }
 
 --
diff --git a/src/Text/Pandoc/Templates.hs b/src/Text/Pandoc/Templates.hs
--- a/src/Text/Pandoc/Templates.hs
+++ b/src/Text/Pandoc/Templates.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}
+{-# LANGUAGE TypeSynonymInstances, FlexibleInstances, CPP #-}
 {-
 Copyright (C) 2009-2010 John MacFarlane <jgm@berkeley.edu>
 
@@ -72,7 +72,12 @@
 import Control.Monad (liftM, when, forM)
 import System.FilePath
 import Data.List (intercalate, intersperse)
+#if MIN_VERSION_blaze_html(0,5,0)
+import Text.Blaze.Html (Html)
+import Text.Blaze.Internal (preEscapedString)
+#else
 import Text.Blaze (preEscapedString, Html)
+#endif
 import Data.ByteString.Lazy.UTF8 (ByteString, fromString)
 import Text.Pandoc.Shared (readDataFile)
 import qualified Control.Exception.Extensible as E (try, IOException)
diff --git a/src/Text/Pandoc/Writers/ConTeXt.hs b/src/Text/Pandoc/Writers/ConTeXt.hs
--- a/src/Text/Pandoc/Writers/ConTeXt.hs
+++ b/src/Text/Pandoc/Writers/ConTeXt.hs
@@ -86,8 +86,9 @@
 
 -- escape things as needed for ConTeXt
 
-escapeCharForConTeXt :: Char -> String
-escapeCharForConTeXt ch =
+escapeCharForConTeXt :: WriterOptions -> Char -> String
+escapeCharForConTeXt opts ch =
+ let ligatures = writerTeXLigatures opts in
  case ch of
     '{'    -> "\\letteropenbrace{}"
     '}'    -> "\\letterclosebrace{}"
@@ -95,7 +96,7 @@
     '$'    -> "\\$"
     '|'    -> "\\letterbar{}"
     '^'    -> "\\letterhat{}"
-    '%'    -> "\\%"
+    '%'    -> "\\letterpercent "
     '~'    -> "\\lettertilde{}"
     '&'    -> "\\&"
     '#'    -> "\\#"
@@ -105,15 +106,15 @@
     ']'    -> "{]}"
     '_'    -> "\\letterunderscore{}"
     '\160' -> "~"
-    '\x2014' -> "---"
-    '\x2013' -> "--"
-    '\x2019' -> "'"
+    '\x2014' | ligatures -> "---"
+    '\x2013' | ligatures -> "--"
+    '\x2019' | ligatures -> "'"
     '\x2026' -> "\\ldots{}"
     x      -> [x]
 
 -- | Escape string for ConTeXt
-stringToConTeXt :: String -> String
-stringToConTeXt = concatMap escapeCharForConTeXt
+stringToConTeXt :: WriterOptions -> String -> String
+stringToConTeXt opts = concatMap (escapeCharForConTeXt opts)
 
 -- | Convert Elements to ConTeXt
 elementToConTeXt :: WriterOptions -> Element -> State WriterState Doc
@@ -254,8 +255,9 @@
   return $ braces $ "\\sc " <> contents
 inlineToConTeXt (Code _ str) | not ('{' `elem` str || '}' `elem` str) =
   return $ "\\type" <> braces (text str)
-inlineToConTeXt (Code _ str) =
-  return $ "\\mono" <> braces (text $ stringToConTeXt str)
+inlineToConTeXt (Code _ str) = do
+  opts <- gets stOptions
+  return $ "\\mono" <> braces (text $ stringToConTeXt opts str)
 inlineToConTeXt (Quoted SingleQuote lst) = do
   contents <- inlineListToConTeXt lst
   return $ "\\quote" <> braces contents
@@ -263,7 +265,9 @@
   contents <- inlineListToConTeXt lst
   return $ "\\quotation" <> braces contents
 inlineToConTeXt (Cite _ lst) = inlineListToConTeXt lst
-inlineToConTeXt (Str str) = return $ text $ stringToConTeXt str
+inlineToConTeXt (Str str) = do
+  opts <- gets stOptions
+  return $ text $ stringToConTeXt opts str
 inlineToConTeXt (Math InlineMath str) =
   return $ char '$' <> text str <> char '$'
 inlineToConTeXt (Math DisplayMath str) =
@@ -298,7 +302,7 @@
   label <-  inlineListToConTeXt txt
   return $ "\\useURL"
            <> brackets (text ref)
-           <> brackets (text $ escapeStringUsing [('#',"\\#")] src)
+           <> brackets (text $ escapeStringUsing [('#',"\\#"),('%',"\\%")] src)
            <> brackets empty
            <> brackets label
            <> "\\from"
diff --git a/src/Text/Pandoc/Writers/Docx.hs b/src/Text/Pandoc/Writers/Docx.hs
--- a/src/Text/Pandoc/Writers/Docx.hs
+++ b/src/Text/Pandoc/Writers/Docx.hs
@@ -146,7 +146,8 @@
   let styledoc = case findEntryByPath stylepath refArchive >>=
                       parseXMLDoc . toString . fromEntry of
                         Just d  -> d
-                        Nothing -> error $ stylepath ++ "missing in reference docx"
+                        Nothing -> error $ "Unable to parse " ++ stylepath ++
+                                           " from reference.docx"
   let styledoc' = styledoc{ elContent = elContent styledoc ++ map Elem newstyles }
   let styleEntry = toEntry stylepath epochtime $ fromString $ showTopElement' styledoc'
   -- construct word/numbering.xml
@@ -488,7 +489,10 @@
 getParaProps = do
   props <- gets stParaProperties
   listLevel <- gets stListLevel
-  numid <- getNumId
+  listMarker <- gets stListMarker
+  numid <- case listMarker of
+                 NoMarker -> return 1
+                 _        -> getNumId
   let listPr = if listLevel >= 0
                   then [ mknode "w:numPr" []
                          [ mknode "w:numId" [("w:val",show numid)] ()
diff --git a/src/Text/Pandoc/Writers/HTML.hs b/src/Text/Pandoc/Writers/HTML.hs
--- a/src/Text/Pandoc/Writers/HTML.hs
+++ b/src/Text/Pandoc/Writers/HTML.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE OverloadedStrings, CPP #-}
 {-# OPTIONS_GHC -fno-warn-deprecations #-}
 {-
 Copyright (C) 2006-2010 John MacFarlane <jgm@berkeley.edu>
@@ -46,7 +46,12 @@
 import Data.String ( fromString )
 import Data.Maybe ( catMaybes )
 import Control.Monad.State
+#if MIN_VERSION_blaze_html(0,5,0)
+import Text.Blaze.Html hiding(contents)
+import Text.Blaze.Internal(preEscapedString)
+#else
 import Text.Blaze
+#endif
 import qualified Text.Blaze.Html5 as H5
 import qualified Text.Blaze.XHtml1.Transitional as H
 import qualified Text.Blaze.XHtml1.Transitional.Attributes as A
diff --git a/src/Text/Pandoc/Writers/LaTeX.hs b/src/Text/Pandoc/Writers/LaTeX.hs
--- a/src/Text/Pandoc/Writers/LaTeX.hs
+++ b/src/Text/Pandoc/Writers/LaTeX.hs
@@ -56,7 +56,6 @@
               , stEnumerate     :: Bool          -- true if document needs fancy enumerated lists
               , stTable         :: Bool          -- true if document has a table
               , stStrikeout     :: Bool          -- true if document has strikeout
-              , stSubscript     :: Bool          -- true if document has subscript
               , stUrl           :: Bool          -- true if document has visible URL link
               , stGraphics      :: Bool          -- true if document contains images
               , stLHS           :: Bool          -- true if document has literate haskell code
@@ -75,7 +74,7 @@
   WriterState { stInNote = False, stInTable = False,
                 stTableNotes = [], stOLLevel = 1, stOptions = options,
                 stVerbInNote = False, stEnumerate = False,
-                stTable = False, stStrikeout = False, stSubscript = False,
+                stTable = False, stStrikeout = False,
                 stUrl = False, stGraphics = False,
                 stLHS = False, stBook = writerChapters options,
                 stCsquotes = False, stHighlighting = False,
@@ -148,7 +147,6 @@
                  [ ("fancy-enums", "yes") | stEnumerate st ] ++
                  [ ("tables", "yes") | stTable st ] ++
                  [ ("strikeout", "yes") | stStrikeout st ] ++
-                 [ ("subscript", "yes") | stSubscript st ] ++
                  [ ("url", "yes") | stUrl st ] ++
                  [ ("numbersections", "yes") | writerNumberSections options ] ++
                  [ ("lhs", "yes") | stLHS st ] ++
@@ -176,9 +174,11 @@
 
 -- escape things as needed for LaTeX
 stringToLaTeX :: Bool -> String -> State WriterState String
-stringToLaTeX _     []     = return ""
-stringToLaTeX isUrl (x:xs) = do
+stringToLaTeX  _     []     = return ""
+stringToLaTeX  isUrl (x:xs) = do
+  opts <- gets stOptions
   rest <- stringToLaTeX isUrl xs
+  let ligatures = writerTeXLigatures opts
   when (x == '€') $
      modify $ \st -> st{ stUsesEuro = True }
   return $
@@ -203,13 +203,13 @@
        '[' -> "{[}" ++ rest  -- to avoid interpretation as
        ']' -> "{]}" ++ rest  -- optional arguments
        '\160' -> "~" ++ rest
-       '\x2018' -> "`" ++ rest
-       '\x2019' -> "'" ++ rest
-       '\x201C' -> "``" ++ rest
-       '\x201D' -> "''" ++ rest
        '\x2026' -> "\\ldots{}" ++ rest
-       '\x2014' -> "---" ++ rest
-       '\x2013' -> "--" ++ rest
+       '\x2018' | ligatures -> "`" ++ rest
+       '\x2019' | ligatures -> "'" ++ rest
+       '\x201C' | ligatures -> "``" ++ rest
+       '\x201D' | ligatures -> "''" ++ rest
+       '\x2014' | ligatures -> "---" ++ rest
+       '\x2013' | ligatures -> "--" ++ rest
        _        -> x : rest
 
 -- | Puts contents into LaTeX command.
@@ -280,7 +280,8 @@
          return result
        _ -> do
          contents <- blockListToLaTeX lst
-         return $ "\\begin{quote}" $$ contents $$ "\\end{quote}"
+         return $ "\\begin{quote}" $$ chomp contents $$ "\\end{quote}"
+                  <> blankline
 blockToLaTeX (CodeBlock (_,classes,keyvalAttr) str) = do
   opts <- gets stOptions
   case () of
@@ -299,7 +300,11 @@
                           return "Verbatim"
                      else return "verbatim"
            return $ flush (text ("\\begin{" ++ env ++ "}") $$ text str $$
-                    text ("\\end{" ++ env ++ "}")) $$ cr -- final cr because of notes
+                    text ("\\end{" ++ env ++ "}")) <> text "\n" <> blankline
+                    -- note: we use 'text "\n"' instead of cr to make this
+                    -- resistant to the 'chomp' in footnotes; a footnote
+                    -- ending with a Verbatim environment must have a
+                    -- cr before the closing }
          listingsCodeBlock = do
            st <- get
            let params = if writerListings (stOptions st)
@@ -340,7 +345,8 @@
   incremental <- gets stIncremental
   let inc = if incremental then "[<+->]" else ""
   items <- mapM listItemToLaTeX lst
-  return $ text ("\\begin{itemize}" ++ inc) $$ vcat items $$ "\\end{itemize}"
+  return $ text ("\\begin{itemize}" ++ inc) $$ chomp (vcat items) $$
+             "\\end{itemize}" <> blankline
 blockToLaTeX (OrderedList (start, numstyle, numdelim) lst) = do
   st <- get
   let inc = if stIncremental st then "[<+->]" else ""
@@ -361,12 +367,13 @@
                              "}{" ++ show (start - 1) ++ "}"
                         else empty
   return $ text ("\\begin{enumerate}" ++ inc) <> exemplar $$ resetcounter $$
-           vcat items $$ "\\end{enumerate}"
+           chomp (vcat items) $$ "\\end{enumerate}" <> blankline
 blockToLaTeX (DefinitionList lst) = do
   incremental <- gets stIncremental
   let inc = if incremental then "[<+->]" else ""
   items <- mapM defListItemToLaTeX lst
-  return $ text ("\\begin{description}" ++ inc) $$ vcat items $$ "\\end{description}"
+  return $ text ("\\begin{description}" ++ inc) $$ chomp (vcat items) $$
+               "\\end{description}" <> blankline
 blockToLaTeX HorizontalRule = return $
   "\\begin{center}\\rule{3in}{0.4pt}\\end{center}" $$ blankline
 blockToLaTeX (Header level lst) = sectionHeader "" level lst
@@ -503,11 +510,7 @@
 inlineToLaTeX (Superscript lst) =
   inlineListToLaTeX lst >>= return . inCmd "textsuperscript"
 inlineToLaTeX (Subscript lst) = do
-  modify $ \s -> s{ stSubscript = True }
-  contents <- inlineListToLaTeX lst
-  -- oddly, latex includes \textsuperscript but not \textsubscript
-  -- so we have to define it (using a different name so as not to conflict with memoir class):
-  return $ inCmd "textsubscr" contents
+  inlineListToLaTeX lst >>= return . inCmd "textsubscript"
 inlineToLaTeX (SmallCaps lst) =
   inlineListToLaTeX lst >>= return . inCmd "textsc"
 inlineToLaTeX (Cite cits lst) = do
@@ -535,23 +538,11 @@
                   Just  h -> modify (\st -> st{ stHighlighting = True }) >>
                              return (text h)
          rawCode = liftM (text . (\s -> "\\texttt{" ++ s ++ "}"))
-                       $ stringToLaTeX False str
-inlineToLaTeX (Quoted SingleQuote lst) = do
-  contents <- inlineListToLaTeX lst
-  csquotes <- liftM stCsquotes get
-  if csquotes
-     then return $ "\\enquote" <> braces contents
-     else do
-       let s1 = if (not (null lst)) && (isQuoted (head lst))
-                   then "\\,"
-                   else empty
-       let s2 = if (not (null lst)) && (isQuoted (last lst))
-                   then "\\,"
-                   else empty
-       return $ char '`' <> s1 <> contents <> s2 <> char '\''
-inlineToLaTeX (Quoted DoubleQuote lst) = do
+                          $ stringToLaTeX False str
+inlineToLaTeX (Quoted qt lst) = do
   contents <- inlineListToLaTeX lst
   csquotes <- liftM stCsquotes get
+  opts <- gets stOptions
   if csquotes
      then return $ "\\enquote" <> braces contents
      else do
@@ -561,7 +552,16 @@
        let s2 = if (not (null lst)) && (isQuoted (last lst))
                    then "\\,"
                    else empty
-       return $ "``" <> s1 <> contents <> s2 <> "''"
+       let inner = s1 <> contents <> s2
+       return $ case qt of
+                DoubleQuote ->
+                   if writerTeXLigatures opts
+                      then text "``" <> inner <> text "''"
+                      else char '\x201C' <> inner <> char '\x201D'
+                SingleQuote ->
+                   if writerTeXLigatures opts
+                      then char '`' <> inner <> char '\''
+                      else char '\x2018' <> inner <> char '\x2019'
 inlineToLaTeX (Str str) = liftM text $ stringToLaTeX False str
 inlineToLaTeX (Math InlineMath str) = return $ char '$' <> text str <> char '$'
 inlineToLaTeX (Math DisplayMath str) = return $ "\\[" <> text str <> "\\]"
@@ -570,6 +570,10 @@
 inlineToLaTeX (RawInline _ _) = return empty
 inlineToLaTeX (LineBreak) = return "\\\\"
 inlineToLaTeX Space = return space
+inlineToLaTeX (Link txt ('#':ident, _)) = do
+  contents <- inlineListToLaTeX txt
+  ident' <- stringToLaTeX False ident
+  return $ text "\\hyperref" <> brackets (text ident') <> braces contents
 inlineToLaTeX (Link txt (src, _)) =
   case txt of
         [Code _ x] | x == src ->  -- autolink
@@ -596,7 +600,7 @@
        let marker = cycle ['a'..'z'] !! length curnotes
        modify $ \s -> s{ stTableNotes = (marker, contents') : curnotes }
        return $ "\\tmark" <> brackets (char marker) <> space
-     else return $ "\\footnote" <> braces (nest 2 contents')
+     else return $ "\\footnote" <> braces (chomp $ nest 2 contents')
      -- note: a \n before } needed when note ends with a Verbatim environment
 
 citationsToNatbib :: [Citation] -> State WriterState Doc
diff --git a/src/Text/Pandoc/Writers/Markdown.hs b/src/Text/Pandoc/Writers/Markdown.hs
--- a/src/Text/Pandoc/Writers/Markdown.hs
+++ b/src/Text/Pandoc/Writers/Markdown.hs
@@ -152,7 +152,7 @@
 -- | Escape special characters for Markdown.
 escapeString :: String -> String
 escapeString = escapeStringUsing markdownEscapes
-  where markdownEscapes = backslashEscapes "\\`*_>#~^"
+  where markdownEscapes = backslashEscapes "\\`*_$<>#~^"
 
 -- | Construct table of contents from list of header blocks.
 tableOfContents :: WriterOptions -> [Block] -> Doc 
@@ -254,7 +254,7 @@
   if writerStrictMarkdown opts || attribs == nullAttr
      then nest (writerTabStop opts) (text str) <> blankline
      else -- use delimited code block
-          flush (tildes <> space <> attrs <> cr <> text str <>
+          (tildes <> space <> attrs <> cr <> text str <>
                   cr <> tildes) <> blankline
             where tildes  = text "~~~~"
                   attrs = attrsToMarkdown attribs
diff --git a/src/Text/Pandoc/Writers/RST.hs b/src/Text/Pandoc/Writers/RST.hs
--- a/src/Text/Pandoc/Writers/RST.hs
+++ b/src/Text/Pandoc/Writers/RST.hs
@@ -97,7 +97,7 @@
   let label'' = if ':' `elem` (render Nothing label')
                    then char '`' <> label' <> char '`'
                    else label'
-  return $ ".. _" <> label'' <> ": " <> text src
+  return $ nowrap $ ".. _" <> label'' <> ": " <> text src
 
 -- | Return RST representation of notes.
 notesToRST :: [[Block]] -> State WriterState Doc
diff --git a/src/Text/Pandoc/Writers/Texinfo.hs b/src/Text/Pandoc/Writers/Texinfo.hs
--- a/src/Text/Pandoc/Writers/Texinfo.hs
+++ b/src/Text/Pandoc/Writers/Texinfo.hs
@@ -344,7 +344,8 @@
 -- | Convert list of inline elements to Texinfo acceptable for a node name.
 inlineListForNode :: [Inline]  -- ^ Inlines to convert
                   -> State WriterState Doc
-inlineListForNode = return . text . filter (not . disallowedInNode) . stringify
+inlineListForNode = return . text . stringToTexinfo .
+                    filter (not . disallowedInNode) . stringify
 
 -- periods, commas, colons, and parentheses are disallowed in node names
 disallowedInNode :: Char -> Bool
diff --git a/src/Text/Pandoc/XML.hs b/src/Text/Pandoc/XML.hs
--- a/src/Text/Pandoc/XML.hs
+++ b/src/Text/Pandoc/XML.hs
@@ -38,7 +38,7 @@
                          fromEntities ) where
 
 import Text.Pandoc.Pretty
-import Data.Char (ord, isAscii)
+import Data.Char (ord, isAscii, isSpace)
 import Text.HTML.TagSoup.Entity (lookupEntity)
 
 -- | Remove everything between <...>
@@ -106,8 +106,8 @@
 fromEntities ('&':xs) =
   case lookupEntity ent of
         Just c  -> c : fromEntities rest
-        Nothing -> '&' : fromEntities rest
-    where (ent, rest) = case break (==';') xs of
+        Nothing -> '&' : fromEntities xs
+    where (ent, rest) = case break (\c -> isSpace c || c == ';') xs of
                              (zs,';':ys) -> (zs,ys)
                              _           -> ("",xs)
 fromEntities (x:xs) = x : fromEntities xs
diff --git a/src/pandoc.hs b/src/pandoc.hs
--- a/src/pandoc.hs
+++ b/src/pandoc.hs
@@ -135,6 +135,7 @@
     , optSlideLevel        :: Maybe Int  -- ^ Header level that creates slides
     , optSetextHeaders     :: Bool       -- ^ Use atx headers for markdown level 1-2
     , optAscii             :: Bool       -- ^ Use ascii characters only in html
+    , optTeXLigatures      :: Bool       -- ^ Use TeX ligatures for quotes/dashes
     }
 
 -- | Defaults for command-line options.
@@ -187,6 +188,7 @@
     , optSlideLevel        = Nothing
     , optSetextHeaders     = True
     , optAscii             = False
+    , optTeXLigatures      = True
     }
 
 -- | A list of functions, each transforming the options data structure
@@ -438,6 +440,11 @@
                   (\opt -> return opt { optNumberSections = True }))
                  "" -- "Number sections in LaTeX"
 
+    , Option "" ["no-tex-ligatures"]
+                 (NoArg
+                  (\opt -> return opt { optTeXLigatures = False }))
+                 "" -- "Don't use tex ligatures for quotes, dashes"
+
     , Option "" ["listings"]
                  (NoArg
                   (\opt -> return opt { optListings = True }))
@@ -689,6 +696,7 @@
     ".ltx"      -> "latex"
     ".rst"      -> "rst"
     ".lhs"      -> "markdown+lhs"
+    ".db"       -> "docbook"
     ".textile"  -> "textile"
     ".native"   -> "native"
     ".json"     -> "json"
@@ -803,6 +811,7 @@
               , optSlideLevel        = slideLevel
               , optSetextHeaders     = setextHeaders
               , optAscii             = ascii
+              , optTeXLigatures      = texLigatures
              } = opts
 
   when dumpArgs $
@@ -917,7 +926,8 @@
                                                      lhsExtension sources,
                               stateStandalone      = standalone',
                               stateCitations       = map CSL.refId refs,
-                              stateSmart           = smart || laTeXOutput || writerName' == "context",
+                              stateSmart           = smart || (texLigatures &&
+                                       (laTeXOutput || writerName' == "context")),
                               stateOldDashes       = oldDashes,
                               stateColumns         = columns,
                               stateStrict          = strict,
@@ -960,7 +970,8 @@
                                       writerSlideLevel       = slideLevel,
                                       writerHighlight        = highlight,
                                       writerHighlightStyle   = highlightStyle,
-                                      writerSetextHeaders    = setextHeaders
+                                      writerSetextHeaders    = setextHeaders,
+                                      writerTeXLigatures     = texLigatures
                                       }
 
   when (writerName' `elem` nonTextFormats&& outputFile == "-") $
diff --git a/templates/default.beamer b/templates/default.beamer
--- a/templates/default.beamer
+++ b/templates/default.beamer
@@ -7,6 +7,7 @@
 $endif$
 \usepackage{amssymb,amsmath}
 \usepackage{ifxetex,ifluatex}
+\usepackage{fixltx2e} % provides \textsubscript
 \ifxetex
   \usepackage{fontspec,xltxtra,xunicode}
   \defaultfontfeatures{Mapping=tex-text,Scale=MatchLowercase}
@@ -63,9 +64,6 @@
 \usepackage[normalem]{ulem}
 % avoid problems with \sout in headers with hyperref:
 \pdfstringdefDisableCommands{\renewcommand{\sout}{}}
-$endif$
-$if(subscript)$
-\newcommand{\textsubscr}[1]{\ensuremath{_{\scriptsize\textrm{#1}}}}
 $endif$
 \setlength{\parindent}{0pt}
 \setlength{\parskip}{6pt plus 2pt minus 1pt}
diff --git a/templates/default.latex b/templates/default.latex
--- a/templates/default.latex
+++ b/templates/default.latex
@@ -1,6 +1,7 @@
 \documentclass[$if(fontsize)$$fontsize$,$endif$$if(lang)$$lang$,$endif$]{$documentclass$}
 \usepackage{amssymb,amsmath}
 \usepackage{ifxetex,ifluatex}
+\usepackage{fixltx2e} % provides \textsubscript
 \ifxetex
   \usepackage{fontspec,xltxtra,xunicode}
   \defaultfontfeatures{Mapping=tex-text,Scale=MatchLowercase}
@@ -102,6 +103,7 @@
               pdfauthor={$author-meta$},
               pdftitle={$title-meta$},
               colorlinks=true,
+              urlcolor=blue,
               linkcolor=blue]{hyperref}
 \else
   \usepackage[unicode=true,
@@ -109,6 +111,7 @@
               pdfauthor={$author-meta$},
               pdftitle={$title-meta$},
               colorlinks=true,
+              urlcolor=blue,
               linkcolor=blue]{hyperref}
 \fi
 \hypersetup{breaklinks=true, pdfborder={0 0 0}}
@@ -116,9 +119,6 @@
 \usepackage[normalem]{ulem}
 % avoid problems with \sout in headers with hyperref:
 \pdfstringdefDisableCommands{\renewcommand{\sout}{}}
-$endif$
-$if(subscript)$
-\newcommand{\textsubscr}[1]{\ensuremath{_{\scriptsize\textrm{#1}}}}
 $endif$
 \setlength{\parindent}{0pt}
 \setlength{\parskip}{6pt plus 2pt minus 1pt}
diff --git a/templates/default.texinfo b/templates/default.texinfo
--- a/templates/default.texinfo
+++ b/templates/default.texinfo
@@ -1,5 +1,5 @@
 \input texinfo
-@documentencoding utf-8
+@documentencoding UTF-8
 $for(header-includes)$
 $header-includes$
 $endfor$
diff --git a/tests/lhs-test.latex b/tests/lhs-test.latex
--- a/tests/lhs-test.latex
+++ b/tests/lhs-test.latex
@@ -1,6 +1,7 @@
 \documentclass[]{article}
 \usepackage{amssymb,amsmath}
 \usepackage{ifxetex,ifluatex}
+\usepackage{fixltx2e} % provides \textsubscript
 \ifxetex
   \usepackage{fontspec,xltxtra,xunicode}
   \defaultfontfeatures{Mapping=tex-text,Scale=MatchLowercase}
@@ -42,6 +43,7 @@
               pdfauthor={},
               pdftitle={},
               colorlinks=true,
+              urlcolor=blue,
               linkcolor=blue]{hyperref}
 \else
   \usepackage[unicode=true,
@@ -49,6 +51,7 @@
               pdfauthor={},
               pdftitle={},
               colorlinks=true,
+              urlcolor=blue,
               linkcolor=blue]{hyperref}
 \fi
 \hypersetup{breaklinks=true, pdfborder={0 0 0}}
@@ -79,11 +82,11 @@
 \begin{verbatim}
 f *** g = first f >>> second g
 \end{verbatim}
+
 Block quote:
 
 \begin{quote}
 foo bar
-
 \end{quote}
 
 \end{document}
diff --git a/tests/lhs-test.latex+lhs b/tests/lhs-test.latex+lhs
--- a/tests/lhs-test.latex+lhs
+++ b/tests/lhs-test.latex+lhs
@@ -1,6 +1,7 @@
 \documentclass[]{article}
 \usepackage{amssymb,amsmath}
 \usepackage{ifxetex,ifluatex}
+\usepackage{fixltx2e} % provides \textsubscript
 \ifxetex
   \usepackage{fontspec,xltxtra,xunicode}
   \defaultfontfeatures{Mapping=tex-text,Scale=MatchLowercase}
@@ -24,6 +25,7 @@
               pdfauthor={},
               pdftitle={},
               colorlinks=true,
+              urlcolor=blue,
               linkcolor=blue]{hyperref}
 \else
   \usepackage[unicode=true,
@@ -31,6 +33,7 @@
               pdfauthor={},
               pdftitle={},
               colorlinks=true,
+              urlcolor=blue,
               linkcolor=blue]{hyperref}
 \fi
 \hypersetup{breaklinks=true, pdfborder={0 0 0}}
@@ -59,11 +62,11 @@
 \begin{verbatim}
 f *** g = first f >>> second g
 \end{verbatim}
+
 Block quote:
 
 \begin{quote}
 foo bar
-
 \end{quote}
 
 \end{document}
diff --git a/tests/textile-reader.native b/tests/textile-reader.native
--- a/tests/textile-reader.native
+++ b/tests/textile-reader.native
@@ -67,9 +67,9 @@
  ,([Str "beer"],
    [[Plain [Str "fresh",Space,Str "and",Space,Str "bitter"]]])]
 ,Header 1 [Str "Inline",Space,Str "Markup"]
-,Para [Str "This",Space,Str "is",Space,Emph [Str "emphasized"],Str ",",Space,Str "and",Space,Str "so",Space,Emph [Str "is",Space,Str "this"],Str ".",LineBreak,Str "This",Space,Str "is",Space,Strong [Str "strong"],Str ",",Space,Str "and",Space,Str "so",Space,Strong [Str "is",Space,Str "this"],Str ".",LineBreak,Str "A",Space,Link [Strong [Str "strong",Space,Str "link"]] ("http://www.foobar.com",""),Str "."]
+,Para [Str "This",Space,Str "is",Space,Emph [Str "emphasized"],Str ",",Space,Str "and",Space,Str "so",Space,Emph [Str "is",Space,Str "this"],Str ".",LineBreak,Str "This",Space,Str "is",Space,Strong [Str "strong"],Str ",",Space,Str "and",Space,Str "so",Space,Strong [Str "is",Space,Str "this"],Str ".",LineBreak,Str "Hyphenated-words-are-ok",Str ",",Space,Str "as",Space,Str "well",Space,Str "as",Space,Str "strange_underscore_notation",Str ".",LineBreak,Str "A",Space,Link [Strong [Str "strong",Space,Str "link"]] ("http://www.foobar.com",""),Str "."]
 ,Para [Emph [Strong [Str "This",Space,Str "is",Space,Str "strong",Space,Str "and",Space,Str "em",Str "."]],LineBreak,Str "So",Space,Str "is",Space,Strong [Emph [Str "this"]],Space,Str "word",Space,Str "and",Space,Emph [Strong [Str "that",Space,Str "one"]],Str ".",LineBreak,Strikeout [Str "This",Space,Str "is",Space,Str "strikeout",Space,Str "and",Space,Strong [Str "strong"]]]
-,Para [Str "Superscripts",Str ":",Space,Str "a",Superscript [Str "bc"],Str "d",Space,Str "a",Superscript [Strong [Str "hello"]],Space,Str "a",Superscript [Str "hello",Space,Str "there"],Str ".",LineBreak,Str "Subscripts",Str ":",Space,Str "H",Subscript [Str "2"],Str "O",Str ",",Space,Str "H",Subscript [Str "23"],Str "O",Str ",",Space,Str "H",Subscript [Str "many",Space,Str "of",Space,Str "them"],Str "O",Str "."]
+,Para [Str "Superscripts",Str ":",Space,Str "a",Superscript [Str "bc"],Str "d",Space,Str "a",Superscript [Strong [Str "hello"]],Space,Str "a",Superscript [Str "hello",Space,Str "there"],Str ".",LineBreak,Str "Subscripts",Str ":",Space,Subscript [Str "here"],Space,Str "H",Subscript [Str "2"],Str "O",Str ",",Space,Str "H",Subscript [Str "23"],Str "O",Str ",",Space,Str "H",Subscript [Str "many",Space,Str "of",Space,Str "them"],Str "O",Str "."]
 ,Para [Str "Dashes",Space,Str ":",Space,Str "How",Space,Str "cool",Space,Str "\8212",Space,Str "automatic",Space,Str "dashes",Str "."]
 ,Para [Str "Elipses",Space,Str ":",Space,Str "He",Space,Str "thought",Space,Str "and",Space,Str "thought",Space,Str "\8230",Space,Str "and",Space,Str "then",Space,Str "thought",Space,Str "some",Space,Str "more",Str "."]
 ,Para [Str "Quotes",Space,Str "and",Space,Str "apostrophes",Space,Str ":",Space,Quoted DoubleQuote [Str "I",Str "\8217",Str "d",Space,Str "like",Space,Str "to",Space,Str "thank",Space,Str "you"],Space,Str "for",Space,Str "example",Str "."]
@@ -139,8 +139,12 @@
  [[Plain [Str "this",Space,Str "<",Str "div",Str ">",Space,Str "won",Str "\8217",Str "t",Space,Str "produce",Space,Str "raw",Space,Str "html",Space,Str "blocks",Space,Str "<",Str "/div",Str ">"]]
  ,[Plain [Str "but",Space,Str "this",Space,RawInline "html" "<strong>",Space,Str "will",Space,Str "produce",Space,Str "inline",Space,Str "html",Space,RawInline "html" "</strong>"]]]
 ,Para [Str "Can",Space,Str "you",Space,Str "prove",Space,Str "that",Space,Str "2",Space,Str "<",Space,Str "3",Space,Str "?"]
+,Header 1 [Str "Raw",Space,Str "LaTeX"]
+,Para [Str "This",Space,Str "Textile",Space,Str "reader",Space,Str "also",Space,Str "accepts",Space,Str "raw",Space,Str "LaTeX",Space,Str "for",Space,Str "blocks",Space,Str ":"]
+,RawBlock "latex" "\\begin{itemize}\n  \\item one\n  \\item two\n\\end{itemize}"
+,Para [Str "and",Space,Str "for",Space,RawInline "latex" "\\emph{inlines}",Str "."]
 ,Header 1 [Str "Acronyms",Space,Str "and",Space,Str "marks"]
-,Para [Str "PBS",Space,Str "(",Str "Public",Space,Str "Broadcasting",Space,Str "System",Str ")"]
+,Para [Str "PBS (Public Broadcasting System)"]
 ,Para [Str "Hi",Str "\8482"]
 ,Para [Str "Hi",Space,Str "\8482"]
 ,Para [Str "\174",Space,Str "Hi",Str "\174"]
diff --git a/tests/textile-reader.textile b/tests/textile-reader.textile
--- a/tests/textile-reader.textile
+++ b/tests/textile-reader.textile
@@ -115,14 +115,15 @@
 
 This is _emphasized_, and so __is this__.
 This is *strong*, and so **is this**.
+Hyphenated-words-are-ok, as well as strange_underscore_notation.
 A "*strong link*":http://www.foobar.com.
 
 _*This is strong and em.*_
 So is *_this_* word and __**that one**__.
 -This is strikeout and *strong*-
 
-Superscripts:  a^bc^d a^*hello*^ a^hello there^.
-Subscripts: H~2~O, H~23~O, H~many of them~O.
+Superscripts: a[^bc^]d a^*hello*^ a[^hello there^].
+Subscripts: ~here~ H[~2~]O, H[~23~]O, H[~many of them~]O.
 
 Dashes : How cool -- automatic dashes.
 
@@ -197,6 +198,17 @@
 * but this <strong> will produce inline html </strong>
 
 Can you prove that 2 < 3 ?
+
+h1. Raw LaTeX
+
+This Textile reader also accepts raw LaTeX for blocks :
+
+\begin{itemize}
+  \item one
+  \item two
+\end{itemize}
+
+and for \emph{inlines}.
 
 h1. Acronyms and marks
 
diff --git a/tests/writer.latex b/tests/writer.latex
--- a/tests/writer.latex
+++ b/tests/writer.latex
@@ -1,6 +1,7 @@
 \documentclass[]{article}
 \usepackage{amssymb,amsmath}
 \usepackage{ifxetex,ifluatex}
+\usepackage{fixltx2e} % provides \textsubscript
 \ifxetex
   \usepackage{fontspec,xltxtra,xunicode}
   \defaultfontfeatures{Mapping=tex-text,Scale=MatchLowercase}
@@ -41,6 +42,7 @@
               pdfauthor={John MacFarlane; Anonymous},
               pdftitle={Pandoc Test Suite},
               colorlinks=true,
+              urlcolor=blue,
               linkcolor=blue]{hyperref}
 \else
   \usepackage[unicode=true,
@@ -48,13 +50,13 @@
               pdfauthor={John MacFarlane; Anonymous},
               pdftitle={Pandoc Test Suite},
               colorlinks=true,
+              urlcolor=blue,
               linkcolor=blue]{hyperref}
 \fi
 \hypersetup{breaklinks=true, pdfborder={0 0 0}}
 \usepackage[normalem]{ulem}
 % avoid problems with \sout in headers with hyperref:
 \pdfstringdefDisableCommands{\renewcommand{\sout}{}}
-\newcommand{\textsubscr}[1]{\ensuremath{_{\scriptsize\textrm{#1}}}}
 \setlength{\parindent}{0pt}
 \setlength{\parskip}{6pt plus 2pt minus 1pt}
 \setlength{\emergencystretch}{3em}  % prevent overfull lines
@@ -117,8 +119,8 @@
 
 \begin{quote}
 This is a block quote. It is pretty short.
-
 \end{quote}
+
 \begin{quote}
 Code in a block quote:
 
@@ -127,6 +129,7 @@
     print "working";
 }
 \end{verbatim}
+
 A list:
 
 \begin{enumerate}[1.]
@@ -135,17 +138,18 @@
 \item
   item two
 \end{enumerate}
+
 Nested block quotes:
 
 \begin{quote}
 nested
-
 \end{quote}
+
 \begin{quote}
 nested
-
 \end{quote}
 \end{quote}
+
 This should not be a block quote: 2 \textgreater{} 1.
 
 And a following paragraph.
@@ -165,6 +169,7 @@
 
 this code block is indented by one tab
 \end{verbatim}
+
 And:
 
 \begin{verbatim}
@@ -172,6 +177,7 @@
 
 These should not be escaped:  \$ \\ \> \[ \{
 \end{verbatim}
+
 \begin{center}\rule{3in}{0.4pt}\end{center}
 
 \section{Lists}
@@ -188,6 +194,7 @@
 \item
   asterisk 3
 \end{itemize}
+
 Asterisks loose:
 
 \begin{itemize}
@@ -198,6 +205,7 @@
 \item
   asterisk 3
 \end{itemize}
+
 Pluses tight:
 
 \begin{itemize}
@@ -208,6 +216,7 @@
 \item
   Plus 3
 \end{itemize}
+
 Pluses loose:
 
 \begin{itemize}
@@ -218,6 +227,7 @@
 \item
   Plus 3
 \end{itemize}
+
 Minuses tight:
 
 \begin{itemize}
@@ -228,6 +238,7 @@
 \item
   Minus 3
 \end{itemize}
+
 Minuses loose:
 
 \begin{itemize}
@@ -238,6 +249,7 @@
 \item
   Minus 3
 \end{itemize}
+
 \subsection{Ordered}
 
 Tight:
@@ -250,6 +262,7 @@
 \item
   Third
 \end{enumerate}
+
 and:
 
 \begin{enumerate}[1.]
@@ -260,6 +273,7 @@
 \item
   Three
 \end{enumerate}
+
 Loose using tabs:
 
 \begin{enumerate}[1.]
@@ -270,6 +284,7 @@
 \item
   Third
 \end{enumerate}
+
 and using spaces:
 
 \begin{enumerate}[1.]
@@ -280,6 +295,7 @@
 \item
   Three
 \end{enumerate}
+
 Multiple paragraphs:
 
 \begin{enumerate}[1.]
@@ -292,6 +308,7 @@
 \item
   Item 3.
 \end{enumerate}
+
 \subsection{Nested}
 
 \begin{itemize}
@@ -306,6 +323,7 @@
     \end{itemize}
   \end{itemize}
 \end{itemize}
+
 Here's another:
 
 \begin{enumerate}[1.]
@@ -324,6 +342,7 @@
 \item
   Third
 \end{enumerate}
+
 Same thing but with paragraphs:
 
 \begin{enumerate}[1.]
@@ -343,6 +362,7 @@
 \item
   Third
 \end{enumerate}
+
 \subsection{Tabs and spaces}
 
 \begin{itemize}
@@ -358,6 +378,7 @@
     this is an example list item indented with spaces
   \end{itemize}
 \end{itemize}
+
 \subsection{Fancy list markers}
 
 \begin{enumerate}[(1)]
@@ -383,6 +404,7 @@
     \end{enumerate}
   \end{enumerate}
 \end{enumerate}
+
 Nesting:
 
 \begin{enumerate}[A.]
@@ -403,6 +425,7 @@
     \end{enumerate}
   \end{enumerate}
 \end{enumerate}
+
 Autonumbering:
 
 \begin{enumerate}
@@ -415,6 +438,7 @@
     Nested.
   \end{enumerate}
 \end{enumerate}
+
 Should not be a list item:
 
 M.A.~2007
@@ -435,6 +459,7 @@
 \item[banana]
 yellow fruit
 \end{description}
+
 Tight using tabs:
 
 \begin{description}
@@ -445,6 +470,7 @@
 \item[banana]
 yellow fruit
 \end{description}
+
 Loose:
 
 \begin{description}
@@ -456,8 +482,8 @@
 
 \item[banana]
 yellow fruit
-
 \end{description}
+
 Multiple blocks with italics:
 
 \begin{description}
@@ -472,11 +498,12 @@
 \begin{verbatim}
 { orange code block }
 \end{verbatim}
+
 \begin{quote}
 orange block quote
-
 \end{quote}
 \end{description}
+
 Multiple definitions, tight:
 
 \begin{description}
@@ -489,6 +516,7 @@
 
 bank
 \end{description}
+
 Multiple definitions, loose:
 
 \begin{description}
@@ -501,8 +529,8 @@
 orange fruit
 
 bank
-
 \end{description}
+
 Blank line after term, indented marker, alternate markers:
 
 \begin{description}
@@ -521,6 +549,7 @@
   sublist
 \end{enumerate}
 \end{description}
+
 \section{HTML Blocks}
 
 Simple block on one line:
@@ -544,11 +573,13 @@
     foo
 </div>
 \end{verbatim}
+
 As should this:
 
 \begin{verbatim}
 <div>foo</div>
 \end{verbatim}
+
 Now, nested:
 
 foo
@@ -561,6 +592,7 @@
 \begin{verbatim}
 <!-- Comment -->
 \end{verbatim}
+
 Just plain comment, with trailing spaces on the line:
 
 Code:
@@ -568,6 +600,7 @@
 \begin{verbatim}
 <hr />
 \end{verbatim}
+
 Hr's:
 
 \begin{center}\rule{3in}{0.4pt}\end{center}
@@ -596,7 +629,8 @@
 Superscripts: a\textsuperscript{bc}d a\textsuperscript{\emph{hello}}
 a\textsuperscript{hello~there}.
 
-Subscripts: H\textsubscr{2}O, H\textsubscr{23}O, H\textsubscr{many~of~them}O.
+Subscripts: H\textsubscript{2}O, H\textsubscript{23}O,
+H\textsubscript{many~of~them}O.
 
 These should not be superscripts or subscripts, because of the unescaped
 spaces: a\^{}b c\^{}d, a\textasciitilde{}b c\textasciitilde{}d.
@@ -645,6 +679,7 @@
 \item
   Here's one that has a line break in it: $\alpha + \omega \times x^2$.
 \end{itemize}
+
 These shouldn't be math:
 
 \begin{itemize}
@@ -658,6 +693,7 @@
 \item
   Escaped \texttt{\$}: \$73 \emph{this should be emphasized} 23\$.
 \end{itemize}
+
 Here's a LaTeX table:
 
 \begin{tabular}{|l|l|}\hline
@@ -684,6 +720,7 @@
 \item
   copyright: ©
 \end{itemize}
+
 AT\&T has an ampersand in their name.
 
 AT\&T is another way to write it.
@@ -773,6 +810,7 @@
 \begin{verbatim}
 [not]: /url
 \end{verbatim}
+
 Foo \href{/url/}{bar}.
 
 Foo \href{/url/}{biz}.
@@ -801,19 +839,21 @@
 \item
   It should.
 \end{itemize}
+
 An e-mail address:
 \href{mailto:nobody@nowhere.net}{\texttt{nobody@nowhere.net}}
 
 \begin{quote}
 Blockquoted: \url{http://example.com/}
-
 \end{quote}
+
 Auto-links should not occur here:
 \texttt{\textless{}http://example.com/\textgreater{}}
 
 \begin{verbatim}
 or here: <http://example.com/>
 \end{verbatim}
+
 \begin{center}\rule{3in}{0.4pt}\end{center}
 
 \section{Images}
@@ -843,6 +883,7 @@
 \begin{Verbatim}
   { <code> }
 \end{Verbatim}
+
   If you want, you can indent every line, but you can also be lazy and just
   indent the first line of each block.} This should \emph{not} be a footnote
 reference, because it contains a space.{[}\^{}my note{]} Here is an inline
@@ -852,12 +893,13 @@
 
 \begin{quote}
 Notes can go in quotes.\footnote{In quote.}
-
 \end{quote}
+
 \begin{enumerate}[1.]
 \item
   And in list items.\footnote{In list.}
 \end{enumerate}
+
 This paragraph should not be part of the note, as it is not indented.
 
 \end{document}
diff --git a/tests/writer.markdown b/tests/writer.markdown
--- a/tests/writer.markdown
+++ b/tests/writer.markdown
@@ -528,10 +528,10 @@
 These shouldn’t be math:
 
 -   To get the famous equation, write `$e = mc^2$`.
--   $22,000 is a *lot* of money. So is $34,000. (It worked if “lot” is
+-   \$22,000 is a *lot* of money. So is \$34,000. (It worked if “lot” is
     emphasized.)
--   Shoes ($20) and socks ($5).
--   Escaped `$`: $73 *this should be emphasized* 23$.
+-   Shoes (\$20) and socks (\$5).
+-   Escaped `$`: \$73 *this should be emphasized* 23\$.
 
 Here’s a LaTeX table:
 
@@ -560,7 +560,7 @@
 
 This & that.
 
-4 < 5.
+4 \< 5.
 
 6 \> 5.
 
diff --git a/tests/writer.texinfo b/tests/writer.texinfo
--- a/tests/writer.texinfo
+++ b/tests/writer.texinfo
@@ -1,5 +1,5 @@
 \input texinfo
-@documentencoding utf-8
+@documentencoding UTF-8
 
 @macro textstrikeout{text}
 ~~\text\~~
