Add HTML content to rendered web pages?

I’d like to add HTML content to rendered web pages. My current use case is a table of contents (TOC), listing (and linking to) each of the page’s headings. Here’s some science fiction for a possible approach:

  • grab the output of Phoenix.View.render/3
  • turn the IO List into a single binary string
  • extract the heading levels and text content
  • generate the TOC (e.g., an HTML list of links)
  • add the TOC and anchors to the page’s HTML
  • turn it all back into an IO List

Problem is, I’m not sure about the best way to grab render's output. Should I override render in some manner, pipe its output into another function, use a pipe_through in router.ex, or what? Suggestions welcome…


I’m probably misunderstanding your problem, but wouldn’t it be easier to write a module with functions containing the headings with links and use them both in the pages and in the ToC?

defmodule Headings do
  # not sure it would work

  titles_for_routes = %{
    Routes.page_path(YourWeb.Endpoint, :index) => "This is the Index PAGE",
    # ...
  }, fn {route, title} ->
    def title(unquote(route)), do: unquote(title)

  def title(_unmatched), do: "Some default title"
# on the page
<title><%= Headings.title(@conn.private[:phoenix][:route]) # or whereever phoenix stores it's current route %></title>
# in the toc
  <%=, fn route -> %>
    <li><%= link(Headings.title(route), to: route) %></li>
  <% end) %>
1 Like

Thanks for the thoughtful and detailed reply. The problem with this approach, in my case, is that I have a number of places and ways in which headings are generated. For example:

  • Some headings are hard-wired into the templates.
  • Some headings are generated automagically, along with page sections, if the relevant data is available.
  • Some headings are encoded in Markdown source code.

Because I’d rather not couple the TOC generation to each of these spots in the code, I’m thinking about a post-processing approach: if there’s a heading in the resulting HTML, I index it.

Here are some links that may help to show what’s going on:

1 Like