Hello guys, I am not sure if this question has been asked before, but I did a search and did not find it.
I am looking to trim the html rendered from a ~F"“” sigil.
defp produce_trimmed_html(assigns) do
html = ~F"""
<somecomponent />
"""
String.trim(html)
end
Here, String.trim is not working because the html is not a string but binary. How can I do this?
Can you show an example of what binary are you getting so we can see why String.trim
doesn’t work on it? All other things being normal, it should work on a binary as well.
I am not able to retrieve the binary data.
Even a simple html causes an error.
defp some_method(assigns) do
item = ~F"""
<div></div>
"""
String.trim(item)
end
VSCode reports this:
The function call will not succeed.
String.trim(
_item :: %Phoenix.LiveView.Rendered{
:dynamic => (_ -> []),
:fingerprint => 264_197_832_235_070_763_522_609_757_631_039_213_058,
:root => true,
:static => [<<_::96>>, ...]
}
)
will never return since the success typing is:
(binary()) :: binary()
The Surface error I am getting on the console is this:
no function clause matching in String.trim/1
(elixir 1.13.4) lib/string.ex:1241: String.trim(%Phoenix.LiveView.Rendered{dynamic: #Function<0.132818971/1 in MoonWeb.Pages.IconsPage.get_import_text_by_attribute/2>, fingerprint: 264197832235070763522609757631039213058, root: true, static: ["<div></div>\n"]})
It tells me that item is not a string but binary()
As the error message tells you sigil_F doesn’t return a string. It returns a struct, which is required to optimize templates in LV usage (split dynamic vs. static parts, …). You simply cannot run String.trim
on that.
Hi @alexisdevtailor!
You can achieve that with something like:
~F"""
<somecomponent />
"""
|> Phoenix.HTML.Safe.to_iodata()
|> IO.iodata_to_binary()
|> String.trim()
3 Likes
An alternative approach might work, by trimming first and sigiling later. Maybe something like:
defp produce_trimmed_html(assigns) do
"""
<somecomponent />
"""
|> String.trim
|> sigil_F
end
1 Like
@msaraiva Thank you for this suggestion.
It works well, the only problem is that Safe is converting the html tags into safe representations. The data is not user supplied and I am pretty sure it is safe, so I don’t want to convert the html result into safe representation. Is there a way to do this?
@christhekeele Thank you for this suggestion. I am trying to this in a live_view and I get an error stating that sigil_F/1 is undefined. Do I need to import something first? 
Note that returning a trimmed string rather than %Phoenix.LiveView.Rendered{}
will remove all diffing, so this is almost definitely not what you want to do unless it’s the top-level render of a dead view. Even the the marginal trimming savings is not going to be worth the extra work.
3 Likes
Upon some digging, I’m now quite sure sigil macros are obliged to do all their work at compile-time only, and are not designed to readily accept run-time strings without a bit of hackery. You could always try to craft a runtime-friendly variant of whatever the sigil does under the covers, but as @chrismccord points out there are other reasons to rethink the approach.