fix #221: scale image pastes, drop text box, fix raw view and size
- image pastes render the image scaled to fit the viewer box (aspect ratio preserved, max-height 70vh), no text/code box below it - link pill moved under the image as a small inline chip - /raw serves image attachment bytes as an image instead of empty text - view details size reports the actual attachment file size
This commit is contained in:
@@ -810,15 +810,35 @@ button[type="submit"]:focus-visible,
|
||||
}
|
||||
.file-chip .file-chip-remove:hover { color: var(--danger, #c0392b); }
|
||||
.attachment-bar { display: flex; flex-direction: column; gap: 10px; }
|
||||
.attachment-chip {
|
||||
/* #221: the link pill under an image preview stays a small inline chip,
|
||||
left-aligned under the image, not stretched above it. */
|
||||
.attachment-bar .attachment-chip {
|
||||
display: inline-flex; align-items: center; gap: 12px; align-self: flex-start;
|
||||
border: 1px solid var(--border); border-radius: var(--radius);
|
||||
padding: 8px 16px; text-decoration: none; color: var(--fg);
|
||||
background: var(--surface-2); font-size: 21.6px;
|
||||
padding: 6px 14px; text-decoration: none; color: var(--fg);
|
||||
background: var(--surface-2); font-size: 19px;
|
||||
}
|
||||
.attachment-bar .attachment-chip:hover { border-color: var(--accent); }
|
||||
.attachment-bar .attachment-chip .attachment-name {
|
||||
max-width: 320px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
||||
}
|
||||
/* #221: images scale to fit the viewer box, aspect ratio preserved. */
|
||||
.attachment-preview {
|
||||
max-width: 100%;
|
||||
align-self: flex-start;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius);
|
||||
background: var(--surface-2);
|
||||
overflow: hidden;
|
||||
}
|
||||
.attachment-preview img {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
max-height: 70vh;
|
||||
width: auto;
|
||||
height: auto;
|
||||
object-fit: contain;
|
||||
}
|
||||
.attachment-chip:hover { border-color: var(--accent); }
|
||||
.attachment-chip .attachment-size { color: var(--muted-fg); font-size: 19px; }
|
||||
.attachment-preview img { max-width: 480px; max-height: 360px; border-radius: var(--radius); border: 1px solid var(--border); }
|
||||
|
||||
/* #139: CSP-safe replacements for inline style attributes (style-src 'self') */
|
||||
.hidden { display: none; }
|
||||
|
||||
@@ -39,19 +39,27 @@
|
||||
{{if .Attachment}}
|
||||
<div class="float">
|
||||
<div class="attachment-bar">
|
||||
{{if .AttachmentImage}}
|
||||
<div class="attachment-preview"><img src="/f/{{.Attachment.ID}}/{{.Attachment.Filename}}" alt="{{.Attachment.Filename}}"></div>
|
||||
<a class="attachment-chip" href="/f/{{.Attachment.ID}}/{{.Attachment.Filename}}" data-mime="{{.Attachment.Mime}}">
|
||||
<span class="attachment-name">{{.Attachment.Filename}}</span>
|
||||
<span class="attachment-size">{{.Attachment.SizeHuman}}</span>
|
||||
</a>
|
||||
{{else}}
|
||||
<a class="attachment-chip" href="/f/{{.Attachment.ID}}/{{.Attachment.Filename}}" data-mime="{{.Attachment.Mime}}">
|
||||
<span class="attachment-name">{{.Attachment.Filename}}</span>
|
||||
<span class="attachment-size">{{.Attachment.SizeHuman}}</span>
|
||||
</a>
|
||||
{{if or (eq .Attachment.Mime "image/png") (eq .Attachment.Mime "image/jpeg") (eq .Attachment.Mime "image/gif") (eq .Attachment.Mime "image/webp")}}
|
||||
<div class="attachment-preview"><img src="/f/{{.Attachment.ID}}/{{.Attachment.Filename}}" alt="{{.Attachment.Filename}}"></div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{if not .AttachmentImage}}
|
||||
<div class="float">
|
||||
<div class="code" id="code"><div class="gutter" id="gutter">{{.Gutter}}</div><div class="codebody" id="codebody">{{.ContentHTML}}</div></div>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
<input type="hidden" id="raw-content" value="{{.ContentAttr}}">
|
||||
<script src="/static/paste.js" defer data-paste-id="{{.ID}}"></script>
|
||||
|
||||
+18
-2
@@ -252,20 +252,35 @@ func (h *Handlers) renderPaste(w http.ResponseWriter, row *store.PasteRow, justC
|
||||
http.Error(w, "db error", 500)
|
||||
return
|
||||
}
|
||||
// #221: image attachments render the image, not a text/code box. Size
|
||||
// comes from the attachment's actual file size, not the text content.
|
||||
attImage := false
|
||||
if attachment != nil {
|
||||
switch attachment.Mime {
|
||||
case "image/png", "image/jpeg", "image/gif", "image/webp":
|
||||
attImage = true
|
||||
}
|
||||
}
|
||||
sizeHuman := humanSize(len(row.Content))
|
||||
lineCount := lines
|
||||
if attachment != nil {
|
||||
sizeHuman = attachment.SizeHuman
|
||||
lineCount = 1
|
||||
}
|
||||
data := map[string]any{
|
||||
"Page": "paste",
|
||||
"ID": row.ID,
|
||||
"Title": row.Title.String,
|
||||
"Language": row.Language.String,
|
||||
"StatsSummary": summary,
|
||||
"SizeHuman": humanSize(len(row.Content)),
|
||||
"SizeHuman": sizeHuman,
|
||||
"HasPassword": row.PasswordHash.Valid,
|
||||
"BurnAfterRead": row.BurnAfterRead,
|
||||
"CustomSlug": row.CustomSlug.String,
|
||||
"ContentHTML": template.HTML(langpkg.HighlightCode(row.Content, row.Language.String)), // safe: HighlightCode escapes all non-span text
|
||||
"ContentAttr": row.Content,
|
||||
"Gutter": strings.TrimSuffix(gutter, "\n"),
|
||||
"LineCount": lines,
|
||||
"LineCount": lineCount,
|
||||
"SizeBytes": len(row.Content),
|
||||
"CreatedAgo": agoString(row.CreatedAt),
|
||||
"CreatedAtUnix": row.CreatedAt,
|
||||
@@ -279,6 +294,7 @@ func (h *Handlers) renderPaste(w http.ResponseWriter, row *store.PasteRow, justC
|
||||
"ReadsTotal": int(row.ReadsLimit.Int64),
|
||||
"JustCreated": justCreated,
|
||||
"Attachment": attachment,
|
||||
"AttachmentImage": attImage,
|
||||
"Host": "this host",
|
||||
}
|
||||
h.renderPage(w, "paste.html", data)
|
||||
|
||||
Reference in New Issue
Block a user