Skip to content

Commit a62675e

Browse files
authored
Add before_closing_body_tag mfa support (#1670)
1 parent 1e73873 commit a62675e

14 files changed

+120
-11
lines changed

Diff for: README.md

+40-1
Original file line numberDiff line numberDiff line change
@@ -215,18 +215,57 @@ ExDoc renders Markdown content for you, but you can extend it to render complex
215215
```elixir
216216
docs: [
217217
# ...
218+
before_closing_head_tag: &before_closing_head_tag/1,
218219
before_closing_body_tag: &before_closing_body_tag/1
219220
]
220221

221222
# ...
222223

224+
defp before_closing_head_tag(:html) do
225+
"""
226+
<!-- HTML injected at the end of the <head> element -->
227+
"""
228+
end
229+
230+
defp before_closing_head_tag(:epub), do: ""
231+
223232
defp before_closing_body_tag(:html) do
224233
"""
225234
<!-- HTML injected at the end of the <body> element -->
226235
"""
227236
end
228237

229-
defp before_closing_body_tag(_), do: ""
238+
defp before_closing_body_tag(:epub), do: ""
239+
```
240+
241+
You could use `MFA` as well:
242+
243+
```elixir
244+
docs: [
245+
# ...
246+
before_closing_head_tag: {MyModule, :before_closing_head_tag, ["Demo"]},
247+
before_closing_body_tag: {MyModule, :before_closing_body_tag, ["Demo"]}
248+
]
249+
250+
# ...
251+
252+
defmodule MyModule do
253+
def before_closing_head_tag(:html, name) do
254+
# ...
255+
end
256+
257+
def before_closing_head_tag(:epub, name) do
258+
# ...
259+
end
260+
261+
def before_closing_body_tag(:html, name) do
262+
# ...
263+
end
264+
265+
def before_closing_body_tag(:html, name) do
266+
# ...
267+
end
268+
end
230269
```
231270

232271
### Rendering Math

Diff for: lib/ex_doc/config.ex

+2-2
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ defmodule ExDoc.Config do
5151
apps: [atom()],
5252
assets: nil | String.t(),
5353
authors: nil | [String.t()],
54-
before_closing_body_tag: (atom() -> String.t()),
55-
before_closing_head_tag: (atom() -> String.t()),
54+
before_closing_body_tag: (atom() -> String.t()) | mfa(),
55+
before_closing_head_tag: (atom() -> String.t()) | mfa(),
5656
canonical: nil | String.t(),
5757
cover: nil | Path.t(),
5858
deps: [{ebin_path :: String.t(), doc_url :: String.t()}],

Diff for: lib/ex_doc/formatter/epub/templates.ex

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ defmodule ExDoc.Formatter.EPUB.Templates do
33

44
require EEx
55

6+
import ExDoc.Utils, only: [before_closing_body_tag: 2, before_closing_head_tag: 2]
7+
68
alias ExDoc.Formatter.HTML
79
alias ExDoc.Formatter.HTML.Templates, as: H
810

Diff for: lib/ex_doc/formatter/epub/templates/extra_template.eex

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@
44
</h1>
55
<%= content %>
66
<%# Extra content specified by the user (e.g. custom Javascript) %>
7-
<%= config.before_closing_body_tag.(:epub) %>
7+
<%= before_closing_body_tag(config, :epub) %>
88
</body>
99
</html>

Diff for: lib/ex_doc/formatter/epub/templates/head_template.eex

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@
99
href="<%= H.asset_rev "#{config.output}/OEBPS", "dist/epub-#{config.proglang}-*.css" %>" />
1010
<script src="<%= H.asset_rev "#{config.output}/OEBPS", "dist/epub-*.js" %>"></script>
1111
<%# Extra content specified by the user (e.g. custom CSS) %>
12-
<%= config.before_closing_head_tag.(:epub) %>
12+
<%= before_closing_head_tag(config, :epub) %>
1313
</head>
1414
<body class="content-inner">

Diff for: lib/ex_doc/formatter/epub/templates/module_template.eex

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,6 @@
4343
</section>
4444
<% end %>
4545
<%# Extra content specified by the user (e.g. custom Javascript) %>
46-
<%= config.before_closing_body_tag.(:epub) %>
46+
<%= before_closing_body_tag(config, :epub) %>
4747
</body>
4848
</html>

Diff for: lib/ex_doc/formatter/epub/templates/nav_template.eex

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,6 @@
2121
</ol>
2222
</nav>
2323
<%# Extra content specified by the user (e.g. custom Javascript) %>
24-
<%= config.before_closing_body_tag.(:epub) %>
24+
<%= before_closing_body_tag(config, :epub) %>
2525
</body>
2626
</html>

Diff for: lib/ex_doc/formatter/epub/templates/title_template.eex

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,6 @@
1111
<% end %>
1212
</div>
1313
<%# Extra content specified by the user (e.g. custom Javascript) %>
14-
<%= config.before_closing_body_tag.(:epub) %>
14+
<%= before_closing_body_tag(config, :epub) %>
1515
</body>
1616
</html>

Diff for: lib/ex_doc/formatter/html/templates.ex

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ defmodule ExDoc.Formatter.HTML.Templates do
22
@moduledoc false
33
require EEx
44

5-
import ExDoc.Utils, only: [h: 1]
5+
import ExDoc.Utils, only: [h: 1, before_closing_body_tag: 2, before_closing_head_tag: 2]
66

77
# TODO: It should not depend on the parent module. Move required HTML functions to Utils.
88
# TODO: Add tests that assert on the returned structured, not on JSON

Diff for: lib/ex_doc/formatter/html/templates/footer_template.eex

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,6 @@
4040
</section>
4141
</div>
4242
<%# Extra content specified by the user (e.g. custom Javascript) %>
43-
<%= config.before_closing_body_tag.(:html) %>
43+
<%= before_closing_body_tag(config, :html) %>
4444
</body>
4545
</html>

Diff for: lib/ex_doc/formatter/html/templates/head_template.eex

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
<% end %>
2626
<script async src="<%= asset_rev config.output, "dist/html-*.js" %>"></script>
2727
<%# Extra content specified by the user (e.g. custom CSS) %>
28-
<%= config.before_closing_head_tag.(:html) %>
28+
<%= before_closing_head_tag(config, :html) %>
2929
</head>
3030
<body data-type="<%= sidebar_type(page.type) %>" class="page-<%= page.type %>">
3131
<script>

Diff for: lib/ex_doc/utils.ex

+22
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,28 @@
11
defmodule ExDoc.Utils do
22
@moduledoc false
33

4+
@doc """
5+
Runs the `before_closing_head_tag` callback.
6+
"""
7+
def before_closing_head_tag(%{before_closing_head_tag: {m, f, a}}, module) do
8+
apply(m, f, [module | a])
9+
end
10+
11+
def before_closing_head_tag(%{before_closing_head_tag: before_closing_head_tag}, module) do
12+
before_closing_head_tag.(module)
13+
end
14+
15+
@doc """
16+
Runs the `before_closing_body_tag` callback.
17+
"""
18+
def before_closing_body_tag(%{before_closing_body_tag: {m, f, a}}, module) do
19+
apply(m, f, [module | a])
20+
end
21+
22+
def before_closing_body_tag(%{before_closing_body_tag: before_closing_body_tag}, module) do
23+
before_closing_body_tag.(module)
24+
end
25+
426
@doc """
527
HTML escapes the given string.
628

Diff for: test/ex_doc/formatter/epub_test.exs

+22
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ defmodule ExDoc.Formatter.EPUBTest do
99
defp before_closing_head_tag(:epub), do: @before_closing_head_tag_content_epub
1010
defp before_closing_body_tag(:epub), do: @before_closing_body_tag_content_epub
1111

12+
def before_closing_head_tag(:epub, name), do: "<meta name=#{name}>"
13+
def before_closing_body_tag(:epub, name), do: "<p>#{name}</p>"
14+
1215
defp doc_config(%{tmp_dir: tmp_dir} = _context) do
1316
[
1417
app: :elixir,
@@ -188,6 +191,25 @@ defmodule ExDoc.Formatter.EPUBTest do
188191
end
189192
end
190193

194+
test "before_closing_*_tags required by the user are in the right place using MFA",
195+
%{tmp_dir: tmp_dir} = context do
196+
generate_docs_and_unzip(
197+
context,
198+
doc_config(context,
199+
before_closing_head_tag: {__MODULE__, :before_closing_head_tag, ["Demo"]},
200+
before_closing_body_tag: {__MODULE__, :before_closing_body_tag, ["Demo"]}
201+
)
202+
)
203+
204+
oebps_dir = tmp_dir <> "/epub/OEBPS"
205+
206+
for basename <- @example_basenames do
207+
content = File.read!(Path.join(oebps_dir, basename))
208+
assert content =~ ~r[<meta name=Demo>\s*</head>]
209+
assert content =~ ~r[<p>Demo</p>\s*</body>]
210+
end
211+
end
212+
191213
test "assets required by the user end up in the right place", %{tmp_dir: tmp_dir} = context do
192214
File.mkdir_p!("test/tmp/epub_assets/hello")
193215
File.touch!("test/tmp/epub_assets/hello/world.png")

Diff for: test/ex_doc/formatter/html_test.exs

+24
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ defmodule ExDoc.Formatter.HTMLTest do
1717
defp before_closing_head_tag(:html), do: @before_closing_head_tag_content_html
1818
defp before_closing_body_tag(:html), do: @before_closing_body_tag_content_html
1919

20+
def before_closing_head_tag(:html, name), do: "<meta name=#{name}>"
21+
def before_closing_body_tag(:html, name), do: "<p>#{name}</p>"
22+
2023
defp doc_config(%{tmp_dir: tmp_dir} = _context) do
2124
[
2225
apps: [:elixir],
@@ -548,6 +551,27 @@ defmodule ExDoc.Formatter.HTMLTest do
548551
%{
549552
tmp_dir: tmp_dir
550553
} = context do
554+
generate_docs(
555+
doc_config(context,
556+
before_closing_head_tag: {__MODULE__, :before_closing_head_tag, ["Demo"]},
557+
before_closing_body_tag: {__MODULE__, :before_closing_body_tag, ["Demo"]},
558+
extras: ["test/fixtures/README.md"]
559+
)
560+
)
561+
562+
content = File.read!(tmp_dir <> "/html/api-reference.html")
563+
assert content =~ ~r[<meta name=Demo>\s*</head>]
564+
assert content =~ ~r[<p>Demo</p>\s*</body>]
565+
566+
content = File.read!(tmp_dir <> "/html/readme.html")
567+
assert content =~ ~r[<meta name=Demo>\s*</head>]
568+
assert content =~ ~r[<p>Demo</p>\s*</body>]
569+
end
570+
571+
test "before_closing_*_tags required by the user are placed in the right place using MFA",
572+
%{
573+
tmp_dir: tmp_dir
574+
} = context do
551575
generate_docs(
552576
doc_config(context,
553577
before_closing_head_tag: &before_closing_head_tag/1,

0 commit comments

Comments
 (0)