diff --git a/go.mod b/go.mod index 08cd873..eb4c287 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,8 @@ module github.com/thomiceli/opengist go 1.20 require ( + github.com/alecthomas/chroma/v2 v2.12.0 + github.com/dustin/go-humanize v1.0.1 github.com/glebarez/go-sqlite v1.21.2 github.com/glebarez/sqlite v1.9.0 github.com/go-playground/validator/v10 v10.15.4 @@ -13,6 +15,10 @@ require ( github.com/markbates/goth v1.78.0 github.com/rs/zerolog v1.30.0 github.com/stretchr/testify v1.8.4 + github.com/yuin/goldmark v1.6.0 + github.com/yuin/goldmark-emoji v1.0.2 + github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc + go.abhg.dev/goldmark/mermaid v0.5.0 golang.org/x/crypto v0.13.0 golang.org/x/text v0.13.0 gopkg.in/yaml.v3 v3.0.1 @@ -21,7 +27,7 @@ require ( require ( github.com/davecgh/go-spew v1.1.1 // indirect - github.com/dustin/go-humanize v1.0.1 // indirect + github.com/dlclark/regexp2 v1.10.0 // indirect github.com/gabriel-vasile/mimetype v1.4.2 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect diff --git a/go.sum b/go.sum index d16ac2d..0fe936e 100644 --- a/go.sum +++ b/go.sum @@ -34,7 +34,16 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9 dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/alecthomas/assert/v2 v2.2.1 h1:XivOgYcduV98QCahG8T5XTezV5bylXe+lBxLG2K2ink= +github.com/alecthomas/chroma/v2 v2.2.0/go.mod h1:vf4zrexSH54oEjJ7EdB65tGNHmH3pGZmVkgTP5RHvAs= +github.com/alecthomas/chroma/v2 v2.12.0 h1:Wh8qLEgMMsN7mgyG8/qIpegky2Hvzr4By6gEF7cmWgw= +github.com/alecthomas/chroma/v2 v2.12.0/go.mod h1:4TQu7gdfuPjSh76j78ietmqh9LiurGF0EpseFXdKMBw= +github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8= +github.com/alecthomas/repr v0.2.0 h1:HAzS41CIzNW5syS8Mf9UwXhNH1J9aix/BvDRf1Ml2Yk= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/chromedp/cdproto v0.0.0-20230220211738-2b1ec77315c9 h1:wMSvdj3BswqfQOXp2R1bJOAE7xIQLt2dlMQDMf836VY= +github.com/chromedp/chromedp v0.9.1 h1:CC7cC5p1BeLiiS2gfNNPwp3OaUxtRMBjfiw3E3k6dFA= +github.com/chromedp/sysutil v1.0.0 h1:+ZxhTpfpZlmchB58ih/LBHX52ky7w2VhQVKQMucy3Ic= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -46,6 +55,10 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210816181553-5444fa50b93d/go.mod h1:tmAIfUFEirG/Y8jhZ9M+h36obRZAk/1fcSpXwAVlfqE= +github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/dlclark/regexp2 v1.10.0 h1:+/GIL799phkJqYW+3YbOd8LCcbHzT0Pbo8zl70MHsq0= +github.com/dlclark/regexp2 v1.10.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -68,6 +81,9 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/validator/v10 v10.15.4 h1:zMXza4EpOdooxPel5xDqXEdXG5r+WggpvnAKMsalBjs= github.com/go-playground/validator/v10 v10.15.4/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= +github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= +github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= +github.com/gobwas/ws v1.1.0 h1:7RFti/xnNkMJnrK7D1yQ/iCIB5OrrY/54/H930kIbHA= github.com/goccy/go-json v0.9.6/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= @@ -151,12 +167,14 @@ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/jarcoal/httpmock v0.0.0-20180424175123-9c70cfe4a1da/go.mod h1:ks+b9deReOc7jgqp+e7LuFiCBH6Rm5hL32cLcEAArb4= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= @@ -177,6 +195,7 @@ github.com/lestrrat-go/httpcc v1.0.0/go.mod h1:tGS/u00Vh5N6FHNkExqGGNId8e0Big+++ github.com/lestrrat-go/iter v1.0.1/go.mod h1:zIdgO1mRKhn8l9vrZJZz9TUMMFbQbLeTsbqPDrJ/OJc= github.com/lestrrat-go/jwx v1.2.21/go.mod h1:9cfxnOH7G1gN75CaJP2hKGcxFEx5sPh1abRIA/ZJVh4= github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/markbates/going v1.0.0/go.mod h1:I6mnB4BPnEeqo85ynXIx1ZFLLbtiLHNXVgWeFO9OGOA= github.com/markbates/goth v1.78.0 h1:7VEIFDycJp9deyVv3YraGBPdD0ZYQW93Y3Aw1eVP3BY= github.com/markbates/goth v1.78.0/go.mod h1:X6xdNgpapSENS0O35iTBBcMHoJDQDfI9bJl+APCkYMc= @@ -220,7 +239,17 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.7/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yuin/goldmark v1.4.15/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yuin/goldmark v1.6.0 h1:boZcn2GTjpsynOsC0iJHnBWa4Bi0qzfJjthwauItG68= +github.com/yuin/goldmark v1.6.0/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yuin/goldmark-emoji v1.0.2 h1:c/RgTShNgHTtc6xdz2KKI74jJr6rWi7FPgnP9GAsO5s= +github.com/yuin/goldmark-emoji v1.0.2/go.mod h1:RhP/RWpexdp+KHs7ghKnifRoIs/Bq4nDS7tRbCkOwKY= +github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc h1:+IAOyRda+RLrxa1WC7umKOZRsGq4QrFFMYApOeHzQwQ= +github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc/go.mod h1:ovIvrum6DQJA4QsJSovrkC4saKHQVs7TvcaeO8AIl5I= +go.abhg.dev/goldmark/mermaid v0.5.0 h1:mDkykpSPJ+5wCQ8bSXgzJ2KQskjXkI5Ndxz7JYDHW38= +go.abhg.dev/goldmark/mermaid v0.5.0/go.mod h1:OCyk2o85TX2drWHH+HRy6bih2yZlUwbbv/R1MMh1YLs= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= diff --git a/internal/db/gist.go b/internal/db/gist.go index d11fe5e..0e3168a 100644 --- a/internal/db/gist.go +++ b/internal/db/gist.go @@ -2,11 +2,12 @@ package db import ( "fmt" + "github.com/dustin/go-humanize" + "github.com/labstack/echo/v4" "os/exec" "strings" "time" - "github.com/labstack/echo/v4" "github.com/thomiceli/opengist/internal/git" "gorm.io/gorm" ) @@ -339,8 +340,16 @@ func (gist *Gist) File(revision string, filename string, truncate bool) (*git.Fi return nil, nil } + var size int64 + + size, err = git.GetFileSize(gist.User.Username, gist.Uuid, revision, filename) + if err != nil { + return nil, err + } + return &git.File{ Filename: filename, + Size: humanize.IBytes(uint64(size)), Content: content, Truncated: truncated, }, err diff --git a/internal/git/commands.go b/internal/git/commands.go index 707c81e..bee20d1 100644 --- a/internal/git/commands.go +++ b/internal/git/commands.go @@ -149,6 +149,25 @@ func GetFileContent(user string, gist string, revision string, filename string, return content, truncated, nil } +func GetFileSize(user string, gist string, revision string, filename string) (int64, error) { + repositoryPath := RepositoryPath(user, gist) + + cmd := exec.Command( + "git", + "cat-file", + "-s", + revision+":"+filename, + ) + cmd.Dir = repositoryPath + + stdout, err := cmd.Output() + if err != nil { + return 0, err + } + + return strconv.ParseInt(strings.TrimSuffix(string(stdout), "\n"), 10, 64) +} + func GetLog(user string, gist string, skip int) ([]*Commit, error) { repositoryPath := RepositoryPath(user, gist) diff --git a/internal/git/output_parser.go b/internal/git/output_parser.go index 3d51927..9012631 100644 --- a/internal/git/output_parser.go +++ b/internal/git/output_parser.go @@ -12,6 +12,7 @@ import ( type File struct { Filename string + Size string OldFilename string Content string Truncated bool diff --git a/internal/render/highlight.go b/internal/render/highlight.go new file mode 100644 index 0000000..d70326d --- /dev/null +++ b/internal/render/highlight.go @@ -0,0 +1,134 @@ +package render + +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/thomiceli/opengist/internal/db" + "github.com/thomiceli/opengist/internal/git" +) + +type RenderedFile struct { + *git.File + Type string + Lines []string + HTML string +} + +type RenderedGist struct { + *db.Gist + Lines []string + HTML string +} + +func HighlightFile(file *git.File) (RenderedFile, error) { + rendered := RenderedFile{ + File: file, + } + + style := newStyle() + lexer := newLexer(file.Filename) + if lexer.Config().Name == "markdown" { + return MarkdownFile(file) + } + + formatter := html.New(html.WithClasses(true), html.PreventSurroundingPre(true)) + + iterator, err := lexer.Tokenise(nil, file.Content) + if err != nil { + return rendered, err + } + + htmlbuf := bytes.Buffer{} + w := bufio.NewWriter(&htmlbuf) + + tokensLines := chroma.SplitTokensIntoLines(iterator.Tokens()) + lines := make([]string, 0, len(tokensLines)) + for _, tokens := range tokensLines { + iterator = chroma.Literator(tokens...) + err = formatter.Format(&htmlbuf, style, iterator) + if err != nil { + return rendered, fmt.Errorf("unable to format code: %w", err) + } + lines = append(lines, htmlbuf.String()) + htmlbuf.Reset() + } + + _ = w.Flush() + + rendered.Lines = lines + rendered.Type = parseFileTypeName(*lexer.Config()) + + return rendered, err +} + +func HighlightGistPreview(gist *db.Gist) (RenderedGist, error) { + rendered := RenderedGist{ + Gist: gist, + } + + style := newStyle() + lexer := newLexer(gist.PreviewFilename) + if lexer.Config().Name == "markdown" { + return MarkdownGistPreview(gist) + } + + formatter := html.New(html.WithClasses(true), html.PreventSurroundingPre(true)) + + iterator, err := lexer.Tokenise(nil, gist.Preview) + if err != nil { + return rendered, err + } + + htmlbuf := bytes.Buffer{} + w := bufio.NewWriter(&htmlbuf) + + tokensLines := chroma.SplitTokensIntoLines(iterator.Tokens()) + lines := make([]string, 0, len(tokensLines)) + for _, tokens := range tokensLines { + iterator = chroma.Literator(tokens...) + err = formatter.Format(&htmlbuf, style, iterator) + if err != nil { + return rendered, fmt.Errorf("unable to format code: %w", err) + } + lines = append(lines, htmlbuf.String()) + htmlbuf.Reset() + } + + _ = w.Flush() + + rendered.Lines = lines + + return rendered, err +} + +func parseFileTypeName(config chroma.Config) string { + fileType := config.Name + if fileType == "fallback" || fileType == "plaintext" { + return "Text" + } + + return fileType +} + +func newLexer(filename string) chroma.Lexer { + var lexer chroma.Lexer + if lexer = lexers.Get(filename); lexer == nil { + lexer = lexers.Fallback + } + + return lexer +} + +func newStyle() *chroma.Style { + var style *chroma.Style + if style = styles.Get("catppuccin-latte"); style == nil { + style = styles.Fallback + } + + return style +} diff --git a/internal/render/markdown.go b/internal/render/markdown.go new file mode 100644 index 0000000..c3c1d16 --- /dev/null +++ b/internal/render/markdown.go @@ -0,0 +1,47 @@ +package render + +import ( + "bytes" + "github.com/alecthomas/chroma/v2/formatters/html" + "github.com/thomiceli/opengist/internal/db" + "github.com/thomiceli/opengist/internal/git" + "github.com/yuin/goldmark" + emoji "github.com/yuin/goldmark-emoji" + highlighting "github.com/yuin/goldmark-highlighting/v2" + "github.com/yuin/goldmark/extension" + "go.abhg.dev/goldmark/mermaid" +) + +func MarkdownGistPreview(gist *db.Gist) (RenderedGist, error) { + var buf bytes.Buffer + err := newMarkdown().Convert([]byte(gist.Preview), &buf) + + return RenderedGist{ + Gist: gist, + HTML: buf.String(), + }, err +} + +func MarkdownFile(file *git.File) (RenderedFile, error) { + var buf bytes.Buffer + err := newMarkdown().Convert([]byte(file.Content), &buf) + + return RenderedFile{ + File: file, + HTML: buf.String(), + Type: "Markdown", + }, err +} + +func newMarkdown() goldmark.Markdown { + return goldmark.New( + goldmark.WithExtensions( + extension.GFM, + highlighting.NewHighlighting( + highlighting.WithStyle("catppuccin-latte"), + highlighting.WithFormatOptions(html.WithClasses(true))), + emoji.Emoji, + &mermaid.Extender{}, + ), + ) +} diff --git a/internal/web/gist.go b/internal/web/gist.go index 2a0367c..2b94ccc 100644 --- a/internal/web/gist.go +++ b/internal/web/gist.go @@ -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" @@ -232,11 +234,20 @@ func allGists(ctx echo.Context) error { } } + renderedFiles := make([]*render.RenderedGist, 0, len(gists)) + for _, gist := range gists { + rendered, err := render.HighlightGistPreview(gist) + if err != nil { + log.Warn().Err(err).Msg("Error rendering gist preview for " + gist.Uuid + " - " + gist.PreviewFilename) + } + renderedFiles = append(renderedFiles, &rendered) + } + if err != nil { return errorRes(500, "Error fetching gists", err) } - if err = paginate(ctx, gists, pageInt, 10, "gists", fromUserStr, 2, "&sort="+sort+"&order="+order); err != nil { + if err = paginate(ctx, renderedFiles, pageInt, 10, "gists", fromUserStr, 2, "&sort="+sort+"&order="+order); err != nil { return errorRes(404, "Page not found", nil) } @@ -261,9 +272,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.HighlightFile(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") diff --git a/internal/web/server.go b/internal/web/server.go index 880f7ac..cb651b2 100644 --- a/internal/web/server.go +++ b/internal/web/server.go @@ -117,6 +117,9 @@ var ( "toStr": func(i interface{}) string { return fmt.Sprint(i) }, + "safe": func(s string) template.HTML { + return template.HTML(s) + }, } ) diff --git a/package-lock.json b/package-lock.json index 8e4a536..e27c2a5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,9 +20,7 @@ "codemirror": "^6.0.1", "cssnano": "^5.1.15", "dayjs": "^1.11.9", - "github-markdown-css": "^5.2.0", - "highlight.js": "^11.7.0", - "markdown-it": "^13.0.1", + "github-markdown-css": "^5.5.0", "nodemon": "^2.0.22", "postcss": "^8.4.13", "postcss-cssnext": "^3.1.1", @@ -614,9 +612,9 @@ } }, "node_modules/@lezer/javascript": { - "version": "1.4.10", - "resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.4.10.tgz", - "integrity": "sha512-XJu3fZjHVVjJcRS7kHdwBO50irXc4H8rQwgm6SmT3Y8IHWk7WzpaLsaR2vdr/jSk/J4pQhXc1WLul7jVdxC+0Q==", + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.4.11.tgz", + "integrity": "sha512-B5Y9EJF4BWiMgj4ufxUo2hrORnmMBDrMtR+L7dwIO5pocuSAahG6QBwXR6PbKJOjRywJczU2r2LJPg79ER91TQ==", "dev": true, "dependencies": { "@lezer/highlight": "^1.1.3", @@ -1591,15 +1589,6 @@ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, - "node_modules/dom-serializer/node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, "node_modules/domelementtype": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", @@ -1662,13 +1651,10 @@ } }, "node_modules/entities": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", - "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", "dev": true, - "engines": { - "node": ">=0.12" - }, "funding": { "url": "https://github.com/fb55/entities?sponsor=1" } @@ -1980,15 +1966,6 @@ "node": ">= 0.4" } }, - "node_modules/highlight.js": { - "version": "11.9.0", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.9.0.tgz", - "integrity": "sha512-fJ7cW7fQGCYAkgv4CPfwFHrfd/cLS4Hau96JuJ+ZTOWhjnhoeN1ub1tFmALm/+lW5z4WCAuAV9bm05AP0mS6Gw==", - "dev": true, - "engines": { - "node": ">=12.0.0" - } - }, "node_modules/ignore-by-default": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", @@ -2204,15 +2181,6 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true }, - "node_modules/linkify-it": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-4.0.1.tgz", - "integrity": "sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==", - "dev": true, - "dependencies": { - "uc.micro": "^1.0.1" - } - }, "node_modules/loader-runner": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", @@ -2290,22 +2258,6 @@ "node": ">=10" } }, - "node_modules/markdown-it": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-13.0.2.tgz", - "integrity": "sha512-FtwnEuuK+2yVU7goGn/MJ0WBZMM9ZPgU9spqlFs7/A/pDIUNSOQZhUgOqYCficIuR2QaFnrt8LHqBWsbTAoI5w==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1", - "entities": "~3.0.1", - "linkify-it": "^4.0.1", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" - }, - "bin": { - "markdown-it": "bin/markdown-it.js" - } - }, "node_modules/math-expression-evaluator": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/math-expression-evaluator/-/math-expression-evaluator-1.4.0.tgz", @@ -2318,12 +2270,6 @@ "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", "dev": true }, - "node_modules/mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", - "dev": true - }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -4880,12 +4826,6 @@ "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", "dev": true }, - "node_modules/uc.micro": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", - "dev": true - }, "node_modules/undefsafe": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", diff --git a/package.json b/package.json index b4fa934..c42ec05 100644 --- a/package.json +++ b/package.json @@ -20,9 +20,7 @@ "codemirror": "^6.0.1", "cssnano": "^5.1.15", "dayjs": "^1.11.9", - "github-markdown-css": "^5.2.0", - "highlight.js": "^11.7.0", - "markdown-it": "^13.0.1", + "github-markdown-css": "^5.5.0", "nodemon": "^2.0.22", "postcss": "^8.4.13", "postcss-cssnext": "^3.1.1", diff --git a/public/catppuccin-latte.css b/public/catppuccin-latte.css new file mode 100644 index 0000000..93bc24b --- /dev/null +++ b/public/catppuccin-latte.css @@ -0,0 +1,73 @@ +/* Error */ .chroma .err { color: #d20f39 } +/* LineLink */ .chroma .lnlinks { outline: none; text-decoration: none; color: inherit } +/* LineTableTD */ .chroma .lntd { vertical-align: top; padding: 0; margin: 0; border: 0; } +/* LineTable */ .chroma .lntable { border-spacing: 0; padding: 0; margin: 0; border: 0; } +/* LineHighlight */ .chroma .hl { color: #bcc0cc } +/* LineNumbersTable */ .chroma .lnt { white-space: pre; -webkit-user-select: none; user-select: none; margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #8c8fa1 } +/* LineNumbers */ .chroma .ln { white-space: pre; -webkit-user-select: none; user-select: none; margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #8c8fa1 } +/* Line */ .chroma .line { display: flex; } +/* Keyword */ .chroma .k { color: #8839ef } +/* KeywordConstant */ .chroma .kc { color: #fe640b } +/* KeywordDeclaration */ .chroma .kd { color: #d20f39 } +/* KeywordNamespace */ .chroma .kn { color: #179299 } +/* KeywordPseudo */ .chroma .kp { color: #8839ef } +/* KeywordReserved */ .chroma .kr { color: #8839ef } +/* KeywordType */ .chroma .kt { color: #d20f39 } +/* NameAttribute */ .chroma .na { color: #1e66f5 } +/* NameBuiltin */ .chroma .nb { color: #04a5e5 } +/* NameBuiltinPseudo */ .chroma .bp { color: #04a5e5 } +/* NameClass */ .chroma .nc { color: #df8e1d } +/* NameConstant */ .chroma .no { color: #df8e1d } +/* NameDecorator */ .chroma .nd { color: #1e66f5; font-weight: bold } +/* NameEntity */ .chroma .ni { color: #179299 } +/* NameException */ .chroma .ne { color: #fe640b } +/* NameFunction */ .chroma .nf { color: #1e66f5 } +/* NameFunctionMagic */ .chroma .fm { color: #1e66f5 } +/* NameLabel */ .chroma .nl { color: #04a5e5 } +/* NameNamespace */ .chroma .nn { color: #fe640b } +/* NameProperty */ .chroma .py { color: #fe640b } +/* NameTag */ .chroma .nt { color: #8839ef } +/* NameVariable */ .chroma .nv { color: #dc8a78 } +/* NameVariableClass */ .chroma .vc { color: #dc8a78 } +/* NameVariableGlobal */ .chroma .vg { color: #dc8a78 } +/* NameVariableInstance */ .chroma .vi { color: #dc8a78 } +/* NameVariableMagic */ .chroma .vm { color: #dc8a78 } +/* LiteralString */ .chroma .s { color: #40a02b } +/* LiteralStringAffix */ .chroma .sa { color: #d20f39 } +/* LiteralStringBacktick */ .chroma .sb { color: #40a02b } +/* LiteralStringChar */ .chroma .sc { color: #40a02b } +/* LiteralStringDelimiter */ .chroma .dl { color: #1e66f5 } +/* LiteralStringDoc */ .chroma .sd { color: #9ca0b0 } +/* LiteralStringDouble */ .chroma .s2 { color: #40a02b } +/* LiteralStringEscape */ .chroma .se { color: #1e66f5 } +/* LiteralStringHeredoc */ .chroma .sh { color: #9ca0b0 } +/* LiteralStringInterpol */ .chroma .si { color: #40a02b } +/* LiteralStringOther */ .chroma .sx { color: #40a02b } +/* LiteralStringRegex */ .chroma .sr { color: #179299 } +/* LiteralStringSingle */ .chroma .s1 { color: #40a02b } +/* LiteralStringSymbol */ .chroma .ss { color: #40a02b } +/* LiteralNumber */ .chroma .m { color: #fe640b } +/* LiteralNumberBin */ .chroma .mb { color: #fe640b } +/* LiteralNumberFloat */ .chroma .mf { color: #fe640b } +/* LiteralNumberHex */ .chroma .mh { color: #fe640b } +/* LiteralNumberInteger */ .chroma .mi { color: #fe640b } +/* LiteralNumberIntegerLong */ .chroma .il { color: #fe640b } +/* LiteralNumberOct */ .chroma .mo { color: #fe640b } +/* Operator */ .chroma .o { color: #04a5e5; font-weight: bold } +/* OperatorWord */ .chroma .ow { color: #04a5e5; font-weight: bold } +/* Comment */ .chroma .c { color: #9ca0b0; font-style: italic } +/* CommentHashbang */ .chroma .ch { color: #9ca0b0; font-style: italic } +/* CommentMultiline */ .chroma .cm { color: #9ca0b0; font-style: italic } +/* CommentSingle */ .chroma .c1 { color: #9ca0b0; font-style: italic } +/* CommentSpecial */ .chroma .cs { color: #9ca0b0; font-style: italic } +/* CommentPreproc */ .chroma .cp { color: #9ca0b0; font-style: italic } +/* CommentPreprocFile */ .chroma .cpf { color: #9ca0b0; font-weight: bold; font-style: italic } +/* GenericDeleted */ .chroma .gd { color: #d20f39; background-color: #ccd0da } +/* GenericEmph */ .chroma .ge { font-style: italic } +/* GenericError */ .chroma .gr { color: #d20f39 } +/* GenericHeading */ .chroma .gh { color: #fe640b; font-weight: bold } +/* GenericInserted */ .chroma .gi { color: #40a02b; background-color: #ccd0da } +/* GenericStrong */ .chroma .gs { font-weight: bold } +/* GenericSubheading */ .chroma .gu { color: #fe640b; font-weight: bold } +/* GenericTraceback */ .chroma .gt { color: #d20f39 } +/* GenericUnderline */ .chroma .gl { text-decoration: underline } diff --git a/public/catppuccin-macchiato.css b/public/catppuccin-macchiato.css new file mode 100644 index 0000000..cc4714b --- /dev/null +++ b/public/catppuccin-macchiato.css @@ -0,0 +1,73 @@ +/* Error */ .chroma .err { color: #f38ba8 } +/* LineLink */ .chroma .lnlinks { outline: none; text-decoration: none; color: inherit } +/* LineTableTD */ .chroma .lntd { vertical-align: top; padding: 0; margin: 0; border: 0; } +/* LineTable */ .chroma .lntable { border-spacing: 0; padding: 0; margin: 0; border: 0; } +/* LineHighlight */ .chroma .hl { color: #45475a } +/* LineNumbersTable */ .chroma .lnt { white-space: pre; -webkit-user-select: none; user-select: none; margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #7f849c } +/* LineNumbers */ .chroma .ln { white-space: pre; -webkit-user-select: none; user-select: none; margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #7f849c } +/* Line */ .chroma .line { display: flex; } +/* Keyword */ .chroma .k { color: #cba6f7 } +/* KeywordConstant */ .chroma .kc { color: #fab387 } +/* KeywordDeclaration */ .chroma .kd { color: #f38ba8 } +/* KeywordNamespace */ .chroma .kn { color: #94e2d5 } +/* KeywordPseudo */ .chroma .kp { color: #cba6f7 } +/* KeywordReserved */ .chroma .kr { color: #cba6f7 } +/* KeywordType */ .chroma .kt { color: #f38ba8 } +/* NameAttribute */ .chroma .na { color: #89b4fa } +/* NameBuiltin */ .chroma .nb { color: #89dceb } +/* NameBuiltinPseudo */ .chroma .bp { color: #89dceb } +/* NameClass */ .chroma .nc { color: #f9e2af } +/* NameConstant */ .chroma .no { color: #f9e2af } +/* NameDecorator */ .chroma .nd { color: #89b4fa; font-weight: bold } +/* NameEntity */ .chroma .ni { color: #94e2d5 } +/* NameException */ .chroma .ne { color: #fab387 } +/* NameFunction */ .chroma .nf { color: #89b4fa } +/* NameFunctionMagic */ .chroma .fm { color: #89b4fa } +/* NameLabel */ .chroma .nl { color: #89dceb } +/* NameNamespace */ .chroma .nn { color: #fab387 } +/* NameProperty */ .chroma .py { color: #fab387 } +/* NameTag */ .chroma .nt { color: #cba6f7 } +/* NameVariable */ .chroma .nv { color: #f5e0dc } +/* NameVariableClass */ .chroma .vc { color: #f5e0dc } +/* NameVariableGlobal */ .chroma .vg { color: #f5e0dc } +/* NameVariableInstance */ .chroma .vi { color: #f5e0dc } +/* NameVariableMagic */ .chroma .vm { color: #f5e0dc } +/* LiteralString */ .chroma .s { color: #a6e3a1 } +/* LiteralStringAffix */ .chroma .sa { color: #f38ba8 } +/* LiteralStringBacktick */ .chroma .sb { color: #a6e3a1 } +/* LiteralStringChar */ .chroma .sc { color: #a6e3a1 } +/* LiteralStringDelimiter */ .chroma .dl { color: #89b4fa } +/* LiteralStringDoc */ .chroma .sd { color: #6c7086 } +/* LiteralStringDouble */ .chroma .s2 { color: #a6e3a1 } +/* LiteralStringEscape */ .chroma .se { color: #89b4fa } +/* LiteralStringHeredoc */ .chroma .sh { color: #6c7086 } +/* LiteralStringInterpol */ .chroma .si { color: #a6e3a1 } +/* LiteralStringOther */ .chroma .sx { color: #a6e3a1 } +/* LiteralStringRegex */ .chroma .sr { color: #94e2d5 } +/* LiteralStringSingle */ .chroma .s1 { color: #a6e3a1 } +/* LiteralStringSymbol */ .chroma .ss { color: #a6e3a1 } +/* LiteralNumber */ .chroma .m { color: #fab387 } +/* LiteralNumberBin */ .chroma .mb { color: #fab387 } +/* LiteralNumberFloat */ .chroma .mf { color: #fab387 } +/* LiteralNumberHex */ .chroma .mh { color: #fab387 } +/* LiteralNumberInteger */ .chroma .mi { color: #fab387 } +/* LiteralNumberIntegerLong */ .chroma .il { color: #fab387 } +/* LiteralNumberOct */ .chroma .mo { color: #fab387 } +/* Operator */ .chroma .o { color: #89dceb; font-weight: bold } +/* OperatorWord */ .chroma .ow { color: #89dceb; font-weight: bold } +/* Comment */ .chroma .c { color: #6c7086; font-style: italic } +/* CommentHashbang */ .chroma .ch { color: #6c7086; font-style: italic } +/* CommentMultiline */ .chroma .cm { color: #6c7086; font-style: italic } +/* CommentSingle */ .chroma .c1 { color: #6c7086; font-style: italic } +/* CommentSpecial */ .chroma .cs { color: #6c7086; font-style: italic } +/* CommentPreproc */ .chroma .cp { color: #6c7086; font-style: italic } +/* CommentPreprocFile */ .chroma .cpf { color: #6c7086; font-weight: bold; font-style: italic } +/* GenericDeleted */ .chroma .gd { color: #f38ba8; background-color: #313244 } +/* GenericEmph */ .chroma .ge { font-style: italic } +/* GenericError */ .chroma .gr { color: #f38ba8 } +/* GenericHeading */ .chroma .gh { color: #fab387; font-weight: bold } +/* GenericInserted */ .chroma .gi { color: #a6e3a1; background-color: #313244 } +/* GenericStrong */ .chroma .gs { font-weight: bold } +/* GenericSubheading */ .chroma .gu { color: #fab387; font-weight: bold } +/* GenericTraceback */ .chroma .gt { color: #f38ba8 } +/* GenericUnderline */ .chroma .gl { text-decoration: underline } diff --git a/public/gist.ts b/public/gist.ts new file mode 100644 index 0000000..e87ff65 --- /dev/null +++ b/public/gist.ts @@ -0,0 +1,38 @@ +document.querySelectorAll('.table-code').forEach((el) => { + el.addEventListener('click', event => { + if (event.target && (event.target as HTMLElement).matches('.line-num')) { + Array.from(document.querySelectorAll('.table-code .selected')).forEach((el) => el.classList.remove('selected')); + + const nextSibling = (event.target as HTMLElement).nextSibling; + if (nextSibling instanceof HTMLElement) { + nextSibling.classList.add('selected'); + } + + const filename = el.dataset.filenameSlug; + const line = (event.target as HTMLElement).textContent; + const url = location.protocol + '//' + location.host + location.pathname; + const hash = '#file-' + filename + '-' + line; + window.history.pushState(null, null, url + hash); + location.hash = hash; + } + }); +}); + +let copybtnhtml = ``; + +document.querySelectorAll('.markdown-body pre').forEach((el) => { + el.innerHTML = copybtnhtml + `` + el.innerHTML + ``; +}); + +document.querySelectorAll('.md-code-copy-btn').forEach(button => { + button.addEventListener('click', function() { + let code = this.nextElementSibling.textContent; + navigator.clipboard.writeText(code).catch((err) => { + console.error('Could not copy text: ', err); + }); + }); +}); + + + + diff --git a/public/hljs.ts b/public/hljs.ts deleted file mode 100644 index 9d3e588..0000000 --- a/public/hljs.ts +++ /dev/null @@ -1,49 +0,0 @@ -import hljs from 'highlight.js'; -import md from 'markdown-it'; - -document.querySelectorAll('.markdown').forEach((e: HTMLElement) => { - e.innerHTML = md({ - html: true, - highlight: function (str, lang) { - if (lang && hljs.getLanguage(lang)) { - try { - return '
' +
-                        hljs.highlight(str, {language: lang, ignoreIllegals: true}).value +
-                        '
'; - } catch (__) { - } - } - - return '
' + md().utils.escapeHtml(str) + '
'; - } - }).render(e.textContent); -}); - -document.querySelectorAll('.table-code').forEach((el) => { - const ext = el.dataset.filename?.split('.').pop() || ''; - if (hljs.getLanguage(ext) && ext !== 'txt') { - el.querySelectorAll('td.line-code').forEach((ell) => { - ell.classList.add('language-' + ext); - hljs.highlightElement(ell); - }); - } - - el.addEventListener('click', event => { - if (event.target && (event.target as HTMLElement).matches('.line-num')) { - Array.from(document.querySelectorAll('.table-code .selected')).forEach((el) => el.classList.remove('selected')); - - const nextSibling = (event.target as HTMLElement).nextSibling; - if (nextSibling instanceof HTMLElement) { - nextSibling.classList.add('selected'); - } - - - const filename = el.dataset.filenameSlug; - const line = (event.target as HTMLElement).textContent; - const url = location.protocol + '//' + location.host + location.pathname; - const hash = '#file-' + filename + '-' + line; - window.history.pushState(null, null, url + hash); - location.hash = hash; - } - }); -}); diff --git a/public/style.css b/public/style.css index cd71221..203c8d3 100644 --- a/public/style.css +++ b/public/style.css @@ -156,3 +156,23 @@ dl.dl-config dd { .markdown-body { @apply dark:bg-gray-900 !important; } + +.markdown-body pre { + @apply flex relative items-start p-0 !important; +} + +.markdown-body .code-div { + @apply p-4 max-w-full overflow-x-auto !important; +} + +.markdown-body code { + @apply overflow-auto whitespace-pre !important; +} + +.chroma.preview.markdown code { + @apply p-4 !important; +} + +.mermaid { + background: #f6f8fa !important; +} diff --git a/public/style.scss b/public/style.scss index f21e64d..ba2fcbb 100644 --- a/public/style.scss +++ b/public/style.scss @@ -1,9 +1,9 @@ :root { @import "github-markdown-css/github-markdown-light"; - @import 'highlight.js/scss/base16/one-light.scss'; + @import './catppuccin-latte'; } .dark { @import "github-markdown-css/github-markdown-dark"; - @import 'highlight.js/scss/base16/onedark.scss'; + @import './catppuccin-macchiato'; } diff --git a/templates/base/base_footer.html b/templates/base/base_footer.html index c2c234c..99089cd 100644 --- a/templates/base/base_footer.html +++ b/templates/base/base_footer.html @@ -30,9 +30,6 @@ - - - diff --git a/templates/base/gist_footer.html b/templates/base/gist_footer.html index 4a02d1e..d791ac6 100644 --- a/templates/base/gist_footer.html +++ b/templates/base/gist_footer.html @@ -4,6 +4,7 @@ {{ end }} {{ define "gist_footer" }} + {{ end }} diff --git a/templates/base/gist_header.html b/templates/base/gist_header.html index 6262f5c..2d8636a 100644 --- a/templates/base/gist_header.html +++ b/templates/base/gist_header.html @@ -94,7 +94,7 @@

{{ .locale.Tr "gist.header.last-active" }} {{ .gist.UpdatedAt }} {{ if .gist.Private }} • {{ visibilityStr .gist.Private false }} {{ end }}

-

{{ .gist.Description }}

+

{{ .gist.Description }}

@@ -128,7 +128,7 @@
- +
diff --git a/templates/pages/all.html b/templates/pages/all.html index 70a7980..561a296 100644 --- a/templates/pages/all.html +++ b/templates/pages/all.html @@ -152,17 +152,17 @@
{{ if isMarkdown $gist.PreviewFilename }} -
{{ $gist.Preview }}
+
{{ $gist.HTML | safe }}
{{ else }} - +
{{ $ii := "1" }} {{ $i := toInt $ii }} - {{ range $line := lines $gist.Preview }} + {{ range $line := $gist.Lines }} - + {{ $i = inc $i }} {{ end }} diff --git a/templates/pages/gist.html b/templates/pages/gist.html index 7e9eca0..c07a90e 100644 --- a/templates/pages/gist.html +++ b/templates/pages/gist.html @@ -3,7 +3,7 @@ {{ if .files }}
{{ range $file := .files }} - {{ $csv := csvFile $file }} + {{ $csv := csvFile $file.File }}
@@ -12,7 +12,11 @@ - {{ $file.Filename }} + {{ $file.Filename }} + + @@ -63,16 +67,16 @@ {{ end }}
{{$i}}{{ $line }}{{ $line | safe }}
{{ else if isMarkdown $file.Filename }} -
{{ $file.Content }}
+
{{ $file.HTML | safe }}
{{ else }}
{{ $fileslug := slug $file.Filename }} {{ if ne $file.Content "" }} - +
{{ $ii := "1" }} {{ $i := toInt $ii }} - {{ range $line := lines $file.Content }}{{ $i = inc $i }}{{ end }} + {{ range $line := $file.Lines }}{{ $i = inc $i }}{{ end }}
{{$i}}{{ $line }}
{{$i}}{{ $line | safe }}
{{ end }} @@ -90,5 +94,11 @@

{{ .locale.Tr "gist.no-content" }}

{{ end }} + + + + + + {{ template "gist_footer" .}} {{ template "footer" .}} diff --git a/templates/pages/revisions.html b/templates/pages/revisions.html index 5bc06af..ee2b020 100644 --- a/templates/pages/revisions.html +++ b/templates/pages/revisions.html @@ -50,7 +50,7 @@ {{ else if eq $file.Content "" }}

{{ $.locale.Tr "gist.revision.empty-file" }}

{{ else }} - +
{{ $left := 0 }} {{ $right := 0 }} diff --git a/vite.config.js b/vite.config.js index 5d3ed1d..b161107 100644 --- a/vite.config.js +++ b/vite.config.js @@ -9,7 +9,7 @@ export default defineConfig({ assetsDir: 'assets', manifest: true, rollupOptions: { - input: ['./public/main.ts', './public/editor.ts', './public/admin.ts', './public/hljs.ts'] + input: ['./public/main.ts', './public/editor.ts', './public/admin.ts', './public/gist.ts'] }, assetsInlineLimit: 0, }