Skip to content

Commit

Permalink
Rendering previews
Browse files Browse the repository at this point in the history
  • Loading branch information
thomiceli committed Dec 18, 2023
1 parent 0168e9e commit 4def229
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 55 deletions.
39 changes: 4 additions & 35 deletions internal/db/gist.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
package db

import (
"bufio"
"bytes"
"fmt"
"github.com/alecthomas/chroma/v2"
"github.com/alecthomas/chroma/v2/formatters/html"
"github.com/alecthomas/chroma/v2/lexers"
"github.com/alecthomas/chroma/v2/styles"
"github.com/dustin/go-humanize"
"github.com/labstack/echo/v4"
"os/exec"
Expand Down Expand Up @@ -346,42 +340,17 @@ func (gist *Gist) File(revision string, filename string, truncate bool) (*git.Fi
return nil, nil
}

size, err := git.GetFileSize(gist.User.Username, gist.Uuid, revision, filename)
if err != nil {
return nil, err
}

var lexer chroma.Lexer
if lexer = lexers.Get(filename); lexer == nil {
lexer = lexers.Fallback
}

style := styles.Get("catppuccin-latte")
if style == nil {
style = styles.Fallback
}
var size int64

formatter := html.New(html.WithClasses(true), html.PreventSurroundingPre(true))

iterator, err := lexer.Tokenise(nil, content)
size, err = git.GetFileSize(gist.User.Username, gist.Uuid, revision, filename)
if err != nil {
return nil, err
}

htmlbuf := bytes.Buffer{}
w := bufio.NewWriter(&htmlbuf)

if err = formatter.Format(w, style, iterator); err != nil {
return nil, err
}

_ = w.Flush()

return &git.File{
Filename: filename,
FileType: lexer.Config().Name,
FileSize: humanize.IBytes(uint64(size)),
Content: htmlbuf.String(),
Size: humanize.IBytes(uint64(size)),
Content: content,
Truncated: truncated,
}, err
}
Expand Down
3 changes: 1 addition & 2 deletions internal/git/output_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ import (

type File struct {
Filename string
FileType string
FileSize string
Size string
OldFilename string
Content string
Truncated bool
Expand Down
93 changes: 93 additions & 0 deletions internal/render/highlight.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package render

import (
"bufio"
"bytes"
"github.com/alecthomas/chroma/v2"
"github.com/alecthomas/chroma/v2/formatters/html"
"github.com/alecthomas/chroma/v2/lexers"
"github.com/alecthomas/chroma/v2/styles"
"github.com/thomiceli/opengist/internal/git"
)

type RenderedFile struct {
File *git.File
Type string
HTML string
}

func File(file *git.File) (RenderedFile, error) {
colorFile := RenderedFile{
File: file,
}

var lexer chroma.Lexer
if lexer = lexers.Get(file.Filename); lexer == nil {
lexer = lexers.Fallback
}

style := styles.Get("catppuccin-latte")
if style == nil {
style = styles.Fallback
}

formatter := html.New(html.WithClasses(true), html.PreventSurroundingPre(true))

iterator, err := lexer.Tokenise(nil, file.Content)
if err != nil {
return colorFile, err
}

htmlbuf := bytes.Buffer{}
w := bufio.NewWriter(&htmlbuf)

if err = formatter.Format(w, style, iterator); err != nil {
return colorFile, err
}

_ = w.Flush()

colorFile.HTML = htmlbuf.String()
colorFile.Type = parseFileTypeName(*lexer.Config())

return colorFile, err
}

func Code(filename, code string) (string, error) {
var lexer chroma.Lexer
if lexer = lexers.Get(filename); lexer == nil {
lexer = lexers.Fallback
}

style := styles.Get("catppuccin-latte")
if style == nil {
style = styles.Fallback
}

formatter := html.New(html.WithClasses(true), html.PreventSurroundingPre(true))

iterator, err := lexer.Tokenise(nil, code)
if err != nil {
return code, err
}

htmlbuf := bytes.Buffer{}
w := bufio.NewWriter(&htmlbuf)

if err = formatter.Format(w, style, iterator); err != nil {
return code, err
}

_ = w.Flush()

return htmlbuf.String(), err
}

func parseFileTypeName(config chroma.Config) string {
fileType := config.Name
if fileType == "fallback" || fileType == "plaintext" {
return "Text"
}

return fileType
}
21 changes: 20 additions & 1 deletion internal/web/gist.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"archive/zip"
"bytes"
"errors"
"github.com/rs/zerolog/log"
"github.com/thomiceli/opengist/internal/render"
"html/template"
"net/url"
"regexp"
Expand Down Expand Up @@ -232,6 +234,14 @@ func allGists(ctx echo.Context) error {
}
}

for _, gist := range gists {
rendered, err := render.Code(gist.PreviewFilename, gist.Preview)
if err != nil {
log.Warn().Err(err).Msg("Error rendering gist preview for " + gist.Uuid + " - " + gist.PreviewFilename)
}
gist.Preview = rendered
}

if err != nil {
return errorRes(500, "Error fetching gists", err)
}
Expand Down Expand Up @@ -261,9 +271,18 @@ func gistIndex(ctx echo.Context) error {
return notFound("Revision not found")
}

renderedFiles := make([]render.RenderedFile, 0, len(files))
for _, file := range files {
rendered, err := render.File(file)
if err != nil {
log.Warn().Err(err).Msg("Error rendering gist preview for " + gist.Uuid + " - " + gist.PreviewFilename)
}
renderedFiles = append(renderedFiles, rendered)
}

setData(ctx, "page", "code")
setData(ctx, "commit", revision)
setData(ctx, "files", files)
setData(ctx, "files", renderedFiles)
setData(ctx, "revision", revision)
setData(ctx, "htmlTitle", gist.Title)
return html(ctx, "gist.html")
Expand Down
2 changes: 1 addition & 1 deletion templates/pages/all.html
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ <h6 class="text-xs text-slate-700 dark:text-slate-300 py-1">{{ $gist.Description

<tr>
<td class="select-none line-num px-4">{{$i}}</td>
<td class="line-code">{{ $line }}</td>
<td class="line-code">{{ $line | safe }}</td>
</tr>
{{ $i = inc $i }}
{{ end }}
Expand Down
34 changes: 18 additions & 16 deletions templates/pages/gist.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,43 +3,45 @@
{{ if .files }}
<div class="grid gap-y-4">
{{ range $file := .files }}
{{ $csv := csvFile $file }}
{{ $csv := csvFile $file.File }}
<div class="rounded-md border border-1 border-gray-200 dark:border-gray-700 overflow-auto">
<div class="border-b-1 border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800 my-auto block">
<div class="ml-4 py-1.5 flex">

<span class="flex-auto inline-flex items-center text-sm text-slate-700 dark:text-slate-300 filename" id="file-{{ slug $file.Filename }}">
<span class="flex-auto inline-flex items-center text-sm text-slate-700 dark:text-slate-300 filename" id="file-{{ slug $file.File.Filename }}">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-slate-700 dark:text-slate-300" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4" />
</svg>
<a href="{{ $.c.ExternalUrl }}#file-{{ slug $file.Filename }}" class="hover:text-primary-600 ml-2 mr-1">{{ $file.Filename }}</a>
<span class="text-gray-400"> · {{ $file.FileSize }} · {{ $file.FileType }}</span>
<a href="{{ $.c.ExternalUrl }}#file-{{ slug $file.File.Filename }}" class="hover:text-primary-600 ml-2 mr-1">{{ $file.File.Filename }}</a>
<span class="hidden sm:block">
<span class="text-gray-400"> · {{ $file.File.Size }} · {{ $file.Type }}</span>
</span>
</span>

<span class="isolate inline-flex rounded-md shadow-sm mr-2">
<a href="{{ $.c.ExternalUrl }}/{{ $.gist.User.Username }}/{{ $.gist.Uuid }}/raw/{{ $.commit }}/{{$file.Filename}}" class="relative inline-flex items-center rounded-l-md bg-white text-gray-500 dark:text-slate-300 float-right px-2.5 py-1 leading-4 text-xs font-medium dark:bg-gray-600 border border-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 hover:text-slate-700 dark:hover:text-slate-300 select-none">
<a href="{{ $.c.ExternalUrl }}/{{ $.gist.User.Username }}/{{ $.gist.Uuid }}/raw/{{ $.commit }}/{{$file.File.Filename}}" class="relative inline-flex items-center rounded-l-md bg-white text-gray-500 dark:text-slate-300 float-right px-2.5 py-1 leading-4 text-xs font-medium dark:bg-gray-600 border border-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 hover:text-slate-700 dark:hover:text-slate-300 select-none">
{{ $.locale.Tr "gist.raw" }}
</a>
<button type="button" class="relative -ml-px inline-flex items-center bg-white text-gray-500 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-10 px-1 py-1 dark:text-slate-300 dark:bg-gray-600 dark:hover:bg-gray-700 copy-gist-btn">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-5 h-5">
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 01-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 011.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 00-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 01-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 00-3.375-3.375h-1.5a1.125 1.125 0 01-1.125-1.125v-1.5a3.375 3.375 0 00-3.375-3.375H9.75" />
</svg>
</button>
<a href="{{ $.c.ExternalUrl }}/{{ $.gist.User.Username }}/{{ $.gist.Uuid }}/download/{{ $.commit }}/{{$file.Filename}}" class="relative -ml-px inline-flex items-center rounded-r-md bg-white text-gray-500 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-10 px-1 py-1 dark:text-slate-300 dark:bg-gray-600 dark:hover:bg-gray-700">
<a href="{{ $.c.ExternalUrl }}/{{ $.gist.User.Username }}/{{ $.gist.Uuid }}/download/{{ $.commit }}/{{$file.File.Filename}}" class="relative -ml-px inline-flex items-center rounded-r-md bg-white text-gray-500 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-10 px-1 py-1 dark:text-slate-300 dark:bg-gray-600 dark:hover:bg-gray-700">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-5 h-5">
<path stroke-linecap="round" stroke-linejoin="round" d="M3 16.5v2.25A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75V16.5M16.5 12L12 16.5m0 0L7.5 12m4.5 4.5V3" />
</svg>
</a>
</span>

<div class="hidden gist-content">{{ $file.Content }}</div>
<div class="hidden gist-content">{{ $file.File.Content }}</div>
</div>
{{ if $file.Truncated }}
{{ if $file.File.Truncated }}
<div class="text-sm px-4 py-1.5 border-t-1 border-gray-200 dark:border-gray-700">
{{ $.locale.Tr "gist.file-truncated" }} <a href="{{ $.c.ExternalUrl }}/{{ $.gist.User.Username }}/{{ $.gist.Uuid }}/raw/{{ $.commit }}/{{$file.Filename}}">{{ $.locale.Tr "gist.watch-full-file" }}.</a>
{{ $.locale.Tr "gist.file-truncated" }} <a href="{{ $.c.ExternalUrl }}/{{ $.gist.User.Username }}/{{ $.gist.Uuid }}/raw/{{ $.commit }}/{{$file.File.Filename}}">{{ $.locale.Tr "gist.watch-full-file" }}.</a>
</div>
{{ end }}
{{ if and (not $csv) (isCsv $file.Filename) }}
{{ if and (not $csv) (isCsv $file.File.Filename) }}
<div class="text-sm px-4 py-1.5 border-t-1 border-gray-200 dark:border-gray-700">
{{ $.locale.Tr "gist.file-not-valid" }}
</div>
Expand All @@ -64,17 +66,17 @@
</tr>
{{ end }}
</table>
{{ else if isMarkdown $file.Filename }}
<div class="markdown markdown-body p-8">{{ $file.Content }}</div>
{{ else if isMarkdown $file.File.Filename }}
<div class="markdown markdown-body p-8">{{ $file.File.Content }}</div>
{{ else }}
<div class="code">
{{ $fileslug := slug $file.Filename }}
{{ if ne $file.Content "" }}
<table class="chroma table-code w-full whitespace-pre" data-filename-slug="{{ $fileslug }}" data-filename="{{ $file.Filename }}" style="font-size: 0.8em; border-spacing: 0; border-collapse: collapse;">
{{ $fileslug := slug $file.File.Filename }}
{{ if ne $file.File.Content "" }}
<table class="chroma table-code w-full whitespace-pre" data-filename-slug="{{ $fileslug }}" data-filename="{{ $file.File.Filename }}" style="font-size: 0.8em; border-spacing: 0; border-collapse: collapse;">
<tbody>
{{ $ii := "1" }}
{{ $i := toInt $ii }}
{{ range $line := lines $file.Content }}<tr><td id="file-{{ $fileslug }}-{{$i}}" class="select-none line-num px-4">{{$i}}</td><td class="line-code">{{ $line | safe }}</td></tr>{{ $i = inc $i }}{{ end }}
{{ range $line := lines $file.HTML }}<tr><td id="file-{{ $fileslug }}-{{$i}}" class="select-none line-num px-4">{{$i}}</td><td class="line-code">{{ $line | safe }}</td></tr>{{ $i = inc $i }}{{ end }}
</tbody>
</table>
{{ end }}
Expand Down

0 comments on commit 4def229

Please sign in to comment.