Top Related Projects
Elixir is a dynamic, functional language for building scalable and maintainable applications
Peace of mind from prototype to production
The GraphQL toolkit for Elixir
A toolkit for data mapping and language integrated query.
A curated list of amazingly awesome Elixir and Erlang libraries, resources and shiny things. Updates:
Quick Overview
ExDoc is a tool for generating documentation for Elixir projects. It produces HTML and EPUB documentation from Elixir source code, making it easy for developers to create and maintain comprehensive documentation for their libraries and applications.
Pros
- Generates clean, well-structured HTML and EPUB documentation
- Supports Markdown in documentation comments
- Integrates well with the Elixir ecosystem and Mix build tool
- Customizable themes and output options
Cons
- Limited support for non-Elixir languages within the same project
- May require additional setup for complex project structures
- Learning curve for advanced customization options
- Documentation generation can be slow for very large projects
Code Examples
- Basic module documentation:
defmodule MyModule do
@moduledoc """
This is a sample module.
It demonstrates basic ExDoc usage.
"""
@doc """
Adds two numbers together.
## Examples
iex> MyModule.add(2, 3)
5
"""
def add(a, b), do: a + b
end
- Generating documentation:
# In mix.exs
def project do
[
app: :my_app,
version: "0.1.0",
deps: deps(),
docs: [
main: "MyModule",
extras: ["README.md"]
]
]
end
defp deps do
[
{:ex_doc, "~> 0.27", only: :dev, runtime: false}
]
end
- Custom grouping of modules:
# In mix.exs
def docs do
[
groups_for_modules: [
"Core": [MyApp.Core.Module1, MyApp.Core.Module2],
"Utils": [MyApp.Utils.Module1, MyApp.Utils.Module2]
]
]
end
Getting Started
- Add ExDoc to your project's dependencies in
mix.exs
:
defp deps do
[{:ex_doc, "~> 0.27", only: :dev, runtime: false}]
end
-
Run
mix deps.get
to install ExDoc. -
Add documentation to your modules using
@moduledoc
and@doc
attributes. -
Generate documentation by running:
mix docs
- The generated documentation will be available in the
doc/
directory.
Competitor Comparisons
Elixir is a dynamic, functional language for building scalable and maintainable applications
Pros of Elixir
- Core language implementation with a broader scope and functionality
- Provides the foundation for the entire Elixir ecosystem
- Includes the Erlang/OTP integration, enabling robust concurrent and distributed systems
Cons of Elixir
- Larger codebase, potentially more complex to contribute to or understand fully
- Slower release cycle due to its core nature and need for extensive testing
- Requires more system resources to build and run
Code Comparison
Elixir (core language feature):
defmodule Example do
def greet(name) do
IO.puts("Hello, #{name}!")
end
end
ExDoc (documentation generation):
defmodule MyApp do
@moduledoc """
Documentation for MyApp.
"""
@doc "Prints hello"
def hello, do: :world
end
Summary
Elixir is the core language implementation, providing the foundation for the entire Elixir ecosystem, including features like concurrency and OTP integration. It has a broader scope but is more complex and resource-intensive. ExDoc, on the other hand, is a specialized tool for generating documentation from Elixir code. It's more focused in purpose, easier to contribute to, and has a faster release cycle. While Elixir defines the language itself, ExDoc enhances the development experience by improving code documentation.
Peace of mind from prototype to production
Pros of Phoenix
- Full-featured web framework with built-in routing, controllers, and views
- Real-time capabilities with channels for WebSocket communication
- Scalable architecture designed for high-performance applications
Cons of Phoenix
- Steeper learning curve due to its comprehensive feature set
- Potentially overkill for simple documentation projects
- Requires more setup and configuration compared to ExDoc
Code Comparison
ExDoc (generating documentation):
defmodule MyApp do
@moduledoc """
Documentation for MyApp
"""
def hello do
"Hello, World!"
end
end
Phoenix (defining a route and controller):
defmodule MyAppWeb.Router do
use MyAppWeb, :router
get "/", PageController, :index
end
defmodule MyAppWeb.PageController do
use MyAppWeb, :controller
def index(conn, _params) do
render(conn, "index.html")
end
end
Summary
ExDoc is a specialized tool for generating documentation from Elixir code, while Phoenix is a comprehensive web framework. ExDoc is simpler to use for documentation purposes, but Phoenix offers a full suite of features for building web applications. The choice between them depends on the project's requirements: use ExDoc for straightforward documentation needs, and Phoenix for building robust web applications with advanced features like real-time communication.
The GraphQL toolkit for Elixir
Pros of Absinthe
- Specialized for GraphQL API development in Elixir
- Provides a robust schema definition DSL
- Offers built-in support for real-time subscriptions
Cons of Absinthe
- Steeper learning curve for developers new to GraphQL
- More complex setup compared to ExDoc's straightforward documentation generation
- Limited to GraphQL-specific use cases
Code Comparison
ExDoc (documentation generation):
defmodule MyModule do
@moduledoc """
This module does something awesome.
"""
def my_function(arg) do
# Function implementation
end
end
Absinthe (GraphQL schema definition):
defmodule MySchema do
use Absinthe.Schema
query do
field :my_query, :string do
resolve fn _, _, _ ->
{:ok, "Query result"}
end
end
end
end
While ExDoc focuses on generating documentation from code comments, Absinthe provides a DSL for defining GraphQL schemas and resolvers. ExDoc is essential for creating project documentation, whereas Absinthe is specifically designed for building GraphQL APIs in Elixir applications. ExDoc is more universally applicable across Elixir projects, while Absinthe caters to a specific architectural pattern. Both tools serve different purposes within the Elixir ecosystem, with ExDoc enhancing code readability and Absinthe facilitating API development.
A toolkit for data mapping and language integrated query.
Pros of Ecto
- More comprehensive database toolkit with query building, migrations, and schemas
- Supports multiple databases (PostgreSQL, MySQL, SQLite)
- Active development with frequent updates and improvements
Cons of Ecto
- Steeper learning curve due to its broader scope and functionality
- Requires more setup and configuration for basic usage
- Larger codebase and dependencies
Code Comparison
Ecto query example:
query =
from u in User,
where: u.age > 18,
select: u.name
Repo.all(query)
ExDoc documentation example:
defmodule MyModule do
@moduledoc """
This module does something awesome.
"""
@doc """
Performs an amazing operation.
"""
def amazing_function(arg) do
# Function implementation
end
end
Summary
Ecto is a powerful database toolkit for Elixir, offering a wide range of features for database interactions. ExDoc, on the other hand, is focused on generating documentation for Elixir projects. While Ecto provides more functionality for database operations, it comes with increased complexity. ExDoc offers a simpler, more focused tool for improving code documentation. The choice between the two depends on the specific needs of your project: database management or documentation generation.
A curated list of amazingly awesome Elixir and Erlang libraries, resources and shiny things. Updates:
Pros of awesome-elixir
- Comprehensive list of Elixir resources, libraries, and tools
- Community-driven with frequent updates and contributions
- Serves as a valuable reference for Elixir developers of all levels
Cons of awesome-elixir
- Not focused on generating documentation for Elixir projects
- Lacks built-in functionality for code analysis or documentation generation
- Requires manual curation and maintenance
Code comparison
While a direct code comparison isn't relevant due to the different nature of these projects, here's a brief example of how they might be used:
awesome-elixir (README.md):
## Testing
* [ExUnit](https://hexdocs.pm/ex_unit/ExUnit.html) - Built-in test framework for Elixir.
* [Mox](https://github.com/plataformatec/mox) - Mocks and explicit contracts for Elixir.
ex_doc (usage in mix.exs):
def deps do
[{:ex_doc, "~> 0.24", only: :dev, runtime: false}]
end
Summary
awesome-elixir is a curated list of Elixir resources, while ex_doc is a tool for generating documentation for Elixir projects. awesome-elixir provides a comprehensive overview of the Elixir ecosystem, making it easier for developers to discover useful libraries and tools. However, it doesn't offer the specific functionality of ex_doc, which focuses on creating high-quality documentation for individual Elixir projects.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
ExDoc
ExDoc is a tool to generate documentation for Erlang and Elixir projects. To see an example, you can access Elixir's official docs.
Features
ExDoc ships with many features:
- Automatically generates online- and offline-accessible HTML and EPUB documents from your API documentation.
- Responsive design, covering phones and tablets.
- Support for custom pages, guides, livebooks and cheatsheets.
- Support for custom grouping of modules, functions, and pages in the sidebar.
- Customizable logo.
- A direct link back to the source code for every documented entity.
- Full-text search.
- Keyboard shortcuts. (Press
?
to show help.) - Quick-search with autocompletion support. (
s
keyboard shortcut.) - Go-to shortcut with auto-complete to take the reader to any HexDocs package documentation. (
g
keyboard shortcut.) - Support for night mode, activated according to the browser preference.
- Tooltips for links to modules and functions, both for the current project and other projects.
- Version dropdown, automatically configured when hosted on HexDocs.
Usage
You can use ExDoc with Mix (recommended for Elixir projects), with Rebar (recommended for Erlang projects), or via the command line.
Mix
ExDoc requires Elixir v1.12 or later. Then add ExDoc as a dependency:
def deps do
[
{:ex_doc, "~> 0.31", only: :dev, runtime: false},
]
end
Then run mix deps.get
.
Erlang development environment {: .warning}
Some Operating System distributions split Erlang into multiple packages, and at least one ExDoc dependency (
earmark_parser
) requires the Erlang development environment. If you see a message like "/usr/lib/erlang/lib/parsetools-2.3.1/include/yeccpre.hrl: no such file or directory", it means you lack this environment. For instance, on the Debian operating system and its derivatives, you need toapt install erlang-dev
.
ExDoc will automatically pull in information from your projects, such as the application and version. However, you may want to set :name
, :source_url
and :homepage_url
in order to have nicer output from ExDoc:
def project do
[
app: :my_app,
version: "0.1.0-dev",
deps: deps(),
# Docs
name: "MyApp",
source_url: "https://github.com/USER/PROJECT",
homepage_url: "http://YOUR_PROJECT_HOMEPAGE",
docs: [
main: "MyApp", # The main page in the docs
logo: "path/to/logo.png",
extras: ["README.md"]
]
]
end
Now you are ready to generate your project documentation with mix docs
. To see all options available, run mix help docs
.
To learn about how to document your projects, see Elixir's writing documentation page.
Rebar3
From Erlang/OTP 24+, you can use ExDoc to render your Erlang documentation written with EDoc. See rebar3_ex_doc
for more information.
CLI
You can use ExDoc via the command line.
-
Install ExDoc as an escript:
$ mix escript.install hex ex_doc
-
Now you are ready to use it in your projects. Move into your project directory and make sure it's compiled:
$ cd PATH_TO_YOUR_PROJECT $ mix compile
-
Invoke the
ex_doc
executable from your project:$ ex_doc "PROJECT_NAME" "PROJECT_VERSION" _build/dev/lib/project/ebin -m "PROJECT_MODULE" -u "https://github.com/GITHUB_USER/GITHUB_REPO" -l path/to/logo.png
Examples of appropriate values:
PROJECT_NAME => Ecto PROJECT_VERSION => 0.1.0 PROJECT_MODULE => Ecto (the main module provided by the library) GITHUB_USER => elixir-lang GITHUB_REPO => ecto
You can specify a config file via the --config
option, both Elixir and Erlang formats are supported. Invoke ex_doc
without arguments to learn more.
Syntax highlighting
ExDoc uses the makeup project for syntax highlighting. By default, highlighters for Erlang and Elixir are included. To syntax-highlight other languages, simply add the equivalent makeup_LANGUAGE
package to your mix.exs
/rebar.config
file. For example, for HTML support you would add:
Elixir (Mix)
{:makeup_html, ">= 0.0.0", only: :dev, runtime: false}
Erlang (Rebar3)
{makeup_html, "0.1.1"}
You can find all supported languages under the Makeup organization on GitHub and view them at Makeup's website.
Additional pages
You can publish additional pages in your project documentation by configuring them as :extras
. The following formats and extensions are supported:
-
Markdown (
.md
extension) - useful for general long-term text. Learn more. -
Cheatsheets (
.cheatmd
extension) - useful for discovery and quick reference. Learn more. -
Livebooks (
.livemd
extension) - useful for tutorials, interactive examples, and deep dives. Learn more.
For example, you can set your :extras
to:
Elixir
extras: ["README.md", "LICENSE", "tutorial.livemd", "cheatsheet.cheatmd"]
Run mix help docs
for more information on configuration.
Erlang
{extras, [<<"README.md">>, <<"cheatsheet.cheatmd">>]}.
Metadata
ExDoc supports metadata keys in your documentation.
Elixir
In Elixir, you can add metadata to modules and functions.
For a module, use @moduledoc
, which is equivalent to adding the annotation to everything inside the module (functions, macros, callbacks, types):
@moduledoc since: "1.10.0"
For a function, use @doc
:
@doc since: "1.13.1"
Erlang
In Erlang's EDoc:
%% @since 0.1.0
The following metadata is available for both modules and functions:
deprecated
(binary) - marks a module/function as deprecated, with the given string as the reason.since
(binary) - declares a module/function available from a particular version.
The following metadata is available for modules:
tags
(list of atoms) - a list of strings to be added as tags to the module. (Not supported by EDoc.)
Auto-linking
ExDoc for Elixir and Erlang will automatically generate links across modules and functions if you enclose them in backticks.
Elixir
ExDoc will automatically link modules, functions, types or callbacks defined in your project and its dependencies (including Erlang and Elixir). ExDoc will automatically link to it at the dependency's documentation at hexdocs.pm. The link can be configured by setting docs: [deps: [my_dep: "https://path/to/docs/"]]
in your mix.exs
.
ExDoc supports linking to modules (`MyModule`
and `m:MyModule`
), functions (`MyModule.function/1`
), types (`t:MyModule.type/2`
) and callbacks (`c:MyModule.callback/3`
). If you want to link a function, type or callback in the current module, you may skip the module name, for example: `function/1`
.
You can also use custom text, such as [custom text](`MyModule.function/1`)
. Link to extra pages using the syntax [Up and running](Up and running.md)
. The final link will be automatically converted to up-and-running.html
.
Link to extra pages in another application using the syntax [Writing Documentation](`e:elixir:writing-documentation.html`)
, skipping the directory in which the page is. The final link will be automatically converted to https://hexdocs.pm/elixir/writing-documentation.html
.
It is also possible to place anchors after the module name and extra pages. For example:
-
`m:Keyword#module-duplicate-keys-and-ordering`
will create a link tohttps://hexdocs.pm/elixir/Keyword.html#module-duplicate-keys-and-ordering
-
`e:elixir:syntax-reference.md#expressions`
will create a link tohttps://hexdocs.pm/elixir/syntax-reference.html#expressions
Erlang
ExDoc will automatically link modules, functions, types or callbacks defined in your project and its dependencies (including Erlang and Elixir). ExDoc will automatically link to it at the dependency's documentation at hexdocs.pm. The link can be configured by setting docs: [deps: [my_dep: "https://path/to/docs/"]]
in your mix.exs
. The link can be configured by setting {docs, [{deps, [{my_dep, "https://path/to/docs/"}]}]}
in your rebar3.config
.
ExDoc supports linking to modules (`m:my_module`
), functions (`my_module:function/1`
), types (`t:my_module:type/2`
) and callbacks (`c:my_module:callback/3`
). If you want to link a function, type or callback in the current module, you may skip the module name; e.g.: `function/1`
.
You can also use custom text, such as [custom text](`my_module:function/1`)
. This also allows you to refer to Erlang/OTP modules: [The array module](`array`)
(note that when a module is given as the link target, it is not necessary nor possible to use the m:
prefix).
Link to extra pages using the syntax [Up and running](Up and running.md)
. The final link will be automatically converted to up-and-running.html
.
Link to extra pages in another application using the syntax [Using unicode](`e:stdlib:unicode_usage.html`)
, skipping the directory in which the page is. The final link will be automatically converted to https://hexdocs.pm/elixir/writing-documentation.html
.
It is also possible to place anchors after the module name and extra pages. For example:
-
`m:argparse#quick-start`
will create a link tohttps://erlang.org/doc/man/argparse#quick-start
-
`e:stdlib:unicode-usage.md#what-unicode-is`
will create a link tohttps://erlang.org/doc/apps/stdlib/unicode-usage.html#what-unicode-is
Admonition blocks
You may want to draw attention to certain statements by taking them out of the content's flow and labeling them with a priority. Such statements are called admonitions. (They are also known as asides or callouts.) An admonition block is rendered based on the assigned label or class. ExDoc supports warning
, error
, info
, tip
and neutral
tags, on header levels h3
and h4
.
The syntax is as follows:
> #### Error {: .error}
>
> This syntax will render an error block
The result for the previous syntax is:
Error {: .error}
This syntax will render an error block
For example, if you change the class name to neutral
, you get the same admonition block in neutral style:
Neutral {: .neutral}
This syntax will render a neutral block
Tabsets
Where only one section of content of a series is likely to apply to the reader, you may wish to define a set of tabs.
This example contains code blocks, separating them into tabs based on language:
Elixir
IO.puts "Hello, world!"
Erlang
io:fwrite("Hello, world!\n").
Tabbed content must be defined between <!-- tabs-open -->
and <!-- tabs-close -->
HTML comments. Each h3
heading results in a new tab panel, with its text setting the tab button label.
Here is the above example's source:
<!-- tabs-open -->
### Elixir
```elixir
IO.puts "Hello, world!"
```
### Erlang
```erlang
io:fwrite("Hello, world!\n").
```
<!-- tabs-close -->
Extensions
ExDoc renders Markdown content for you, but you can extend it to render complex objects on the page using JavaScript. To inject custom JavaScript into every page, add this to your configuration:
docs: [
# ...
before_closing_head_tag: &before_closing_head_tag/1,
before_closing_body_tag: &before_closing_body_tag/1
]
# ...
defp before_closing_head_tag(:html) do
"""
<!-- HTML injected at the end of the <head> element -->
"""
end
defp before_closing_head_tag(:epub), do: ""
defp before_closing_body_tag(:html) do
"""
<!-- HTML injected at the end of the <body> element -->
"""
end
defp before_closing_body_tag(:epub), do: ""
Besides an anonymous function, you can also pass a module-function-args
tuple. It will call the given module and function, with the format prefixed to the arguments:
docs: [
# ...
before_closing_head_tag: {MyModule, :before_closing_head_tag, []},
before_closing_body_tag: {MyModule, :before_closing_body_tag, []}
]
Or you can pass a map where the key is the format:
docs: [
# ...
before_closing_head_tag: %{html: "...", epub: "..."},
before_closing_body_tag: %{html: "...", epub: "..."}
]
Rendering Math
If you write TeX-style math in your Markdown, such as $\sum_{i}^{N} x_i$
, it ends up as raw text on the generated pages. To render expressions, we recommend using KaTeX, a JavaScript library that turns expressions into graphics. To load and trigger KaTeX on every documentation page, we can insert the following HTML:
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.4/dist/katex.min.css" integrity="sha384-vKruj+a13U8yHIkAyGgK1J3ArTLzrFGBbBc0tDp4ad/EyewESeXE/Iv67Aj8gKZ0" crossorigin="anonymous">
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.4/dist/katex.min.js" integrity="sha384-PwRUT/YqbnEjkZO0zZxNqcxACrXe+j766U2amXcgMg5457rve2Y7I6ZJSm2A0mS4" crossorigin="anonymous"></script>
<link href="https://cdn.jsdelivr.net/npm/katex-copytex@1.0.2/dist/katex-copytex.min.css" rel="stylesheet" type="text/css">
<script defer src="https://cdn.jsdelivr.net/npm/katex-copytex@1.0.2/dist/katex-copytex.min.js" crossorigin="anonymous"></script>
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.4/dist/contrib/auto-render.min.js" integrity="sha384-+VBxd3r6XgURycqtZ117nYw44OOcIax56Z4dCRWbxyPt0Koah1uHoK0o4+/RRE05" crossorigin="anonymous"
onload="renderMathInElement(document.body, {
delimiters: [
{left: '$$', right: '$$', display: true},
{left: '$', right: '$', display: false},
]
});"></script>
</script>
For more details and configuration options, see the KaTeX Auto-render Extension.
Rendering Vega-Lite plots
Snippets are also objects you may want to render in a special manner. For example, assuming your Markdown includes Vega-Lite specification in vega-lite
code snippets:
<script defer src="https://cdn.jsdelivr.net/npm/vega@5.20.2"></script>
<script defer src="https://cdn.jsdelivr.net/npm/vega-lite@5.1.1"></script>
<script defer src="https://cdn.jsdelivr.net/npm/vega-embed@6.18.2"></script>
<script>
document.addEventListener("DOMContentLoaded", function () {
for (const codeEl of document.querySelectorAll("pre code.vega-lite")) {
try {
const preEl = codeEl.parentElement;
const spec = JSON.parse(codeEl.textContent);
const plotEl = document.createElement("div");
preEl.insertAdjacentElement("afterend", plotEl);
vegaEmbed(plotEl, spec);
preEl.remove();
} catch (error) {
console.log("Failed to render Vega-Lite plot: " + error)
}
}
});
</script>
For more details and configuration options, see vega/vega-embed.
Rendering Mermaid graphs
Similarly to the example above, if your Markdown includes Mermaid graph specification in mermaid
code snippets:
<script>
function mermaidLoaded() {
mermaid.initialize({
startOnLoad: false,
theme: document.body.className.includes("dark") ? "dark" : "default"
});
let id = 0;
for (const codeEl of document.querySelectorAll("pre code.mermaid")) {
const preEl = codeEl.parentElement;
const graphDefinition = codeEl.textContent;
const graphEl = document.createElement("div");
const graphId = "mermaid-graph-" + id++;
mermaid.render(graphId, graphDefinition).then(({svg, bindFunctions}) => {
graphEl.innerHTML = svg;
bindFunctions?.(graphEl);
preEl.insertAdjacentElement("afterend", graphEl);
preEl.remove();
});
}
}
</script>
<script async src="https://cdn.jsdelivr.net/npm/mermaid@10.2.3/dist/mermaid.min.js" onload="mermaidLoaded();"></script>
For more details and configuration options, see the Mermaid usage docs.
Contributing
The easiest way to test changes to ExDoc is to locally rebuild the app and its own documentation:
- Run
mix setup
to install all dependencies - Run
mix build
to generate the docs and open up the generateddoc/index.html
- (optional) Run
npm run --prefix assets build:watch
if working on assets for automatic recompilation - Run
mix lint
to check linting and formatting (andmix fix
to automatically fix it) - (important) Do not add the files in the
formatters/
directory to your commits, those will be handled by the maintainers
See the README in the assets/
directory for more information on working on the assets.
License
ExDoc source code is released under the Apache 2 License. The generated contents, however, are under different licenses based on projects used to help render HTML, including CSS, JS, and other assets.
Any documentation generated by ExDoc, or any documentation generated by any "Derivative Works" (as specified in the Apache 2 License), must include a direct, readable, and visible link to the ExDoc repository on each rendered material. For HTML pages, every single page is a rendered material. For PDF, EPUB and other ebook formats, the whole body of documentation is a rendered material.
Top Related Projects
Elixir is a dynamic, functional language for building scalable and maintainable applications
Peace of mind from prototype to production
The GraphQL toolkit for Elixir
A toolkit for data mapping and language integrated query.
A curated list of amazingly awesome Elixir and Erlang libraries, resources and shiny things. Updates:
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot