zf

zenflows testing
git clone https://s.sonu.ch/~srfsh/zf.git
Log | Files | Refs | Submodules | README | LICENSE

pure_link_helpers.ex (2532B)


      1 defmodule EarmarkParser.Helpers.PureLinkHelpers do
      2   @moduledoc false
      3 
      4   import EarmarkParser.Helpers.AstHelpers, only: [render_link: 2]
      5 
      6   @pure_link_rgx ~r{
      7     \A
      8     (\s*)
      9     (
     10       (?:https?://|www\.)
     11       [^\s<>]*
     12       [^\s<>?!.,:*_~]
     13     )
     14   }ux
     15 
     16   def convert_pure_link(src) do
     17     case Regex.run(@pure_link_rgx, src) do
     18       [_match, spaces, link_text] ->
     19         if String.ends_with?(link_text, ")") do
     20           remove_trailing_closing_parens(spaces, link_text)
     21         else
     22           make_result(spaces, link_text)
     23         end
     24 
     25       _ ->
     26         nil
     27     end
     28   end
     29 
     30   @split_at_ending_parens ~r{ (.*?) (\)*) \z}x
     31   defp remove_trailing_closing_parens(leading_spaces, link_text) do
     32     [_, link_text, trailing_parens] = Regex.run(@split_at_ending_parens, link_text)
     33     trailing_paren_count = String.length(trailing_parens)
     34 
     35     # try to balance parens from the rhs
     36     unbalanced_count = balance_parens(String.reverse(link_text), trailing_paren_count)
     37     balanced_parens = String.slice(trailing_parens, 0, trailing_paren_count - unbalanced_count)
     38 
     39     make_result(leading_spaces, link_text <> balanced_parens)
     40   end
     41 
     42   defp make_result(leading_spaces, link_text) do
     43     link =
     44       if String.starts_with?(link_text, "www.") do
     45         render_link("http://" <> link_text, link_text)
     46       else
     47         render_link(link_text, link_text)
     48       end
     49 
     50     if leading_spaces == "" do
     51       {link, String.length(link_text)}
     52     else
     53       {[leading_spaces, link], String.length(leading_spaces) + String.length(link_text)}
     54     end
     55   end
     56 
     57   # balance parens and return unbalanced *trailing* paren count
     58   defp balance_parens(reverse_text, trailing_count, non_trailing_count \\ 0)
     59 
     60   defp balance_parens(<<>>, trailing_paren_count, _non_trailing_count), do: trailing_paren_count
     61 
     62   defp balance_parens(_reverse_text, 0, _non_trailing_count), do: 0
     63 
     64   defp balance_parens(")" <> rest, trailing_paren_count, non_trailing_count) do
     65     balance_parens(rest, trailing_paren_count, non_trailing_count + 1)
     66   end
     67 
     68   defp balance_parens("(" <> rest, trailing_paren_count, non_trailing_count) do
     69     # non-trailing paren must be balanced before trailing paren
     70     if non_trailing_count > 0 do
     71       balance_parens(rest, trailing_paren_count, non_trailing_count - 1)
     72     else
     73       balance_parens(rest, trailing_paren_count - 1, non_trailing_count)
     74     end
     75   end
     76 
     77   defp balance_parens(<<_::utf8,rest::binary>>, trailing_paren_count, non_trailing_count) do
     78     balance_parens(rest, trailing_paren_count, non_trailing_count)
     79   end
     80 end