Skip to content

Commit 28ff9a3

Browse files
authored
Remove "Specs" heading and render full typespecs (#1455)
1 parent 6ba40a7 commit 28ff9a3

File tree

11 files changed

+45
-8
lines changed

11 files changed

+45
-8
lines changed

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,8 @@ The easiest way to test changes to ExDoc is to locally rebuild the app and its o
277277
4. Run `mix lint` to check if the Elixir and JavaScript files are properly formatted.
278278
You can run `mix fix` to let the JavaScript linter and Elixir formatter fix the code automatically before submitting your pull request
279279

280+
Note that Node 17 or later is not supported due to [API breaking changes with Webpack](https://github.com/webpack/webpack/issues/14532).
281+
280282
## License
281283

282284
ExDoc source code is released under [Apache 2 License](LICENSE). The generated contents, however, are under different licenses based on projects used to help render HTML, including CSS, JS, and other assets.

assets/less/content/functions.less

+4-2
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,6 @@
5858
}
5959

6060
.specs {
61-
padding: 1em;
62-
6361
pre {
6462
font-family: @monoFontFamily;
6563
font-size: 0.9em;
@@ -69,6 +67,10 @@
6967
margin: 0;
7068
padding: 0;
7169
}
70+
71+
.attribute {
72+
color: @mediumGray;
73+
}
7274
}
7375

7476
.docstring {

assets/less/night/content/functions.less

+4
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919
color: @nightTextBody;
2020
}
2121

22+
.specs .attribute {
23+
color: @nightMediumGray;
24+
}
25+
2226
div.deprecated {
2327
background-color: @nightDeprecated;
2428
}

lib/ex_doc/formatter/html/templates.ex

+8-1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@ defmodule ExDoc.Formatter.HTML.Templates do
3131
nil
3232
end
3333

34+
@doc """
35+
Format the attribute type used to define the spec of the given `node`.
36+
"""
37+
def format_spec_attribute(module, node) do
38+
module.language.format_spec_attribute(node)
39+
end
40+
3441
@doc """
3542
Get defaults clauses.
3643
"""
@@ -297,7 +304,7 @@ defmodule ExDoc.Formatter.HTML.Templates do
297304
end
298305

299306
templates = [
300-
detail_template: [:node, :_module],
307+
detail_template: [:node, :module],
301308
footer_template: [:config, :node],
302309
head_template: [:config, :page],
303310
module_template: [:config, :module, :summary, :nodes_map],

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

+1-2
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,9 @@
2626

2727
<section class="docstring">
2828
<%= if specs = get_specs(node) do %>
29-
<h2>Specs</h2>
3029
<div class="specs">
3130
<%= for spec <- specs do %>
32-
<pre translate="no"><%= spec %></pre>
31+
<pre translate="no"><span class="attribute"><%= format_spec_attribute(module, node) %></span> <%= spec %></pre>
3332
<% end %>
3433
</div>
3534
<% end %>

lib/ex_doc/language.ex

+5
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,11 @@ defmodule ExDoc.Language do
131131
opts: keyword()
132132
}
133133

134+
@doc """
135+
Return an attribute in the canonical representation.
136+
"""
137+
@callback format_spec_attribute(%ExDoc.FunctionNode{} | %ExDoc.TypeNode{}) :: String.t()
138+
134139
def get(:elixir, _module), do: {:ok, ExDoc.Language.Elixir}
135140
def get(:erlang, _module), do: {:ok, ExDoc.Language.Erlang}
136141

lib/ex_doc/language/elixir.ex

+6
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,12 @@ defmodule ExDoc.Language.Elixir do
202202
}
203203
end
204204

205+
@impl true
206+
def format_spec_attribute(%ExDoc.TypeNode{type: type}), do: "@#{type}"
207+
def format_spec_attribute(%ExDoc.FunctionNode{type: :callback}), do: "@callback"
208+
def format_spec_attribute(%ExDoc.FunctionNode{type: :macrocallback}), do: "@macrocallback"
209+
def format_spec_attribute(%ExDoc.FunctionNode{}), do: "@spec"
210+
205211
## Module Helpers
206212

207213
defp nesting_info(title, prefixes) do

lib/ex_doc/language/erlang.ex

+5
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,11 @@ defmodule ExDoc.Language.Erlang do
163163
}
164164
end
165165

166+
@impl true
167+
def format_spec_attribute(%ExDoc.TypeNode{type: type}), do: "-#{type}"
168+
def format_spec_attribute(%ExDoc.FunctionNode{type: :callback}), do: "-callback"
169+
def format_spec_attribute(%ExDoc.FunctionNode{}), do: "-spec"
170+
166171
## Shared between Erlang & Elixir
167172

168173
@doc false

test/ex_doc/formatter/html/erlang_test.exs

+4-2
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,11 @@ defmodule ExDoc.Formatter.HTML.ErlangTest do
2424

2525
doc = generate_docs(c)
2626

27-
assert [_] = Floki.find(doc, "pre:fl-contains('foo(atom()) -> atom().')")
27+
assert "-spec foo(atom()) -> atom()." =
28+
doc |> Floki.find("pre:fl-contains('foo(atom())')") |> Floki.text()
2829

29-
assert [_] = Floki.find(doc, "pre:fl-contains('t() :: atom().')")
30+
assert "-type t() :: atom()." =
31+
doc |> Floki.find("pre:fl-contains('t() :: atom().')") |> Floki.text()
3032
end
3133

3234
defp generate_docs(c) do

test/ex_doc/formatter/html/templates_test.exs

+5-1
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@ defmodule ExDoc.Formatter.HTML.TemplatesTest do
418418
integer = ~s[<a href="https://hexdocs.pm/elixir/typespecs.html#basic-types">integer</a>()]
419419

420420
public_html =
421-
~S[public(t) :: {t, ] <>
421+
~S[<span class="attribute">@type</span> public(t) :: {t, ] <>
422422
~s[<a href="https://hexdocs.pm/elixir/String.html#t:t/0">String.t</a>(), ] <>
423423
~S[<a href="TypesAndSpecs.Sub.html#t:t/0">TypesAndSpecs.Sub.t</a>(), ] <>
424424
~S[<a href="#t:opaque/0">opaque</a>(), :ok | :error}]
@@ -428,13 +428,15 @@ defmodule ExDoc.Formatter.HTML.TemplatesTest do
428428
assert content =~ public_html
429429
refute content =~ ~s[<strong>private\(t\)]
430430
assert content =~ ~s[A public type]
431+
assert content =~ ~s[<span class="attribute">@spec</span> add(]
431432
assert content =~ ~s[add(#{integer}, <a href="#t:opaque/0">opaque</a>()) :: #{integer}]
432433
refute content =~ ~s[minus(#{integer}, #{integer}) :: #{integer}]
433434

434435
assert content =~
435436
~s[Basic type: <a href=\"https://hexdocs.pm/elixir/typespecs.html#basic-types\"><code class=\"inline\">atom/0</code></a>.]
436437

437438
assert content =~ ~r{opaque/0.*<span class="note">\(opaque\)</span>}ms
439+
assert content =~ ~r{<span class="attribute">@opaque</span> opaque}
438440
end
439441

440442
test "outputs summaries" do
@@ -482,6 +484,7 @@ defmodule ExDoc.Formatter.HTML.TemplatesTest do
482484

483485
assert content =~ ~r{Callbacks}
484486
assert content =~ ~r{<section class="detail" id="c:hello/1">}
487+
assert content =~ ~s[<span class="attribute">@callback</span> hello(]
485488
assert content =~ ~s[hello(%URI{})]
486489
assert content =~ ~s[greet(arg1)]
487490

@@ -492,6 +495,7 @@ defmodule ExDoc.Formatter.HTML.TemplatesTest do
492495

493496
assert content =~ ~r{Callbacks}
494497
assert content =~ ~r{<section class="detail" id="c:bye/1">}
498+
assert content =~ ~s[<span class="attribute">@macrocallback</span> bye(]
495499
end
496500

497501
## PROTOCOLS

test/ex_doc/retriever/erlang_test.exs

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ defmodule ExDoc.Retriever.ErlangTest do
3333
function_groups: [:Callbacks, :Functions],
3434
group: nil,
3535
id: "mod",
36+
language: ExDoc.Language.Erlang,
3637
module: :mod,
3738
nested_context: nil,
3839
nested_title: nil,

0 commit comments

Comments
 (0)