But I need access to the first matched element, so (aaaM). Partly because I also want to HTML Escape it as well. Ok, I need to use the match in anonymous function…but…sadly.
iex(15)> String.replace("<source>(aaaM)</source>", ~r/<source>(.*)<\/source>/, fn match, code-> "<code><pre>#{match}</pre></code>" end)
warning: variable "code" is unused (if the variable is not meant to be used, prefix it with an underscore)
iex:15
** (FunctionClauseError) no function clause matching in String.replace/4
The following arguments were given to String.replace/4:
# 1
"<source>(aaaM)</source>"
# 2
~r/<source>(.*)<\/source>/
# 3
#Function<43.65746770/2 in :erl_eval.expr/5>
# 4
[]
Attempted function clauses (showing 1 out of 1):
def replace(subject, pattern, replacement, options) when is_binary(subject) and is_binary(replacement) or is_function(replacement, 1) and is_list(options)
(elixir 1.13.1) lib/string.ex:1477: String.replace/4
I’m not sure I follow, I’m now supplying 4 arguments. Even if I parenthesises the multiple arguments for the anonymous function. Anyone point out where I am being a dummy?
OK, that makes sense if the arity is 1. Is there no way to get access to the multiple matched elements in the regex if you use an anonymous function? I would like to HTML Escape the contents of the <source> tag
OK, looks like I got it. I needed Regex.replace rather than String.replace
def standardize_code(body) do
Regex.replace(~r/<source>(.*?)<\/source>/s, body, fn _, code ->
case Phoenix.HTML.html_escape(code) do
{:safe, html} ->
"<code><pre>#{html}</pre></code>"
_ ->
"NOT ITS NOT SAFE"
end
end)
end
Hello, just a note. The function Phoenix.HTML.html_escape does always return {:safe, content} according to the spec. Because if it finds code, that needs to be escaped, it escapes it… That tuple is for phoenix rendering where you put this tuple into template, informing it that the given content is already escaped.
There is also {:raw, content} that tells phoenix that you insist on putting the content into final result as-is.
String.replace with a Regex uses Regex.replace under the hood, but the declaration of String.replace specifically narrows the allowed type of the function. Looks like it’s been that way since the feature was added:
Using Regex.replace directly should do what you want.
** (FunctionClauseError) no function clause matching in :erl_eval."-inside-an-interpreted-fun-"/1
The following arguments were given to :erl_eval."-inside-an-interpreted-fun-"/1:
# 1
"hello"