<NME> Writers.jl
<BEF> """
A module that provides several renderers for `Document` objects. The supported
formats are currently:

  * `:html` -- generates a complete HTML site with navigation and search included.
  * `:latex` -- generates a PDF using LuaLaTeX.

"""
module Writers

import ..Documenter:
    Anchors,
    Builder,
    Documents,
    Expanders,
    Documenter,
    Utilities

using Compat

# Driver method for document rendering.
# -------------------------------------

"""
Writes a [`Documents.Document`](@ref) object to `build` directory in specified file format.
"""
function render(doc::Documents.Document)
    mime = Formats.mimetype(doc.user.format)
    for (src, page) in doc.internal.pages
        open(Formats.extension(doc.user.format, page.build), "w") do io
            for elem in page.elements
                node = page.mapping[elem]
                render(io, mime, node, page, doc)
            end
        end
    end
end

include("MarkdownWriter.jl")
include("HTMLWriter.jl")

```julia
abstract type CustomFormat <: FormatSelector end

Selectors.order(::Type{CustomFormat}) = 4.0 # or a higher number.
Selectors.matcher(::Type{CustomFormat}, fmt, _) = fmt === :custom
Selectors.runner(::Type{CustomFormat}, _, doc) = CustomWriter.render(doc)

# Definition of `CustomWriter` module below...
```
"""
function render(doc::Documents.Document)
    # Render each format. Additional formats must define an `order`, `matcher`, `runner`, as
    # well as their own rendering methods in a separate module.
    for each in doc.user.format
        Selectors.dispatch(FormatSelector, each, doc)
    end
end

include("HTMLWriter.jl")
include("LaTeXWriter.jl")

end

<MSG> Use multiple dispatch to determine the Writer

The writers need to be able to implement render methods on a whole
Document, instead of just on a Page-by-Page basis, since generally
all formats have to write some generic files as well, not just
individual pages.

Effectively this change means that every writer should overload a
    render(::Format, doc)
method, which should then perform the whole write process, including
all generic, non-page files. This overload should be the only method
that the rest of the Documenter code should be aware of.

<DFF> @@ -18,23 +18,26 @@ import ..Documenter:
 
 using Compat
 
-# Driver method for document rendering.
-# -------------------------------------
+"""
+A parametric type that allows us to use multiple dispatch to pick the appropriate
+writer for each output format.
 
+The parameter `f` should be an instance of the [`Formats.Format`](@ref) enumeration.
 """
-Writes a [`Documents.Document`](@ref) object to `build` directory in specified file format.
+immutable Writer{f} end
+Writer(f::Formats.Format) = Writer{f}()
+
 """
-function render(doc::Documents.Document)
-    mime = Formats.mimetype(doc.user.format)
-    for (src, page) in doc.internal.pages
-        open(Formats.extension(doc.user.format, page.build), "w") do io
-            for elem in page.elements
-                node = page.mapping[elem]
-                render(io, mime, node, page, doc)
-            end
-        end
-    end
-end
+Writes a [`Documents.Document`](@ref) object to `.user.build` directory in
+the format specified in `.user.format`.
+
+The method should be overloaded in each writer as
+
+    render(::Writer{format}, doc)
+
+where `format` is one of the values of the [`Formats.Format`](@ref) enumeration.
+"""
+render(doc::Documents.Document) = render(Writer(doc.user.format), doc)
 
 include("MarkdownWriter.jl")
 include("HTMLWriter.jl")

Use multiple dispatch to determine the Writer