Packages
earmark_parser
1.4.28
1.4.46
1.4.45
1.4.44
1.4.43
1.4.42
1.4.41
1.4.40
1.4.39
1.4.38
1.4.37
1.4.36
1.4.35
1.4.34
1.4.33
1.4.32
1.4.31
1.4.30
1.4.29
1.4.28
1.4.27
1.4.26
1.4.25
1.4.24
1.4.23
1.4.22
1.4.21
1.4.20
1.4.20-pre
1.4.19
1.4.18
1.4.17
1.4.16
1.4.16-pre2
1.4.16-pre1
1.4.16-pre
1.4.15
1.4.13
1.4.12
1.4.11
1.4.10
1.4.9
1.4.8
AST parser and generator for Markdown
Current section
Files
Jump to
Current section
Files
lib/earmark_parser/helpers/pure_link_helpers.ex
defmodule EarmarkParser.Helpers.PureLinkHelpers do
@moduledoc false
import EarmarkParser.Helpers.AstHelpers, only: [render_link: 2]
@pure_link_rgx ~r{
\A
(\s*)
(
(?:https?://|www\.)
[^\s<>]*
[^\s<>?!.,:*_~]
)
}ux
def convert_pure_link(src) do
case Regex.run(@pure_link_rgx, src) do
[_match, spaces, link_text] ->
if String.ends_with?(link_text, ")") do
remove_trailing_closing_parens(spaces, link_text)
else
make_result(spaces, link_text)
end
_ ->
nil
end
end
@split_at_ending_parens ~r{ (.*?) (\)*) \z}x
defp remove_trailing_closing_parens(leading_spaces, link_text) do
[_, link_text, trailing_parens] = Regex.run(@split_at_ending_parens, link_text)
trailing_paren_count = String.length(trailing_parens)
# try to balance parens from the rhs
unbalanced_count = balance_parens(String.reverse(link_text), trailing_paren_count)
balanced_parens = String.slice(trailing_parens, 0, trailing_paren_count - unbalanced_count)
make_result(leading_spaces, link_text <> balanced_parens)
end
defp make_result(leading_spaces, link_text) do
link =
if String.starts_with?(link_text, "www.") do
render_link("http://" <> link_text, link_text)
else
render_link(link_text, link_text)
end
if leading_spaces == "" do
{link, String.length(link_text)}
else
{[leading_spaces, link], String.length(leading_spaces) + String.length(link_text)}
end
end
# balance parens and return unbalanced *trailing* paren count
defp balance_parens(reverse_text, trailing_count, non_trailing_count \\ 0)
defp balance_parens(<<>>, trailing_paren_count, _non_trailing_count), do: trailing_paren_count
defp balance_parens(_reverse_text, 0, _non_trailing_count), do: 0
defp balance_parens(")" <> rest, trailing_paren_count, non_trailing_count) do
balance_parens(rest, trailing_paren_count, non_trailing_count + 1)
end
defp balance_parens("(" <> rest, trailing_paren_count, non_trailing_count) do
# non-trailing paren must be balanced before trailing paren
if non_trailing_count > 0 do
balance_parens(rest, trailing_paren_count, non_trailing_count - 1)
else
balance_parens(rest, trailing_paren_count - 1, non_trailing_count)
end
end
defp balance_parens(<<_::utf8,rest::binary>>, trailing_paren_count, non_trailing_count) do
balance_parens(rest, trailing_paren_count, non_trailing_count)
end
end