LiveView + MDEx: How do I use phoenix components in render function?

Hi there! With the release of MDEx v0.11.0 which adds support for Phoenix components. I have been trying to render the markdown with phoenix components in it, but I’m not able to do that.

Here’s how my system is working:

I have some markdown files that roughly look like this:

%{ title: "First blog", description: "a description" }
---

# Hello World

<.button>This is a button</.button>

and I use nimble_publisher with MDEx to compile these markdown files into HTML:

# Using Nimble publisher
defmodule MyApp.Blog do
  use NimblePublisher,
    build: MyApp.Blog.Article,
    from: Application.app_dir(:my_app, "priv/posts/*.md"),
    as: :blogs,
    html_converter: MyApp.Converter

  def all_blogs, do: @blogs
end

# MyApp.Blog.Article 
defmodule MyApp.Blog.Article do
  defstruct title: "",,
            description: "",
            body: ""

  def build(filepath, attrs, body) do

    struct!(
      __MODULE__,
      [body: body] ++ Map.to_list(attrs)
    )
  end
end

# MyApp.Converter
defmodule MyApp.Converter do
  def convert(_path, body, attrs, _opts) do
    MDEx.to_html!(body, extension: [phoenix_heex: true, autolink: true, header_ids: ""])
  end
end

Here’s how the compiled markdown looks like:

<h1><a href=\"#hello-world\" aria-hidden=\"true\" class=\"anchor\" id=\"hello-world\"></a>Hello World</h1>\n<.button>This is a button</.button>

And In my LiveView, I don’t have any idea how to get Phoenix to render the components:

defmodule MyApp.BlogLive.Show do
  use MyAppWeb, :live_view

  alias MyApp.Blog

  @impl true
  def mount(_params, _session, socket) do
    [blog] = Blog.all_blogs()
    %{body: body} = blog

    {:ok, socket |> assign(body: body)}
  end

  @impl true
  def render(assigns) do
    ~H"""
    <Layouts.app>
      {raw(@body)}
    </Layouts.app>
    """
  end
end

I understand that raw function won’t work because It’ll just render the HTML part.

How do I get Phoenix to render the HTML along with Phoenix components here?

Any help is appreciated!

Working on a new function to make the integration with nimble_publisher, tableau, and SSG more straightforward. To be released very soon.

4 Likes