1defmodule Earmark.Helpers do 2 3 @doc """ 4 Expand tabs to multiples of 4 columns 5 """ 6 def expand_tabs(line) do 7 Regex.replace(~r{(.*?)\t}, line, &expander/2) 8 end 9 10 defp expander(_, leader) do 11 extra = 4 - rem(String.length(leader), 4) 12 leader <> pad(extra) 13 end 14 15 @doc """ 16 Remove newlines at end of line 17 """ 18 def remove_line_ending(line) do 19 line |> String.trim_trailing("\n") |> String.trim_trailing("\r") 20 end 21 22 defp pad(1), do: " " 23 defp pad(2), do: " " 24 defp pad(3), do: " " 25 defp pad(4), do: " " 26 27 @doc """ 28 `Regex.replace` with the arguments in the correct order 29 """ 30 31 def replace(text, regex, replacement, options \\ []) do 32 Regex.replace(regex, text, replacement, options) 33 end 34 35 @doc """ 36 Encode URIs to be included in the `<a>` elements. 37 38 Percent-escapes a URI, and after that escapes any 39 `&`, `<`, `>`, `"`, `'`. 40 """ 41 def encode(html) do 42 URI.encode(html) |> escape(true) 43 end 44 45 @doc """ 46 Replace <, >, and quotes with the corresponding entities. If 47 `encode` is true, convert ampersands, too, otherwise only 48 convert non-entity ampersands. 49 """ 50 51 def escape(html, encode \\ false) 52 53 def escape(html, false), do: _escape(Regex.replace(~r{&(?!#?\w+;)}, html, "&")) 54 def escape(html, _), do: _escape(String.replace(html, "&", "&")) 55 56 defp _escape(html) do 57 html 58 |> String.replace("<", "<") 59 |> String.replace(">", ">") 60 |> String.replace("\"", """) 61 |> String.replace("'", "'") 62 end 63 64 65end 66 67# SPDX-License-Identifier: Apache-2.0 68