diff --git a/INSTALL.md b/INSTALL.md
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -3,22 +3,18 @@
 ## Windows
 
   - There is a package installer at pandoc's [download page].
+    This will install pandoc, replacing older versions, and
+    update your path to include the directory where pandoc's
+    binaries are installed.
 
+  - If you prefer not to use the msi installer, we also provide
+    a zip file that contains pandoc's binaries and
+    documentation.  Simply unzip this file and move the binaries
+    to a directory of your choice.
+
   - For PDF output, you'll also need to install LaTeX.
     We recommend [MiKTeX](http://miktex.org/).
 
-  - If you'd prefer, you can extract the `pandoc` and `pandoc-citeproc`
-    executables from the MSI and copy them directly to any directory,
-    without running the installer.  Here is an example showing how to
-    extract the executables from the pandoc-1.19.1 installer and copy
-    them to `C:\Utils\Console\`:
-
-        mkdir "%TEMP%\pandoc\"
-        start /wait msiexec.exe /a pandoc-1.19.1-windows.msi /qn targetdir="%TEMP%\pandoc\"
-        copy /y "%TEMP%\pandoc\pandoc.exe" C:\Utils\Console\
-        copy /y "%TEMP%\pandoc\pandoc-citeproc.exe" C:\Utils\Console\
-        rmdir /s /q "%TEMP%\pandoc\"
-
 ## macOS
 
   - You can install pandoc using
@@ -29,15 +25,10 @@
     by downloading [this script][uninstaller]
     and running it with `perl uninstall-pandoc.pl`.
 
-  - It is possible to extract the pandoc and pandoc-citeproc
-    executables from the macOS pkg file, if you'd rather not run
-    the installer.  To do this (for the version 1.19.1 package):
-
-        mkdir pandoc-extract
-        cd pandoc-extract
-        xar -x -f ../pandoc-2.0-macOS.pkg
-        cat pandoc.pkg/Payload | gunzip -dc | cpio -i
-        # executables are now in ./usr/bin/, man pages in ./usr/share/man
+  - We also provide a zip file containing the binaries and man
+    pages, for those who prefer not to use the installer.  Simply
+    unzip the file and move the binaries and man pages to
+    whatever directory you like.
 
   - For PDF output, you'll also need LaTeX.  Because a full [MacTeX]
     installation takes more than a gigabyte of disk space, we recommend
diff --git a/MANUAL.txt b/MANUAL.txt
--- a/MANUAL.txt
+++ b/MANUAL.txt
@@ -1,6 +1,6 @@
 % Pandoc User's Guide
 % John MacFarlane
-% November 20, 2017
+% December 2, 2017
 
 Synopsis
 ========
@@ -427,6 +427,12 @@
 
 :   Specify the base level for headers (defaults to 1).
 
+`--strip-empty-paragraphs`
+
+:   Ignore paragraphs with non content.  This option is useful
+    for converting word processing documents where users have
+    used empty paragraphs to create inter-paragraph space.
+
 `--indented-code-classes=`*CLASSES*
 
 :   Specify classes to use for indented code blocks--for example,
@@ -685,8 +691,16 @@
     Instead of a *STYLE* name, a JSON file with extension
     `.theme` may be supplied.  This will be parsed as a KDE
     syntax highlighting theme and (if valid) used as the
-    highlighting style.  To see a sample theme that can be
-    modified, `pandoc --print-default-data-file default.theme`.
+    highlighting style.
+
+    To generate the JSON version of an existing style,
+    use `--print-highlight-style`.
+
+`--print-highlight-style=`*STYLE*|*FILE*
+
+:   Prints a JSON version of a highlighting style, which can
+    be modified, saved with a `.theme` extension, and used
+    with `--highlight-style`.
 
 `--syntax-definition=`*FILE*
 
diff --git a/changelog b/changelog
--- a/changelog
+++ b/changelog
@@ -1,3 +1,163 @@
+pandoc (2.0.4)
+
+  * Add `--print-highlight-style` option.  This generates a JSON version
+    of a highlighting style, which can be saved as a `.theme` file, modified,
+    and used with `--highlight-style` (#4106, #4096).
+
+  * Add `--strip-empty-paragraphs` option.  This works for any input format.
+    It is primarily intended for use with docx and odt documents where
+    empty paragraphs have been used for inter-paragraph spaces.
+
+  * Support `--webtex` for `gfm` output.
+
+  * Recognize `.muse` file extension.
+
+  * Support beamer `\alert` in LaTeX reader. Closes #4091.
+
+  * Docx reader: don't strip out empty paragraphs (#2252).
+    Users who have a conversion pipeline from docx may want to consider adding
+    `--strip-empty-paragraphs` to the command line.
+
+  * Org reader (Albert Krewinkel): Allow empty list items (#4090).
+
+  * Muse reader (Alexander Krotov):
+
+    + Parse markup in definition list terms.
+    + Allow definition to end with EOF.
+    + Make code blocks round trip.
+    + Drop common space prefix from list items.
+    + Add partial round trip test.
+    + Don't interpret XML entities.
+    + Remove `nested`.
+    + Parse `~~` as non-breaking space in Emacs mode.
+    + Correctly remove indentation from notes.  Exactly one space is
+      required and considered to be part of the marker.
+    + Allow list items to be empty.
+    + Add ordered list test.
+    + Add more multiline definition tests.
+    + Don't allow blockquotes within lists.
+    + Fix reading of multiline definitions.
+    + Add inline `<literal>` support.
+    + Concatenate inlines of the same type
+
+  * Docx writer: allow empty paragraphs (#2252).
+
+  * CommonMark/gfm writer:
+
+    + Use raw html for native divs/spans (#4113).  This allows a pandoc
+      markdown native div or span to be rendered in gfm using raw html tags.
+    + Implement `raw_html` and `raw_tex` extensions.  Note that `raw_html`
+      is enabled by default for `gfm`, while `raw_tex` is disabled by default.
+
+  * Muse writer (Alexander Krotov):
+
+    + Test that inline math conversion result is normalized.
+      Without normalization this test produced
+      `<em>a</em><em>b</em><em>c</em>`.
+    + Improve inline list normalization and move to writer.
+    + Escape hash symbol.
+    + Escape `----` to avoid accidental horizontal rules.
+    + Escape only `</code>` inside code tag.
+    + Additional `<verbatim>` is not needed as `<code>` is verbatim already.
+
+  * LaTeX writer:
+
+    + Allow specifying just width or height for image size.
+      Previously both needed to be specified (unless the image was
+      being resized to be smaller than its original size).
+      If height but not width is specified, we now set width to
+      textwidth. If width but not height is specified, we now set
+      height to textheight.  Since we have `keepaspectratio`, this
+      yields the desired result.
+    + Escape `~` and `_` in code with `--listings` (#4111).
+
+  * HTML writer: export `tagWithAttributes`.  This is a helper allowing
+    other writers to create single HTML tags.
+
+  * Let papersizes `a0`, `a1`, `a2`, ... be case-insensitive by
+    converting the case as needed in LaTeX and ConTeXt writers.
+
+  * Change `fixDisplayMath` from `Text.Pandoc.Writers.Shared`
+    so that it no longer produces empty `Para`'s as an artifact.
+
+  * `Text.Pandoc.Shared.blocksToInlines`:  rewrote using builder.
+    This gives us automatic normalization, so we don't get
+    for example two consecutive Spaces.
+
+  * Include default CSS for 'underline' class in HTML-based templates.
+
+  * revealjs template:  add `tex2jax` configuration for the
+    math plugin.  With the next release of reveal.js, this will
+    fix the problem of `$`s outside of math contexts being
+    interpreted as math delimiters (#4027).
+
+  * `pandoc.lua` module for use in lua filters (Albert Krewinkel):
+
+    + Add basic lua List module (#4099, #4081).  The List module is
+      automatically loaded, but not assigned to a global variable. It can be
+      included in filters by calling `List = require 'List'`.  Lists of blocks,
+      lists of inlines, and lists of classes are now given `List` as a metatable,
+      making working with them more convenient.  E.g., it is now possible to
+      concatenate lists of inlines using Lua's concatenation operator `..`
+      (requires at least one of the operants to have `List` as a metatable):
+
+          function Emph (emph)
+            local s = {pandoc.Space(), pandoc.Str 'emphasized'}
+            return pandoc.Span(emph.content .. s)
+          end
+
+      The `List` metatable is assigned to the tables which get passed to
+      the constructors `MetaBlocks`, `MetaInline`, and `MetaList`. This
+      enables the use of the resulting objects as lists.
+    + `Lua/StackInstances`: push Pandoc and Meta via constructor.
+      Pandoc and Meta elements are now pushed by calling the respective
+      constructor functions of the pandoc Lua module. This makes serialization
+      consistent with the way blocks and inlines are pushed to lua and allows
+      to use List methods with the `blocks` value.
+    + Add documentation for pandoc.List in `lua-filters.md`.
+
+  * Use latest tagsoup.  This fixes a bug in parsing HTML tags with
+    `&` (but not a valid entity) following them (#4094, #4088).
+
+  * Use skylighting 0.4.4.1, fixing the color of unmarked code text
+    when `numberLines` is used (#4103).
+
+  * Make `normalizeDate` more forgiving (Mauro Bieg, #4101), not
+    requiring a leading 0 on single-digit days.
+
+  * Fix `--help` output for `--highlight-style` to include `FILE` (Mauro
+    Bieg, #4095).
+
+  * Clearer deprecation warning for `--latexmathml, --asciimathml, -m`.
+    Previously we only mentioned `--latexmathml`, even if `-m` was
+    used.
+
+  * Changelog: fix description of lua filters in 2.0 release
+    (Albert Krewinkel).  Lua filters were initially run *after* conventional
+    (JSON) filters.  However, this was changed later to make it easier to deal
+    with files in the mediabag. The changelog is updated to describe that
+    feature of the 2.0 release correctly.
+
+  * Change Generic JSON instances to TemplateHaskell (Jasper Van der Jeugt,
+    #4085).  This reduces compile time and memory usage significantly.
+
+  * `lua-filters.md`: Added tikz filter example.
+
+  * Create alternative zip file for macOS binaries.
+
+  * Create alternative zip file for Windows binaries.
+
+  * Update INSTALL.md since we now provide zips for binaries.
+
+  * Relax `http-types` dependency (Justus Sagemüller, #4084).
+
+  * Add `epub.md`, `getting-started.md` to docs.  These used to live in
+    the website repo.
+
+  * Add `packages` target to Makefile.
+
+  * Bump bounds for binary, http-types, tasty-hunit
+
 pandoc (2.0.3)
 
   * Lua filters: preload text module (Albert Krewinkel, #4077).
@@ -378,7 +538,7 @@
   * Added lua filters (Albert Krewinkel, #3514).  The new `--lua-filter`
     option works like `--filter` but takes pathnames of special lua filters
     and uses the lua interpreter baked into pandoc, so that no external
-    interpreter is needed.  Note that lua filters are all applied after
+    interpreter is needed.  Note that lua filters are all applied before
     regular filters, regardless of their position on the command line.
     For documentation of lua filters, see `doc/lua-filters.md`.
 
diff --git a/data/List.lua b/data/List.lua
new file mode 100644
--- /dev/null
+++ b/data/List.lua
@@ -0,0 +1,120 @@
+--[[
+List.lua
+
+Copyright © 2017 Albert Krewinkel
+
+Permission to use, copy, modify, and/or distribute this software for any purpose
+with or without fee is hereby granted, provided that the above copyright notice
+and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+]]
+
+--- Pandoc's List type and helper methods
+-- @classmod pandoc.List
+-- @author Albert Krewinkel
+-- @copyright © 2017 Albert Krewinkel
+-- @license MIT
+local List = {
+  _VERSION = "0.1.0"
+}
+
+function List:new (o)
+  o = o or {}
+  setmetatable(o, self)
+  self.__index = self
+  return o
+end
+
+function List:__call (o)
+  return self:new(o)
+end
+
+--- Concatenates two lists.
+-- @param list second list concatenated to the first
+-- @return a new list containing all elements from list1 and list2
+function List:__concat (list)
+  local res = List.clone(self)
+  List.extend(res, list)
+  return res
+end
+
+--- Returns a (shallow) copy of the list.
+function List:clone ()
+  local lst = setmetatable({}, getmetatable(self))
+  List.extend(lst, self)
+  return lst
+end
+
+--- Checks if the list has an item equal to the given needle.
+-- @param needle item to search for
+-- @param init index at which the search is started
+-- @return true if a list item is equal to the needle, false otherwise
+function List:includes (needle, init)
+  return not (List.find(self, needle, init) == nil)
+end
+
+--- Returns the value and index of the first occurrence of the given item.
+-- @param needle item to search for
+-- @param init index at which the search is started
+-- @return first item equal to the needle, or nil if no such item exists.
+-- @return index of that element
+function List:find (needle, init)
+  return List.find_if(self, function(x) return x == needle end, init)
+end
+
+--- Returns the value and index of the first element for which the predicate
+--- holds true.
+-- @param pred the predicate function
+-- @param init index at which the search is started
+-- @return first item for which `test` succeeds, or nil if no such item exists.
+-- @return index of that element
+function List:find_if (pred, init)
+  init = (init == nil and 1) or (init < 0 and #self - init) or init
+  for i = init, #self do
+    if pred(self[i], i) then
+      return self[i], i
+    end
+  end
+  return nil
+end
+
+--- Adds the given list to the end of this list.
+-- @param list list to appended
+function List:extend (list)
+  for i = 1, #list do
+    self[#self + 1] = list[i]
+  end
+end
+
+--- Returns a copy of the current list by applying the given function to all
+-- elements.
+-- @param fn function which is applied to all list items.
+function List:map (fn)
+  local res = setmetatable({}, getmetatable(self))
+  for i = 1, #self do
+    res[i] = fn(self[i], i)
+  end
+  return res
+end
+
+--- Returns a new list containing all items satisfying a given condition.
+-- @param pred condition items must satisfy.
+-- @return a new list containing all items for which `test` was true.
+function List:filter (pred)
+  local res = setmetatable({}, getmetatable(self))
+  for i = 1, #self do
+    if pred(self[i], i) then
+      res[#res + 1] = self[i]
+    end
+  end
+  return res
+end
+
+return List
diff --git a/data/pandoc.lua b/data/pandoc.lua
--- a/data/pandoc.lua
+++ b/data/pandoc.lua
@@ -26,6 +26,8 @@
   _VERSION = "0.3.0"
 }
 
+local List = require 'pandoc.List'
+
 ------------------------------------------------------------------------
 -- The base class for pandoc's AST elements.
 -- @type Element
@@ -141,7 +143,7 @@
 function M.Pandoc(blocks, meta)
   meta = meta or {}
   return {
-    ["blocks"] = blocks,
+    ["blocks"] = List:new(blocks),
     ["meta"] = meta,
     ["pandoc-api-version"] = {1,17,0,5},
   }
@@ -151,6 +153,21 @@
 M.Doc = M.Pandoc
 
 ------------------------------------------------------------------------
+-- Meta
+-- @section Meta
+
+--- Create a new Meta object. It sets the metatable of the given table to
+--- `Meta`.
+-- @function Meta
+-- @tparam meta table table containing document meta information
+M.Meta = {}
+M.Meta.__call = function(t, meta)
+  return setmetatable(meta, self)
+end
+setmetatable(M.Meta, M.Meta)
+
+
+------------------------------------------------------------------------
 -- MetaValue
 -- @section MetaValue
 M.MetaValue = Element:make_subtype{}
@@ -168,25 +185,25 @@
 --- Meta list
 -- @function MetaList
 -- @tparam {MetaValue,...} meta_values list of meta values
-
---- Meta map
--- @function MetaMap
--- @tparam table key_value_map a string-indexed map of meta values
-M.meta_value_types = {
+M.meta_value_list_types = {
   "MetaBlocks",
   "MetaInlines",
   "MetaList",
-  "MetaMap",
 }
-for i = 1, #M.meta_value_types do
-  M[M.meta_value_types[i]] = M.MetaValue:create_constructor(
-    M.meta_value_types[i],
+for i = 1, #M.meta_value_list_types do
+  M[M.meta_value_list_types[i]] = M.MetaValue:create_constructor(
+    M.meta_value_list_types[i],
     function(content)
-      return content
+      return List:new(content)
     end
   )
 end
 
+--- Meta map
+-- @function MetaMap
+-- @tparam table key_value_map a string-indexed map of meta values
+M.MetaValue:create_constructor("MetaMap", function (mm) return mm end)
+
 --- Creates string to be used in meta data.
 -- Does nothing, lua strings are meta strings.
 -- @function MetaString
@@ -250,7 +267,7 @@
 -- @treturn     Block block quote element
 M.DefinitionList = M.Block:create_constructor(
   "DefinitionList",
-  function(content) return {c = content} end,
+  function(content) return {c = List:new(content)} end,
   "content"
 )
 
@@ -262,7 +279,7 @@
 M.Div = M.Block:create_constructor(
   "Div",
   function(content, attr)
-    return {c = {attr or M.Attr(), content}}
+    return {c = {attr or M.Attr(), List:new(content)}}
   end,
   {{"identifier", "classes", "attributes"}, "content"}
 )
@@ -295,7 +312,7 @@
 -- @treturn     Block                   block quote element
 M.LineBlock = M.Block:create_constructor(
   "LineBlock",
-  function(content) return {c = content} end,
+  function(content) return {c = List:new(content)} end,
   "content"
 )
 
@@ -316,7 +333,7 @@
   "OrderedList",
   function(items, listAttributes)
     listAttributes = listAttributes or {1, M.DefaultStyle, M.DefaultDelim}
-    return {c = {listAttributes, items}}
+    return {c = {listAttributes, List:new(items)}}
   end,
   {{"start", "style", "delimiter"}, "content"}
 )
@@ -327,7 +344,7 @@
 -- @treturn     Block                   block quote element
 M.Para = M.Block:create_constructor(
   "Para",
-  function(content) return {c = content} end,
+  function(content) return {c = List:new(content)} end,
   "content"
 )
 
@@ -337,7 +354,7 @@
 -- @treturn     Block                   block quote element
 M.Plain = M.Block:create_constructor(
   "Plain",
-  function(content) return {c = content} end,
+  function(content) return {c = List:new(content)} end,
   "content"
 )
 
@@ -363,7 +380,15 @@
 M.Table = M.Block:create_constructor(
   "Table",
   function(caption, aligns, widths, headers, rows)
-    return {c = {caption, aligns, widths, headers, rows}}
+    return {
+      c = {
+        List:new(caption),
+        List:new(aligns),
+        List:new(widths),
+        List:new(headers),
+        List:new(rows)
+      }
+    }
   end,
   {"caption", "aligns", "widths", "headers", "rows"}
 )
@@ -386,7 +411,9 @@
 -- @treturn Inline citations element
 M.Cite = M.Inline:create_constructor(
   "Cite",
-  function(content, citations) return {c = {citations, content}} end,
+  function(content, citations)
+    return {c = {List:new(citations), List:new(content)}}
+  end,
   {"citations", "content"}
 )
 
@@ -407,7 +434,7 @@
 -- @treturn Inline emphasis element
 M.Emph = M.Inline:create_constructor(
   "Emph",
-  function(content) return {c = content} end,
+  function(content) return {c = List:new(content)} end,
   "content"
 )
 
@@ -423,7 +450,7 @@
   function(caption, src, title, attr)
     title = title or ""
     attr = attr or M.Attr()
-    return {c = {attr, caption, {src, title}}}
+    return {c = {attr, List:new(caption), {src, title}}}
   end,
   {{"identifier", "classes", "attributes"}, "caption", {"src", "title"}}
 )
@@ -448,7 +475,7 @@
   function(content, target, title, attr)
     title = title or ""
     attr = attr or M.Attr()
-    return {c = {attr, content, {target, title}}}
+    return {c = {attr, List:new(content), {target, title}}}
   end,
   {{"identifier", "classes", "attributes"}, "content", {"target", "title"}}
 )
@@ -489,7 +516,7 @@
 -- @tparam      {Block,...} content     footnote block content
 M.Note = M.Inline:create_constructor(
   "Note",
-  function(content) return {c = content} end,
+  function(content) return {c = List:new(content)} end,
   "content"
 )
 
@@ -500,7 +527,7 @@
 -- @treturn     Inline                  quoted element
 M.Quoted = M.Inline:create_constructor(
   "Quoted",
-  function(quotetype, content) return {c = {quotetype, content}} end,
+  function(quotetype, content) return {c = {quotetype, List:new(content)}} end,
   {"quotetype", "content"}
 )
 --- Creates a single-quoted inline element (DEPRECATED).
@@ -541,7 +568,7 @@
 -- @treturn     Inline                  smallcaps element
 M.SmallCaps = M.Inline:create_constructor(
   "SmallCaps",
-  function(content) return {c = content} end,
+  function(content) return {c = List:new(content)} end,
   "content"
 )
 
@@ -568,7 +595,9 @@
 -- @treturn Inline span element
 M.Span = M.Inline:create_constructor(
   "Span",
-  function(content, attr) return {c = {attr or M.Attr(), content}} end,
+  function(content, attr)
+    return {c = {attr or M.Attr(), List:new(content)}}
+  end,
   {{"identifier", "classes", "attributes"}, "content"}
 )
 
@@ -588,7 +617,7 @@
 -- @treturn     Inline                  strikeout element
 M.Strikeout = M.Inline:create_constructor(
   "Strikeout",
-  function(content) return {c = content} end,
+  function(content) return {c = List:new(content)} end,
   "content"
 )
 
@@ -598,7 +627,7 @@
 -- @treturn     Inline                  strong element
 M.Strong = M.Inline:create_constructor(
   "Strong",
-  function(content) return {c = content} end,
+  function(content) return {c = List:new(content)} end,
   "content"
 )
 
@@ -608,7 +637,7 @@
 -- @treturn     Inline                  subscript element
 M.Subscript = M.Inline:create_constructor(
   "Subscript",
-  function(content) return {c = content} end,
+  function(content) return {c = List:new(content)} end,
   "content"
 )
 
@@ -618,7 +647,7 @@
 -- @treturn     Inline                  strong element
 M.Superscript = M.Inline:create_constructor(
   "Superscript",
-  function(content) return {c = content} end,
+  function(content) return {c = List:new(content)} end,
   "content"
 )
 
@@ -627,24 +656,8 @@
 -- Helpers
 -- @section helpers
 
--- Find a value pair in a list.
--- @function find
--- @tparam table list to be searched
--- @param needle element to search for
--- @param[opt] key when non-nil, compare on this field of each list element
-local function find (alist, needle, key)
-  local test
-  if key then
-    test = function(x) return x[key] == needle end
-  else
-    test = function(x) return x == needle end
-  end
-  for i, k in ipairs(alist) do
-    if test(k) then
-      return i, k
-    end
-  end
-  return nil
+local function assoc_key_equals (x)
+  return function (y) return y[1] == x end
 end
 
 -- Lookup a value in an associative list
@@ -652,7 +665,7 @@
 -- @tparam {{key, value},...} alist associative list
 -- @param key key for which the associated value is to be looked up
 local function lookup(alist, key)
-  return (select(2, find(alist, key, 1)) or {})[2]
+  return (List.find_if(alist, assoc_key_equals(key)) or {})[2]
 end
 
 --- Return an iterator which returns key-value pairs of an associative list.
@@ -684,7 +697,7 @@
   end,
 
   __newindex = function (t, k, v)
-    local idx, cur = find(t, k, 1)
+    local cur, idx = List.find_if(t, assoc_key_equals(k))
     if v == nil then
       table.remove(t, idx)
     elseif cur then
@@ -729,7 +742,7 @@
 -- @return element attributes
 M.Attr.__call = function(t, identifier, classes, attributes)
   identifier = identifier or ''
-  classes = classes or {}
+  classes = List:new(classes or {})
   attributes = setmetatable(to_alist(attributes or {}), AttributeList)
   local attr = {identifier, classes, attributes}
   setmetatable(attr, t)
diff --git a/data/templates/default.dzslides b/data/templates/default.dzslides
--- a/data/templates/default.dzslides
+++ b/data/templates/default.dzslides
@@ -15,6 +15,7 @@
   <style type="text/css">
       code{white-space: pre-wrap;}
       span.smallcaps{font-variant: small-caps;}
+      span.underline{text-decoration: underline;}
       div.line-block{white-space: pre-line;}
       div.column{display: inline-block; vertical-align: top; width: 50%;}
 $if(quotes)$
diff --git a/data/templates/default.epub2 b/data/templates/default.epub2
--- a/data/templates/default.epub2
+++ b/data/templates/default.epub2
@@ -9,6 +9,7 @@
   <style type="text/css">
       code{white-space: pre-wrap;}
       span.smallcaps{font-variant: small-caps;}
+      span.underline{text-decoration: underline;}
       div.line-block{white-space: pre-line;}
       div.column{display: inline-block; vertical-align: top; width: 50%;}
 $if(quotes)$
diff --git a/data/templates/default.epub3 b/data/templates/default.epub3
--- a/data/templates/default.epub3
+++ b/data/templates/default.epub3
@@ -8,6 +8,7 @@
   <style type="text/css">
       code{white-space: pre-wrap;}
       span.smallcaps{font-variant: small-caps;}
+      span.underline{text-decoration: underline;}
       div.line-block{white-space: pre-line;}
       div.column{display: inline-block; vertical-align: top; width: 50%;}
 $if(quotes)$
diff --git a/data/templates/default.html4 b/data/templates/default.html4
--- a/data/templates/default.html4
+++ b/data/templates/default.html4
@@ -17,6 +17,7 @@
   <style type="text/css">
       code{white-space: pre-wrap;}
       span.smallcaps{font-variant: small-caps;}
+      span.underline{text-decoration: underline;}
       div.line-block{white-space: pre-line;}
       div.column{display: inline-block; vertical-align: top; width: 50%;}
 $if(quotes)$
diff --git a/data/templates/default.html5 b/data/templates/default.html5
--- a/data/templates/default.html5
+++ b/data/templates/default.html5
@@ -17,6 +17,7 @@
   <style type="text/css">
       code{white-space: pre-wrap;}
       span.smallcaps{font-variant: small-caps;}
+      span.underline{text-decoration: underline;}
       div.line-block{white-space: pre-line;}
       div.column{display: inline-block; vertical-align: top; width: 50%;}
 $if(quotes)$
diff --git a/data/templates/default.revealjs b/data/templates/default.revealjs
--- a/data/templates/default.revealjs
+++ b/data/templates/default.revealjs
@@ -20,6 +20,7 @@
   <style type="text/css">
       code{white-space: pre-wrap;}
       span.smallcaps{font-variant: small-caps;}
+      span.underline{text-decoration: underline;}
       div.line-block{white-space: pre-line;}
       div.column{display: inline-block; vertical-align: top; width: 50%;}
 $if(quotes)$
@@ -234,6 +235,18 @@
         math: {
           mathjax: 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js',
           config: 'TeX-AMS_HTML-full',
+          tex2jax: {
+            inlineMath: [['\\(','\\)']],
+            displayMath: [['\\[','\\]']],
+            balanceBraces: true,
+            processEscapes: false,
+            processRefs: true,
+            processEnvironments: true,
+            preview: 'TeX',
+            skipTags: ['script','noscript','style','textarea','pre','code'],
+            ignoreClass: 'tex2jax_ignore',
+            processClass: 'tex2jax_process'
+          },
         },
 $endif$
 
diff --git a/data/templates/default.s5 b/data/templates/default.s5
--- a/data/templates/default.s5
+++ b/data/templates/default.s5
@@ -18,6 +18,7 @@
   <style type="text/css">
       code{white-space: pre-wrap;}
       span.smallcaps{font-variant: small-caps;}
+      span.underline{text-decoration: underline;}
       div.line-block{white-space: pre-line;}
       div.column{display: inline-block; vertical-align: top; width: 50%;}
 $if(quotes)$
diff --git a/data/templates/default.slideous b/data/templates/default.slideous
--- a/data/templates/default.slideous
+++ b/data/templates/default.slideous
@@ -19,6 +19,7 @@
   <style type="text/css">
       code{white-space: pre-wrap;}
       span.smallcaps{font-variant: small-caps;}
+      span.underline{text-decoration: underline;}
       div.line-block{white-space: pre-line;}
       div.column{display: inline-block; vertical-align: top; width: 50%;}
 $if(quotes)$
diff --git a/data/templates/default.slidy b/data/templates/default.slidy
--- a/data/templates/default.slidy
+++ b/data/templates/default.slidy
@@ -19,6 +19,7 @@
   <style type="text/css">
       code{white-space: pre-wrap;}
       span.smallcaps{font-variant: small-caps;}
+      span.underline{text-decoration: underline;}
       div.line-block{white-space: pre-line;}
       div.column{display: inline-block; vertical-align: top; width: 50%;}
 $if(quotes)$
diff --git a/man/pandoc.1 b/man/pandoc.1
--- a/man/pandoc.1
+++ b/man/pandoc.1
@@ -1,5 +1,5 @@
 .\"t
-.TH PANDOC 1 "November 20, 2017" "pandoc 2.0.3"
+.TH PANDOC 1 "December 2, 2017" "pandoc 2.0.4"
 .SH NAME
 pandoc - general markup converter
 .SH SYNOPSIS
@@ -431,6 +431,13 @@
 .RS
 .RE
 .TP
+.B \f[C]\-\-strip\-empty\-paragraphs\f[]
+Ignore paragraphs with non content.
+This option is useful for converting word processing documents where
+users have used empty paragraphs to create inter\-paragraph space.
+.RS
+.RE
+.TP
 .B \f[C]\-\-indented\-code\-classes=\f[]\f[I]CLASSES\f[]
 Specify classes to use for indented code blocks\-\-for example,
 \f[C]perl,numberLines\f[] or \f[C]haskell\f[].
@@ -738,8 +745,16 @@
 \f[C]\&.theme\f[] may be supplied.
 This will be parsed as a KDE syntax highlighting theme and (if valid)
 used as the highlighting style.
-To see a sample theme that can be modified,
-\f[C]pandoc\ \-\-print\-default\-data\-file\ default.theme\f[].
+.PP
+To generate the JSON version of an existing style, use
+\f[C]\-\-print\-highlight\-style\f[].
+.RE
+.TP
+.B \f[C]\-\-print\-highlight\-style=\f[]\f[I]STYLE\f[]|\f[I]FILE\f[]
+Prints a JSON version of a highlighting style, which can be modified,
+saved with a \f[C]\&.theme\f[] extension, and used with
+\f[C]\-\-highlight\-style\f[].
+.RS
 .RE
 .TP
 .B \f[C]\-\-syntax\-definition=\f[]\f[I]FILE\f[]
diff --git a/pandoc.cabal b/pandoc.cabal
--- a/pandoc.cabal
+++ b/pandoc.cabal
@@ -1,5 +1,5 @@
 name:            pandoc
-version:         2.0.3
+version:         2.0.4
 cabal-version:   >= 1.10
 build-type:      Custom
 license:         GPL
@@ -11,7 +11,7 @@
 stability:       alpha
 homepage:        http://pandoc.org
 category:        Text
-tested-with:     GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.2, GHC == 8.2.1
+tested-with:     GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.2, GHC == 8.2.2
 synopsis:        Conversion between markup formats
 description:     Pandoc is a Haskell library for converting from one markup
                  format to another, and a command-line tool that uses
@@ -110,6 +110,8 @@
                  data/sample.lua
                  -- pandoc lua module
                  data/pandoc.lua
+                 -- lua List module
+                 data/List.lua
                  -- sample highlighting theme
                  data/default.theme
                  -- bash completion template
@@ -315,10 +317,10 @@
                  pandoc-types >= 1.17.3 && < 1.18,
                  aeson >= 0.7 && < 1.3,
                  aeson-pretty >= 0.8 && < 0.9,
-                 tagsoup >= 0.13.7 && < 0.15,
+                 tagsoup >= 0.14.2 && < 0.15,
                  base64-bytestring >= 0.1 && < 1.1,
                  zlib >= 0.5 && < 0.7,
-                 skylighting >= 0.4.3.2 && <0.5,
+                 skylighting >= 0.4.4.1 && < 0.5,
                  data-default >= 0.4 && < 0.8,
                  temporary >= 1.1 && < 1.3,
                  blaze-html >= 0.5 && < 0.10,
@@ -328,7 +330,7 @@
                  vector >= 0.10 && < 0.13,
                  hslua >= 0.9 && < 0.10,
                  hslua-module-text >= 0.1.2 && < 0.2,
-                 binary >= 0.5 && < 0.9,
+                 binary >= 0.5 && < 0.10,
                  SHA >= 1.6 && < 1.7,
                  haddock-library >= 1.1 && < 1.5,
                  deepseq >= 1.3 && < 1.5,
@@ -338,7 +340,7 @@
                  doctemplates >= 0.2.1 && < 0.3,
                  http-client >= 0.4.30 && < 0.6,
                  http-client-tls >= 0.2.4 && < 0.4,
-                 http-types >= 0.8 && < 0.10,
+                 http-types >= 0.8 && < 0.12,
                  case-insensitive >= 1.2 && < 1.3
   if os(windows)
     cpp-options:      -D_WINDOWS
@@ -560,7 +562,7 @@
                   temporary >= 1.1 && < 1.3,
                   Diff >= 0.2 && < 0.4,
                   tasty >= 0.11 && < 0.13,
-                  tasty-hunit >= 0.9 && < 0.10,
+                  tasty-hunit >= 0.9 && < 0.11,
                   tasty-quickcheck >= 0.8 && < 0.10,
                   tasty-golden >= 2.3 && < 2.4,
                   QuickCheck >= 2.4 && < 2.11,
diff --git a/src/Text/Pandoc/App.hs b/src/Text/Pandoc/App.hs
--- a/src/Text/Pandoc/App.hs
+++ b/src/Text/Pandoc/App.hs
@@ -1,6 +1,7 @@
 {-# LANGUAGE CPP                 #-}
 {-# LANGUAGE DeriveGeneric       #-}
 {-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell     #-}
 {-# LANGUAGE TupleSections       #-}
 {-
 Copyright (C) 2006-2017 John MacFarlane <jgm@berkeley.edu>
@@ -44,8 +45,8 @@
 import Control.Monad
 import Control.Monad.Except (catchError, throwError)
 import Control.Monad.Trans
-import Data.Aeson (FromJSON (..), ToJSON (..), defaultOptions, eitherDecode',
-                   encode, genericToEncoding)
+import Data.Aeson (defaultOptions, eitherDecode', encode)
+import Data.Aeson.TH (deriveJSON)
 import qualified Data.ByteString as BS
 import qualified Data.ByteString.Lazy as B
 import Data.Char (toLower, toUpper)
@@ -62,7 +63,10 @@
 import GHC.Generics
 import Network.URI (URI (..), parseURI)
 import Paths_pandoc (getDataDir)
-import Skylighting (Style, Syntax (..), defaultSyntaxMap, parseTheme)
+import Data.Aeson.Encode.Pretty (encodePretty', Config(..), keyOrder,
+         defConfig, Indent(..), NumberFormat(..))
+import Skylighting (Style, Syntax (..), defaultSyntaxMap, parseTheme,
+                    pygments)
 import Skylighting.Parser (addSyntaxDefinition, missingIncludes,
                            parseSyntaxDefinition)
 import System.Console.GetOpt
@@ -82,8 +86,8 @@
 import Text.Pandoc.PDF (makePDF)
 import Text.Pandoc.Process (pipeProcess)
 import Text.Pandoc.SelfContained (makeDataURI, makeSelfContained)
-import Text.Pandoc.Shared (eastAsianLineBreakFilter, headerShift, isURI, ordNub,
-                           safeRead, tabFilter)
+import Text.Pandoc.Shared (eastAsianLineBreakFilter, stripEmptyParagraphs,
+         headerShift, isURI, ordNub, safeRead, tabFilter)
 import qualified Text.Pandoc.UTF8 as UTF8
 import Text.Pandoc.Writers.Math (defaultKaTeXURL, defaultMathJaxURL)
 import Text.Pandoc.XML (toEntities)
@@ -95,10 +99,6 @@
 
 data LineEnding = LF | CRLF | Native deriving (Show, Generic)
 
-instance ToJSON LineEnding where
-  toEncoding = genericToEncoding defaultOptions
-instance FromJSON LineEnding
-
 parseOptions :: [OptDescr (Opt -> IO Opt)] -> Opt -> IO Opt
 parseOptions options' defaults = do
   rawArgs <- map UTF8.decodeArg <$> getArgs
@@ -461,14 +461,17 @@
 
     let transforms = (case optBaseHeaderLevel opts of
                           x | x > 1     -> (headerShift (x - 1) :)
-                            | otherwise -> id) $
+                            | otherwise -> id) .
+                     (if optStripEmptyParagraphs opts
+                         then (stripEmptyParagraphs :)
+                         else id) .
                      (if extensionEnabled Ext_east_asian_line_breaks
                             readerExts &&
                          not (extensionEnabled Ext_east_asian_line_breaks
                               writerExts &&
                               writerWrapText writerOptions == WrapPreserve)
                          then (eastAsianLineBreakFilter :)
-                         else id)
+                         else id) $
                      []
 
     let sourceToDoc :: [FilePath] -> PandocIO Pandoc
@@ -622,6 +625,7 @@
     , optLuaFilters            :: [FilePath] -- ^ Lua filters to apply
     , optEmailObfuscation      :: ObfuscationMethod
     , optIdentifierPrefix      :: String
+    , optStripEmptyParagraphs  :: Bool -- ^ Strip empty paragraphs
     , optIndentedCodeClasses   :: [String] -- ^ Default classes for indented code blocks
     , optDataDir               :: Maybe FilePath
     , optCiteMethod            :: CiteMethod -- ^ Method to output cites
@@ -646,10 +650,6 @@
     , optStripComments         :: Bool       -- ^ Skip HTML comments
     } deriving (Generic, Show)
 
-instance ToJSON Opt where
-  toEncoding = genericToEncoding defaultOptions
-instance FromJSON Opt
-
 -- | Defaults for command-line options.
 defaultOpts :: Opt
 defaultOpts = Opt
@@ -698,6 +698,7 @@
     , optLuaFilters            = []
     , optEmailObfuscation      = NoObfuscation
     , optIdentifierPrefix      = ""
+    , optStripEmptyParagraphs  = False
     , optIndentedCodeClasses   = []
     , optDataDir               = Nothing
     , optCiteMethod            = Citeproc
@@ -753,6 +754,7 @@
     ".htm"      -> "html"
     ".md"       -> "markdown"
     ".markdown" -> "markdown"
+    ".muse"     -> "muse"
     ".tex"      -> "latex"
     ".latex"    -> "latex"
     ".ltx"      -> "latex"
@@ -793,6 +795,7 @@
     ".txt"      -> "markdown"
     ".text"     -> "markdown"
     ".md"       -> "markdown"
+    ".muse"     -> "muse"
     ".markdown" -> "markdown"
     ".textile"  -> "textile"
     ".lhs"      -> "markdown+lhs"
@@ -942,7 +945,12 @@
                   "NUMBER")
                  "" -- "Headers base level"
 
-     , Option "" ["indented-code-classes"]
+    , Option "" ["strip-empty-paragraphs"]
+                 (NoArg
+                  (\opt -> return opt{ optStripEmptyParagraphs = True }))
+                 "" -- "Strip empty paragraphs"
+
+    , Option "" ["indented-code-classes"]
                   (ReqArg
                    (\arg opt -> return opt { optIndentedCodeClasses = words $
                                              map (\c -> if c == ',' then ' ' else c) arg })
@@ -1052,6 +1060,28 @@
                   "FILE")
                   "" -- "Print default data file"
 
+    , Option "" ["print-highlight-style"]
+                 (ReqArg
+                  (\arg _ -> do
+                     sty <- fromMaybe pygments <$>
+                              lookupHighlightStyle (Just arg)
+                     B.putStr $ encodePretty'
+                       defConfig{confIndent = Spaces 4
+                                ,confCompare = keyOrder
+                                  (map T.pack
+                                   ["text-color"
+                                   ,"background-color"
+                                   ,"line-numbers"
+                                   ,"bold"
+                                   ,"italic"
+                                   ,"underline"
+                                   ,"text-styles"])
+                                ,confNumFormat = Generic
+                                ,confTrailingNewline = True} sty
+                     exitSuccess)
+                  "STYLE|FILE")
+                 "" -- "Print default template for FORMAT"
+
     , Option "" ["dpi"]
                  (ReqArg
                   (\arg opt ->
@@ -1124,7 +1154,7 @@
     , Option "" ["highlight-style"]
                 (ReqArg
                  (\arg opt -> return opt{ optHighlightStyle = Just arg })
-                 "STYLE")
+                 "STYLE|FILE")
                  "" -- "Style for highlighted code"
 
     , Option "" ["syntax-definition"]
@@ -1442,7 +1472,7 @@
     , Option "m" ["latexmathml", "asciimathml"]
                  (OptArg
                   (\arg opt -> do
-                      deprecatedOption "--latexmathml"
+                      deprecatedOption "--latexmathml, --asciimathml, -m"
                       return opt { optHTMLMathMethod = LaTeXMathML arg })
                   "URL")
                  "" -- "Use LaTeXMathML script in html output"
@@ -1675,3 +1705,8 @@
     \r -> case r of
        Right () -> return ()
        Left e   -> E.throwIO e
+
+-- see https://github.com/jgm/pandoc/pull/4083
+-- using generic deriving caused long compilation times
+$(deriveJSON defaultOptions ''LineEnding)
+$(deriveJSON defaultOptions ''Opt)
diff --git a/src/Text/Pandoc/Extensions.hs b/src/Text/Pandoc/Extensions.hs
--- a/src/Text/Pandoc/Extensions.hs
+++ b/src/Text/Pandoc/Extensions.hs
@@ -15,8 +15,10 @@
 along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 -}
-{-# LANGUAGE DeriveDataTypeable #-}
-{-# LANGUAGE DeriveGeneric      #-}
+{-# LANGUAGE DeriveDataTypeable         #-}
+{-# LANGUAGE DeriveGeneric              #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE TemplateHaskell            #-}
 
 {- |
    Module      : Text.Pandoc.Extensions
@@ -45,8 +47,8 @@
                               , githubMarkdownExtensions
                               , multimarkdownExtensions )
 where
-import Data.Aeson (FromJSON (..), ToJSON (..), defaultOptions,
-                   genericToEncoding)
+import Data.Aeson (FromJSON (..), ToJSON (..), defaultOptions)
+import Data.Aeson.TH (deriveJSON)
 import Data.Bits (clearBit, setBit, testBit, (.|.))
 import Data.Data (Data)
 import Data.Typeable (Typeable)
@@ -55,11 +57,7 @@
 import Text.Parsec
 
 newtype Extensions = Extensions Integer
-  deriving (Show, Read, Eq, Ord, Data, Typeable, Generic)
-
-instance ToJSON Extensions where
-  toEncoding = genericToEncoding defaultOptions
-instance FromJSON Extensions
+  deriving (Show, Read, Eq, Ord, Data, Typeable, Generic, ToJSON, FromJSON)
 
 instance Monoid Extensions where
   mempty = Extensions 0
@@ -156,10 +154,6 @@
     | Ext_amuse -- ^ Enable Text::Amuse extensions to Emacs Muse markup
     deriving (Show, Read, Enum, Eq, Ord, Bounded, Data, Typeable, Generic)
 
-instance ToJSON Extension where
-  toEncoding = genericToEncoding defaultOptions
-instance FromJSON Extension
-
 -- | Extensions to be used with pandoc-flavored markdown.
 pandocExtensions :: Extensions
 pandocExtensions = extensionsFromList
@@ -373,3 +367,5 @@
           return $ case polarity of
                         '-' -> disableExtension ext
                         _   -> enableExtension ext
+
+$(deriveJSON defaultOptions ''Extension)
diff --git a/src/Text/Pandoc/Lua/PandocModule.hs b/src/Text/Pandoc/Lua/PandocModule.hs
--- a/src/Text/Pandoc/Lua/PandocModule.hs
+++ b/src/Text/Pandoc/Lua/PandocModule.hs
@@ -59,10 +59,12 @@
 import qualified Text.Pandoc.MediaBag as MB
 import Text.Pandoc.Lua.Filter (walkInlines, walkBlocks, LuaFilter)
 
--- | Push the "pandoc" on the lua stack.
+-- | Push the "pandoc" on the lua stack. Requires the `list` module to be
+-- loaded.
 pushPandocModule :: Maybe FilePath -> Lua ()
 pushPandocModule datadir = do
-  script <- liftIO (pandocModuleScript datadir)
+  loadListModule datadir
+  script <- liftIO (moduleScript datadir "pandoc.lua")
   status <- Lua.loadstring script
   unless (status /= Lua.OK) $ Lua.call 0 1
   addFunction "_pipe" pipeFn
@@ -72,9 +74,25 @@
   addFunction "walk_inline" walkInline
 
 -- | Get the string representation of the pandoc module
-pandocModuleScript :: Maybe FilePath -> IO String
-pandocModuleScript datadir = unpack <$>
-  runIOorExplode (setUserDataDir datadir >> readDataFile "pandoc.lua")
+moduleScript :: Maybe FilePath -> FilePath -> IO String
+moduleScript datadir moduleFile = unpack <$>
+  runIOorExplode (setUserDataDir datadir >> readDataFile moduleFile)
+
+-- Loads pandoc's list module without assigning it to a variable.
+pushListModule :: Maybe FilePath -> Lua ()
+pushListModule datadir = do
+  script <- liftIO (moduleScript datadir "List.lua")
+  status <- Lua.loadstring script
+  if status == Lua.OK
+    then Lua.call 0 1
+    else Lua.throwTopMessageAsError' ("Error while loading module `list`\n" ++)
+
+loadListModule :: Maybe FilePath -> Lua ()
+loadListModule datadir = do
+  Lua.getglobal' "package.loaded"
+  pushListModule datadir
+  Lua.setfield (-2) "pandoc.List"
+  Lua.pop 1
 
 walkElement :: (ToLuaStack a, Walkable [Inline] a, Walkable [Block] a)
             => a -> LuaFilter -> Lua NumResults
diff --git a/src/Text/Pandoc/Lua/StackInstances.hs b/src/Text/Pandoc/Lua/StackInstances.hs
--- a/src/Text/Pandoc/Lua/StackInstances.hs
+++ b/src/Text/Pandoc/Lua/StackInstances.hs
@@ -36,17 +36,14 @@
 import Foreign.Lua (FromLuaStack (peek), Lua, LuaInteger, LuaNumber, StackIndex,
                     ToLuaStack (push), Type (..), throwLuaError, tryLua)
 import Text.Pandoc.Definition
-import Text.Pandoc.Lua.Util (addValue, adjustIndexBy, getTable,
-                             pushViaConstructor)
+import Text.Pandoc.Lua.Util (adjustIndexBy, getTable, pushViaConstructor)
 import Text.Pandoc.Shared (safeRead)
 
 import qualified Foreign.Lua as Lua
 
 instance ToLuaStack Pandoc where
-  push (Pandoc meta blocks) = do
-    Lua.newtable
-    addValue "blocks" blocks
-    addValue "meta"   meta
+  push (Pandoc meta blocks) =
+    pushViaConstructor "Pandoc" blocks meta
 
 instance FromLuaStack Pandoc where
   peek idx = do
@@ -55,7 +52,8 @@
     return $ Pandoc meta blocks
 
 instance ToLuaStack Meta where
-  push (Meta mmap) = push mmap
+  push (Meta mmap) =
+    pushViaConstructor "Meta" mmap
 instance FromLuaStack Meta where
   peek idx = Meta <$> peek idx
 
diff --git a/src/Text/Pandoc/Options.hs b/src/Text/Pandoc/Options.hs
--- a/src/Text/Pandoc/Options.hs
+++ b/src/Text/Pandoc/Options.hs
@@ -1,5 +1,6 @@
 {-# LANGUAGE DeriveDataTypeable #-}
 {-# LANGUAGE DeriveGeneric      #-}
+{-# LANGUAGE TemplateHaskell    #-}
 {-
 Copyright (C) 2012-2017 John MacFarlane <jgm@berkeley.edu>
 
@@ -45,8 +46,8 @@
                            , def
                            , isEnabled
                            ) where
-import Data.Aeson (FromJSON (..), ToJSON (..), defaultOptions,
-                   genericToEncoding)
+import Data.Aeson (defaultOptions)
+import Data.Aeson.TH (deriveJSON)
 import Data.Data (Data)
 import Data.Default
 import qualified Data.Set as Set
@@ -75,10 +76,6 @@
 instance HasSyntaxExtensions ReaderOptions where
   getExtensions opts = readerExtensions opts
 
-instance ToJSON ReaderOptions where
-  toEncoding = genericToEncoding defaultOptions
-instance FromJSON ReaderOptions
-
 instance Default ReaderOptions
   where def = ReaderOptions{
                  readerExtensions            = emptyExtensions
@@ -116,29 +113,17 @@
                     | KaTeX String                -- url of KaTeX files
                     deriving (Show, Read, Eq, Data, Typeable, Generic)
 
-instance ToJSON HTMLMathMethod where
-  toEncoding = genericToEncoding defaultOptions
-instance FromJSON HTMLMathMethod
-
 data CiteMethod = Citeproc                        -- use citeproc to render them
                   | Natbib                        -- output natbib cite commands
                   | Biblatex                      -- output biblatex cite commands
                 deriving (Show, Read, Eq, Data, Typeable, Generic)
 
-instance ToJSON CiteMethod where
-  toEncoding = genericToEncoding defaultOptions
-instance FromJSON CiteMethod
-
 -- | Methods for obfuscating email addresses in HTML.
 data ObfuscationMethod = NoObfuscation
                        | ReferenceObfuscation
                        | JavascriptObfuscation
                        deriving (Show, Read, Eq, Data, Typeable, Generic)
 
-instance ToJSON ObfuscationMethod where
-  toEncoding = genericToEncoding defaultOptions
-instance FromJSON ObfuscationMethod
-
 -- | Varieties of HTML slide shows.
 data HTMLSlideVariant = S5Slides
                       | SlidySlides
@@ -148,30 +133,18 @@
                       | NoSlides
                       deriving (Show, Read, Eq, Data, Typeable, Generic)
 
-instance ToJSON HTMLSlideVariant where
-  toEncoding = genericToEncoding defaultOptions
-instance FromJSON HTMLSlideVariant
-
 -- | Options for accepting or rejecting MS Word track-changes.
 data TrackChanges = AcceptChanges
                   | RejectChanges
                   | AllChanges
                   deriving (Show, Read, Eq, Data, Typeable, Generic)
 
-instance ToJSON TrackChanges where
-  toEncoding = genericToEncoding defaultOptions
-instance FromJSON TrackChanges
-
 -- | Options for wrapping text in the output.
 data WrapOption = WrapAuto        -- ^ Automatically wrap to width
                 | WrapNone        -- ^ No non-semantic newlines
                 | WrapPreserve    -- ^ Preserve wrapping of input source
                 deriving (Show, Read, Eq, Data, Typeable, Generic)
 
-instance ToJSON WrapOption where
-  toEncoding = genericToEncoding defaultOptions
-instance FromJSON WrapOption
-
 -- | Options defining the type of top-level headers.
 data TopLevelDivision = TopLevelPart      -- ^ Top-level headers become parts
                       | TopLevelChapter   -- ^ Top-level headers become chapters
@@ -180,20 +153,12 @@
                                           --   heuristics
                       deriving (Show, Read, Eq, Data, Typeable, Generic)
 
-instance ToJSON TopLevelDivision where
-  toEncoding = genericToEncoding defaultOptions
-instance FromJSON TopLevelDivision
-
 -- | Locations for footnotes and references in markdown output
 data ReferenceLocation = EndOfBlock    -- ^ End of block
                        | EndOfSection  -- ^ prior to next section header (or end of document)
                        | EndOfDocument -- ^ at end of document
                        deriving (Show, Read, Eq, Data, Typeable, Generic)
 
-instance ToJSON ReferenceLocation where
-  toEncoding = genericToEncoding defaultOptions
-instance FromJSON ReferenceLocation
-
 -- | Options for writers
 data WriterOptions = WriterOptions
   { writerTemplate          :: Maybe String -- ^ Template to use
@@ -271,3 +236,13 @@
 -- | Returns True if the given extension is enabled.
 isEnabled :: HasSyntaxExtensions a => Extension -> a -> Bool
 isEnabled ext opts = ext `extensionEnabled` getExtensions opts
+
+$(deriveJSON defaultOptions ''ReaderOptions)
+$(deriveJSON defaultOptions ''HTMLMathMethod)
+$(deriveJSON defaultOptions ''CiteMethod)
+$(deriveJSON defaultOptions ''ObfuscationMethod)
+$(deriveJSON defaultOptions ''HTMLSlideVariant)
+$(deriveJSON defaultOptions ''TrackChanges)
+$(deriveJSON defaultOptions ''WrapOption)
+$(deriveJSON defaultOptions ''TopLevelDivision)
+$(deriveJSON defaultOptions ''ReferenceLocation)
diff --git a/src/Text/Pandoc/Readers/Docx.hs b/src/Text/Pandoc/Readers/Docx.hs
--- a/src/Text/Pandoc/Readers/Docx.hs
+++ b/src/Text/Pandoc/Readers/Docx.hs
@@ -534,9 +534,7 @@
       then do modify $ \s -> s { docxDropCap = ils' }
               return mempty
       else do modify $ \s -> s { docxDropCap = mempty }
-              return $ case isNull ils' of
-                True -> mempty
-                _    -> parStyleToTransform pPr $ para ils'
+              return $ parStyleToTransform pPr $ para ils'
 bodyPartToBlocks (ListItem pPr numId lvl (Just levelInfo) parparts) = do
   let
     kvs = case levelInfo of
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
@@ -1147,7 +1147,7 @@
   -- <www.boe.es/buscar/act.php?id=BOE-A-1996-8930#a66>
   -- should NOT be parsed as an HTML tag, see #2277,
   -- so we exclude . even though it's a valid character
-  -- in XML elemnet names
+  -- in XML element names
   let isNameChar c = isAlphaNum c || c == ':' || c == '-' || c == '_'
   let isName s = case s of
                       []     -> False
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
@@ -1245,6 +1245,7 @@
   , ("textup", extractSpaces (spanWith ("",["upright"],[])) <$> tok)
   , ("texttt", ttfamily)
   , ("sout", extractSpaces strikeout <$> tok)
+  , ("alert", skipangles >> spanWith ("",["alert"],[]) <$> tok) -- beamer
   , ("lq", return (str "‘"))
   , ("rq", return (str "’"))
   , ("textquoteleft", return (str "‘"))
diff --git a/src/Text/Pandoc/Readers/Muse.hs b/src/Text/Pandoc/Readers/Muse.hs
--- a/src/Text/Pandoc/Readers/Muse.hs
+++ b/src/Text/Pandoc/Readers/Muse.hs
@@ -55,10 +55,9 @@
 import Text.Pandoc.Definition
 import Text.Pandoc.Logging
 import Text.Pandoc.Options
-import Text.Pandoc.Parsing hiding (nested)
+import Text.Pandoc.Parsing
 import Text.Pandoc.Readers.HTML (htmlTag)
 import Text.Pandoc.Shared (crFilter)
-import Text.Pandoc.XML (fromEntities)
 
 -- | Read Muse from an input string and return a Pandoc document.
 readMuse :: PandocMonad m
@@ -102,15 +101,6 @@
 eol :: Stream s m Char => ParserT s st m ()
 eol = void newline <|> eof
 
-nested :: PandocMonad m => MuseParser m a -> MuseParser m a
-nested p = do
-  nestlevel <- stateMaxNestingLevel <$>  getState
-  guard $ nestlevel > 0
-  updateState $ \st -> st{ stateMaxNestingLevel = stateMaxNestingLevel st - 1 }
-  res <- p
-  updateState $ \st -> st{ stateMaxNestingLevel = nestlevel }
-  return res
-
 htmlElement :: PandocMonad m => String -> MuseParser m (Attr, String)
 htmlElement tag = try $ do
   (TagOpen _ attr, _) <- htmlTag (~== TagOpen tag [])
@@ -133,12 +123,19 @@
   parsedContent <- parseContent (content ++ "\n")
   return (attr, parsedContent)
   where
-    parseContent = parseFromString $ nested $ manyTill parser endOfContent
+    parseContent = parseFromString $ manyTill parser endOfContent
     endOfContent = try $ skipMany blankline >> skipSpaces >> eof
 
 parseHtmlContent :: PandocMonad m => String -> MuseParser m a -> MuseParser m [a]
 parseHtmlContent tag p = fmap snd (parseHtmlContentWithAttrs tag p)
 
+commonPrefix :: String -> String -> String
+commonPrefix _ [] = []
+commonPrefix [] _ = []
+commonPrefix (x:xs) (y:ys)
+  | x == y    = x : commonPrefix xs ys
+  | otherwise = []
+
 --
 -- directive parsers
 --
@@ -228,23 +225,28 @@
   contents <- manyTill anyChar $ try (optionMaybe blankline >> string "}}}")
   return $ return $ B.codeBlock contents
 
-exampleTag :: PandocMonad m => MuseParser m (F Blocks)
-exampleTag = do
-  (attr, contents) <- htmlElement "example"
-  return $ return $ B.codeBlockWith attr $ chop contents
+-- Trim up to one newline from the beginning and the end,
+-- in case opening and/or closing tags are on separate lines.
+chop :: String -> String
+chop = lchop . rchop
   where lchop s = case s of
                     '\n':ss -> ss
                     _       -> s
         rchop = reverse . lchop . reverse
-        -- Trim up to one newline from the beginning and the end,
-        -- in case opening and/or closing tags are on separate lines.
-        chop = lchop . rchop
 
+exampleTag :: PandocMonad m => MuseParser m (F Blocks)
+exampleTag = do
+  (attr, contents) <- htmlElement "example"
+  return $ return $ B.codeBlockWith attr $ chop contents
+
 literal :: PandocMonad m => MuseParser m (F Blocks)
-literal = (return . rawBlock) <$> htmlElement "literal"
+literal = do
+  guardDisabled Ext_amuse -- Text::Amuse does not support <literal>
+  (return . rawBlock) <$> htmlElement "literal"
   where
-    format (_, _, kvs)        = fromMaybe "html" $ lookup "format" kvs
-    rawBlock (attrs, content) = B.rawBlock (format attrs) content
+    -- FIXME: Emacs Muse inserts <literal> without style into all output formats, but we assume HTML
+    format (_, _, kvs)        = fromMaybe "html" $ lookup "style" kvs
+    rawBlock (attrs, content) = B.rawBlock (format attrs) $ chop content
 
 blockTag :: PandocMonad m
           => (Blocks -> Blocks)
@@ -296,7 +298,8 @@
 para :: PandocMonad m => MuseParser m (F Blocks)
 para = do
  indent <- length <$> many spaceChar
- let f = if indent >= 2 && indent < 6 then B.blockQuote else id
+ st <- stateParserContext <$> getState
+ let f = if st /= ListItemState && indent >= 2 && indent < 6 then B.blockQuote else id
  fmap (f . B.para) . trimInlinesF . mconcat <$> many1Till inline endOfParaElement
  where
    endOfParaElement = lookAhead $ endOfInput <|> endOfPara <|> newBlockElement
@@ -315,8 +318,8 @@
 amuseNoteBlock = try $ do
   guardEnabled Ext_amuse
   pos <- getPosition
-  ref <- noteMarker <* skipSpaces
-  content <- listItemContents $ 2 + length ref
+  ref <- noteMarker <* spaceChar
+  content <- listItemContents $ 3 + length ref
   oldnotes <- stateNotes' <$> getState
   case M.lookup ref oldnotes of
     Just _  -> logMessage $ DuplicateNoteReference ref pos
@@ -369,7 +372,7 @@
 listLine :: PandocMonad m => Int -> MuseParser m String
 listLine markerLength = try $ do
   indentWith markerLength
-  anyLineNewline
+  manyTill anyChar eol
 
 withListContext :: PandocMonad m => MuseParser m a -> MuseParser m a
 withListContext p = do
@@ -380,11 +383,11 @@
   updateState (\st -> st {stateParserContext = oldContext})
   return parsed
 
-listContinuation :: PandocMonad m => Int -> MuseParser m String
+listContinuation :: PandocMonad m => Int -> MuseParser m [String]
 listContinuation markerLength = try $ do
   result <- many1 $ listLine markerLength
-  blank <- option "" ("\n" <$ blankline)
-  return $ concat result ++ blank
+  blank <- option id ((++ [""]) <$ blankline)
+  return $ blank result
 
 listStart :: PandocMonad m => MuseParser m Int -> MuseParser m Int
 listStart marker = try $ do
@@ -392,17 +395,24 @@
   st <- stateParserContext <$> getState
   getPosition >>= \pos -> guard (st == ListItemState || sourceColumn pos /= 1)
   markerLength <- marker
-  many1 spaceChar
+  void spaceChar <|> eol
   return $ preWhitespace + markerLength + 1
 
+dropSpacePrefix :: [String] -> [String]
+dropSpacePrefix lns =
+  map (drop maxIndent) lns
+  where flns = filter (\s -> not $ all (== ' ') s) lns
+        maxIndent = if null flns then 0 else length $ takeWhile (== ' ') $ foldl1 commonPrefix flns
+
 listItemContents :: PandocMonad m => Int -> MuseParser m (F Blocks)
 listItemContents markerLength = do
-  firstLine <- anyLineNewline
+  firstLine <- manyTill anyChar eol
   restLines <- many $ listLine markerLength
-  blank <- option "" ("\n" <$ blankline)
-  let first = firstLine ++ concat restLines ++ blank
+  blank <- option id ((++ [""]) <$ blankline)
+  let first = firstLine : blank restLines
   rest <- many $ listContinuation markerLength
-  parseFromString (withListContext parseBlocks) $ concat (first:rest) ++ "\n"
+  let allLines = concat (first : rest)
+  parseFromString (withListContext parseBlocks) $ unlines (dropSpacePrefix allLines)
 
 listItem :: PandocMonad m => MuseParser m Int -> MuseParser m (F Blocks)
 listItem start = try $ do
@@ -428,7 +438,7 @@
 
 orderedList :: PandocMonad m => MuseParser m (F Blocks)
 orderedList = try $ do
-  p@(_, style, delim) <- lookAhead (many spaceChar *> anyOrderedListMarker <* spaceChar)
+  p@(_, style, delim) <- lookAhead (many spaceChar *> anyOrderedListMarker <* (eol <|> void spaceChar))
   guard $ style `elem` [Decimal, LowerAlpha, UpperAlpha, LowerRoman, UpperRoman]
   guard $ delim == Period
   items <- sequence <$> many1 (listItem $ orderedListStart style delim)
@@ -436,20 +446,22 @@
 
 definitionListItem :: PandocMonad m => MuseParser m (F (Inlines, [Blocks]))
 definitionListItem = try $ do
-  term <- termParser
+  rawTerm <- termParser
+  term <- parseFromString (trimInlinesF . mconcat <$> many inline) rawTerm
   many1 spaceChar
   string "::"
-  firstLine <- anyLineNewline
-  restLines <- manyTill anyLineNewline endOfListItemElement
-  let lns = firstLine : restLines
-  lineContent <- parseFromString (withListContext parseBlocks) $ concat lns ++ "\n"
+  firstLine <- manyTill anyChar eol
+  restLines <- manyTill anyLine endOfListItemElement
+  let lns = dropWhile (== ' ') firstLine : dropSpacePrefix restLines
+  lineContent <- parseFromString (withListContext parseBlocks) $ unlines lns
   pure $ do lineContent' <- lineContent
-            pure (B.text term, [lineContent'])
+            term' <- term
+            pure (term', [lineContent'])
   where
     termParser = (guardDisabled Ext_amuse <|> void spaceChar) >> -- Initial space is required by Amusewiki, but not Emacs Muse
                  many spaceChar >>
-                 many1Till anyChar (lookAhead (void (try (spaceChar >> string "::")) <|> void newline))
-    endOfInput = try $ skipMany blankline >> skipSpaces >> eof
+                 many1Till (noneOf "\n") (lookAhead (void (try (spaceChar >> string "::"))))
+    endOfInput = lookAhead $ try $ skipMany blankline >> skipSpaces >> eof
     twoBlankLines = try $ blankline >> skipMany1 blankline
     newDefinitionListItem = try $ void termParser
     endOfListItemElement = lookAhead $ endOfInput <|> newDefinitionListItem <|> twoBlankLines
@@ -569,9 +581,11 @@
              , subscriptTag
              , strikeoutTag
              , verbatimTag
+             , nbsp
              , link
              , code
              , codeTag
+             , inlineLiteralTag
              , whitespace
              , str
              , symbol
@@ -667,8 +681,14 @@
 verbatimTag :: PandocMonad m => MuseParser m (F Inlines)
 verbatimTag = do
   content <- parseHtmlContent "verbatim" anyChar
-  return $ return $ B.text $ fromEntities content
+  return $ return $ B.text content
 
+nbsp :: PandocMonad m => MuseParser m (F Inlines)
+nbsp = do
+  guardDisabled Ext_amuse -- Supported only by Emacs Muse
+  string "~~"
+  return $ return $ B.str "\160"
+
 code :: PandocMonad m => MuseParser m (F Inlines)
 code = try $ do
   pos <- getPosition
@@ -686,13 +706,23 @@
 codeTag :: PandocMonad m => MuseParser m (F Inlines)
 codeTag = do
   (attrs, content) <- parseHtmlContentWithAttrs "code" anyChar
-  return $ return $ B.codeWith attrs $ fromEntities content
+  return $ return $ B.codeWith attrs content
 
+inlineLiteralTag :: PandocMonad m => MuseParser m (F Inlines)
+inlineLiteralTag = do
+  guardDisabled Ext_amuse -- Text::Amuse does not support <literal>
+  (attrs, content) <- parseHtmlContentWithAttrs "literal" anyChar
+  return $ return $ rawInline (attrs, content)
+  where
+    -- FIXME: Emacs Muse inserts <literal> without style into all output formats, but we assume HTML
+    format (_, _, kvs)        = fromMaybe "html" $ lookup "style" kvs
+    rawInline (attrs, content) = B.rawInline (format attrs) content
+
 str :: PandocMonad m => MuseParser m (F Inlines)
-str = fmap (return . B.str) (many1 alphaNum <|> count 1 characterReference)
+str = return . B.str <$> many1 alphaNum
 
 symbol :: PandocMonad m => MuseParser m (F Inlines)
-symbol = (return . B.str) <$> count 1 nonspaceChar
+symbol = return . B.str <$> count 1 nonspaceChar
 
 link :: PandocMonad m => MuseParser m (F Inlines)
 link = try $ do
diff --git a/src/Text/Pandoc/Readers/Org/BlockStarts.hs b/src/Text/Pandoc/Readers/Org/BlockStarts.hs
--- a/src/Text/Pandoc/Readers/Org/BlockStarts.hs
+++ b/src/Text/Pandoc/Readers/Org/BlockStarts.hs
@@ -75,21 +75,25 @@
    latexEnvName :: Monad m => OrgParser m String
    latexEnvName = try $ mappend <$> many1 alphaNum <*> option "" (string "*")
 
-
--- | Parses bullet list marker.
-bulletListStart :: Monad m => OrgParser m ()
-bulletListStart = try $
-  choice
-  [ () <$ skipSpaces  <* oneOf "+-" <* skipSpaces1
-  , () <$ skipSpaces1 <* char '*'   <* skipSpaces1
-  ]
+bulletListStart :: Monad m => OrgParser m Int
+bulletListStart = try $ do
+  ind <- length <$> many spaceChar
+   -- Unindented lists cannot use '*' bullets.
+  oneOf (if ind == 0 then "+-" else "*+-")
+  skipSpaces1 <|> lookAhead eol
+  return (ind + 1)
 
 genericListStart :: Monad m
                  => OrgParser m String
                  -> OrgParser m Int
-genericListStart listMarker = try $
-  (+) <$> (length <$> many spaceChar)
-      <*> (length <$> listMarker <* many1 spaceChar)
+genericListStart listMarker = try $ do
+  ind <- length <$> many spaceChar
+  void listMarker
+  skipSpaces1 <|> lookAhead eol
+  return (ind + 1)
+
+eol :: Monad m => OrgParser m ()
+eol = void (char '\n')
 
 orderedListStart :: Monad m => OrgParser m Int
 orderedListStart = genericListStart orderedListMarker
diff --git a/src/Text/Pandoc/Readers/Org/Blocks.hs b/src/Text/Pandoc/Readers/Org/Blocks.hs
--- a/src/Text/Pandoc/Readers/Org/Blocks.hs
+++ b/src/Text/Pandoc/Readers/Org/Blocks.hs
@@ -744,7 +744,7 @@
   -- is directly followed by a list item, in which case the block is read as
   -- plain text.
   try (guard nl
-       *> notFollowedBy (inList *> (() <$ orderedListStart <|> bulletListStart))
+       *> notFollowedBy (inList *> (orderedListStart <|> bulletListStart))
        *> return (B.para <$> ils))
     <|>  return (B.plain <$> ils)
 
@@ -757,40 +757,34 @@
 list = choice [ definitionList, bulletList, orderedList ] <?> "list"
 
 definitionList :: PandocMonad m => OrgParser m (F Blocks)
-definitionList = try $ do n <- lookAhead (bulletListStart' Nothing)
-                          fmap (B.definitionList . compactifyDL) . sequence
-                            <$> many1 (definitionListItem $ bulletListStart' (Just n))
+definitionList = try $ do
+  indent <- lookAhead bulletListStart
+  fmap (B.definitionList . compactifyDL) . sequence
+    <$> many1 (definitionListItem (bulletListStart `indented` indent))
 
 bulletList :: PandocMonad m => OrgParser m (F Blocks)
-bulletList = try $ do n <- lookAhead (bulletListStart' Nothing)
-                      fmap (B.bulletList . compactify) . sequence
-                        <$> many1 (listItem (bulletListStart' $ Just n))
-
-orderedList :: PandocMonad m => OrgParser m (F Blocks)
-orderedList = fmap (B.orderedList . compactify) . sequence
-              <$> many1 (listItem orderedListStart)
+bulletList = try $ do
+  indent <- lookAhead bulletListStart
+  fmap (B.bulletList . compactify) . sequence
+    <$> many1 (listItem (bulletListStart `indented` indent))
 
-bulletListStart' :: Monad m => Maybe Int -> OrgParser m Int
--- returns length of bulletList prefix, inclusive of marker
-bulletListStart' Nothing  = do ind <- length <$> many spaceChar
-                               oneOf (bullets $ ind == 0)
-                               skipSpaces1
-                               return (ind + 1)
-bulletListStart' (Just n) = do count (n-1) spaceChar
-                               oneOf (bullets $ n == 1)
-                               many1 spaceChar
-                               return n
+indented :: Monad m => OrgParser m Int -> Int -> OrgParser m Int
+indented indentedMarker minIndent = try $ do
+  n <- indentedMarker
+  guard (minIndent <= n)
+  return n
 
--- Unindented lists are legal, but they can't use '*' bullets.
--- We return n to maintain compatibility with the generic listItem.
-bullets :: Bool -> String
-bullets unindented = if unindented then "+-" else "*+-"
+orderedList :: PandocMonad m => OrgParser m (F Blocks)
+orderedList = try $ do
+  indent <- lookAhead orderedListStart
+  fmap (B.orderedList . compactify) . sequence
+    <$> many1 (listItem (orderedListStart `indented` indent))
 
 definitionListItem :: PandocMonad m
                    => OrgParser m Int
                    -> OrgParser m (F (Inlines, [Blocks]))
-definitionListItem parseMarkerGetLength = try $ do
-  markerLength <- parseMarkerGetLength
+definitionListItem parseIndentedMarker = try $ do
+  markerLength <- parseIndentedMarker
   term <- manyTill (noneOf "\n\r") (try definitionMarker)
   line1 <- anyLineNewline
   blank <- option "" ("\n" <$ blankline)
@@ -802,13 +796,12 @@
    definitionMarker =
      spaceChar *> string "::" <* (spaceChar <|> lookAhead newline)
 
-
--- parse raw text for one list item, excluding start marker and continuations
+-- | parse raw text for one list item
 listItem :: PandocMonad m
          => OrgParser m Int
          -> OrgParser m (F Blocks)
-listItem start = try . withContext ListItemState $ do
-  markerLength <- try start
+listItem parseIndentedMarker = try . withContext ListItemState $ do
+  markerLength <- try parseIndentedMarker
   firstLine <- anyLineNewline
   blank <- option "" ("\n" <$ blankline)
   rest <- concat <$> many (listContinuation markerLength)
@@ -818,9 +811,9 @@
 -- Note: nested lists are parsed as continuations.
 listContinuation :: Monad m => Int
                  -> OrgParser m String
-listContinuation markerLength = try $
+listContinuation markerLength = try $ do
   notFollowedBy' blankline
-  *> (mappend <$> (concat <$> many1 listLine)
-              <*> many blankline)
+  mappend <$> (concat <$> many1 listLine)
+          <*> many blankline
  where
    listLine = try $ indentWith markerLength *> anyLineNewline
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
@@ -72,6 +72,7 @@
                      inlineListToIdentifier,
                      isHeaderBlock,
                      headerShift,
+                     stripEmptyParagraphs,
                      isTightList,
                      addMetaField,
                      makeMeta,
@@ -106,7 +107,7 @@
 import Data.Char (isAlpha, isDigit, isLetter, isLower, isSpace, isUpper,
                   toLower)
 import Data.Data (Data, Typeable)
-import Data.List (find, intercalate, stripPrefix)
+import Data.List (find, intercalate, intersperse, stripPrefix)
 import qualified Data.Map as M
 import Data.Maybe (mapMaybe)
 import Data.Monoid ((<>))
@@ -291,7 +292,7 @@
              parseTime defaultTimeLocale
 #endif
         formats = ["%x","%m/%d/%Y", "%D","%F", "%d %b %Y",
-                    "%d %B %Y", "%b. %d, %Y", "%B %d, %Y",
+                    "%e %B %Y", "%b. %e, %Y", "%B %e, %Y",
                     "%Y%m%d", "%Y%m", "%Y"]
 
 --
@@ -529,6 +530,14 @@
         shift (Header level attr inner) = Header (level + n) attr inner
         shift x                         = x
 
+-- | Remove empty paragraphs.
+stripEmptyParagraphs :: Pandoc -> Pandoc
+stripEmptyParagraphs = walk go
+  where go :: [Block] -> [Block]
+        go = filter (not . isEmptyParagraph)
+        isEmptyParagraph (Para []) = True
+        isEmptyParagraph _         = False
+
 -- | Detect if a list is tight.
 isTightList :: [[Block]] -> Bool
 isTightList = all firstIsPlain
@@ -708,37 +717,40 @@
 --- Squash blocks into inlines
 ---
 
-blockToInlines :: Block -> [Inline]
-blockToInlines (Plain ils) = ils
-blockToInlines (Para ils) = ils
-blockToInlines (LineBlock lns) = combineLines lns
-blockToInlines (CodeBlock attr str) = [Code attr str]
-blockToInlines (RawBlock fmt str) = [RawInline fmt str]
-blockToInlines (BlockQuote blks) = blocksToInlines blks
+blockToInlines :: Block -> Inlines
+blockToInlines (Plain ils) = B.fromList ils
+blockToInlines (Para ils) = B.fromList ils
+blockToInlines (LineBlock lns) = B.fromList $ combineLines lns
+blockToInlines (CodeBlock attr str) = B.codeWith attr str
+blockToInlines (RawBlock (Format fmt) str) = B.rawInline fmt str
+blockToInlines (BlockQuote blks) = blocksToInlines' blks
 blockToInlines (OrderedList _ blkslst) =
-  concatMap blocksToInlines blkslst
+  mconcat $ map blocksToInlines' blkslst
 blockToInlines (BulletList blkslst) =
-  concatMap blocksToInlines blkslst
+  mconcat $ map blocksToInlines' blkslst
 blockToInlines (DefinitionList pairslst) =
-  concatMap f pairslst
+  mconcat $ map f pairslst
   where
-    f (ils, blkslst) = ils ++
-      [Str ":", Space] ++
-      concatMap blocksToInlines blkslst
-blockToInlines (Header _ _  ils) = ils
-blockToInlines HorizontalRule = []
+    f (ils, blkslst) = B.fromList ils <> B.str ":" <> B.space <>
+      mconcat (map blocksToInlines' blkslst)
+blockToInlines (Header _ _  ils) = B.fromList ils
+blockToInlines HorizontalRule = mempty
 blockToInlines (Table _ _ _ headers rows) =
-  intercalate [LineBreak] $ map (concatMap blocksToInlines) tbl
-  where
-    tbl = headers : rows
-blockToInlines (Div _ blks) = blocksToInlines blks
-blockToInlines Null = []
+  mconcat $ intersperse B.linebreak $
+    map (mconcat . map blocksToInlines') (headers:rows)
+blockToInlines (Div _ blks) = blocksToInlines' blks
+blockToInlines Null = mempty
 
-blocksToInlinesWithSep :: [Inline] -> [Block] -> [Inline]
-blocksToInlinesWithSep sep blks = intercalate sep $ map blockToInlines blks
+blocksToInlinesWithSep :: Inlines -> [Block] -> Inlines
+blocksToInlinesWithSep sep =
+  mconcat . intersperse sep . map blockToInlines
 
+blocksToInlines' :: [Block] -> Inlines
+blocksToInlines' = blocksToInlinesWithSep parSep
+  where parSep = B.space <> B.str "¶" <> B.space
+
 blocksToInlines :: [Block] -> [Inline]
-blocksToInlines = blocksToInlinesWithSep [Space, Str "¶", Space]
+blocksToInlines = B.toList . blocksToInlines'
 
 
 --
diff --git a/src/Text/Pandoc/Writers/CommonMark.hs b/src/Text/Pandoc/Writers/CommonMark.hs
--- a/src/Text/Pandoc/Writers/CommonMark.hs
+++ b/src/Text/Pandoc/Writers/CommonMark.hs
@@ -39,13 +39,14 @@
 import Data.Monoid (Any (..), (<>))
 import Data.Text (Text)
 import qualified Data.Text as T
+import Network.HTTP (urlEncode)
 import Text.Pandoc.Class (PandocMonad)
 import Text.Pandoc.Definition
 import Text.Pandoc.Options
 import Text.Pandoc.Shared (isTightList, linesToPara, substitute)
 import Text.Pandoc.Templates (renderTemplate')
 import Text.Pandoc.Walk (query, walk, walkM)
-import Text.Pandoc.Writers.HTML (writeHtml5String)
+import Text.Pandoc.Writers.HTML (writeHtml5String, tagWithAttributes)
 import Text.Pandoc.Writers.Shared
 
 -- | Convert Pandoc to CommonMark.
@@ -110,9 +111,12 @@
 blockToNodes opts (LineBlock lns) ns = blockToNodes opts (linesToPara lns) ns
 blockToNodes _ (CodeBlock (_,classes,_) xs) ns = return
   (node (CODE_BLOCK (T.pack (unwords classes)) (T.pack xs)) [] : ns)
-blockToNodes _ (RawBlock fmt xs) ns
-  | fmt == Format "html" = return (node (HTML_BLOCK (T.pack xs)) [] : ns)
-  | otherwise = return (node (CUSTOM_BLOCK (T.pack xs) T.empty) [] : ns)
+blockToNodes opts (RawBlock fmt xs) ns
+  | fmt == Format "html" && isEnabled Ext_raw_html opts
+              = return (node (HTML_BLOCK (T.pack xs)) [] : ns)
+  | fmt == Format "latex" || fmt == Format "tex" && isEnabled Ext_raw_tex opts
+              = return (node (CUSTOM_BLOCK (T.pack xs) T.empty) [] : ns)
+  | otherwise = return ns
 blockToNodes opts (BlockQuote bs) ns = do
   nodes <- blocksToNodes opts bs
   return (node BLOCK_QUOTE nodes : ns)
@@ -136,9 +140,13 @@
 blockToNodes _ HorizontalRule ns = return (node THEMATIC_BREAK [] : ns)
 blockToNodes opts (Header lev _ ils) ns =
   return (node (HEADING lev) (inlinesToNodes opts ils) : ns)
-blockToNodes opts (Div _ bs) ns = do
+blockToNodes opts (Div attr bs) ns = do
   nodes <- blocksToNodes opts bs
-  return (nodes ++ ns)
+  let op = tagWithAttributes opts True False "div" attr
+  if isEnabled Ext_raw_html opts
+     then return (node (HTML_BLOCK op) [] : nodes ++
+                  [node (HTML_BLOCK (T.pack "</div>")) []] ++ ns)
+     else return (nodes ++ ns)
 blockToNodes opts (DefinitionList items) ns =
   blockToNodes opts (BulletList items') ns
   where items' = map dlToBullet items
@@ -262,9 +270,12 @@
   inlineToNodes opts (Image alt ils (url,tit))
 inlineToNodes opts (Image _ ils (url,tit)) =
   (node (IMAGE (T.pack url) (T.pack tit)) (inlinesToNodes opts ils) :)
-inlineToNodes _ (RawInline fmt xs)
-  | fmt == Format "html" = (node (HTML_INLINE (T.pack xs)) [] :)
-  | otherwise = (node (CUSTOM_INLINE (T.pack xs) T.empty) [] :)
+inlineToNodes opts (RawInline fmt xs)
+  | fmt == Format "html" && isEnabled Ext_raw_html opts
+              = (node (HTML_INLINE (T.pack xs)) [] :)
+  | (fmt == Format "latex" || fmt == Format "tex") && isEnabled Ext_raw_tex opts
+              = (node (CUSTOM_INLINE (T.pack xs) T.empty) [] :)
+  | otherwise = id
 inlineToNodes opts (Quoted qt ils) =
   ((node (TEXT start) [] :
    inlinesToNodes opts ils ++ [node (TEXT end) []]) ++)
@@ -276,13 +287,28 @@
                             | isEnabled Ext_smart opts -> ("\"", "\"")
                             | otherwise -> ("“", "”")
 inlineToNodes _ (Code _ str) = (node (CODE (T.pack str)) [] :)
-inlineToNodes _ (Math mt str) =
-  case mt of
-    InlineMath  ->
-      (node (HTML_INLINE (T.pack ("\\(" ++ str ++ "\\)"))) [] :)
-    DisplayMath ->
-      (node (HTML_INLINE (T.pack ("\\[" ++ str ++ "\\]"))) [] :)
-inlineToNodes opts (Span _ ils) = (inlinesToNodes opts ils ++)
+inlineToNodes opts (Math mt str) =
+  case writerHTMLMathMethod opts of
+       WebTeX url ->
+           let core = inlineToNodes opts
+                        (Image nullAttr [Str str] (url ++ urlEncode str, str))
+               sep = if mt == DisplayMath
+                        then (node LINEBREAK [] :)
+                        else id
+           in  (sep . core . sep)
+       _  ->
+           case mt of
+            InlineMath  ->
+              (node (HTML_INLINE (T.pack ("\\(" ++ str ++ "\\)"))) [] :)
+            DisplayMath ->
+              (node (HTML_INLINE (T.pack ("\\[" ++ str ++ "\\]"))) [] :)
+inlineToNodes opts (Span attr ils) =
+  let nodes = inlinesToNodes opts ils
+      op = tagWithAttributes opts True False "span" attr
+  in  if isEnabled Ext_raw_html opts
+         then ((node (HTML_INLINE op) [] : nodes ++
+                [node (HTML_INLINE (T.pack "</span>")) []]) ++)
+         else (nodes ++)
 inlineToNodes opts (Cite _ ils) = (inlinesToNodes opts ils ++)
 inlineToNodes _ (Note _) = id -- should not occur
 -- we remove Note elements in preprocessing
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
@@ -31,7 +31,7 @@
 -}
 module Text.Pandoc.Writers.ConTeXt ( writeConTeXt ) where
 import Control.Monad.State.Strict
-import Data.Char (ord)
+import Data.Char (ord, isDigit)
 import Data.List (intercalate, intersperse)
 import Data.Maybe (mapMaybe)
 import Data.Text (Text)
@@ -104,8 +104,9 @@
                 $ defField "number-sections" (writerNumberSections options)
                 $ maybe id (defField "context-lang") mblang
                 $ (case getField "papersize" metadata of
-                        Just ("a4" :: String) -> resetField "papersize"
-                                                    ("A4" :: String)
+                        Just (('a':d:ds) :: String)
+                          | all isDigit (d:ds) -> resetField "papersize"
+                                                     (('A':d:ds) :: String)
                         _                     -> id) metadata
   let context' = defField "context-dir" (toContextDir
                                          $ getField "dir" context) context
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
@@ -922,8 +922,6 @@
   captionNode <- withParaProp (pCustomStyle "ImageCaption")
                  $ blockToOpenXML opts (Para alt)
   return $ mknode "w:p" [] (paraProps ++ contents) : captionNode
--- fixDisplayMath sometimes produces a Para [] as artifact
-blockToOpenXML' _ (Para []) = return []
 blockToOpenXML' opts (Para lst) = do
   isFirstPara <- gets stFirstPara
   paraProps <- getParaProps $ case lst of
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
@@ -41,7 +41,8 @@
   writeSlidy,
   writeSlideous,
   writeDZSlides,
-  writeRevealJs
+  writeRevealJs,
+  tagWithAttributes
   ) where
 import Control.Monad.State.Strict
 import Data.Char (ord, toLower)
@@ -55,6 +56,7 @@
 import Network.HTTP (urlEncode)
 import Network.URI (URI (..), parseURIReference, unEscapeString)
 import Numeric (showHex)
+import Text.Blaze.Internal (customLeaf)
 import Text.Blaze.Html hiding (contents)
 import Text.Pandoc.Definition
 import Text.Pandoc.Highlighting (formatHtmlBlock, formatHtmlInline, highlight,
@@ -83,7 +85,7 @@
 import Text.Blaze.Html.Renderer.Text (renderHtml)
 import qualified Text.Blaze.XHtml1.Transitional as H
 import qualified Text.Blaze.XHtml1.Transitional.Attributes as A
-import Text.Pandoc.Class (PandocMonad, report)
+import Text.Pandoc.Class (PandocMonad, report, runPure)
 import Text.Pandoc.Error
 import Text.Pandoc.Logging
 import Text.TeXMath
@@ -541,6 +543,21 @@
 -- | Obfuscate string using entities.
 obfuscateString :: String -> String
 obfuscateString = concatMap obfuscateChar . fromEntities
+
+-- | Create HTML tag with attributes.
+tagWithAttributes :: WriterOptions
+                  -> Bool -- ^ True for HTML5
+                  -> Bool -- ^ True if self-closing tag
+                  -> Text -- ^ Tag text
+                  -> Attr -- ^ Pandoc style tag attributes
+                  -> Text
+tagWithAttributes opts html5 selfClosing tagname attr =
+  let mktag = (TL.toStrict . renderHtml <$> evalStateT
+               (addAttrs opts attr (customLeaf (textTag tagname) selfClosing))
+               defaultWriterState{ stHtml5 = html5 })
+  in  case runPure mktag of
+           Left _  -> mempty
+           Right t -> t
 
 addAttrs :: PandocMonad m
          => WriterOptions -> Attr -> Html -> StateT WriterState m Html
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
@@ -253,8 +253,10 @@
                   defField "section-titles" True $
                   defField "geometry" geometryFromMargins $
                   (case getField "papersize" metadata of
-                        Just ("A4" :: String) -> resetField "papersize"
-                                                    ("a4" :: String)
+                        -- uppercase a4, a5, etc.
+                        Just (('A':d:ds) :: String)
+                          | all isDigit (d:ds) -> resetField "papersize"
+                                                    (('a':d:ds) :: String)
                         _                     -> id)
                   metadata
   let context' =
@@ -1011,7 +1013,7 @@
         let chr = case "!\"&'()*,-./:;?@_" \\ str of
                        (c:_) -> c
                        []    -> '!'
-        let str' = escapeStringUsing (backslashEscapes "\\{}%") str
+        let str' = escapeStringUsing (backslashEscapes "\\{}%~_") str
         -- we always put lstinline in a dummy 'passthrough' command
         -- (defined in the default template) so that we don't have
         -- to change the way we escape characters depending on whether
@@ -1122,7 +1124,12 @@
                          Just dim         ->
                            [d <> text (show dim)]
                          Nothing          ->
-                           []
+                           case dir of
+                                Width | isJust (dimension Height attr) ->
+                                  [d <> "\\textwidth"]
+                                Height | isJust (dimension Width attr) ->
+                                  [d <> "\\textheight"]
+                                _ -> []
       dimList = showDim Width ++ showDim Height
       dims = if null dimList
                 then empty
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
@@ -1068,9 +1068,8 @@
   return $ text str'
 inlineToMarkdown opts (Math InlineMath str) =
   case writerHTMLMathMethod opts of
-       WebTeX url ->
-             inlineToMarkdown opts (Image nullAttr [Str str]
-                 (url ++ urlEncode str, str))
+       WebTeX url -> inlineToMarkdown opts
+                       (Image nullAttr [Str str] (url ++ urlEncode str, str))
        _ | isEnabled Ext_tex_math_dollars opts ->
              return $ "$" <> text str <> "$"
          | isEnabled Ext_tex_math_single_backslash opts ->
diff --git a/src/Text/Pandoc/Writers/Muse.hs b/src/Text/Pandoc/Writers/Muse.hs
--- a/src/Text/Pandoc/Writers/Muse.hs
+++ b/src/Text/Pandoc/Writers/Muse.hs
@@ -284,16 +284,40 @@
 
 -- | Escape special characters for Muse if needed.
 conditionalEscapeString :: String -> String
-conditionalEscapeString s
-  | any (`elem` ("*<=>[]|" :: String)) s ||
-    "::" `isInfixOf` s = escapeString s
-  | otherwise = s
+conditionalEscapeString s =
+  if any (`elem` ("#*<=>[]|" :: String)) s ||
+     "::" `isInfixOf` s ||
+     "----" `isInfixOf` s
+    then escapeString s
+    else s
 
+normalizeInlineList :: [Inline] -> [Inline]
+normalizeInlineList (Emph x1 : Emph x2 : ils)
+  = normalizeInlineList $ Emph (x1 ++ x2) : ils
+normalizeInlineList (Strong x1 : Strong x2 : ils)
+  = normalizeInlineList $ Strong (x1 ++ x2) : ils
+normalizeInlineList (Strikeout x1 : Strikeout x2 : ils)
+  = normalizeInlineList $ Strikeout (x1 ++ x2) : ils
+normalizeInlineList (Superscript x1 : Superscript x2 : ils)
+  = normalizeInlineList $ Superscript (x1 ++ x2) : ils
+normalizeInlineList (Subscript x1 : Subscript x2 : ils)
+  = normalizeInlineList $ Subscript (x1 ++ x2) : ils
+normalizeInlineList (SmallCaps x1 : SmallCaps x2 : ils)
+  = normalizeInlineList $ SmallCaps (x1 ++ x2) : ils
+normalizeInlineList (Code a1 x1 : Code a2 x2 : ils) | a1 == a2
+  = normalizeInlineList $ Code a1 (x1 ++ x2) : ils
+normalizeInlineList (RawInline f1 x1 : RawInline f2 x2 : ils) | f1 == f2
+  = normalizeInlineList $ RawInline f1 (x1 ++ x2) : ils
+normalizeInlineList (Span a1 x1 : Span a2 x2 : ils) | a1 == a2
+  = normalizeInlineList $ Span a1 (x1 ++ x2) : ils
+normalizeInlineList (x:xs) = x : normalizeInlineList xs
+normalizeInlineList [] = []
+
 -- | Convert list of Pandoc inline elements to Muse.
 inlineListToMuse :: PandocMonad m
                  => [Inline]
                  -> StateT WriterState m Doc
-inlineListToMuse lst = liftM hcat (mapM inlineToMuse lst)
+inlineListToMuse lst = liftM hcat (mapM inlineToMuse (normalizeInlineList lst))
 
 -- | Convert Pandoc inline element to Muse.
 inlineToMuse :: PandocMonad m
@@ -328,7 +352,7 @@
 -- so just fallback to expanding inlines.
 inlineToMuse (Cite _  lst) = inlineListToMuse lst
 inlineToMuse (Code _ str) = return $
-  "<code>" <> text (conditionalEscapeString str) <> "</code>"
+  "<code>" <> text (substitute "</code>" "<</code><code>/code>" str) <> "</code>"
 inlineToMuse (Math InlineMath str) =
   lift (texMathToInlines InlineMath str) >>= inlineListToMuse
 inlineToMuse (Math DisplayMath str) = do
diff --git a/src/Text/Pandoc/Writers/Shared.hs b/src/Text/Pandoc/Writers/Shared.hs
--- a/src/Text/Pandoc/Writers/Shared.hs
+++ b/src/Text/Pandoc/Writers/Shared.hs
@@ -196,13 +196,19 @@
 fixDisplayMath (Plain lst)
   | any isDisplayMath lst && not (all isDisplayMath lst) =
     -- chop into several paragraphs so each displaymath is its own
-    Div ("",["math"],[]) $ map (Plain . stripLeadingTrailingSpace) $
+    Div ("",["math"],[]) $
+       map Plain $
+       filter (not . null) $
+       map stripLeadingTrailingSpace $
        groupBy (\x y -> (isDisplayMath x && isDisplayMath y) ||
                          not (isDisplayMath x || isDisplayMath y)) lst
 fixDisplayMath (Para lst)
   | any isDisplayMath lst && not (all isDisplayMath lst) =
     -- chop into several paragraphs so each displaymath is its own
-    Div ("",["math"],[]) $ map (Para . stripLeadingTrailingSpace) $
+    Div ("",["math"],[]) $
+       map Para $
+       filter (not . null) $
+       map stripLeadingTrailingSpace $
        groupBy (\x y -> (isDisplayMath x && isDisplayMath y) ||
                          not (isDisplayMath x || isDisplayMath y)) lst
 fixDisplayMath x = x
diff --git a/stack.yaml b/stack.yaml
--- a/stack.yaml
+++ b/stack.yaml
@@ -10,11 +10,12 @@
 - pandoc-types-1.17.3
 - hslua-0.9.2
 - hslua-module-text-0.1.2
-- skylighting-0.4.3.2
+- skylighting-0.4.4.1
 - texmath-0.10
 - cmark-gfm-0.1.1
 - QuickCheck-2.10.0.1
 - tasty-quickcheck-0.9.1
 - doctemplates-0.2.1
 - haddock-library-1.4.3
-resolver: lts-9.9
+- tagsoup-0.14.2
+resolver: lts-9.14
diff --git a/test/Tests/Readers/Docx.hs b/test/Tests/Readers/Docx.hs
--- a/test/Tests/Readers/Docx.hs
+++ b/test/Tests/Readers/Docx.hs
@@ -10,6 +10,7 @@
 import Test.Tasty.HUnit
 import Tests.Helpers
 import Text.Pandoc
+import Text.Pandoc.Shared (stripEmptyParagraphs)
 import qualified Text.Pandoc.Class as P
 import Text.Pandoc.MediaBag (MediaBag, lookupMedia, mediaDirectory)
 import Text.Pandoc.UTF8 as UTF8
@@ -37,20 +38,23 @@
 instance ToPandoc NoNormPandoc where
   toPandoc = unNoNorm
 
-compareOutput :: ReaderOptions
-                 -> FilePath
-                 -> FilePath
-                 -> IO (NoNormPandoc, NoNormPandoc)
-compareOutput opts docxFile nativeFile = do
+compareOutput :: Bool
+              -> ReaderOptions
+              -> FilePath
+              -> FilePath
+              -> IO (NoNormPandoc, NoNormPandoc)
+compareOutput strip opts docxFile nativeFile = do
   df <- B.readFile docxFile
   nf <- UTF8.toText <$> BS.readFile nativeFile
   p <- runIOorExplode $ readDocx opts df
   df' <- runIOorExplode $ readNative def nf
-  return $ (noNorm p, noNorm df')
+  return $ (noNorm (if strip
+                       then stripEmptyParagraphs p
+                       else p), noNorm df')
 
 testCompareWithOptsIO :: ReaderOptions -> String -> FilePath -> FilePath -> IO TestTree
 testCompareWithOptsIO opts name docxFile nativeFile = do
-  (dp, np) <- compareOutput opts docxFile nativeFile
+  (dp, np) <- compareOutput True opts docxFile nativeFile
   return $ test id name (dp, np)
 
 testCompareWithOpts :: ReaderOptions -> String -> FilePath -> FilePath -> TestTree
@@ -71,6 +75,11 @@
 testForWarningsWithOpts opts name docxFile expected =
   unsafePerformIO $ testForWarningsWithOptsIO opts name docxFile expected
 
+testCompareNoStrip :: String -> FilePath -> FilePath -> TestTree
+testCompareNoStrip name docxFile nativeFile = unsafePerformIO $ do
+  (dp, np) <- compareOutput False defopts docxFile nativeFile
+  return $ test id name (dp, np)
+
 -- testForWarnings :: String -> FilePath -> [String] -> TestTree
 -- testForWarnings = testForWarningsWithOpts defopts
 
@@ -257,6 +266,10 @@
             "dropcap paragraphs"
             "docx/drop_cap.docx"
             "docx/drop_cap.native"
+          , testCompareNoStrip
+            "empty paragraphs without stripping"
+            "docx/drop_cap.docx"
+            "docx/drop_cap_nostrip.native"
           ]
         , testGroup "track changes"
           [ testCompare
diff --git a/test/Tests/Readers/Muse.hs b/test/Tests/Readers/Muse.hs
--- a/test/Tests/Readers/Muse.hs
+++ b/test/Tests/Readers/Muse.hs
@@ -5,10 +5,12 @@
 import Data.Text (Text)
 import qualified Data.Text as T
 import Test.Tasty
+-- import Test.Tasty.QuickCheck
 import Tests.Helpers
 import Text.Pandoc
 import Text.Pandoc.Arbitrary ()
 import Text.Pandoc.Builder
+-- import Text.Pandoc.Walk (walk)
 
 amuse :: Text -> Pandoc
 amuse = purely $ readMuse def { readerExtensions = extensionsFromList [Ext_amuse]}
@@ -24,6 +26,28 @@
 spcSep :: [Inlines] -> Inlines
 spcSep = mconcat . intersperse space
 
+{-
+-- Tables and code blocks don't round-trip yet
+
+removeTables :: Block -> Block
+removeTables (Table{}) = Para [Str "table was here"]
+removeTables x = x
+
+-- Demand that any AST produced by Muse reader and written by Muse writer can be read back exactly the same way.
+-- Currently we remove code blocks and tables and compare third rewrite to the second.
+-- First and second rewrites are not equal yet.
+roundTrip :: Block -> Bool
+roundTrip b = d'' == d'''
+  where d = walk removeTables $ Pandoc nullMeta [b]
+        d' = rewrite d
+        d'' = rewrite d'
+        d''' = rewrite d''
+        rewrite = amuse . T.pack . (++ "\n") . T.unpack .
+                  (purely $ writeMuse def { writerExtensions = extensionsFromList [Ext_amuse]
+                                          , writerWrapText = WrapPreserve
+                                          })
+-}
+
 tests :: [TestTree]
 tests =
   [ testGroup "Inlines"
@@ -31,6 +55,8 @@
           "Hello, World" =?>
           para "Hello, World"
 
+      , "Muse is not XML" =: "&lt;" =?> para "&lt;"
+
       , "Emphasis" =:
         "*Foo bar*" =?>
         para (emph . spcSep $ ["Foo", "bar"])
@@ -81,6 +107,9 @@
 
       , "Linebreak" =: "Line <br>  break" =?> para ("Line" <> linebreak <> "break")
 
+      , test emacsMuse "Non-breaking space"
+        ("Foo~~bar" =?> para ("Foo\160bar"))
+
       , testGroup "Code markup"
         [ "Code" =: "=foo(bar)=" =?> para (code "foo(bar)")
 
@@ -123,6 +152,8 @@
 
       , "Verbatim tag" =: "*<verbatim>*</verbatim>*" =?> para (emph "*")
 
+      , "Verbatim inside code" =: "<code><verbatim>foo</verbatim></code>" =?> para (code "<verbatim>foo</verbatim>")
+
       , testGroup "Links"
         [ "Link without description" =:
           "[[https://amusewiki.org/]]" =?>
@@ -149,10 +180,20 @@
         , "No implicit links" =: "http://example.org/index.php?action=view&id=1"
                =?> para "http://example.org/index.php?action=view&id=1"
         ]
+
+      , testGroup "Literal"
+        [ test emacsMuse "Inline literal"
+          ("Foo<literal style=\"html\">lit</literal>bar" =?>
+          para (text "Foo" <> rawInline "html" "lit" <> text "bar"))
+        , "No literal in Text::Amuse" =:
+          "Foo<literal style=\"html\">lit</literal>bar" =?>
+          para "Foo<literal style=\"html\">lit</literal>bar"
+        ]
       ]
 
   , testGroup "Blocks"
-      [ "Block elements end paragraphs" =:
+      [ -- testProperty "Round trip" roundTrip,
+        "Block elements end paragraphs" =:
         T.unlines [ "First paragraph"
                   , "----"
                   , "Second paragraph"
@@ -302,7 +343,71 @@
                     , "</example>"
                     ] =?>
           codeBlock "Example line\n"
+        , "Example inside list" =:
+          T.unlines [ " - <example>"
+                    , "   foo"
+                    , "   </example>"
+                    ] =?>
+          bulletList [ codeBlock "foo" ]
+        , "Example inside list with empty lines" =:
+          T.unlines [ " - <example>"
+                    , "   foo"
+                    , "   </example>"
+                    , ""
+                    , "   bar"
+                    , ""
+                    , "   <example>"
+                    , "   baz"
+                    , "   </example>"
+                    ] =?>
+          bulletList [ codeBlock "foo" <> para "bar" <> codeBlock "baz" ]
+        , "Indented example inside list" =:
+          T.unlines [ " -  <example>"
+                    , "    foo"
+                    , "    </example>"
+                    ] =?>
+          bulletList [ codeBlock "foo" ]
+        , "Example inside definition list" =:
+          T.unlines [ " foo :: <example>"
+                    , "        bar"
+                    , "        </example>"
+                    ] =?>
+          definitionList [ ("foo", [codeBlock "bar"]) ]
+        , "Example inside list definition with empty lines" =:
+          T.unlines [ " term :: <example>"
+                    , "         foo"
+                    , "         </example>"
+                    , ""
+                    , "         bar"
+                    , ""
+                    , "         <example>"
+                    , "         baz"
+                    , "         </example>"
+                    ] =?>
+          definitionList [ ("term", [codeBlock "foo" <> para "bar" <> codeBlock "baz"]) ]
+        , "Example inside note" =:
+          T.unlines [ "Foo[1]"
+                    , ""
+                    , "[1] <example>"
+                    , "    bar"
+                    , "    </example>"
+                    ] =?>
+          para ("Foo" <> note (codeBlock "bar"))
         ]
+      , testGroup "Literal blocks"
+        [ test emacsMuse "Literal block"
+          (T.unlines [ "<literal style=\"latex\">"
+                    , "\\newpage"
+                    , "</literal>"
+                    ] =?>
+          rawBlock "latex" "\\newpage")
+        , "No literal blocks in Text::Amuse" =:
+          T.unlines [ "<literal style=\"latex\">"
+                    , "\\newpage"
+                    , "</literal>"
+                    ] =?>
+          para "<literal style=\"latex\">\n\\newpage\n</literal>"
+        ]
       , "Center" =: "<center>Hello, world</center>" =?> para (text "Hello, world")
       , "Right" =: "<right>Hello, world</right>" =?> para (text "Hello, world")
       , testGroup "Comments"
@@ -510,23 +615,56 @@
         ]
     , testGroup "Lists"
       [ "Bullet list" =:
-         T.unlines
+        T.unlines
            [ " - Item1"
            , ""
            , " - Item2"
            ] =?>
-         bulletList [ para "Item1"
-                    , para "Item2"
-                    ]
+        bulletList [ para "Item1"
+                   , para "Item2"
+                   ]
       , "Ordered list" =:
-         T.unlines
-           [ " 1. Item1"
-           , ""
-           , " 2. Item2"
-           ] =?>
-         orderedListWith (1, Decimal, Period) [ para "Item1"
-                                              , para "Item2"
-                                              ]
+        T.unlines
+          [ " 1. Item1"
+          , ""
+          , " 2. Item2"
+          ] =?>
+        orderedListWith (1, Decimal, Period) [ para "Item1"
+                                             , para "Item2"
+                                             ]
+      , "Ordered list with implicit numbers" =:
+        T.unlines
+          [ " 1. Item1"
+          , ""
+          , " 1. Item2"
+          , ""
+          , " 1. Item3"
+          ] =?>
+        orderedListWith (1, Decimal, Period) [ para "Item1"
+                                             , para "Item2"
+                                             , para "Item3"
+                                             ]
+      , "Bullet list with empty items" =:
+        T.unlines
+          [ " -"
+          , ""
+          , " - Item2"
+          ] =?>
+        bulletList [ mempty
+                   , para "Item2"
+                   ]
+      , "Ordered list with empty items" =:
+        T.unlines
+          [ " 1."
+          , ""
+          , " 2."
+          , ""
+          , " 3. Item3"
+          ] =?>
+        orderedListWith (1, Decimal, Period) [ mempty
+                                             , mempty
+                                             , para "Item3"
+                                             ]
       , testGroup "Nested lists"
         [ "Nested list" =:
           T.unlines
@@ -696,6 +834,10 @@
           ] =?>
         para "Foo" <>
         definitionList [ ("Bar", [ para "baz" ]) ]
+      , "One-line definition list" =: " foo :: bar" =?>
+        definitionList [ ("foo", [ para "bar" ]) ]
+      , "Definition list term with emphasis" =: " *Foo* :: bar\n" =?>
+        definitionList [ (emph "Foo", [ para "bar" ]) ]
       , "Multi-line definition lists" =:
         T.unlines
           [ " First term :: Definition of first term"
@@ -705,6 +847,31 @@
         definitionList [ ("First term", [ para "Definition of first term\nand its continuation." ])
                        , ("Second term", [ para "Definition of second term." ])
                        ]
+      , test emacsMuse "Multi-line definition lists from Emacs Muse manual"
+        (T.unlines
+          [ "Term1 ::"
+          , "  This is a first definition"
+          , "  And it has two lines;"
+          , "no, make that three."
+          , ""
+          , "Term2 :: This is a second definition"
+          ] =?>
+         definitionList [ ("Term1", [ para "This is a first definition\nAnd it has two lines;\nno, make that three."])
+                        , ("Term2", [ para "This is a second definition"])
+                        ])
+      -- Text::Amuse requires indentation with one space
+      , "Multi-line definition lists from Emacs Muse manual with initial space" =:
+        (T.unlines
+          [ " Term1 ::"
+          , "  This is a first definition"
+          , "  And it has two lines;"
+          , "no, make that three."
+          , ""
+          , " Term2 :: This is a second definition"
+          ] =?>
+         definitionList [ ("Term1", [ para "This is a first definition\nAnd it has two lines;\nno, make that three."])
+                        , ("Term2", [ para "This is a second definition"])
+                        ])
       -- Emacs Muse creates two separate lists when indentation of items is different.
       -- We follow Amusewiki and allow different indentation within one list.
       , "Changing indentation" =:
diff --git a/test/Tests/Readers/Org.hs b/test/Tests/Readers/Org.hs
--- a/test/Tests/Readers/Org.hs
+++ b/test/Tests/Readers/Org.hs
@@ -1262,6 +1262,12 @@
                   , headerWith ("notvalidlistitem", [], []) 1 "NotValidListItem"
                   ]
 
+      , "Empty bullet points" =:
+          T.unlines [ "-"
+                    , "- "
+                    ] =?>
+          bulletList [ plain "", plain "" ]
+
       , "Simple Ordered List" =:
           ("1. Item1\n" <>
            "2. Item2\n") =?>
@@ -1288,6 +1294,12 @@
                               , plain "Item2"
                               ]
           in orderedListWith listStyle listStructure
+
+      , "Empty ordered list item" =:
+          T.unlines [ "1."
+                    , "3. "
+                    ] =?>
+          orderedList [ plain "", plain "" ]
 
       , "Nested Ordered Lists" =:
           ("1. One\n" <>
diff --git a/test/Tests/Writers/Muse.hs b/test/Tests/Writers/Muse.hs
--- a/test/Tests/Writers/Muse.hs
+++ b/test/Tests/Writers/Muse.hs
@@ -236,6 +236,7 @@
                       ]
             ]
           , "horizontal rule" =: horizontalRule =?> "----"
+          , "escape horizontal rule" =: para (text "----") =?> "<verbatim>----</verbatim>"
           , testGroup "tables"
             [ "table without header" =:
               let rows = [[para $ text "Para 1.1", para $ text "Para 1.2"]
@@ -278,6 +279,8 @@
                =?> "<verbatim>foo<</verbatim><verbatim>/verbatim>bar</verbatim>"
             , "escape pipe to avoid accidental tables" =: str "foo | bar"
                =?> "<verbatim>foo | bar</verbatim>"
+            , "escape hash to avoid accidental anchors" =: text "#foo bar"
+              =?> "<verbatim>#foo</verbatim> bar"
             , "escape definition list markers" =: str "::" =?> "<verbatim>::</verbatim>"
             -- We don't want colons to be escaped if they can't be confused
             -- with definition list item markers.
@@ -296,8 +299,8 @@
           -- Cite is trivial
           , testGroup "code"
             [ "simple" =: code "foo" =?> "<code>foo</code>"
-            , "escape lightweight markup" =: code "foo = bar" =?> "<code><verbatim>foo = bar</verbatim></code>"
-            , "escape tag" =: code "<code>foo = bar</code> baz" =?> "<code><verbatim><code>foo = bar</code> baz</verbatim></code>"
+            , "escape tag" =: code "<code>foo = bar</code> baz" =?> "<code><code>foo = bar<</code><code>/code> baz</code>"
+            , "normalization" =: code "</co" <> code "de>" =?> "<code><</code><code>/code></code>"
             ]
           , testGroup "spaces"
             [ "space" =: text "a" <> space <> text "b" =?> "a b"
@@ -310,6 +313,7 @@
           , testGroup "math"
             [ "inline math" =: math "2^3" =?> "2<sup>3</sup>"
             , "display math" =: displayMath "2^3" =?> "<verse>2<sup>3</sup></verse>"
+            , "multiple letters in inline math" =: math "abc" =?> "<em>abc</em>"
             ]
           , "raw inline"
             =: rawInline "html" "<mark>marked text</mark>"
diff --git a/test/command/3450.md b/test/command/3450.md
--- a/test/command/3450.md
+++ b/test/command/3450.md
@@ -8,5 +8,5 @@
 % pandoc -fmarkdown-implicit_figures -t latex
 ![image](lalune.jpg){height=2em}
 ^D
-\includegraphics[height=2em]{lalune.jpg}
+\includegraphics[width=\textwidth,height=2em]{lalune.jpg}
 ```
diff --git a/test/command/4091.md b/test/command/4091.md
new file mode 100644
--- /dev/null
+++ b/test/command/4091.md
@@ -0,0 +1,6 @@
+```
+% pandoc -f latex
+\alert<3>{foo}
+^D
+<p><span class="alert">foo</span></p>
+```
diff --git a/test/command/4113.md b/test/command/4113.md
new file mode 100644
--- /dev/null
+++ b/test/command/4113.md
@@ -0,0 +1,12 @@
+```
+% pandoc -t gfm
+::::{.bug}
+I am a [bug]{#bug}.
+::::
+^D
+<div class="bug">
+
+I am a <span id="bug">bug</span>.
+
+</div>
+```
diff --git a/test/docx/0_level_headers.native b/test/docx/0_level_headers.native
--- a/test/docx/0_level_headers.native
+++ b/test/docx/0_level_headers.native
@@ -1,15 +1,15 @@
 [Table [] [AlignDefault] [0.0]
  [[]]
- [[[]]
+ [[[Plain []]]
  ,[[Plain [Str "User\8217s",Space,Str "Guide"]]]
- ,[[]]
- ,[[]]
- ,[[]]
+ ,[[Plain []]]
+ ,[[Plain []]]
+ ,[[Plain []]]
  ,[[Plain [Str "11",Space,Str "August",Space,Str "2017"]]]
- ,[[]]
- ,[[]]
- ,[[]]
- ,[[]]]
+ ,[[Plain []]]
+ ,[[Plain []]]
+ ,[[Plain []]]
+ ,[[Plain []]]]
 ,Para [Str "CONTENTS"]
 ,Para [Strong [Str "Section",Space,Str "Page"]]
 ,Para [Str "FIGURES",Space,Str "iv"]
diff --git a/test/docx/comments.native b/test/docx/comments.native
--- a/test/docx/comments.native
+++ b/test/docx/comments.native
@@ -1,4 +1,4 @@
 [Para [Str "I",Space,Str "want",Space,Span ("",["comment-start"],[("id","0"),("author","Jesse Rosenthal"),("date","2016-05-09T16:13:00Z")]) [Str "I",Space,Str "left",Space,Str "a",Space,Str "comment."],Str "some",Space,Str "text",Space,Str "to",Space,Str "have",Space,Str "a",Space,Str "comment",Space,Span ("",["comment-end"],[("id","0")]) [],Str "on",Space,Str "it."]
 ,Para [Str "This",Space,Str "is",Space,Span ("",["comment-start"],[("id","1"),("author","Jesse Rosenthal"),("date","2016-05-09T16:13:00Z")]) [Str "A",Space,Str "comment",Space,Str "across",Space,Str "paragraphs."],Str "a",Space,Str "new",Space,Str "paragraph."]
 ,Para [Str "And",Space,Str "so",Span ("",["comment-end"],[("id","1")]) [],Space,Str "is",Space,Str "this."]
-,Para [Str "One",Space,Span ("",["comment-start"],[("id","2"),("author","Jesse Rosenthal"),("date","2016-05-09T16:14:00Z")]) [Str "This",Space,Str "one",Space,Str "has",Space,Str "multiple",Space,Str "paragraphs.",Space,Str "\182",Space,Str "See?"],Str "more",Span ("",["comment-end"],[("id","2")]) [],Str ".",Space,Str "And",Space,Str "this",Space,Str "is",Space,Str "one",Space,Str "with",Space,Str "a",Space,Span ("",["comment-start"],[("id","3"),("author","Jesse Rosenthal"),("date","2016-06-22T14:35:00Z")]) [Str "Do",Space,Str "something."],Span ("",["comment-start"],[("id","4"),("author","Jesse Rosenthal"),("date","2016-06-22T14:36:00Z")]) [Str "Do",Space,Str "something",Space,Str "else."],Str "comment",Space,Str "in",Space,Str "a",Space,Str "comment",Span ("",["comment-end"],[("id","3")]) [Span ("",["comment-end"],[("id","4")]) []],Str "."]]
+,Para [Str "One",Space,Span ("",["comment-start"],[("id","2"),("author","Jesse Rosenthal"),("date","2016-05-09T16:14:00Z")]) [Str "This",Space,Str "one",Space,Str "has",Space,Str "multiple",Space,Str "paragraphs.",Space,Str "\182",Space,Str "\182",Space,Str "See?"],Str "more",Span ("",["comment-end"],[("id","2")]) [],Str ".",Space,Str "And",Space,Str "this",Space,Str "is",Space,Str "one",Space,Str "with",Space,Str "a",Space,Span ("",["comment-start"],[("id","3"),("author","Jesse Rosenthal"),("date","2016-06-22T14:35:00Z")]) [Str "Do",Space,Str "something."],Span ("",["comment-start"],[("id","4"),("author","Jesse Rosenthal"),("date","2016-06-22T14:36:00Z")]) [Str "Do",Space,Str "something",Space,Str "else."],Str "comment",Space,Str "in",Space,Str "a",Space,Str "comment",Span ("",["comment-end"],[("id","3")]) [Span ("",["comment-end"],[("id","4")]) []],Str "."]]
diff --git a/test/docx/drop_cap_nostrip.native b/test/docx/drop_cap_nostrip.native
new file mode 100644
--- /dev/null
+++ b/test/docx/drop_cap_nostrip.native
@@ -0,0 +1,9 @@
+[Para [Str "Drop",Space,Str "cap."]
+,Para []
+,Para [Str "Next",Space,Str "paragraph."]
+,Para []
+,Para [Str "Drop",Space,Str "cap",Space,Str "in",Space,Str "margin."]
+,Para []
+,Para []
+,Para []
+,Para [Str "Drop",Space,Str "cap",Space,Str "(not",Space,Str "really)."]]
diff --git a/test/lhs-test.html b/test/lhs-test.html
--- a/test/lhs-test.html
+++ b/test/lhs-test.html
@@ -8,29 +8,32 @@
   <style type="text/css">
       code{white-space: pre-wrap;}
       span.smallcaps{font-variant: small-caps;}
+      span.underline{text-decoration: underline;}
       div.line-block{white-space: pre-line;}
       div.column{display: inline-block; vertical-align: top; width: 50%;}
   </style>
   <style type="text/css">
-div.sourceLine, a.sourceLine { display: inline-block; min-height: 1.25em; }
+a.sourceLine { display: inline-block; min-height: 1.25em; }
 a.sourceLine { pointer-events: none; color: inherit; text-decoration: inherit; }
 .sourceCode { overflow: visible; }
 code.sourceCode { white-space: pre; }
 @media print {
 code.sourceCode { white-space: pre-wrap; }
-div.sourceLine, a.sourceLine { text-indent: -1em; padding-left: 1em; }
+a.sourceLine { text-indent: -1em; padding-left: 1em; }
 }
-pre.numberSource div.sourceLine, .numberSource a.sourceLine
+pre.numberSource a.sourceLine
   { position: relative; }
-pre.numberSource div.sourceLine::before, .numberSource a.sourceLine::before
+pre.numberSource a.sourceLine::before
   { content: attr(data-line-number);
     position: absolute; left: -5em; text-align: right; vertical-align: baseline;
     border: none; pointer-events: all;
     -webkit-touch-callout: none; -webkit-user-select: none;
     -khtml-user-select: none; -moz-user-select: none;
     -ms-user-select: none; user-select: none;
-    padding: 0 4px; width: 4em; }
-pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; color: #aaaaaa;  padding-left: 4px; }
+    padding: 0 4px; width: 4em;
+    color: #aaaaaa;
+  }
+pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
 @media screen {
 a.sourceLine::before { text-decoration: underline; color: initial; }
 }
@@ -72,9 +75,9 @@
 <h1 id="lhs-test">lhs test</h1>
 <p><code>unsplit</code> is an arrow that takes a pair of values and combines them to
 return a single value:</p>
-<pre class="sourceCode literate haskell" id="cb1"><code class="sourceCode haskell"><div class="sourceLine" id="cb1-1" data-line-number="1"><span class="ot">unsplit ::</span> (<span class="dt">Arrow</span> a) <span class="ot">=&gt;</span> (b <span class="ot">-&gt;</span> c <span class="ot">-&gt;</span> d) <span class="ot">-&gt;</span> a (b, c) d</div>
-<div class="sourceLine" id="cb1-2" data-line-number="2">unsplit <span class="fu">=</span> arr <span class="fu">.</span> uncurry</div>
-<div class="sourceLine" id="cb1-3" data-line-number="3">          <span class="co">-- arr (\op (x,y) -&gt; x `op` y)</span></div></code></pre>
+<pre class="sourceCode literate haskell" id="cb1"><code class="sourceCode haskell"><a class="sourceLine" id="cb1-1" data-line-number="1"><span class="ot">unsplit ::</span> (<span class="dt">Arrow</span> a) <span class="ot">=&gt;</span> (b <span class="ot">-&gt;</span> c <span class="ot">-&gt;</span> d) <span class="ot">-&gt;</span> a (b, c) d</a>
+<a class="sourceLine" id="cb1-2" data-line-number="2">unsplit <span class="fu">=</span> arr <span class="fu">.</span> uncurry</a>
+<a class="sourceLine" id="cb1-3" data-line-number="3">          <span class="co">-- arr (\op (x,y) -&gt; x `op` y)</span></a></code></pre>
 <p><code>(***)</code> combines two arrows into a new arrow by running the two arrows on a
 pair of values (one arrow on the first item of the pair and one arrow on the
 second item of the pair).</p>
diff --git a/test/lhs-test.html+lhs b/test/lhs-test.html+lhs
--- a/test/lhs-test.html+lhs
+++ b/test/lhs-test.html+lhs
@@ -8,29 +8,32 @@
   <style type="text/css">
       code{white-space: pre-wrap;}
       span.smallcaps{font-variant: small-caps;}
+      span.underline{text-decoration: underline;}
       div.line-block{white-space: pre-line;}
       div.column{display: inline-block; vertical-align: top; width: 50%;}
   </style>
   <style type="text/css">
-div.sourceLine, a.sourceLine { display: inline-block; min-height: 1.25em; }
+a.sourceLine { display: inline-block; min-height: 1.25em; }
 a.sourceLine { pointer-events: none; color: inherit; text-decoration: inherit; }
 .sourceCode { overflow: visible; }
 code.sourceCode { white-space: pre; }
 @media print {
 code.sourceCode { white-space: pre-wrap; }
-div.sourceLine, a.sourceLine { text-indent: -1em; padding-left: 1em; }
+a.sourceLine { text-indent: -1em; padding-left: 1em; }
 }
-pre.numberSource div.sourceLine, .numberSource a.sourceLine
+pre.numberSource a.sourceLine
   { position: relative; }
-pre.numberSource div.sourceLine::before, .numberSource a.sourceLine::before
+pre.numberSource a.sourceLine::before
   { content: attr(data-line-number);
     position: absolute; left: -5em; text-align: right; vertical-align: baseline;
     border: none; pointer-events: all;
     -webkit-touch-callout: none; -webkit-user-select: none;
     -khtml-user-select: none; -moz-user-select: none;
     -ms-user-select: none; user-select: none;
-    padding: 0 4px; width: 4em; }
-pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; color: #aaaaaa;  padding-left: 4px; }
+    padding: 0 4px; width: 4em;
+    color: #aaaaaa;
+  }
+pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
 @media screen {
 a.sourceLine::before { text-decoration: underline; color: initial; }
 }
@@ -72,9 +75,9 @@
 <h1 id="lhs-test">lhs test</h1>
 <p><code>unsplit</code> is an arrow that takes a pair of values and combines them to
 return a single value:</p>
-<pre class="sourceCode literate literatehaskell" id="cb1"><code class="sourceCode literatehaskell"><div class="sourceLine" id="cb1-1" data-line-number="1"><span class="ot">&gt; unsplit ::</span> (<span class="dt">Arrow</span> a) <span class="ot">=&gt;</span> (b <span class="ot">-&gt;</span> c <span class="ot">-&gt;</span> d) <span class="ot">-&gt;</span> a (b, c) d</div>
-<div class="sourceLine" id="cb1-2" data-line-number="2"><span class="ot">&gt;</span> unsplit <span class="fu">=</span> arr <span class="fu">.</span> uncurry</div>
-<div class="sourceLine" id="cb1-3" data-line-number="3"><span class="ot">&gt;</span>           <span class="co">-- arr (\op (x,y) -&gt; x `op` y)</span></div></code></pre>
+<pre class="sourceCode literate literatehaskell" id="cb1"><code class="sourceCode literatehaskell"><a class="sourceLine" id="cb1-1" data-line-number="1"><span class="ot">&gt; unsplit ::</span> (<span class="dt">Arrow</span> a) <span class="ot">=&gt;</span> (b <span class="ot">-&gt;</span> c <span class="ot">-&gt;</span> d) <span class="ot">-&gt;</span> a (b, c) d</a>
+<a class="sourceLine" id="cb1-2" data-line-number="2"><span class="ot">&gt;</span> unsplit <span class="fu">=</span> arr <span class="fu">.</span> uncurry</a>
+<a class="sourceLine" id="cb1-3" data-line-number="3"><span class="ot">&gt;</span>           <span class="co">-- arr (\op (x,y) -&gt; x `op` y)</span></a></code></pre>
 <p><code>(***)</code> combines two arrows into a new arrow by running the two arrows on a
 pair of values (one arrow on the first item of the pair and one arrow on the
 second item of the pair).</p>
diff --git a/test/s5-basic.html b/test/s5-basic.html
--- a/test/s5-basic.html
+++ b/test/s5-basic.html
@@ -13,6 +13,7 @@
   <style type="text/css">
       code{white-space: pre-wrap;}
       span.smallcaps{font-variant: small-caps;}
+      span.underline{text-decoration: underline;}
       div.line-block{white-space: pre-line;}
       div.column{display: inline-block; vertical-align: top; width: 50%;}
   </style>
diff --git a/test/s5-fancy.html b/test/s5-fancy.html
--- a/test/s5-fancy.html
+++ b/test/s5-fancy.html
@@ -13,6 +13,7 @@
   <style type="text/css">
       code{white-space: pre-wrap;}
       span.smallcaps{font-variant: small-caps;}
+      span.underline{text-decoration: underline;}
       div.line-block{white-space: pre-line;}
       div.column{display: inline-block; vertical-align: top; width: 50%;}
   </style>
diff --git a/test/s5-inserts.html b/test/s5-inserts.html
--- a/test/s5-inserts.html
+++ b/test/s5-inserts.html
@@ -11,6 +11,7 @@
   <style type="text/css">
       code{white-space: pre-wrap;}
       span.smallcaps{font-variant: small-caps;}
+      span.underline{text-decoration: underline;}
       div.line-block{white-space: pre-line;}
       div.column{display: inline-block; vertical-align: top; width: 50%;}
   </style>
diff --git a/test/writer.html4 b/test/writer.html4
--- a/test/writer.html4
+++ b/test/writer.html4
@@ -11,6 +11,7 @@
   <style type="text/css">
       code{white-space: pre-wrap;}
       span.smallcaps{font-variant: small-caps;}
+      span.underline{text-decoration: underline;}
       div.line-block{white-space: pre-line;}
       div.column{display: inline-block; vertical-align: top; width: 50%;}
   </style>
diff --git a/test/writer.html5 b/test/writer.html5
--- a/test/writer.html5
+++ b/test/writer.html5
@@ -11,6 +11,7 @@
   <style type="text/css">
       code{white-space: pre-wrap;}
       span.smallcaps{font-variant: small-caps;}
+      span.underline{text-decoration: underline;}
       div.line-block{white-space: pre-line;}
       div.column{display: inline-block; vertical-align: top; width: 50%;}
   </style>
diff --git a/test/writer.muse b/test/writer.muse
--- a/test/writer.muse
+++ b/test/writer.muse
@@ -478,8 +478,8 @@
 
 So is <strong><em>this</em></strong> word.
 
-This is code: <code><verbatim>></verbatim></code>, <code>$</code>,
-<code>\</code>, <code>\$</code>, <code><verbatim><html></verbatim></code>.
+This is code: <code>></code>, <code>$</code>, <code>\</code>, <code>\$</code>,
+<code><html></code>.
 
 <del>This is <em>strikeout</em>.</del>
 
@@ -529,8 +529,7 @@
 
 These shouldn’t be math:
 
- - To get the famous equation, write
-   <code><verbatim>$e = mc^2$</verbatim></code>.
+ - To get the famous equation, write <code>$e = mc^2$</code>.
  - $22,000 is a <em>lot</em> of money. So is $34,000. (It worked if "lot" is
    emphasized.)
  - Shoes ($20) and socks ($5).
@@ -590,7 +589,7 @@
 
 Greater-than: <verbatim>></verbatim>
 
-Hash: #
+Hash: <verbatim>#</verbatim>
 
 Period: .
 
@@ -673,8 +672,7 @@
 Blockquoted: [[http://example.com/]]
 </quote>
 
-Auto-links should not occur here:
-<code><verbatim><http://example.com/></verbatim></code>
+Auto-links should not occur here: <code><http://example.com/></code>
 
 <example>
 or here: <http://example.com/>
@@ -722,9 +720,8 @@
     indent the first line of each block.
 
 [3] This is <em>easier</em> to type. Inline notes may contain
-    [[http://google.com][links]] and <code><verbatim>]</verbatim></code>
-    verbatim characters, as well as <verbatim>[bracketed</verbatim>
-    <verbatim>text].</verbatim>
+    [[http://google.com][links]] and <code>]</code> verbatim characters, as
+    well as <verbatim>[bracketed</verbatim> <verbatim>text].</verbatim>
 
 [4] In quote.
 
