Packages
ex_doc
0.7.0
0.40.3
0.40.2
0.40.1
0.40.0
0.39.3
0.39.2
0.39.1
0.39.0
0.38.4
0.38.3
0.38.2
0.38.1
0.38.0
0.37.3
0.37.2
0.37.1
0.37.0
0.37.0-rc.2
0.37.0-rc.1
0.37.0-rc.0
0.36.1
0.36.0
0.35.1
0.35.0
0.34.2
0.34.1
0.34.0
0.33.0
0.32.2
0.32.1
0.32.0
0.31.2
0.31.1
0.31.0
0.30.9
0.30.8
0.30.7
0.30.6
0.30.5
0.30.4
0.30.3
0.30.2
0.30.1
0.30.0
0.29.4
0.29.3
0.29.2
0.29.1
0.29.0
0.28.6
0.28.5
0.28.4
0.28.3
0.28.2
0.28.1
0.28.0
0.27.3
0.27.2
0.27.1
0.27.0
0.26.0
0.25.5
0.25.4
0.25.3
0.25.2
0.25.1
0.25.0
0.24.2
0.24.1
0.24.0
0.23.0
0.22.6
0.22.5
0.22.4
0.22.2
0.22.1
0.22.0
0.21.3
0.21.2
0.21.1
0.21.0
0.20.2
0.20.1
0.20.0
0.19.3
0.19.2
0.19.1
0.19.0
0.19.0-rc
0.18.4
0.18.3
0.18.2
0.18.1
0.18.0
retired
0.17.1
0.17.0
retired
0.16.4
0.16.3
0.16.2
0.16.1
0.16.0
0.15.1
0.15.0
0.14.5
0.14.4
0.14.3
0.14.2
0.14.1
0.14.0
0.13.2
0.13.1
0.13.0
0.12.0
0.11.5
0.11.4
0.11.3
0.11.2
0.11.1
0.11.0
0.10.0
0.9.0
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.7.3
0.7.2
0.7.1
0.7.0
0.6.2
0.6.1
0.6.0
0.5.2
0.5.1
ExDoc is a documentation generation tool for Elixir
Current section
Files
Jump to
Current section
Files
lib/ex_doc/formatter/html.ex
defmodule ExDoc.Formatter.HTML do
@moduledoc """
Provide HTML-formatted documentation
"""
alias ExDoc.Formatter.HTML.Templates
alias ExDoc.Formatter.HTML.Autolink
@doc """
Generate HTML documentation for the given modules
"""
def run(modules, config) do
output = Path.expand(config.output)
:ok = File.mkdir_p output
generate_index(output, config)
generate_assets(output, config)
has_readme = config.readme && generate_readme(output, modules, config)
all = Autolink.all(modules)
modules = filter_list(:modules, all)
exceptions = filter_list(:exceptions, all)
protocols = filter_list(:protocols, all)
generate_overview(modules, exceptions, protocols, output, config)
generate_list(:modules, modules, all, output, config, has_readme)
generate_list(:exceptions, exceptions, all, output, config, has_readme)
generate_list(:protocols, protocols, all, output, config, has_readme)
Path.join(config.output, "index.html")
end
defp generate_index(output, config) do
content = Templates.index_template(config)
:ok = File.write("#{output}/index.html", content)
end
defp generate_overview(modules, exceptions, protocols, output, config) do
content = Templates.overview_template(config, modules, exceptions, protocols)
:ok = File.write("#{output}/overview.html", content)
end
defp assets do
[{ templates_path("css/*.css"), "css" },
{ templates_path("js/*.js"), "js" }]
end
defp generate_assets(output, _config) do
Enum.each assets, fn({ pattern, dir }) ->
output = "#{output}/#{dir}"
File.mkdir output
Enum.map Path.wildcard(pattern), fn(file) ->
base = Path.basename(file)
File.copy file, "#{output}/#{base}"
end
end
end
defp generate_readme(output, modules, config) do
File.rm("#{output}/README.html")
readme_path = Path.expand(config.readme)
write_readme(output, File.read(readme_path), modules, config)
end
defp write_readme(output, {:ok, content}, modules, config) do
content = Autolink.project_doc(content, modules)
readme_html = Templates.readme_template(config, content) |> pretty_codeblocks
File.write("#{output}/README.html", readme_html)
true
end
defp write_readme(_, _, _, _) do
false
end
@doc false
# Helper to handle plain code blocks (```...```) without
# language specification and indentation code blocks
def pretty_codeblocks(bin) do
Regex.replace(~r/<pre><code\s*(class=\"\")?>/,
bin, "<pre class=\"codeblock\">")
end
@doc false
# Helper to split modules into different categories.
#
# Public so that code in Template can use it.
def categorize_modules(nodes) do
[modules: filter_list(:modules, nodes),
exceptions: filter_list(:exceptions, nodes),
protocols: filter_list(:protocols, nodes)]
end
defp filter_list(:modules, nodes) do
Enum.filter nodes, &match?(%ExDoc.ModuleNode{type: x} when not x in [:exception, :protocol, :impl], &1)
end
defp filter_list(:exceptions, nodes) do
Enum.filter nodes, &match?(%ExDoc.ModuleNode{type: x} when x in [:exception], &1)
end
defp filter_list(:protocols, nodes) do
Enum.filter nodes, &match?(%ExDoc.ModuleNode{type: x} when x in [:protocol], &1)
end
defp generate_list(scope, nodes, all, output, config, has_readme) do
Enum.each nodes, &generate_module_page(&1, all, output, config)
content = Templates.list_page(scope, nodes, config, has_readme)
File.write("#{output}/#{scope}_list.html", content)
end
defp generate_module_page(node, modules, output, config) do
content = Templates.module_page(node, config, modules)
File.write("#{output}/#{node.id}.html", content)
end
defp templates_path(other) do
Path.expand("html/templates/#{other}", __DIR__)
end
end