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
12 changes: 9 additions & 3 deletions lib/ex_doc/formatter/html.ex
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,17 @@ defmodule ExDoc.Formatter.HTML do
end

@doc false
# Helper to handle plain code blocks (```...```) without
# Helper to handle plain code blocks (```...```) with and without
# language specification and indentation code blocks
def pretty_codeblocks(bin) do
Regex.replace(~r/<pre><code\s*(class=\"\")?>/,
bin, "<pre class=\"codeblock\">")
bin = Regex.replace(~r/<pre><code(\s+class=\"\")?>\s*iex&gt;/,
# Add "elixir" class for now, until we have support for
# "iex" in highlight.js
bin, "<pre><code class=\"iex elixir\">iex&gt;")
bin = Regex.replace(~r/<pre><code(\s+class=\"\")?>/,
bin, "<pre><code class=\"elixir\">")

bin
end

@doc false
Expand Down
11 changes: 3 additions & 8 deletions lib/ex_doc/markdown.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,11 @@ defmodule ExDoc.Markdown do

@markdown_processor_key :markdown_processor

def to_html(text) when is_binary(text) do
text = get_markdown_processor().to_html(text)
import ExDoc.Formatter.HTML, only: [pretty_codeblocks: 1]

# handle code blocks (```...```) with language specification
text = Regex.replace(~r/<pre><code\s*(class=\"\")?>\s*iex&gt;/,
#add "elixir" class for now, until we have support for iex in highlight.js
text, "<pre><code class=\"iex elixir\">iex&gt;")
def to_html(text) when is_binary(text) do
text = get_markdown_processor().to_html(text) |> pretty_codeblocks

text = Regex.replace(~r/<pre><code(\s+class=\"\")?>/,
text, "<pre><code class=\"elixir\">")
text
end

Expand Down
12 changes: 12 additions & 0 deletions lib/ex_doc/markdown/hoedown.ex
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,17 @@ defmodule ExDoc.Markdown.Hoedown do
autolink: Keyword.get(opts, :autolink, true),
fenced_code: Keyword.get(opts, :fenced_code, true),
tables: Keyword.get(opts, :tables, true))
|> pretty_codeblocks
end

@doc false
# Helper to handle fenced code blocks (```...```) with
# language specification
defp pretty_codeblocks(bin) do
# Hoedown parser puts the prefix "language-" as part of the class value
bin = Regex.replace(~r/<pre><code\s+class=\"language-([^\"]+)\">/,
bin, "<pre><code class=\"\\1\">")

bin
end
end
13 changes: 13 additions & 0 deletions lib/ex_doc/markdown/pandoc.ex
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ defmodule ExDoc.Markdown.Pandoc do
|> text_to_file()
|> open_port(opts)
|> process_port()
|> pretty_codeblocks()
end

defp text_to_file(text) do
Expand Down Expand Up @@ -53,4 +54,16 @@ defmodule ExDoc.Markdown.Pandoc do
{status, List.to_string(data)}
end
end

@doc false
# Helper to handle fenced code blocks (```...```) with
# language specification
defp pretty_codeblocks(bin) do
# Pandoc parser puts the class attribute inside the `pre` tag
# Move the class attribute to the code element to keep consistency.
bin = Regex.replace(~r/<pre\s+class=\"([^\"]+)\"><code>/,
bin, "<pre><code class=\"\\1\">")

bin
end
end
10 changes: 8 additions & 2 deletions test/ex_doc/formatter/html_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,16 @@ defmodule ExDoc.Formatter.HTMLTest do
test "make markdown codeblocks pretty" do
with_empty_class = "<pre><code class=\"\">mix run --no-halt path/to/file.exs"
without_class = "<pre><code>mix run --no-halt path/to/file.exs"
iex_detected_with_empty_class = "<pre><code class=\"\">iex&gt; max(4, 5)"
iex_detected_without_class = "<pre><code>iex&gt; max(4, 5)"

assert HTML.pretty_codeblocks(with_empty_class) ==
"<pre class=\"codeblock\">mix run --no-halt path/to/file.exs"
"<pre><code class=\"elixir\">mix run --no-halt path/to/file.exs"
assert HTML.pretty_codeblocks(without_class) ==
"<pre class=\"codeblock\">mix run --no-halt path/to/file.exs"
"<pre><code class=\"elixir\">mix run --no-halt path/to/file.exs"
assert HTML.pretty_codeblocks(iex_detected_with_empty_class) ==
"<pre><code class=\"iex elixir\">iex&gt; max(4, 5)"
assert HTML.pretty_codeblocks(iex_detected_without_class) ==
"<pre><code class=\"iex elixir\">iex&gt; max(4, 5)"
end
end
6 changes: 6 additions & 0 deletions test/ex_doc/markdown/hoedown_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,10 @@ defmodule ExDoc.Markdown.HoedownTest do
test "to_html handles empty input" do
assert Markdown.to_html("") == ""
end

test "pretty Markdown fenced code blocks for Hoedown" do
hoedown_with_language_specified = "```elixir\nmix run --no-halt path/to/file.exs\n```"
expected = "<pre><code class=\"elixir\">mix run --no-halt path/to/file.exs\n</code></pre>\n"
assert Markdown.to_html(hoedown_with_language_specified) == expected
end
end
6 changes: 6 additions & 0 deletions test/ex_doc/markdown/pandoc_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,10 @@ defmodule MarkdownTest.PandocTest do
test "to_html converts to rst" do
assert Markdown.to_html("`hello`", format: "rst") == "``hello``\n"
end

test "pretty Markdown fenced code blocks for Pandoc" do
pandoc_with_language_specified = "```elixir\nmix run --no-halt path/to/file.exs\n```"
expected = "<pre><code class=\"elixir\">mix run --no-halt path/to/file.exs</code></pre>\n"
assert Markdown.to_html(pandoc_with_language_specified) == expected
end
end