Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid trailing slash on void elements. #460

Merged
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
20 changes: 10 additions & 10 deletions bench/simple_data_bench.exs
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ defmodule Bench.SimpleDataBench do
Elixir | awesome

never is.



### Adding HTML attributes with the IAL extension
Expand Down Expand Up @@ -260,22 +260,22 @@ defmodule Bench.SimpleDataBench do
Thusly

mypara
<hr />
<hr>

Becomes

<p>mypara</p>
<hr />
<hr>

While

mypara
<hr />
<hr>

will be transformed into

<p>mypara
<hr /></p>
<hr></p>

## Integration

Expand Down Expand Up @@ -355,7 +355,7 @@ defmodule Bench.SimpleDataBench do
- description of the error


`options` can be an `%Earmark.Options{}` structure, or can be passed in as a `Keyword` argument (with legal keys for `%Earmark.Options`
`options` can be an `%Earmark.Options{}` structure, or can be passed in as a `Keyword` argument (with legal keys for `%Earmark.Options`

* `renderer`: ModuleName

Expand Down Expand Up @@ -400,7 +400,7 @@ defmodule Bench.SimpleDataBench do
* `pure_links`: boolean

Pure links of the form `~r{\bhttps?://\S+\b}` are rendered as links from now on.
However, by setting the `pure_links` option to `false` this can be disabled and pre 1.4
However, by setting the `pure_links` option to `false` this can be disabled and pre 1.4
behavior can be used.

<!-- END inserted functiondoc Earmark.as_html/2 -->
Expand All @@ -413,7 +413,7 @@ defmodule Bench.SimpleDataBench do
iex(9)> markdown = "My `code` is **best**"
...(9)> {:ok, ast, []} = Earmark.as_ast(markdown)
...(9)> ast
[{"p", [], ["My ", {"code", [{"class", "inline"}], ["code"]}, " is ", {"strong", [], ["best"]}]}]
[{"p", [], ["My ", {"code", [{"class", "inline"}], ["code"]}, " is ", {"strong", [], ["best"]}]}]

Options are passes like to `as_html`, some do not have an effect though (e.g. `smartypants`) as formatting and escaping is not done
for the AST.
Expand All @@ -430,7 +430,7 @@ defmodule Bench.SimpleDataBench do
We also do return a list for a single node


Floki.parse("<!-- comment -->")
Floki.parse("<!-- comment -->")
{:comment, " comment "}

Earmark.as_ast("<!-- comment -->")
Expand Down Expand Up @@ -497,7 +497,7 @@ defmodule Bench.SimpleDataBench do
bench "00 as_html" do
Earmark.as_html(@readme_md)
end

bench "01 as_ast|>transform" do
{:ok, ast, []} = EarmarkParser.as_ast(@readme_md)
Earmark.Transform.transform(ast)
Expand Down
22 changes: 12 additions & 10 deletions lib/earmark.ex
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
defmodule Earmark do
if Version.compare(System.version, "1.12.0") == :lt do
IO.puts(:stderr, "DEPRECATION WARNING: versions < 1.12.0 of Elixir are not tested anymore and will not be supported in Earmark v1.5")
if Version.compare(System.version(), "1.12.0") == :lt do
IO.puts(
:stderr,
"DEPRECATION WARNING: versions < 1.12.0 of Elixir are not tested anymore and will not be supported in Earmark v1.5"
)
end


@type ast_meta :: map()
@type ast_tag :: binary()
@type ast_attribute_name :: binary()
Expand Down Expand Up @@ -103,16 +105,16 @@ defmodule Earmark do

If set HTML will be properly escaped

iex(3)> markdown = "Hello<br />World"
iex(3)> markdown = "Hello<br>World"
...(3)> Earmark.as_html!(markdown)
"<p>\\nHello&lt;br /&gt;World</p>\\n"
"<p>\\nHello&lt;br&gt;World</p>\\n"

However disabling `escape:` gives you maximum control of the created document, which in some
cases (e.g. inside tables) might even be necessary

iex(4)> markdown = "Hello<br />World"
iex(4)> markdown = "Hello<br>World"
...(4)> Earmark.as_html!(markdown, escape: false)
"<p>\\nHello<br />World</p>\\n"
"<p>\\nHello<br>World</p>\\n"

#### `inner_html:` defaulting to `false`

Expand All @@ -127,9 +129,9 @@ defmodule Earmark do
By means of the `inner_html` option the disturbing paragraph can be removed from `as_html!`'s
output

iex(5)> markdown = "Hello<br />World"
iex(5)> markdown = "Hello<br>World"
...(5)> Earmark.as_html!(markdown, escape: false, inner_html: true)
"Hello<br />World\\n"
"Hello<br>World\\n"

**N.B.** that this applies only to top level paragraphs, as can be seen here

Expand Down Expand Up @@ -262,7 +264,6 @@ defmodule Earmark do
do: to_string(version)
end


defp _as_ast(lines, options)

defp _as_ast(lines, %Options{} = options) do
Expand All @@ -273,4 +274,5 @@ defmodule Earmark do
Proxy.as_ast(lines, options)
end
end

# SPDX-License-Identifier: Apache-2.0
7 changes: 3 additions & 4 deletions lib/earmark/cli.ex
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
defmodule Earmark.Cli do


@moduledoc """
The Earmark CLI

Expand All @@ -22,12 +20,12 @@ defmodule Earmark.Cli do
or raise an error otherwise

iex(0)> run!(["test/fixtures/short1.md"])
"<h1>\nHeadline1</h1>\n<hr class=\"thin\" />\n<h2>\nHeadline2</h2>\n"
"<h1>\nHeadline1</h1>\n<hr class=\"thin\">\n<h2>\nHeadline2</h2>\n"
"""
def run!(argv) do
case Earmark.Cli.Implementation.run(argv) do
{:stdio, output} -> output
{_, error} -> raise Earmark.Error, error
{_, error} -> raise Earmark.Error, error
end
end

Expand All @@ -36,4 +34,5 @@ defmodule Earmark.Cli do
if device == :stderr, do: exit(1)
end
end

# SPDX-License-Identifier: Apache-2.0
49 changes: 29 additions & 20 deletions lib/earmark/cli/implementation.ex
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
defmodule Earmark.Cli.Implementation do


alias Earmark.Options
alias Earmark.SysInterface

Expand All @@ -23,7 +21,7 @@ defmodule Earmark.Cli.Implementation do

iex(1)> {:stdio, html} = run(["test/fixtures/short1.md"])
...(1)> html
"<h1>\nHeadline1</h1>\n<hr class=\"thin\" />\n<h2>\nHeadline2</h2>\n"
"<h1>\nHeadline1</h1>\n<hr class=\"thin\">\n<h2>\nHeadline2</h2>\n"

Example: Using EEx

Expand Down Expand Up @@ -97,17 +95,18 @@ defmodule Earmark.Cli.Implementation do
version: :boolean,
wikiklinks: :boolean
]

aliases = [
h: :help,
v: :version
]

case OptionParser.parse(argv, strict: switches, aliases: aliases) do
{ _, _, [_|_]=errors} -> errors
{ [ {:help, true} ], _, _ } -> :help
{ [ {:version, true} ], _, _ } -> :version
{ options, [ file ], _ } -> Map.put(Options.make_options!(options), :file, file)
{ options, [ ], _ } -> Options.make_options!(options)
{_, _, [_ | _] = errors} -> errors
{[{:help, true}], _, _} -> :help
{[{:version, true}], _, _} -> :version
{options, [file], _} -> Map.put(Options.make_options!(options), :file, file)
{options, [], _} -> Options.make_options!(options)
end
end

Expand All @@ -116,53 +115,63 @@ defmodule Earmark.Cli.Implementation do
end

defp _maybe_to_html!(output, %{file: nil}), do: Earmark.Internal.as_html!(output)

defp _maybe_to_html!(output, options) do
filename = options.file

case Path.extname(Path.basename(filename, Path.extname(filename))) do
".html" -> output
_ -> Earmark.Internal.as_html!(output, options)
_ -> Earmark.Internal.as_html!(output, options)
end
end

defp _process(flag_errors_or_options)

defp _process(errors) when is_list(errors) do
{:stderr, _format_errors(errors)}
end

defp _process(:help) do
{:stderr, IO.chardata_to_string([@args, _option_related_help()])}
end

defp _process(:version) do
{:stdio, Earmark.version}
{:stdio, Earmark.version()}
end
defp _process(%Options{file: nil}=options), do: _process_input({:ok, :stdio}, options)
defp _process(%Options{file: filename}=options) do

defp _process(%Options{file: nil} = options), do: _process_input({:ok, :stdio}, options)

defp _process(%Options{file: filename} = options) do
{device_tuple, options_} = _open_file(filename, options)
_process_input(device_tuple, options_)
end

defp _process_input(device_tuple, options)

defp _process_input({:error, reason}, options) do
{:stderr, "Cannot open #{options.file}, reason: #{reason}"}
end
defp _process_input({:ok, io_device}, %Options{eex: true}=options) do
input = SysInterface.readlines(io_device) |> Enum.to_list |> IO.chardata_to_string

defp _process_input({:ok, io_device}, %Options{eex: true} = options) do
input = SysInterface.readlines(io_device) |> Enum.to_list() |> IO.chardata_to_string()
output = EEx.eval_string(input, include: &Earmark.Internal.include(&1, options))
output_ = _maybe_to_html!(output, options)
{:stdio, output_}
end

defp _process_input({:ok, io_device}, options) do
content =
io_device
|> SysInterface.readlines
|> Enum.to_list
io_device
|> SysInterface.readlines()
|> Enum.to_list()

{:stdio, Earmark.as_html!(content, options)}
end

defp _open_file(filename, options) do
case Path.extname(filename) do
".eex" -> {File.open(filename, [:utf8]), %{options|eex: true}}
_ -> {File.open(filename, [:utf8]), options}
".eex" -> {File.open(filename, [:utf8]), %{options | eex: true}}
_ -> {File.open(filename, [:utf8]), options}
end
end

Expand All @@ -180,6 +189,6 @@ defmodule Earmark.Cli.Implementation do
"#{option}"
|> String.replace("_", "-")
end

end

# SPDX-License-Identifier: Apache-2.0
Loading