Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions lib/ex_doc/formatter/html/templates.ex
Original file line number Diff line number Diff line change
Expand Up @@ -232,35 +232,35 @@ defmodule ExDoc.Formatter.HTML.Templates do
end

@doc """
Link secondary headings found with `regex` with in the given `content`.
IDs are prefixed with `prefix`.
Link headings found with `regex` with in the given `content`. IDs are
prefixed with `prefix`.
"""
@h2_regex ~r/<h2.*?>(.*?)<\/h2>/m
@heading_regex ~r/<(h[23]).*?>(.*?)<\/\1>/m
@spec link_headings(String.t, Regex.t, String.t) :: String.t
def link_headings(content, regex \\ @h2_regex, prefix \\ "")
def link_headings(content, regex \\ @heading_regex, prefix \\ "")
def link_headings(nil, _, _), do: nil
def link_headings(content, regex, prefix) do
Regex.replace(regex, content, fn match, title ->
link_heading(match, title, header_to_id(title), prefix)
Regex.replace(regex, content, fn match, tag, title ->
link_heading(match, tag, title, header_to_id(title), prefix)
end)
end

defp link_heading(match, _title, "", _prefix), do: match
defp link_heading(_match, title, id, prefix) do
defp link_heading(match, _tag, _title, "", _prefix), do: match
defp link_heading(_match, tag, title, id, prefix) do
"""
<h2 id="#{prefix}#{id}" class="section-heading">
<#{tag} id="#{prefix}#{id}" class="section-heading">
<a href="##{prefix}#{id}" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a>
#{title}
</h2>
</#{tag}>
"""
end

defp link_moduledoc_headings(content) do
link_headings(content, @h2_regex, "module-")
link_headings(content, @heading_regex, "module-")
end

defp link_detail_headings(content, prefix) do
link_headings(content, @h2_regex, prefix <> "-")
link_headings(content, @heading_regex, prefix <> "-")
end

templates = [
Expand Down
15 changes: 14 additions & 1 deletion test/ex_doc/formatter/html/templates_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,13 @@ defmodule ExDoc.Formatter.HTML.TemplatesTest do

<h2></h2>
""")

assert Templates.link_headings("<h3>Foo</h3>") == """
<h3 id="foo" class="section-heading">
<a href="#foo" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a>
Foo
</h3>
"""
end

test "sidebar items from headers" do
Expand Down Expand Up @@ -163,6 +170,11 @@ defmodule ExDoc.Formatter.HTML.TemplatesTest do
"Example function: Summary should not display trailing puntuation"
end

test "<h3> tags in method `@doc`s are linked" do
content = get_module_page([CompiledWithDocs])
assert content =~ ~r{<h3 id="example_with_h3/0-examples" class="section-heading">.*<a href="#example_with_h3/0-examples" class="hover-link">.*<span class="icon-link" aria-hidden="true"></span>.*</a>.*Examples.*</h3>}ms
end

## LISTING

test "site title text links to homepage_url when set" do
Expand Down Expand Up @@ -210,14 +222,15 @@ defmodule ExDoc.Formatter.HTML.TemplatesTest do
refute content =~ ~r{<small>module</small>}
assert content =~ ~r{moduledoc.*Example.*CompiledWithDocs\.example.*}ms
assert content =~ ~r{<h2 id="module-example-unicode-escaping" class="section-heading">.*<a href="#module-example-unicode-escaping" class="hover-link">.*<span class="icon-link" aria-hidden="true"></span>.*</a>.*Example.*</h2>}ms
assert content =~ ~r{<h3 id="module-example-h3-heading" class="section-heading">.*<a href="#module-example-h3-heading" class="hover-link">.*<span class="icon-link" aria-hidden="true"></span>.*</a>.*Example H3 heading.*</h3>}ms

# Summaries
assert content =~ ~r{example/2.*Some example}ms
assert content =~ ~r{example_without_docs/0.*<section class="docstring">.*</section>}ms
assert content =~ ~r{example_1/0.*<span class="note">\(macro\)</span>}ms

# Source
assert content =~ ~r{<a href="#{source_url()}/blob/master/test/fixtures/compiled_with_docs.ex#L10"[^>]*>\s*<span class="icon-code" aria-hidden="true"></span>\s*<span class="sr-only">View Source</span>\s*</a>}ms
assert content =~ ~r{<a href="#{source_url()}/blob/master/test/fixtures/compiled_with_docs.ex#L14"[^>]*>\s*<span class="icon-code" aria-hidden="true"></span>\s*<span class="sr-only">View Source</span>\s*</a>}ms

# Functions
assert content =~ ~s{<div class="detail" id="example/2">}
Expand Down
6 changes: 3 additions & 3 deletions test/ex_doc/formatter/html_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,15 @@ defmodule ExDoc.Formatter.HTMLTest do
for scheme <- ["http", "https"] do
generate_docs doc_config(source_url: "#{scheme}://github.com/elixir-lang/ex_doc", source_root: File.cwd!)
content = File.read!(file_path)
assert content =~ "https://github.com/elixir-lang/ex_doc/blob/master/test/fixtures/compiled_with_docs.ex#L13"
assert content =~ "https://github.com/elixir-lang/ex_doc/blob/master/test/fixtures/compiled_with_docs.ex#L14"

generate_docs doc_config(source_url: "#{scheme}://gitlab.com/elixir-lang/ex_doc", source_root: File.cwd!)
content = File.read!(file_path)
assert content =~ "https://gitlab.com/elixir-lang/ex_doc/blob/master/test/fixtures/compiled_with_docs.ex#L13"
assert content =~ "https://gitlab.com/elixir-lang/ex_doc/blob/master/test/fixtures/compiled_with_docs.ex#L14"

generate_docs doc_config(source_url: "#{scheme}://bitbucket.org/elixir-lang/ex_doc", source_root: File.cwd!)
content = File.read!(file_path)
assert content =~ "https://bitbucket.org/elixir-lang/ex_doc/src/master/test/fixtures/compiled_with_docs.ex#cl-13"
assert content =~ "https://bitbucket.org/elixir-lang/ex_doc/src/master/test/fixtures/compiled_with_docs.ex#cl-14"

generate_docs doc_config(source_url: "#{scheme}://example.com/elixir-lang/ex_doc", source_root: File.cwd!)
content = File.read!(file_path)
Expand Down
6 changes: 3 additions & 3 deletions test/ex_doc/retriever_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ defmodule ExDoc.RetrieverTest do

test "docs_from_files returns the moduledoc info" do
[module_node] = docs_from_files ["CompiledWithDocs"]
assert module_node.doc == "moduledoc\n\n\#\# Example ☃ Unicode > escaping\n CompiledWithDocs.example\n"
assert module_node.doc == "moduledoc\n\n\#\# Example ☃ Unicode > escaping\n CompiledWithDocs.example\n\n### Example H3 heading\n\nexample\n"
end

test "docs_from_files returns nil if there's no moduledoc info" do
Expand All @@ -56,7 +56,7 @@ defmodule ExDoc.RetrieverTest do

test "docs_from_files returns the doc info for each module function" do
[module_node] = docs_from_files ["CompiledWithDocs"]
[struct, example, example_1, example_without_docs] = module_node.docs
[struct, example, example_1, _example_with_h3, example_without_docs] = module_node.docs

assert struct.id == "__struct__/0"
assert struct.doc == "Some struct"
Expand All @@ -74,7 +74,7 @@ defmodule ExDoc.RetrieverTest do
assert example_1.type == :defmacro
assert example_1.defaults == []

assert example_without_docs.source_url == "http://example.com/test/fixtures/compiled_with_docs.ex\#L18"
assert example_without_docs.source_url == "http://example.com/test/fixtures/compiled_with_docs.ex\#L29"
assert example_without_docs.doc == nil
assert example_without_docs.defaults == []
end
Expand Down
11 changes: 11 additions & 0 deletions test/fixtures/compiled_with_docs.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ defmodule CompiledWithDocs do

## Example ☃ Unicode > escaping
CompiledWithDocs.example

### Example H3 heading

example
"""

@doc "Some struct"
Expand All @@ -15,6 +19,13 @@ defmodule CompiledWithDocs do
@doc "Another example"
defmacro example_1, do: 1

@doc """
Does example action.

### Examples
"""
def example_with_h3, do: 1

def example_without_docs, do: nil

defmodule Nested do
Expand Down