"""
end
defp render_cell_anchor_link(assigns) do
~L"""
<%= remix_icon("link", class: "text-xl") %>
"""
end
# The whole page has to load and then hooks are mounded.
# There may be a tiny delay before the markdown is rendered
# or editors are mounted, so show neat placeholders immediately.
defp render_content_placeholder(_bg_class, true = _empty) do
assigns = %{}
~L"""
"""
end
defp render_content_placeholder(bg_class, false = _empty) do
assigns = %{bg_class: bg_class}
~L"""
"""
end
defp render_outputs(assigns, socket) do
~L"""
<%= for {output, index} <- @cell_view.outputs |> Enum.reverse() |> Enum.with_index(), output != :ignored do %>
"""
end
defp render_output(_socket, text, id) when is_binary(text) do
text
# Captured output usually has a trailing newline that we can ignore,
# because each line is itself an HTML block anyway.
|> String.replace_suffix("\n", "")
|> render_virtualized_output(id, follow: true)
end
defp render_output(_socket, {:text, text}, id) do
render_virtualized_output(text, id)
end
defp render_output(_socket, {:vega_lite_static, spec}, id) do
live_component(LivebookWeb.Output.VegaLiteStaticComponent, id: id, spec: spec)
end
defp render_output(socket, {:vega_lite_dynamic, pid}, id) do
live_render(socket, LivebookWeb.Output.VegaLiteDynamicLive,
id: id,
session: %{"id" => id, "pid" => pid}
)
end
defp render_output(socket, {:table_dynamic, pid}, id) do
live_render(socket, LivebookWeb.Output.TableDynamicLive,
id: id,
session: %{"id" => id, "pid" => pid}
)
end
defp render_output(_socket, {:error, formatted}, _id) do
render_error_message_output(formatted)
end
defp render_output(_socket, output, _id) do
render_error_message_output("""
Unknown output format: #{inspect(output)}. If you're using Kino,
you may want to update Kino and Livebook to the latest version.
""")
end
defp render_virtualized_output(text, id, opts \\ []) do
follow = Keyword.get(opts, :follow, false)
lines = ansi_to_html_lines(text)
assigns = %{lines: lines, id: id, follow: follow}
~L"""
<%= for line <- @lines do %>
<%= line %>
<% end %>
"""
end
defp render_error_message_output(message) do
assigns = %{message: message}
~L"""
<%= @message %>
"""
end
defp render_cell_status(cell_view, evaluation_status, evaluation_time_ms)
defp render_cell_status(_, :evaluating, _) do
render_status_indicator("Evaluating", "bg-blue-500",
animated_circle_class: "bg-blue-400",
change_indicator: true
)
end
defp render_cell_status(_, :queued, _) do
render_status_indicator("Queued", "bg-gray-500", animated_circle_class: "bg-gray-400")
end
defp render_cell_status(:evaluated, _, evaluation_time_ms) do
render_status_indicator("Evaluated", "bg-green-400",
change_indicator: true,
tooltip: evaluated_label(evaluation_time_ms)
)
end
defp render_cell_status(:stale, _, _) do
render_status_indicator("Stale", "bg-yellow-200", change_indicator: true)
end
defp render_cell_status(:aborted, _, _) do
render_status_indicator("Aborted", "bg-red-400")
end
defp render_cell_status(_, _, _), do: nil
defp render_status_indicator(text, circle_class, opts \\ []) do
assigns = %{
text: text,
circle_class: circle_class,
animated_circle_class: Keyword.get(opts, :animated_circle_class),
change_indicator: Keyword.get(opts, :change_indicator, false),
tooltip: Keyword.get(opts, :tooltip)
}
~L"""
<%= @text %>
<%= if @change_indicator do %>
*
<% end %>
<%= if @animated_circle_class do %>
<% end %>
"""
end
defp evaluated_label(time_ms) when is_integer(time_ms) do
evaluation_time =
if time_ms > 100 do
seconds = time_ms |> Kernel./(1000) |> Float.floor(1)
"#{seconds}s"
else
"#{time_ms}ms"
end
"Took " <> evaluation_time
end
defp evaluated_label(_time_ms), do: nil
end