Skip to content

Commit ce39e21

Browse files
committed
Merge pull request #217 from milmazz/pretty_code_blocks
Handle code blocks with and without language spec
2 parents 18d9b9c + 9dd34d6 commit ce39e21

File tree

7 files changed

+57
-13
lines changed

7 files changed

+57
-13
lines changed

lib/ex_doc/formatter/html.ex

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,17 @@ defmodule ExDoc.Formatter.HTML do
7575
end
7676

7777
@doc false
78-
# Helper to handle plain code blocks (```...```) without
78+
# Helper to handle plain code blocks (```...```) with and without
7979
# language specification and indentation code blocks
8080
def pretty_codeblocks(bin) do
81-
Regex.replace(~r/<pre><code\s*(class=\"\")?>/,
82-
bin, "<pre class=\"codeblock\">")
81+
bin = Regex.replace(~r/<pre><code(\s+class=\"\")?>\s*iex&gt;/,
82+
# Add "elixir" class for now, until we have support for
83+
# "iex" in highlight.js
84+
bin, "<pre><code class=\"iex elixir\">iex&gt;")
85+
bin = Regex.replace(~r/<pre><code(\s+class=\"\")?>/,
86+
bin, "<pre><code class=\"elixir\">")
87+
88+
bin
8389
end
8490

8591
@doc false

lib/ex_doc/markdown.ex

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,11 @@ defmodule ExDoc.Markdown do
77

88
@markdown_processor_key :markdown_processor
99

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

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

18-
text = Regex.replace(~r/<pre><code(\s+class=\"\")?>/,
19-
text, "<pre><code class=\"elixir\">")
2015
text
2116
end
2217

lib/ex_doc/markdown/hoedown.ex

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,17 @@ defmodule ExDoc.Markdown.Hoedown do
1616
autolink: Keyword.get(opts, :autolink, true),
1717
fenced_code: Keyword.get(opts, :fenced_code, true),
1818
tables: Keyword.get(opts, :tables, true))
19+
|> pretty_codeblocks
20+
end
21+
22+
@doc false
23+
# Helper to handle fenced code blocks (```...```) with
24+
# language specification
25+
defp pretty_codeblocks(bin) do
26+
# Hoedown parser puts the prefix "language-" as part of the class value
27+
bin = Regex.replace(~r/<pre><code\s+class=\"language-([^\"]+)\">/,
28+
bin, "<pre><code class=\"\\1\">")
29+
30+
bin
1931
end
2032
end

lib/ex_doc/markdown/pandoc.ex

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ defmodule ExDoc.Markdown.Pandoc do
1515
|> text_to_file()
1616
|> open_port(opts)
1717
|> process_port()
18+
|> pretty_codeblocks()
1819
end
1920

2021
defp text_to_file(text) do
@@ -53,4 +54,16 @@ defmodule ExDoc.Markdown.Pandoc do
5354
{status, List.to_string(data)}
5455
end
5556
end
57+
58+
@doc false
59+
# Helper to handle fenced code blocks (```...```) with
60+
# language specification
61+
defp pretty_codeblocks(bin) do
62+
# Pandoc parser puts the class attribute inside the `pre` tag
63+
# Move the class attribute to the code element to keep consistency.
64+
bin = Regex.replace(~r/<pre\s+class=\"([^\"]+)\"><code>/,
65+
bin, "<pre><code class=\"\\1\">")
66+
67+
bin
68+
end
5669
end

test/ex_doc/formatter/html_test.exs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,10 +92,16 @@ defmodule ExDoc.Formatter.HTMLTest do
9292
test "make markdown codeblocks pretty" do
9393
with_empty_class = "<pre><code class=\"\">mix run --no-halt path/to/file.exs"
9494
without_class = "<pre><code>mix run --no-halt path/to/file.exs"
95+
iex_detected_with_empty_class = "<pre><code class=\"\">iex&gt; max(4, 5)"
96+
iex_detected_without_class = "<pre><code>iex&gt; max(4, 5)"
9597

9698
assert HTML.pretty_codeblocks(with_empty_class) ==
97-
"<pre class=\"codeblock\">mix run --no-halt path/to/file.exs"
99+
"<pre><code class=\"elixir\">mix run --no-halt path/to/file.exs"
98100
assert HTML.pretty_codeblocks(without_class) ==
99-
"<pre class=\"codeblock\">mix run --no-halt path/to/file.exs"
101+
"<pre><code class=\"elixir\">mix run --no-halt path/to/file.exs"
102+
assert HTML.pretty_codeblocks(iex_detected_with_empty_class) ==
103+
"<pre><code class=\"iex elixir\">iex&gt; max(4, 5)"
104+
assert HTML.pretty_codeblocks(iex_detected_without_class) ==
105+
"<pre><code class=\"iex elixir\">iex&gt; max(4, 5)"
100106
end
101107
end

test/ex_doc/markdown/hoedown_test.exs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,10 @@ defmodule ExDoc.Markdown.HoedownTest do
2323
test "to_html handles empty input" do
2424
assert Markdown.to_html("") == ""
2525
end
26+
27+
test "pretty Markdown fenced code blocks for Hoedown" do
28+
hoedown_with_language_specified = "```elixir\nmix run --no-halt path/to/file.exs\n```"
29+
expected = "<pre><code class=\"elixir\">mix run --no-halt path/to/file.exs\n</code></pre>\n"
30+
assert Markdown.to_html(hoedown_with_language_specified) == expected
31+
end
2632
end

test/ex_doc/markdown/pandoc_test.exs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,10 @@ defmodule MarkdownTest.PandocTest do
3030
test "to_html converts to rst" do
3131
assert Markdown.to_html("`hello`", format: "rst") == "``hello``\n"
3232
end
33+
34+
test "pretty Markdown fenced code blocks for Pandoc" do
35+
pandoc_with_language_specified = "```elixir\nmix run --no-halt path/to/file.exs\n```"
36+
expected = "<pre><code class=\"elixir\">mix run --no-halt path/to/file.exs</code></pre>\n"
37+
assert Markdown.to_html(pandoc_with_language_specified) == expected
38+
end
3339
end

0 commit comments

Comments
 (0)