Skip to content

Commit 99cf031

Browse files
committed
Render groups descriptions
1 parent 80679ae commit 99cf031

File tree

8 files changed

+113
-6
lines changed

8 files changed

+113
-6
lines changed

lib/ex_doc/formatter/epub/templates/module_template.eex

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@
2525
<%= for {group, nodes} <- summary, key = text_to_id(group.title) do %>
2626
<section id="<%= key %>" class="details-list">
2727
<h1 class="section-heading"><%=h to_string(group.title) %></h1>
28+
<%= if doc = group.rendered_doc do %>
29+
<div class="group-description" id="group-description-<%= key %>">
30+
<%= H.link_group_headings(doc, key) %>
31+
</div>
32+
<% end %>
2833
<div class="<%= key %>-list">
2934
<%= for node <- nodes, do: H.detail_template(node, module) %>
3035
</div>

lib/ex_doc/formatter/html.ex

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,15 @@ defmodule ExDoc.Formatter.HTML do
111111
render_doc(child_node, language, autolink_opts, opts)
112112
end
113113

114+
docs_groups =
115+
for group <- node.docs_groups do
116+
render_doc(group, language, autolink_opts, opts)
117+
end
118+
114119
%{
115120
render_doc(node, language, [{:id, node.id} | autolink_opts], opts)
116-
| docs: docs
121+
| docs: docs,
122+
docs_groups: docs_groups
117123
}
118124
end,
119125
timeout: :infinity

lib/ex_doc/formatter/html/templates.ex

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,10 @@ defmodule ExDoc.Formatter.HTML.Templates do
288288
link_headings(content, prefix <> "-")
289289
end
290290

291+
def link_group_headings(content, key) do
292+
link_headings(content, "group-#{key}-")
293+
end
294+
291295
templates = [
292296
detail_template: [:node, :module],
293297
footer_template: [:config, :node],

lib/ex_doc/formatter/html/templates/module_template.eex

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@
5151
</a>
5252
<span class="text"><%= group.title %></span>
5353
</h1>
54+
<%= if doc = group.rendered_doc do %>
55+
<div class="group-description" id="group-description-<%= key %>">
56+
<%= link_group_headings(doc, key) %>
57+
</div>
58+
<% end %>
5459
<div class="<%= key %>-list">
5560
<%= for node <- nodes, do: detail_template(node, module) %>
5661
</div>

lib/ex_doc/nodes.ex

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,14 @@ defmodule ExDoc.ModuleNode do
2626
metadata: nil
2727

2828
@typep annotation :: atom()
29-
@typep doc_group :: %{
30-
title: String.t() | atom(),
31-
description: String.t() | nil
32-
}
29+
30+
# TODO: Maybe this is worth its own module
31+
@type doc_group :: %{
32+
title: String.t() | atom(),
33+
description: String.t() | nil,
34+
doc: ExDoc.DocAST.t() | nil,
35+
rendered_doc: String.t() | nil
36+
}
3337

3438
@type t :: %__MODULE__{
3539
id: String.t(),
@@ -93,7 +97,7 @@ defmodule ExDoc.DocNode do
9397
signature: String.t(),
9498
specs: [ExDoc.Language.spec_ast()],
9599
annotations: [annotation()],
96-
group: atom() | nil,
100+
group: String.t() | ExDoc.ModuleNode.doc_group() | nil,
97101
doc_file: String.t(),
98102
doc_line: non_neg_integer(),
99103
source_url: String.t() | nil

lib/ex_doc/retriever.ex

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,17 @@ defmodule ExDoc.Retriever do
234234
{[group], seen}
235235
end)
236236

237+
docs_groups =
238+
Enum.map(docs_groups, fn group ->
239+
doc_ast =
240+
case group.description do
241+
nil -> nil
242+
text -> doc_ast("text/markdown", %{"en" => text}, [])
243+
end
244+
245+
Map.merge(group, %{doc: doc_ast, rendered_doc: nil})
246+
end)
247+
237248
# We do not need the full group data in each doc node anymore, only the
238249
# title.
239250
doc_nodes = Enum.map(doc_nodes, &Map.put(&1, :group, &1.group.title))

test/ex_doc/formatter/epub/templates_test.exs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,42 @@ defmodule ExDoc.Formatter.EPUB.TemplatesTest do
145145
assert content =~ ~r{id="functions".*id="example_1/0"}ms
146146
end
147147

148+
test "outputs groups descriptions" do
149+
content =
150+
get_module_page([CompiledWithDocs],
151+
group_for_doc: fn metadata ->
152+
if metadata[:purpose] == :example do
153+
[
154+
title: "Example functions",
155+
description: """
156+
### A section heading example
157+
158+
A content example.
159+
160+
See `example/1` or `example/2`.
161+
A link to `flatten/1`.
162+
"""
163+
]
164+
else
165+
"Functions"
166+
end
167+
end
168+
)
169+
170+
doc = LazyHTML.from_document(content)
171+
172+
assert Enum.count(doc["div.group-description"]) == 1
173+
assert Enum.count(doc["#group-description-example-functions"]) == 1
174+
assert Enum.count(doc["#group-description-example-functions h3"]) == 1
175+
assert Enum.count(doc["#group-example-functions-a-section-heading-example"]) == 1
176+
assert Enum.count(doc["#example-functions .group-description a[href='#example/1']"]) == 1
177+
assert Enum.count(doc["#example-functions .group-description a[href='#example/2']"]) == 1
178+
assert Enum.count(doc["#example-functions .group-description a[href='#flatten/1']"]) == 1
179+
180+
assert content =~ ~s[<span class="text">A section heading example</span>]
181+
assert content =~ "<p>A content example.</p>"
182+
end
183+
148184
test "outputs summaries" do
149185
content = get_module_page([CompiledWithDocs])
150186

test/ex_doc/formatter/html/templates_test.exs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,42 @@ defmodule ExDoc.Formatter.HTML.TemplatesTest do
469469
assert Enum.count(doc["#functions [id='example/2']"]) == 0
470470
end
471471

472+
test "outputs groups descriptions", context do
473+
content =
474+
get_module_page([CompiledWithDocs], context,
475+
group_for_doc: fn metadata ->
476+
if metadata[:purpose] == :example do
477+
[
478+
title: "Example functions",
479+
description: """
480+
### A section heading example
481+
482+
A content example.
483+
484+
See `example/1` or `example/2`.
485+
A link to `flatten/1`.
486+
"""
487+
]
488+
else
489+
"Functions"
490+
end
491+
end
492+
)
493+
494+
doc = LazyHTML.from_document(content)
495+
496+
assert Enum.count(doc["div.group-description"]) == 1
497+
assert Enum.count(doc["#group-description-example-functions"]) == 1
498+
assert Enum.count(doc["#group-description-example-functions h3"]) == 1
499+
assert Enum.count(doc["#group-example-functions-a-section-heading-example"]) == 1
500+
assert Enum.count(doc["#example-functions .group-description a[href='#example/1']"]) == 1
501+
assert Enum.count(doc["#example-functions .group-description a[href='#example/2']"]) == 1
502+
assert Enum.count(doc["#example-functions .group-description a[href='#flatten/1']"]) == 1
503+
504+
assert content =~ ~s[<span class="text">A section heading example</span>]
505+
assert content =~ "<p>A content example.</p>"
506+
end
507+
472508
test "outputs deprecation information", context do
473509
content = get_module_page([CompiledWithDocs], context)
474510

0 commit comments

Comments
 (0)