defmodule LivebookWeb.Output.StdoutComponent do use LivebookWeb, :live_component @impl true def mount(socket) do {:ok, assign(socket, modifiers: [], last_line: nil, last_html_line: nil), temporary_assigns: [html_lines: []]} end @impl true def update(assigns, socket) do {text, assigns} = Map.pop(assigns, :text) socket = assign(socket, assigns) if text do text = (socket.assigns.last_line || "") <> text text = Livebook.Notebook.normalize_stdout(text) last_line = case Livebook.Utils.split_at_last_occurrence(text, "\n") do :error -> text {:ok, _, last_line} -> last_line end {html_lines, modifiers} = LivebookWeb.Helpers.ANSI.ansi_string_to_html_lines_step(text, socket.assigns.modifiers) {html_lines, [last_html_line]} = Enum.split(html_lines, -1) {:ok, assign(socket, html_lines: html_lines, last_html_line: last_html_line, last_line: last_line, modifiers: modifiers )} else {:ok, socket} end end @impl true def render(assigns) do ~H"""
<% # Note 1: We add a newline to each element, so that multiple lines can be copied properly as element.textContent %> <% # Note 2: We glue the tags together to avoid inserting unintended whitespace %>
""" end end