mirror of
https://github.com/thomiceli/opengist.git
synced 2025-06-13 05:47:12 +02:00
Add embedded gists & JSON gist data/metadata (#179)
This commit is contained in:
@ -2,15 +2,19 @@ package web
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/thomiceli/opengist/internal/render"
|
||||
"html/template"
|
||||
"net/url"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/labstack/echo/v4"
|
||||
@ -26,7 +30,17 @@ func gistInit(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
userName := ctx.Param("user")
|
||||
gistName := ctx.Param("gistname")
|
||||
|
||||
gistName = strings.TrimSuffix(gistName, ".git")
|
||||
switch filepath.Ext(gistName) {
|
||||
case ".js":
|
||||
setData(ctx, "gistpage", "js")
|
||||
gistName = strings.TrimSuffix(gistName, ".js")
|
||||
case ".json":
|
||||
setData(ctx, "gistpage", "json")
|
||||
gistName = strings.TrimSuffix(gistName, ".json")
|
||||
case ".git":
|
||||
setData(ctx, "gistpage", "git")
|
||||
gistName = strings.TrimSuffix(gistName, ".git")
|
||||
}
|
||||
|
||||
gist, err := db.GetGist(userName, gistName)
|
||||
if err != nil {
|
||||
@ -71,12 +85,15 @@ func gistInit(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
baseHttpUrl = httpProtocol + "://" + ctx.Request().Host
|
||||
}
|
||||
|
||||
setData(ctx, "baseHttpUrl", baseHttpUrl)
|
||||
|
||||
if config.C.HttpGit {
|
||||
setData(ctx, "httpCloneUrl", baseHttpUrl+"/"+userName+"/"+gistName+".git")
|
||||
}
|
||||
|
||||
setData(ctx, "httpCopyUrl", baseHttpUrl+"/"+userName+"/"+gistName)
|
||||
setData(ctx, "currentUrl", template.URL(ctx.Request().URL.Path))
|
||||
setData(ctx, "embedScript", fmt.Sprintf(`<script src="%s"></script>`, baseHttpUrl+"/"+userName+"/"+gistName+".js"))
|
||||
|
||||
nbCommits, err := gist.NbCommits()
|
||||
if err != nil {
|
||||
@ -256,6 +273,12 @@ func allGists(ctx echo.Context) error {
|
||||
}
|
||||
|
||||
func gistIndex(ctx echo.Context) error {
|
||||
if getData(ctx, "gistpage") == "js" {
|
||||
return gistJs(ctx)
|
||||
} else if getData(ctx, "gistpage") == "json" {
|
||||
return gistJson(ctx)
|
||||
}
|
||||
|
||||
gist := getData(ctx, "gist").(*db.Gist)
|
||||
revision := ctx.Param("revision")
|
||||
|
||||
@ -272,13 +295,9 @@ 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)
|
||||
renderedFiles, err := render.HighlightFiles(files)
|
||||
if err != nil {
|
||||
return errorRes(500, "Error rendering files", err)
|
||||
}
|
||||
|
||||
setData(ctx, "page", "code")
|
||||
@ -289,6 +308,83 @@ func gistIndex(ctx echo.Context) error {
|
||||
return html(ctx, "gist.html")
|
||||
}
|
||||
|
||||
func gistJson(ctx echo.Context) error {
|
||||
gist := getData(ctx, "gist").(*db.Gist)
|
||||
files, err := gist.Files("HEAD")
|
||||
if err != nil {
|
||||
return errorRes(500, "Error fetching files", err)
|
||||
}
|
||||
|
||||
renderedFiles, err := render.HighlightFiles(files)
|
||||
if err != nil {
|
||||
return errorRes(500, "Error rendering files", err)
|
||||
}
|
||||
|
||||
setData(ctx, "files", renderedFiles)
|
||||
|
||||
htmlbuf := bytes.Buffer{}
|
||||
w := bufio.NewWriter(&htmlbuf)
|
||||
if err = ctx.Echo().Renderer.Render(w, "gist_embed.html", dataMap(ctx), ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
_ = w.Flush()
|
||||
|
||||
jsUrl, err := url.JoinPath(getData(ctx, "baseHttpUrl").(string), gist.User.Username, gist.Uuid+".js")
|
||||
if err != nil {
|
||||
return errorRes(500, "Error joining url", err)
|
||||
}
|
||||
|
||||
return ctx.JSON(200, map[string]interface{}{
|
||||
"owner": gist.User.Username,
|
||||
"id": gist.Uuid,
|
||||
"title": gist.Title,
|
||||
"description": gist.Description,
|
||||
"created_at": time.Unix(gist.CreatedAt, 0).Format(time.RFC3339),
|
||||
"visibility": gist.VisibilityStr(),
|
||||
"files": renderedFiles,
|
||||
"embed": map[string]string{
|
||||
"html": htmlbuf.String(),
|
||||
"css": getData(ctx, "baseHttpUrl").(string) + asset("embed.css"),
|
||||
"js": jsUrl,
|
||||
"js_dark": jsUrl + "?dark",
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func gistJs(ctx echo.Context) error {
|
||||
if _, exists := ctx.QueryParams()["dark"]; exists {
|
||||
setData(ctx, "dark", "dark")
|
||||
}
|
||||
|
||||
gist := getData(ctx, "gist").(*db.Gist)
|
||||
files, err := gist.Files("HEAD")
|
||||
if err != nil {
|
||||
return errorRes(500, "Error fetching files", err)
|
||||
}
|
||||
|
||||
renderedFiles, err := render.HighlightFiles(files)
|
||||
if err != nil {
|
||||
return errorRes(500, "Error rendering files", err)
|
||||
}
|
||||
|
||||
setData(ctx, "files", renderedFiles)
|
||||
|
||||
htmlbuf := bytes.Buffer{}
|
||||
w := bufio.NewWriter(&htmlbuf)
|
||||
if err = ctx.Echo().Renderer.Render(w, "gist_embed.html", dataMap(ctx), ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
_ = w.Flush()
|
||||
|
||||
js := `document.write('<link rel="stylesheet" href="%s">')
|
||||
document.write('%s')
|
||||
`
|
||||
js = fmt.Sprintf(js, getData(ctx, "baseHttpUrl").(string)+asset("embed.css"),
|
||||
strings.Replace(htmlbuf.String(), "\n", `\n`, -1))
|
||||
ctx.Response().Header().Set("Content-Type", "application/javascript")
|
||||
return plainText(ctx, 200, js)
|
||||
}
|
||||
|
||||
func revisions(ctx echo.Context) error {
|
||||
gist := getData(ctx, "gist").(*db.Gist)
|
||||
userName := gist.User.Username
|
||||
|
@ -86,12 +86,7 @@ var (
|
||||
|
||||
return defaultAvatar()
|
||||
},
|
||||
"asset": func(file string) string {
|
||||
if dev {
|
||||
return "http://localhost:16157/" + file
|
||||
}
|
||||
return config.C.ExternalUrl + "/" + manifestEntries[file].File
|
||||
},
|
||||
"asset": asset,
|
||||
"dev": func() bool {
|
||||
return dev
|
||||
},
|
||||
@ -482,3 +477,10 @@ func defaultAvatar() string {
|
||||
}
|
||||
return config.C.ExternalUrl + "/" + manifestEntries["default.png"].File
|
||||
}
|
||||
|
||||
func asset(file string) string {
|
||||
if dev {
|
||||
return "http://localhost:16157/" + file
|
||||
}
|
||||
return config.C.ExternalUrl + "/" + manifestEntries[file].File
|
||||
}
|
||||
|
@ -36,6 +36,10 @@ func getData(ctx echo.Context, key string) any {
|
||||
return data[key]
|
||||
}
|
||||
|
||||
func dataMap(ctx echo.Context) echo.Map {
|
||||
return ctx.Request().Context().Value(dataKey).(echo.Map)
|
||||
}
|
||||
|
||||
func html(ctx echo.Context, template string) error {
|
||||
return htmlWithCode(ctx, 200, template)
|
||||
}
|
||||
|
Reference in New Issue
Block a user