samgaw

samgaw

There are already a couple of helper packages on Github to manage inlining external SVG files into templates which is great from a readability point of view. However I’m guessing because of the way templates are evaluated, EEx tags treated as strings.

Taking the thoughtbot package as the base for a simple example, do something along the lines of:

def inline_svg(file_name) do
  path = static_path(file_name)
  case File.read(path) do
    {:ok, file} -> {:safe, file}
    {:error, _} -> raise "No SVG found at #{path}"
  end
end

defp static_path(file_name) do
  path = "assets/static/svg"
  [path, "#{file_name}.svg"] |> Path.join() |> Path.expand
end

That will render the SVG but include the EEx as strings rather than the output of <%= some_func() %> included in the SVG file as expected because of the {:ok, file} -> {:safe, file}. But removing that and going with {:ok, file} -> (file), or wrapping the svg_inline() function with raw() still doesn’t give me the desired outcome.

So I’m wondering where in Phoenix’s order should I be attempting to run this so that tags included in the inlined SVG are rendered as expected?

Thanks.

Showing Posts 1 to 10

hauleth

hauleth

As far as “pure” EEx is concerned there is absolute no difference, as raw EEx do not care about “tags”, as it do not understands them. If you are talking about Phoenix HTML, then code you have presented should work as expected. Are you sure that returned string is wrapped in tuple?

mindok

mindok

There’s a discussion on run-time loading and execution of Eex templates here: Dynamic EEx templates for web app - #7 by OvermindDL1

It sounds like the tags aren’t being evaluated because the templates aren’t getting compiled into functions.

samgaw

samgaw OP

Yeah this is purely in the context of Phoenix HTML.

I created a quick repo to demonstrate the issue. Using the function above, it’s definitely returning the tuple:

> DynImg.inline_svg("eex_test")
{:safe,
 "<svg width=\"100%\" height=\"60px\" viewBox=\"0 0 113 60\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n\t<g stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\" font-family=\"ArialMT, Arial\" font-size=\"24\" font-weight=\"normal\">\n<g transform=\"translate(-244.000000, -76.000000)\" fill=\"#000\">\n<text>\n                <tspan x=\"240.822\" y=\"122\"><%= \"Inlined by function\" %></tspan>\n</text>\n</g>\n    </g>\n</svg>"}

and for plain old SVG images it works exactly as expected. It’s only when I try to inline files with <%= %>, essentially treating the SVGs as templates that I have a problem.

Following @mindok’s link I seem to have to explicitly call EEx, in this case Phoenix.HTML.Engine and pass it through again but after spending the morning on it I’m not sure if I’m even any closer to an answer.

LostKobrakai

LostKobrakai

Your problem is that you’re using a function here. The function will be called at runtime, but at runtime the svg’s won’t be available (when using releases) or at least the path might no longer match. You’d want to use a macro, so you read the svg’s content at compile time and only have the result inlined with all the other eex template contents.

samgaw

samgaw OP

Thanks @LostKobrakai.

Chatting on IRC I was pointed towards macros as well. Thinking about it, it does make sense it just never crossed my mind to consider the difference between macros & functions.

Writing macros isn’t something I’m familiar with so it’ll probably take me a while to rtfm.

hauleth

hauleth

Your macro:

defmacro inline_svg(file_name) do
  path = static_path(file_name)
  case File.read(path) do
    {:ok, file} -> quote do: {:safe, unquote(file)}
    {:error, _} -> raise "No SVG found at #{path}"
  end
end
samgaw

samgaw OP

Thanks @hauleth but same issue after importing your macro into the view (https://github.com/samgaw/dynimg).

samgaw

samgaw OP

Yeah that was one I had tried and linked above. Unfortunately it inlines the SVG file after the template has been evaluated so any EEx tags included appear as strings.

I never worked out a clean way of doing it, and ended up resorting to treating the SVGs template partials and calling them with render/3. I’ll maybe swing back to it at some stage just to make things a little prettier but inlining them as an EEx template does the same job.

I’ve also been keeping an eye on a lib from CoinGaming called Bennu which looks promising, as well as Surface. Those approaches may end up being a better answer.

AndyL

AndyL

@samgaw hmm. Here’s a link to the module with my working code. Maybe this will give you some clues to get things sorted out! :wink:

https://github.com/andyl/phoenix_live_editable/blob/master/lib/phoenix_live_editable/svg.ex

Where Next? Top

Trending in Questions Top

RSP87
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
kszambelanczyk
Hello! Could someone please give me a help/sample code, how to delete a file from s3 using waffle/waffle_ecto from Phoenix app. I creat...
New
RemyXRenard
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
samoloth
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
FlyingNoodle
If a change or preparation module uses Ash.Changeset.get_argument/2 or Ash.Query.get_argument/2 (or any of the other get_argument functio...
New
nseaSeb
Hello, I know there is an approach for handling lists that allows for optimized traversal, but I can’t recall the specific method (somet...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge &amp; Solve. They are GUI (Emerge) and State management (S...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews