From 259ef3e601a271887dce930ed31f04bb456b890d Mon Sep 17 00:00:00 2001 From: Vegard Berg Date: Wed, 13 Sep 2023 20:03:34 +0200 Subject: [PATCH] Initial syntax highlighting added --- .air.toml | 2 +- config/config.go | 10 ++++++ controllers/info.go | 20 ++++++++++++ main.go | 22 +++++++++---- static/tailwind.css | 4 +++ utils/highlight_text.go | 70 ++++++++++++++++++++++++++++++++++++++++ views/pages/bin.templ | 3 +- views/pages/bin_templ.go | 24 +++++++------- 8 files changed, 135 insertions(+), 20 deletions(-) create mode 100644 controllers/info.go create mode 100644 utils/highlight_text.go diff --git a/.air.toml b/.air.toml index 8cd9e00..361cde6 100644 --- a/.air.toml +++ b/.air.toml @@ -3,7 +3,7 @@ testdata_dir = "testdata" tmp_dir = "tmp" [build] -args_bin = [] +args_bin = ["--debug"] bin = "./tmp/main" cmd = "just hot-reload" #cmd = "go build -o ./tmp/main" diff --git a/config/config.go b/config/config.go index c172d1d..eba835e 100644 --- a/config/config.go +++ b/config/config.go @@ -2,6 +2,7 @@ package config import ( "github.com/sirupsen/logrus" + "github.com/spf13/pflag" "github.com/spf13/viper" ) @@ -16,6 +17,7 @@ type smtp struct { var SMTP smtp = smtp{} var BaseURL string = "localhost" +var Debug bool = false func InitConfig() error { viper.SetDefault("host", "[::]") @@ -24,6 +26,7 @@ func InitConfig() error { viper.SetDefault("smtp.enabled", false) viper.SetDefault("user.registration_enabled", false) viper.SetDefault("base_url", "localhost") + viper.SetDefault("debug", false) viper.SetConfigName("config") viper.SetConfigType("toml") @@ -40,6 +43,13 @@ func InitConfig() error { } } + pflag.BoolP("debug", "D", false, "toggle debug mode") + pflag.Parse() + + viper.BindPFlags(pflag.CommandLine) + + Debug = viper.GetBool("debug") + SMTP = smtp{ Enabled: viper.GetBool("smtp.enabled"), Host: viper.GetString("smtp.host"), diff --git a/controllers/info.go b/controllers/info.go new file mode 100644 index 0000000..3b0da3a --- /dev/null +++ b/controllers/info.go @@ -0,0 +1,20 @@ +package controllers + +import ( + "github.com/alecthomas/chroma/formatters" + "github.com/alecthomas/chroma/lexers" + "github.com/alecthomas/chroma/styles" + "github.com/labstack/echo/v4" +) + +func GetInfoHandler(c echo.Context) error { + lexs := lexers.Names(false) + fmts := formatters.Names() + stls := styles.Names() + + return c.JSON(200, map[string][]string{ + "lexers": lexs, + "formatters": fmts, + "styles": stls, + }) +} diff --git a/main.go b/main.go index e99bb22..da076f8 100644 --- a/main.go +++ b/main.go @@ -21,12 +21,21 @@ import ( var static embed.FS func main() { - logrus.SetLevel(logrus.DebugLevel) + logrus.Infoln("Application started.") + config.InitConfig() + + e := echo.New() + e.Debug = config.Debug + + if e.Debug { + logrus.SetLevel(logrus.DebugLevel) + logrus.Infoln("Debug mode enabled.") + } else { + logrus.SetLevel(logrus.WarnLevel) + } logrus.SetFormatter(&prefixed.TextFormatter{ FullTimestamp: true, }) - logrus.Infoln("Application started.") - config.InitConfig() db_string := "bin.db" var err error @@ -40,9 +49,6 @@ func main() { models.DatabaseMigrations(global.DB) - e := echo.New() - e.Debug = false - e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{ LogURI: true, LogStatus: true, @@ -62,6 +68,10 @@ func main() { fs := echo.MustSubFS(static, "./static/") e.StaticFS("/static", fs) + if e.Debug { + e.GET("/info", controllers.GetInfoHandler) + } + e.GET("/", controllers.IndexHandler) e.GET("/new", controllers.GetNewHandler) e.POST("/new", controllers.PostNewHandler) diff --git a/static/tailwind.css b/static/tailwind.css index 5c3c5e8..7b51400 100644 --- a/static/tailwind.css +++ b/static/tailwind.css @@ -767,6 +767,10 @@ video { justify-self: start; } +.overflow-x-scroll { + overflow-x: scroll; +} + .rounded-lg { border-radius: 0.5rem; } diff --git a/utils/highlight_text.go b/utils/highlight_text.go new file mode 100644 index 0000000..ed9595f --- /dev/null +++ b/utils/highlight_text.go @@ -0,0 +1,70 @@ +package utils + +import ( + "bytes" + "context" + "fmt" + "io" + + "github.com/alecthomas/chroma/formatters/html" + "github.com/alecthomas/chroma/lexers" + "github.com/alecthomas/chroma/styles" + "github.com/sirupsen/logrus" +) + +type HighlightedText struct { + text string +} + +func (ht HighlightedText) Render(ctx context.Context, w io.Writer) error { + _, err := w.Write([]byte(ht.text)) + return err +} + +func NewPreText(text string) HighlightedText { + return HighlightedText{ + text: fmt.Sprintf("
%s
", text), + } +} + +func HighlightText(text, lang, style_name string) HighlightedText { + if style_name == "" { + style_name = "solarized-light" + } + style := styles.Get(style_name) + if style == nil { + logrus.WithField("style", style_name).Warnln("Cannot find style") + return NewPreText(text) + } + + lexer := lexers.Get(lang) + if lexer == nil { + return NewPreText(text) + } + + formatter := html.New(html.WithLineNumbers(true)) + if formatter == nil { + return NewPreText(text) + } + + tokens, err := lexer.Tokenise(nil, text) + if err != nil { + return NewPreText(text) + } + + buf := new(bytes.Buffer) + + err = formatter.Format(buf, style, tokens) + if err != nil { + return NewPreText(text) + } + + b, err := io.ReadAll(buf) + if err != nil { + return NewPreText(text) + } + + return HighlightedText{ + text: string(b), + } +} diff --git a/views/pages/bin.templ b/views/pages/bin.templ index f6551a2..341a693 100644 --- a/views/pages/bin.templ +++ b/views/pages/bin.templ @@ -5,6 +5,7 @@ import ( "git.myrkvi.com/myrkvi/bin/config" "git.myrkvi.com/myrkvi/bin/models" + "git.myrkvi.com/myrkvi/bin/utils" "git.myrkvi.com/myrkvi/bin/views/components" ) @@ -25,7 +26,7 @@ templ BinPartial(file models.File) { }

{ file.Description }

-
{ file.Data }
+
@utils.HighlightText(file.Data, file.Language, "")
")
+		_, err = templBuffer.WriteString("

") if err != nil { return err } - var var_8 string = file.Data - _, err = templBuffer.WriteString(templ.EscapeString(var_8)) + err = utils.HighlightText(file.Data, file.Language, "").Render(ctx, templBuffer) if err != nil { return err } - _, err = templBuffer.WriteString("