Fix css, js, json, and images browsing views

Seto Elkahfi committed Jun 17, 2026 at 09:53 UTC 3933a8867ac2d3875810f4b356b4e388f861a9b6
3 files changed +30 -6
app/controllers/blobs_controller.rb
+21 -2
@@ -3,6 +3,19 @@ class BlobsController < ApplicationController
3 before_action :load_repository
4 before_action :ensure_can_read!
5
6 + # Raster image types served inline from the raw endpoint with their real
7 + # content type. SVG is intentionally excluded — serving it inline could
8 + # execute embedded scripts on direct navigation.
9 + RAW_IMAGE_TYPES = {
10 + "png" => "image/png", "jpg" => "image/jpeg", "jpeg" => "image/jpeg",
11 + "gif" => "image/gif", "webp" => "image/webp", "avif" => "image/avif",
12 + "bmp" => "image/bmp", "ico" => "image/x-icon"
13 + }.freeze
14 +
15 + # Types previewed in the blob view via a data URI. SVG is safe here because it
16 + # is loaded through an <img> tag, which browsers sandbox.
17 + PREVIEW_IMAGE_TYPES = RAW_IMAGE_TYPES.merge("svg" => "image/svg+xml").freeze
18 +
19 def show
20 # A file path like ".../app.js" or "...style.css" makes Rails negotiate a
21 # non-HTML format from the trailing extension — which has no template (→
@@ -30,7 +43,12 @@ class BlobsController < ApplicationController
43 @is_binary = content.encoding != Encoding::UTF_8 || !content.valid_encoding? || binary_content?(content)
44 @file_size = content.bytesize
45
33 - unless @is_binary
46 + @image_type = PREVIEW_IMAGE_TYPES[@extension.downcase]
47 + if @image_type
48 + # Embed the image inline as a data URI so it previews without a second
49 + # request. <img>-loaded content is sandboxed, so this is safe for SVG too.
50 + @image_data_uri = "data:#{@image_type};base64,#{[ content ].pack('m0')}"
51 + elsif !@is_binary
52 @highlighted_lines = highlight_lines(content, @filename)
53 @line_count = content.lines.count
54 end
@@ -48,8 +66,9 @@ class BlobsController < ApplicationController
66 return
67 end
68
69 + ext = File.extname(@file_path).delete_prefix(".").downcase
70 send_data content,
52 - type: "text/plain; charset=utf-8",
71 + type: RAW_IMAGE_TYPES[ext] || "text/plain; charset=utf-8",
72 disposition: "inline",
73 filename: File.basename(@file_path)
74 end
app/views/blobs/show.html.erb
+7 -2
@@ -50,7 +50,7 @@
50 <div class="px-4 py-2.5 border-b border-surface-600 flex items-center justify-between bg-surface-600">
51 <div class="flex items-center gap-3 text-xs text-gray-400">
52 <span class="font-mono badge-gray"><%= @extension.presence || "text" %></span>
53 - <% unless @is_binary %>
53 + <% if @line_count %>
54 <span><%= number_with_delimiter(@line_count) %> lines</span>
55 <% end %>
56 <span><%= number_to_human_size(@file_size) %></span>
@@ -61,7 +61,12 @@
61 </div>
62 </div>
63
64 - <% if @is_binary %>
64 + <% if @image_type %>
65 + <div class="px-6 py-10 flex justify-center bg-surface-800">
66 + <img src="<%= @image_data_uri %>" alt="<%= @filename %>"
67 + class="max-w-full h-auto rounded border border-surface-600" />
68 + </div>
69 + <% elsif @is_binary %>
70 <div class="px-6 py-10 text-center text-sm text-gray-400">
71 Binary file — <%= number_to_human_size(@file_size) %>
72 </div>
app/views/layouts/application.html.erb
+2 -2
@@ -39,8 +39,8 @@
39 <div class="max-w-6xl mx-auto px-4 sm:px-6 py-8 flex items-center justify-between text-xs text-gray-500">
40 <span>
41 Get <a href="https://getsigit.5mb.app/" class="hover:text-gray-300 transition-colors" target="_blank" rel="noopener noreferrer">siGit Code &amp; Deploy</a></span>
42 - <div class="flex items-center gap-4">
43 - Runs on <a href="https://smbcloud.xyz/" class="hover:text-gray-300 transition-colors" target="_blank" rel="noopener noreferrer">smbCloud</a>
42 + <div class="flex items-center">
43 + Auth and Mail by&nbsp;<a href="https://smbcloud.xyz/" class="hover:text-gray-300 transition-colors" target="_blank" rel="noopener noreferrer">smbCloud Platform</a>
44 </div>
45 <%= render "shared/dev_panel" if Rails.env.development? %>
46 </div>