Add images and binary content on gist preview (#615)

This commit is contained in:
Thomas Miceli
2026-02-03 15:55:44 +07:00
committed by GitHub
parent fe04c03acb
commit 2e10c1732a
5 changed files with 53 additions and 11 deletions

View File

@@ -73,6 +73,7 @@ type Gist struct {
URL string
Preview string
PreviewFilename string
PreviewMimeType string
Description string
Private Visibility // 0: public, 1: unlisted, 2: private
UserID uint
@@ -551,6 +552,7 @@ func (gist *Gist) UpdatePreviewAndCount(withTimestampUpdate bool) error {
if len(filesStr) == 0 {
gist.Preview = ""
gist.PreviewFilename = ""
gist.PreviewMimeType = ""
} else {
for _, fileStr := range filesStr {
file, err := gist.File("HEAD", fileStr, true)
@@ -562,6 +564,7 @@ func (gist *Gist) UpdatePreviewAndCount(withTimestampUpdate bool) error {
}
gist.Preview = ""
gist.PreviewFilename = file.Filename
gist.PreviewMimeType = file.MimeType.ContentType
if !file.MimeType.CanBeEdited() {
continue

View File

@@ -27,8 +27,9 @@ func (r HighlightedFile) InternalType() string {
type RenderedGist struct {
*db.Gist
Lines []string
HTML string
Lines []string
HTML string
PreviewMimeType *git.MimeType
}
func highlightFile(file *git.File) (HighlightedFile, error) {
@@ -76,6 +77,18 @@ func HighlightGistPreview(gist *db.Gist) (RenderedGist, error) {
Gist: gist,
}
if gist.PreviewMimeType != "" {
mt := &git.MimeType{ContentType: gist.PreviewMimeType}
if mt.CanBeEmbedded() {
rendered.PreviewMimeType = mt
return rendered, nil
}
}
if gist.Preview == "" {
return rendered, nil
}
style := newStyle()
lexer := newLexer(gist.PreviewFilename)
if lexer.Config().Name == "markdown" {

View File

@@ -1,5 +1,4 @@
import '../ts/ipynb.ts';
import PDFObject from 'pdfobject';
document.querySelectorAll<HTMLElement>('.table-code').forEach((el) => {
el.addEventListener('click', event => {
@@ -77,7 +76,3 @@ if (document.getElementById('gist').dataset.own) {
el.disabled = true;
});
}
document.querySelectorAll(".pdf").forEach((el) => {
PDFObject.embed(el.dataset.src || "", el);
})

View File

@@ -2,9 +2,14 @@ import '../css/tailwind.css';
import '../img/favicon-32.png';
import '../img/opengist.svg';
import jdenticon from 'jdenticon/standalone';
import PDFObject from 'pdfobject';
jdenticon.update("[data-jdenticon-value]")
document.querySelectorAll(".pdf").forEach((el) => {
PDFObject.embed(el.dataset.src || "", el);
})
document.addEventListener('DOMContentLoaded', () => {
document.getElementById('user-btn')?.addEventListener("click" , () => {
document.getElementById('user-menu')!.classList.toggle('hidden');

View File

@@ -60,7 +60,33 @@
<div class="rounded-md border border-1 border-gray-200 dark:border-gray-700 overflow-auto hover:border-primary-600">
<div class="code overflow-auto">
{{ if .gist.PreviewFilename }}
{{ if .gist.Preview }}
{{ if .gist.PreviewMimeType }}
{{ if .gist.PreviewMimeType.IsSVG }}
<div class="p-8 flex justify-center">
<img src="{{ .c.ExternalUrl }}/{{ .gist.User.Username }}/{{ .gist.Identifier }}/raw/HEAD/{{ .gist.PreviewFilename }}" alt="{{ .gist.PreviewFilename }}" class="max-h-80 object-contain">
</div>
{{ else if .gist.PreviewMimeType.IsImage }}
<div class="p-8 flex justify-center">
<img src="{{ .c.ExternalUrl }}/{{ .gist.User.Username }}/{{ .gist.Identifier }}/raw/HEAD/{{ .gist.PreviewFilename }}" alt="{{ .gist.PreviewFilename }}" class="max-h-80 object-contain">
</div>
{{ else if .gist.PreviewMimeType.IsAudio }}
<div class="p-8 flex justify-center">
<audio controls class="w-full max-w-lg">
<source src="{{ .c.ExternalUrl }}/{{ .gist.User.Username }}/{{ .gist.Identifier }}/raw/HEAD/{{ .gist.PreviewFilename }}" type="{{ .gist.PreviewMimeType.ContentType }}">
</audio>
</div>
{{ else if .gist.PreviewMimeType.IsVideo }}
<div class="p-8 flex justify-center">
<video controls class="max-h-80 max-w-full">
<source src="{{ .c.ExternalUrl }}/{{ .gist.User.Username }}/{{ .gist.Identifier }}/raw/HEAD/{{ .gist.PreviewFilename }}" type="{{ .gist.PreviewMimeType.ContentType }}">
</video>
</div>
{{ else if .gist.PreviewMimeType.IsPDF }}
<div class="pdf max-h-80" data-src="{{ .c.ExternalUrl }}/{{ .gist.User.Username }}/{{ .gist.Identifier }}/raw/HEAD/{{ .gist.PreviewFilename }}"></div>
{{ else }}
<div class="pl-4 py-0.5 text-xs"><p>{{ .locale.Tr "gist.preview-non-available" }}</p></div>
{{ end }}
{{ else if .gist.Preview }}
{{ if isMarkdown .gist.PreviewFilename }}
<div class="chroma preview markdown markdown-body p-8">{{ .gist.HTML | safe }}</div>
{{ else }}
@@ -80,8 +106,8 @@
</table>
{{ end }}
{{ else }}
<div class="pl-4 py-0.5 text-xs"><p>{{ .locale.Tr "gist.preview-non-available" }}</p></div>
{{ end }}
<div class="pl-4 py-0.5 text-xs"><p>{{ .locale.Tr "gist.preview-non-available" }}</p></div>
{{ end }}
{{ else }}
<div class="pl-4 py-0.5 text-xs"><p>{{ .locale.Tr "gist.no-content" }}</p></div>
{{ end }}