Skip to content

Commit 81b55ed

Browse files
committed
Decouple api reference from extras
1 parent f65d2ff commit 81b55ed

File tree

9 files changed

+126
-99
lines changed

9 files changed

+126
-99
lines changed

lib/ex_doc/formatter/epub.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ defmodule ExDoc.Formatter.EPUB do
6363
defp generate_extras(config) do
6464
for {_title, extras} <- config.extras,
6565
node <- extras,
66-
not is_map_key(node, :url) and node.extension != ".cheatmd" do
66+
not is_map_key(node, :url) and node.type != :cheatmd do
6767
output = "#{config.output}/OEBPS/#{node.id}.xhtml"
6868
html = Templates.extra_template(config, node)
6969

lib/ex_doc/formatter/html.ex

Lines changed: 21 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,11 @@ defmodule ExDoc.Formatter.HTML do
3232
tasks: filter_list(:task, project_nodes)
3333
}
3434

35-
# TODO: api reference should not be treated as an extra
36-
extras =
37-
if config.api_reference do
38-
[build_api_reference(nodes_map, config) | extras]
39-
else
40-
extras
41-
end
42-
4335
all_files =
4436
search_data ++
4537
static_files ++
4638
generate_sidebar_items(nodes_map, extras, config) ++
39+
generate_api_reference(nodes_map, config) ++
4740
generate_extras(extras, config) ++
4841
generate_favicon(@assets_dir, config) ++
4942
generate_logo(@assets_dir, config) ++
@@ -185,7 +178,7 @@ defmodule ExDoc.Formatter.HTML do
185178
end
186179

187180
defp generate_sidebar_items(nodes_map, extras, config) do
188-
content = Templates.create_sidebar_items(nodes_map, extras)
181+
content = Templates.create_sidebar_items(config, nodes_map, extras)
189182

190183
path = "dist/sidebar_items-#{digest(content)}.js"
191184
File.write!(Path.join(config.output, path), content)
@@ -221,8 +214,7 @@ defmodule ExDoc.Formatter.HTML do
221214
next: next && %{path: "#{next.id}.html", title: next.title}
222215
}
223216

224-
extension = node.source_path && Path.extname(node.source_path)
225-
html = Templates.extra_template(config, node, extra_type(extension), refs)
217+
html = Templates.extra_template(config, node, refs)
226218

227219
if File.regular?(output) do
228220
Utils.warn("file #{Path.relative_to_cwd(output)} already exists", [])
@@ -307,24 +299,23 @@ defmodule ExDoc.Formatter.HTML do
307299
]
308300
end
309301

310-
defp build_api_reference(nodes_map, config) do
311-
api_reference = Templates.api_reference_template(nodes_map)
302+
defp generate_api_reference(_nodes_map, %{api_reference: false}) do
303+
[]
304+
end
312305

313-
title_content =
314-
~s{API Reference <small class="app-vsn">#{config.project} v#{config.version}</small>}
306+
defp generate_api_reference(nodes_map, config) do
307+
filename = "api-reference.html"
308+
output = "#{config.output}/#{filename}"
309+
config = set_canonical_url(config, filename)
315310

316-
%{
317-
group: nil,
318-
id: "api-reference",
319-
source_path: nil,
320-
source_url: config.source_url,
321-
title: "API Reference",
322-
title_content: title_content,
323-
content: api_reference,
324-
headers:
325-
if(nodes_map.modules != [], do: [{:h2, "Modules", "modules"}], else: []) ++
326-
if(nodes_map.tasks != [], do: [{:h2, "Mix Tasks", "mix-tasks"}], else: [])
327-
}
311+
html = Templates.api_reference_template(config, nodes_map)
312+
313+
if File.regular?(output) do
314+
Utils.warn("file #{Path.relative_to_cwd(output)} already exists", [])
315+
end
316+
317+
File.write!(output, html)
318+
[filename]
328319
end
329320

330321
@doc """
@@ -441,16 +432,15 @@ defmodule ExDoc.Formatter.HTML do
441432

442433
title_text = title_ast && ExDoc.DocAST.text(title_ast)
443434
title_html = title_ast && ExDoc.DocAST.to_string(title_ast)
444-
445-
group = GroupMatcher.match_extra(groups, input)
446435
title = input_options[:title] || title_text || filename_to_title(input)
447436

437+
group = GroupMatcher.match_extra(groups, input)
448438
source_path = source_file |> Path.relative_to(File.cwd!()) |> String.replace_leading("./", "")
449439
source_url = source_url_pattern.(source_path, 1)
450440
search_data = normalize_search_data!(input_options[:search_data])
451441

452442
%{
453-
extension: extension,
443+
type: extra_type(extension),
454444
source: source,
455445
group: group,
456446
id: id,
@@ -459,9 +449,7 @@ defmodule ExDoc.Formatter.HTML do
459449
source_url: source_url,
460450
search_data: search_data,
461451
title: title,
462-
title_content: title_html || title,
463-
# Remove this field when API reference is no longer treated as an extra
464-
headers: ExDoc.DocAST.extract_headers_with_ids(ast, [:h2])
452+
title_content: title_html || title
465453
}
466454
end
467455

lib/ex_doc/formatter/html/templates.ex

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -46,16 +46,26 @@ defmodule ExDoc.Formatter.HTML.Templates do
4646
@doc """
4747
Create a JS object which holds all the items displayed in the sidebar area
4848
"""
49-
def create_sidebar_items(nodes_map, extras) do
49+
def create_sidebar_items(config, nodes_map, extras) do
5050
nodes =
5151
nodes_map
5252
|> Enum.map(&sidebar_module/1)
5353
|> Map.new()
54-
|> Map.put(:extras, sidebar_extras(extras))
54+
|> Map.put(:extras, api_reference(config, nodes_map) ++ sidebar_extras(extras))
5555

5656
["sidebarNodes=" | ExDoc.Utils.to_json(nodes)]
5757
end
5858

59+
defp api_reference(%{api_reference: false}, _nodes_map), do: []
60+
61+
defp api_reference(_config, nodes_map) do
62+
headers =
63+
if(nodes_map.modules != [], do: [%{id: "Modules", anchor: "modules"}], else: []) ++
64+
if(nodes_map.tasks != [], do: [%{id: "Mix Tasks", anchor: "mix-tasks"}], else: [])
65+
66+
[%{id: "api-reference", title: "API Reference", group: "", headers: headers}]
67+
end
68+
5969
defp sidebar_extras(extras) do
6070
for extra <- extras do
6171
%{id: id, title: title, group: group} = extra
@@ -73,41 +83,41 @@ defmodule ExDoc.Formatter.HTML.Templates do
7383
end)
7484

7585
item
76-
|> Map.put(:headers, headers_to_id_and_anchors(extra.headers))
86+
|> Map.put(:headers, headers(extra.doc))
7787
|> Map.put(:searchData, search_data)
7888

7989
%{url: url} when is_binary(url) ->
8090
Map.put(item, :url, url)
8191

8292
_ ->
83-
Map.put(item, :headers, headers_to_id_and_anchors(extra.headers))
93+
Map.put(item, :headers, headers(extra.doc))
8494
end
8595
end
8696
end
8797

8898
defp sidebar_module({id, modules}) do
8999
modules =
90100
for module <- modules do
91-
extra =
101+
groups =
92102
module
93103
|> module_summary()
94104
|> case do
95105
[] -> []
96106
entries -> [nodeGroups: Enum.map(entries, &sidebar_entries/1)]
97107
end
98108

99-
sections = module_sections(module)
100-
101-
deprecated? = not is_nil(module.deprecated)
102-
103109
pairs =
104110
for key <- [:id, :title, :nested_title, :nested_context],
105111
value = Map.get(module, key),
106112
do: {key, value}
107113

108-
pairs = [{:deprecated, deprecated?} | pairs]
114+
others = [
115+
deprecated: not is_nil(module.deprecated),
116+
sections: headers(module.doc || []),
117+
group: to_string(module.group)
118+
]
109119

110-
Map.new([group: to_string(module.group)] ++ extra ++ pairs ++ sections)
120+
Map.new(groups ++ pairs ++ others)
111121
end
112122

113123
{id, modules}
@@ -135,17 +145,10 @@ defmodule ExDoc.Formatter.HTML.Templates do
135145
%{key: text_to_id(group), name: group, nodes: nodes}
136146
end
137147

138-
defp module_sections(module) do
139-
sections =
140-
(module.doc || [])
141-
|> ExDoc.DocAST.extract_headers_with_ids([:h2])
142-
|> headers_to_id_and_anchors()
143-
144-
[sections: sections]
145-
end
146-
147-
defp headers_to_id_and_anchors(headers) do
148-
Enum.map(headers, fn {:h2, text, anchor} ->
148+
defp headers(doc) do
149+
doc
150+
|> ExDoc.DocAST.extract_headers_with_ids([:h2])
151+
|> Enum.map(fn {:h2, text, anchor} ->
149152
%{id: text, anchor: anchor}
150153
end)
151154
end
@@ -219,13 +222,13 @@ defmodule ExDoc.Formatter.HTML.Templates do
219222

220223
templates = [
221224
detail_template: [:node, :module],
222-
footer_template: [:config, :node],
225+
footer_template: [:config, :source_path],
223226
head_template: [:config, :title, :noindex],
224227
module_template: [:config, :module, :summary],
225228
not_found_template: [:config],
226229
api_reference_entry_template: [:module_node],
227-
api_reference_template: [:nodes_map],
228-
extra_template: [:config, :node, :type, :refs],
230+
api_reference_template: [:config, :nodes_map],
231+
extra_template: [:config, :node, :refs],
229232
search_template: [:config],
230233
sidebar_template: [:config, :type],
231234
summary_template: [:name, :nodes],
Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,38 @@
1-
<%= if nodes_map.modules != [] do %>
2-
<section class="details-list">
3-
<h2 id="modules" class="section-heading">Modules</h2>
4-
<div class="summary">
5-
<%= for module_node <- Enum.sort_by(nodes_map.modules, & &1.id) do
6-
api_reference_entry_template(module_node)
7-
end %>
8-
</div>
9-
</section>
10-
<% end %>
1+
<%= head_template(config, "API Reference", false) %>
2+
<%= sidebar_template(config, :extra) %>
113

12-
<%= if nodes_map.tasks != [] do %>
13-
<section class="details-list">
14-
<h2 id="tasks" class="section-heading">Mix Tasks</h2>
15-
<div class="summary">
16-
<%= for task_node <- nodes_map.tasks do
17-
api_reference_entry_template(task_node)
18-
end %>
19-
</div>
20-
</section>
21-
<% end %>
4+
<div id="top-content">
5+
<div class="heading-with-actions top-heading">
6+
<h1>API Reference <small class="app-vsn"><%= config.project %> v#<%= config.version %></small></h1>
7+
<%= if config.source_url do %>
8+
<a href="<%= config.source_url %>" title="View Source" class="icon-action" rel="help">
9+
<i class="ri-code-s-slash-line" aria-hidden="true"></i>
10+
<span class="sr-only">View Source</span>
11+
</a>
12+
<% end %>
13+
</div>
14+
15+
<%= if nodes_map.modules != [] do %>
16+
<section class="details-list">
17+
<h2 id="modules" class="section-heading">Modules</h2>
18+
<div class="summary">
19+
<%= for module_node <- Enum.sort_by(nodes_map.modules, & &1.id) do
20+
api_reference_entry_template(module_node)
21+
end %>
22+
</div>
23+
</section>
24+
<% end %>
25+
26+
<%= if nodes_map.tasks != [] do %>
27+
<section class="details-list">
28+
<h2 id="tasks" class="section-heading">Mix Tasks</h2>
29+
<div class="summary">
30+
<%= for task_node <- nodes_map.tasks do
31+
api_reference_entry_template(task_node)
32+
end %>
33+
</div>
34+
</section>
35+
<% end %>
36+
</div>
37+
38+
<%= footer_template(config, nil) %>

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
<%= head_template(config, node.title, false) %>
2-
<%= sidebar_template(config, type) %>
2+
<%= sidebar_template(config, node.type) %>
33

44
<div id="top-content">
55
<div class="heading-with-actions top-heading">
66
<h1><%= node.title_content %></h1>
7-
<%= if type == :cheatmd do %>
7+
<%= if node.type == :cheatmd do %>
88
<button onclick="window.print()" title="Print Cheatsheet" class="icon-action" rel="print">
99
<i class="ri-printer-line" aria-hidden="true"></i>
1010
<span class="sr-only">Print Cheatsheet</span>
@@ -18,15 +18,15 @@
1818
<% end %>
1919
</div>
2020

21-
<%= if type == :livemd do %>
21+
<%= if node.type == :livemd do %>
2222
<div class="livebook-badge-container">
2323
<a href="#" class="livebook-badge">
2424
<img src="https://livebook.dev/badge/v1/blue.svg" alt="Run in Livebook" width="150" />
2525
</a>
2626
</div>
2727
<% end %>
2828

29-
<%= if type == :cheatmd do %>
29+
<%= if node.type == :cheatmd do %>
3030
<%= node.doc |> ExDoc.DocAST.sectionize([:h2, :h3]) |> render_doc() %>
3131
<% else %>
3232
<%= node[:content] || render_doc(node.doc) %>
@@ -60,4 +60,4 @@
6060
</div>
6161
</div>
6262

63-
<%= footer_template(config, node) %>
63+
<%= footer_template(config, node.source_path) %>

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<a href="https://preview.hex.pm/preview/<%= config.package %>/<%= config.version %>">Hex Preview</a>
88

9-
<%= source_path = node && Map.get(node, :source_path); if source_path do %>
9+
<%= if source_path do %>
1010
(<a href="https://preview.hex.pm/preview/<%= config.package %>/<%= config.version %>/show/<%= source_path %>">current file</a>)
1111
<% end %>
1212
</span>

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,4 @@
5757
</section>
5858
<% end %>
5959

60-
<%= footer_template(config, module) %>
60+
<%= footer_template(config, module.source_path) %>

0 commit comments

Comments
 (0)