Show URL path in snapshot diff and gallery views
Snapshot names alone don't convey which route produced them.

Assisted-by: Claude Opus 4.6 via Claude Code
change kmzqnzowxuqoxmsqunmvwkklyyynplty
commit 0e4e578b83e65adb19a5b07ddeaf6c34ce49d4ea
author Alpha Chen <alpha@kejadlen.dev>
date
parent qtzpyzlm
diff --git a/Rakefile b/Rakefile
index 85d90aa..286d899 100644
--- a/Rakefile
+++ b/Rakefile
@@ -90,7 +90,9 @@ namespace :snapshots do
     end
 
     manifest = current_dir / "manifest.json"
-    order = manifest.exist? ? JSON.parse(manifest.read).map { |e| e["name"] } : []
+    manifest_entries = manifest.exist? ? JSON.parse(manifest.read) : []
+    order = manifest_entries.map { |e| e["name"] }
+    paths = manifest_entries.each_with_object({}) { |e, h| h[e["name"]] = e["path"] }
     baseline_images = baseline_dir.glob("*.png").map { |f| f.basename(".png").to_s }
     current_images = current_dir.glob("*.png").map { |f| f.basename(".png").to_s }
     all_names = order | current_images | baseline_images
@@ -105,6 +107,7 @@ namespace :snapshots do
 
       {
         name: name,
+        path: paths[name],
         status: status,
         baseline: has_baseline ? "baseline/#{name}.png" : nil,
         current: has_current ? "current/#{name}.png" : nil,
@@ -133,14 +136,16 @@ namespace :snapshots do
     css_sources.each_key { |src| cp src, output_path.dirname.to_s }
 
     manifest = images_dir / "manifest.json"
-    order = manifest.exist? ? JSON.parse(manifest.read).map { |e| e["name"] } : []
+    manifest_entries = manifest.exist? ? JSON.parse(manifest.read) : []
+    order = manifest_entries.map { |e| e["name"] }
+    paths = manifest_entries.each_with_object({}) { |e, h| h[e["name"]] = e["path"] }
     all_pngs = images_dir.glob("*.png").map { |f| f.basename(".png").to_s }
     names = order | all_pngs
 
     title = "Ketchup Snapshots"
     images_rel = images_dir.relative_path_from(output_path.dirname)
     images = names.map do |name|
-      { name: name, filename: (images_rel / "#{name}.png").to_s }
+      { name: name, path: paths[name], filename: (images_rel / "#{name}.png").to_s }
     end
 
     template = (Pathname(__dir__) / "templates/snapshot_gallery.erb").read
diff --git a/lib/ketchup/snapshots.rb b/lib/ketchup/snapshots.rb
index 8291251..40f3aa3 100644
--- a/lib/ketchup/snapshots.rb
+++ b/lib/ketchup/snapshots.rb
@@ -3,6 +3,7 @@
 require "fileutils"
 require "json"
 require "logger"
+require "uri"
 require "pathname"
 
 require "ferrum"
@@ -19,7 +20,6 @@ module Ketchup
         @output_dir = Pathname(output_dir)
         @logger = logger
         @server = server || method(:default_server)
-        @names = []
       end
 
       def call
@@ -43,8 +43,10 @@ module Ketchup
       private
 
       def run_capture
+        entries = []
+
         # 1. Dashboard — populated overdue + upcoming columns
-        snap("dashboard") do
+        entries << snap("dashboard") do
           goto @base
           wait_for(".home")
         end
@@ -54,7 +56,7 @@ module Ketchup
           id: Task.exclude(completed_at: nil).select(:series_id)
         ) || Series.first
 
-        snap("series-detail") do
+        entries << snap("series-detail") do
           goto "#{@base}/series/#{series_with_history.id}"
           wait_for("#series-note-detail")
         end
@@ -67,15 +69,14 @@ module Ketchup
           interval_count: 2,
           interval_unit: "week"
         )
-        snap("new-series-editing", selector: ".column-aside")
+        entries << snap("new-series-editing", selector: ".column-aside")
 
         # 4. Complete a task, snap the resulting detail page
         goto @base
         wait_for(".complete-btn").click
         wait_for(".task-history")
-        snap("after-complete")
+        entries << snap("after-complete")
 
-        entries = @names.map { |name| { name: name } }
         (@output_dir / "manifest.json").write(JSON.pretty_generate(entries))
       end
 
@@ -135,14 +136,15 @@ module Ketchup
       def snap(name, selector: nil)
         yield if block_given?
 
-        path = @output_dir / "#{name}.png"
+        file = @output_dir / "#{name}.png"
         if selector
-          @browser.screenshot(path: path.to_s, selector: selector)
+          @browser.screenshot(path: file.to_s, selector: selector)
         else
-          @browser.screenshot(path: path.to_s)
+          @browser.screenshot(path: file.to_s)
         end
-        @names << name
+        url_path = URI.parse(@browser.current_url).path
         @logger.info(name)
+        { name: name, path: url_path }
       end
 
       def fill_new_series(note:, interval_count: 1, interval_unit: "day")
diff --git a/templates/snapshot_diff.erb b/templates/snapshot_diff.erb
index 7383a88..ebcb15a 100644
--- a/templates/snapshot_diff.erb
+++ b/templates/snapshot_diff.erb
@@ -13,6 +13,9 @@
   <div class="snapshot">
     <h2>
       <%= snap[:name] %>
+      <% if snap[:path] -%>
+      <code><%= snap[:path] %></code>
+      <% end -%>
       <% if snap[:status] == :new %>
       <span class="label new">new</span>
       <% elsif snap[:status] == :removed %>
diff --git a/templates/snapshot_gallery.erb b/templates/snapshot_gallery.erb
index 0f56818..8956852 100644
--- a/templates/snapshot_gallery.erb
+++ b/templates/snapshot_gallery.erb
@@ -11,7 +11,7 @@
   <h1><%= title %></h1>
   <% images.each do |image| %>
   <div class="snapshot">
-    <h2><%= image[:name] %></h2>
+    <h2><%= image[:name] %><% if image[:path] %> <code><%= image[:path] %></code><% end %></h2>
     <img src="<%= image[:filename] %>" alt="<%= image[:name] %>">
   </div>
   <% end %>