Packages
ex_doc
0.15.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.ex
defmodule ExDoc do
@moduledoc """
Elixir Documentation System. ExDoc produces documentation for Elixir projects
"""
defmodule Config do
@moduledoc """
Configuration structure that holds all the available options for ExDoc
You can find more details about this options in the `ExDoc.CLI` module.
"""
defstruct [
assets: nil,
canonical: nil,
deps: [],
extra_section: nil,
extras: [],
filter_prefix: nil,
formatter: "html",
formatter_opts: [],
homepage_url: nil,
logo: nil,
main: nil,
output: "doc",
project: nil,
retriever: ExDoc.Retriever,
source_beam: nil,
source_root: nil,
source_url: nil,
source_url_pattern: nil,
title: nil,
version: nil
]
@type t :: %__MODULE__{
canonical: nil | String.t,
deps: [{ebin_path :: String.t, doc_url :: String.t}],
extra_section: nil | String.t,
extras: list(),
filter_prefix: String.t | nil,
formatter: String.t,
formatter_opts: list(),
homepage_url: nil | String.t,
logo: nil | Path.t,
main: nil | String.t,
output: Path.t,
project: nil | String.t,
retriever: :atom,
source_beam: nil | String.t,
source_root: nil | String.t,
source_url: nil | String.t,
source_url_pattern: nil | String.t,
title: nil | String.t,
version: nil | String.t
}
end
@ex_doc_version Mix.Project.config[:version]
@doc """
Returns the ExDoc version (used in templates).
"""
@spec version :: String.t
def version, do: @ex_doc_version
@doc """
Generates documentation for the given `project`, `vsn` (version)
and `options`.
"""
@spec generate_docs(String.t, String.t, Keyword.t) :: atom
def generate_docs(project, vsn, options) when is_binary(project) and is_binary(vsn) and is_list(options) do
config = build_config(project, vsn, options)
docs = config.retriever.docs_from_dir(config.source_beam, config)
find_formatter(config.formatter).run(docs, config)
end
# Builds configuration by merging `options`, and normalizing the options.
@spec build_config(String.t, String.t, Keyword.t) :: ExDoc.Config.t
defp build_config(project, vsn, options) do
options = normalize_options(options)
preconfig = %Config{
project: project,
version: vsn,
main: options[:main],
homepage_url: options[:homepage_url],
source_root: options[:source_root] || File.cwd!,
}
struct(preconfig, options)
end
# Short path for programmatic interface
defp find_formatter(modname) when is_atom(modname), do: modname
defp find_formatter("ExDoc.Formatter." <> _ = name) do
[name]
|> Module.concat()
|> check_formatter_module(name)
end
defp find_formatter(name) do
[ExDoc.Formatter, String.upcase(name)]
|> Module.concat()
|> check_formatter_module(name)
end
defp check_formatter_module(modname, argname) do
unless Code.ensure_loaded?(modname) do
raise "Formatter module not found for: #{argname}"
end
modname
end
# Helpers
defp normalize_options(options) do
pattern = options[:source_url_pattern] || guess_url(options[:source_url], options[:source_ref] || "master")
options = Keyword.put(options, :source_url_pattern, pattern)
if is_bitstring(options[:output]) do
Keyword.put(options, :output, String.trim_trailing(options[:output], "/"))
else
options
end
end
defp guess_url(url = <<"https://github.com/", _ :: binary>>, ref) do
append_slash(url) <> "blob/#{ref}/%{path}#L%{line}"
end
defp guess_url(url = <<"https://gitlab.com/", _ :: binary>>, ref) do
append_slash(url) <> "blob/#{ref}/%{path}#L%{line}"
end
defp guess_url(url = <<"https://bitbucket.org/", _ :: binary>>, ref) do
append_slash(url) <> "src/#{ref}/%{path}#cl-%{line}"
end
defp guess_url(other, _) do
other
end
defp append_slash(url) do
if :binary.last(url) == ?/, do: url, else: url <> "/"
end
end