EasterPeanut
Nice way to check if iodata is an HTML link?
In a Phoenix template we are trying to check if a Phoenix.HTML.Safe contains iodata that represents an HTML link. Based on whether it’s a link, we want to add a certain class to an element.
We want to check / pattern match on the given input and return true when all the following conditions are met:
- The input is an “a” tag.
- The input is only one node / tag.
- The input can have surrounding whitespace.
Now, to check if the given input is a link, we had the following code:
defp link?({:safe, [60, "a" | _]}), do: true
defp link?({:safe, [" " <> _, [60, "a" | _] | _]}), do: true
defp link?(_), do: false
Example what it should do:
{:safe,
[
" ",
[60, "a", [[32, "href", 61, 34, "/", 34]], 62, "this is a link", 60, 47, "a", 62],
" "
]
}
|> link?()
true
That seemed dirty so we figured it might be better to convert the input by using safe_to_string/1, escape it, and then pattern match or regex on the result.
That still feels tricky, so we now decided to use Floki to do the job, as it looks like a good way to go. However, we are curious as to the alternatives. So, are there any other (maybe simpler) options to achieve this?
Marked As Solved
dimitarvp
Floki is pretty good but it really depends on what kind of HTML input you are dealing with. Meeseeks works better with malformed HTML soups but it has a Rust compiler dependency (which turned out to be a non-issue even on Windows; Rust’s tooling is really nimble).
I’d say though, sanitize your HTML input heavily + use Floki. Do not concern yourself with parsing performance unless you have to parse megabytes of HTML every few seconds.
Also Liked
chrismccord
It would be much easier and faster to implement your own link function which adds the class. This wouldn’t catch hard-coded anchor tags, but if it ticks all the requirement boxes you’re looking at a few minutes of work.
OvermindDL1
Parsing out the iodata/string definitely seems like the wrong step to do this on to me. Why not just have your template functions return out a tuple structure or so encoding your data then just run a final pass over it before encoding it into eex template format? Personally I have a module that defines just about everything used in my templates from various containers to lots of link types to form handlers and a whole lot more. A lot of building up in that is very just tuple structures and it’s been very easy to use and change. ![]()
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance









