fix(microprints): fix source viewer showing stale content when switching files

The source_viewer component used static DOM IDs (id='source-viewer')
with phx-update='ignore'. When switching expanded files, LiveView
reused the same DOM element but phx-update='ignore' prevented content
from being updated, showing the previous file's source.

- Override source_viewer/1 in MicroprintsLive with unique per-file IDs
  generated via :erlang.phash2(file_path)
- Add test verifying expand-switch shows correct source content
- Add test for highlight/expand coupling (collapse when highlighting
  a different file)
- All 160 tests pass
This commit is contained in:
Firehose Bot
2026-05-18 18:04:47 +01:00
parent 36bdc0610e
commit 7c06204ac2
4 changed files with 4289 additions and 6 deletions
+21 -4
View File
@@ -76,12 +76,11 @@ defmodule FirehoseWeb.MicroprintsLive do
highlighted_line={@highlighted_line}
/>
<%= if @expanded_path == path and source do %>
<.source_viewer
<%= if @expanded_path == path and source do %> <.source_viewer
content={source}
highlighted_line={@highlighted_line}
language="elixir"
id={"source-viewer-" <> path}
file_path={path}
/>
<% end %>
<% else %>
@@ -241,5 +240,23 @@ defmodule FirehoseWeb.MicroprintsLive do
# Delegate to MicroprintComponent
defdelegate microprint(assigns), to: MicroprintComponent
defdelegate microprint_legend(assigns), to: MicroprintComponent
defdelegate source_viewer(assigns), to: MicroprintComponent
# Custom source_viewer with unique DOM IDs per file to prevent LiveView
# DOM patching bugs when switching expanded files.
def source_viewer(assigns) do
assigns = assign(assigns, :viewer_id, "source-viewer-" <> Integer.to_string(:erlang.phash2(assigns.file_path, 1_000_000)))
~H"""
<div
id={@viewer_id}
class="source-viewer mt-2 max-h-96 overflow-auto rounded font-mono text-xs"
phx-hook="SourceViewer"
data-highlighted-line={@highlighted_line}
data-language={@language}
style="background: var(--sv-bg); color: var(--sv-text);"
>
<pre id={@viewer_id <> "-pre"} phx-update="ignore" class="m-0 p-2"><code class={"language-#{@language || "plaintext"}"}><%= @content %></code></pre>
</div>
"""
end
end