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 & 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 <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>