commit 1fd025e6d6328f75486aefd8c806f398281a4f4d Author: Andre Henriques Date: Mon Sep 18 00:26:42 2023 +0100 Initial commit diff --git a/.air.toml b/.air.toml new file mode 100644 index 0000000..ba6adb1 --- /dev/null +++ b/.air.toml @@ -0,0 +1,44 @@ +root = "." +testdata_dir = "testdata" +tmp_dir = "tmp" + +[build] + args_bin = [] + bin = "./tmp/main" + cmd = "go build -o ./tmp/main ." + delay = 0 + exclude_dir = ["assets", "tmp", "vendor", "testdata"] + exclude_file = [] + exclude_regex = ["_test.go"] + exclude_unchanged = false + follow_symlink = false + full_bin = "" + include_dir = [] + include_ext = ["go", "tpl", "tmpl", "html"] + include_file = [] + kill_delay = "0s" + log = "build-errors.log" + poll = false + poll_interval = 0 + rerun = false + rerun_delay = 500 + send_interrupt = true + stop_on_error = true + +[color] + app = "" + build = "yellow" + main = "magenta" + runner = "green" + watcher = "cyan" + +[log] + main_only = false + time = false + +[misc] + clean_on_exit = false + +[screen] + clear_on_rebuild = false + keep_scroll = true diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3fec32c --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +tmp/ diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..dcfee58 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module andr3h3nriqu3s.com/m + +go 1.20 diff --git a/handler.go b/handler.go new file mode 100644 index 0000000..ef25fe5 --- /dev/null +++ b/handler.go @@ -0,0 +1,196 @@ +package main + +import ( + "fmt" + "html/template" + "log" + "net/http" + "strings" +) + +func baseLoadTemplate(base string, path string) (*template.Template, any) { + return template.New(base).ParseFiles( + "./views/"+base, + "./views/"+path, + "./views/partials/header.html", + ) +} + +func loadTemplate(path string) (*template.Template, any) { + return baseLoadTemplate("layout.html", path) +} + +func LoadView(writer http.ResponseWriter, path string, data interface{}) { + tmpl, err := loadTemplate(path) + if err != nil { + fmt.Printf("Failed to load view %s\n", path) + fmt.Println(err) + if path == "500.html" { + writer.Write([]byte("

Failed to load 500.html check console for more info

")) + } else { + LoadView(writer, "500.html", nil) + } + return + } + + if err := tmpl.Execute(writer, data); err != nil { + fmt.Printf("Failed to load view %s\n", path) + fmt.Println(err) + writer.WriteHeader(http.StatusInternalServerError) + if path == "500.html" { + writer.Write([]byte("

Failed to load 500.html check console for more info

")) + } else { + LoadView(writer, "500.html", nil) + } + return + } +} + +/** Only returns the html without template */ +func LoadHtml(writer http.ResponseWriter, path string, data interface{}) { + tmpl, err := baseLoadTemplate("html.html", path) + if err != nil { + fmt.Printf("Failed to load template %s\n", path) + fmt.Println(err) + writer.WriteHeader(http.StatusInternalServerError) + if path == "500.html" { + writer.Write([]byte("

Failed to load 500.html check console for more info

")) + } else { + LoadHtml(writer, "500.html", nil) + } + return + } + + if err := tmpl.Execute(writer, data); err != nil { + fmt.Printf("Failed to execute template %s\n", path) + fmt.Println(err) + writer.WriteHeader(http.StatusInternalServerError) + if path == "500.html" { + writer.Write([]byte("

Failed to load 500.html check console for more info

")) + } else { + LoadHtml(writer, "500.html", nil) + } + return + } +} + +type Error struct { + code int + msg *string +} + +type AnswerType int + +const ( + NORMAL AnswerType = iota + HTML + JSON + HTMLFULL +) + +func LoadBasedOnAnswer(ans AnswerType, w http.ResponseWriter, path string, data map[string]interface{}) { + if ans == NORMAL { + LoadView(w, path, nil) + return + } else if ans == HTML { + LoadHtml(w, path, nil) + return + } else if ans == HTMLFULL { + if data == nil { + LoadHtml(w, path, map[string]interface{}{ + "App": true, + }) + } else { + data["App"] = true + LoadHtml(w, path, data) + } + return + } else if ans == JSON { + panic("TODO JSON!") + } else { + panic("unreachable") + } + +} + +type Handler interface { + New() + Startup() + Get(fn func(mode AnswerType, w http.ResponseWriter, r *http.Request) *Error) +} + +type Handle struct{} + +func handleError(err *Error, answerType AnswerType, w http.ResponseWriter) { + if err != nil { + w.WriteHeader(err.code) + if err.code == 404 { + LoadBasedOnAnswer(answerType, w, "404.html", nil) + return + } + if err.msg != nil { + w.Write([]byte(*err.msg)) + } + } +} + +func (x Handle) Get(path string, fn func(mode AnswerType, w http.ResponseWriter, r *http.Request) *Error) { + http.HandleFunc("/"+path, func(w http.ResponseWriter, r *http.Request) { + if r.Method != "Get" { + header := r.Header.Get("REQUEST-TYPE") + if header == "html" { + handleError(fn(HTMLFULL, w, r), HTMLFULL, w) + return + } + handleError(fn(NORMAL, w, r), NORMAL, w) + } + }) + http.HandleFunc("/api/html/"+path, func(w http.ResponseWriter, r *http.Request) { + if r.Method != "Get" { + handleError(fn(HTML, w, r), HTML, w) + } + }) + http.HandleFunc("/api/json/"+path, func(w http.ResponseWriter, r *http.Request) { + if r.Method != "Get" { + handleError(fn(JSON, w, r), JSON, w) + } + }) +} + +func (x Handle) New() { + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path != "/" { + w.WriteHeader(http.StatusNotFound) + LoadView(w, "404.html", nil) + return + } + LoadView(w, "index.html", nil) + }) + + http.HandleFunc("/styles/", func(w http.ResponseWriter, r *http.Request) { + path := r.URL.Path[len("/styles/"):] + if !strings.HasSuffix(path, ".css") { + w.WriteHeader(http.StatusNotFound) + w.Write([]byte("File not found")) + return + } + + t, err := template.ParseFiles("./views/styles/" + path) + + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte("Failed to load template")) + fmt.Println("Error:") + fmt.Println(err) + return + } + + w.Header().Set("Content-Type", "text/css; charset=utf-8") + t.Execute(w, nil) + }) +} + +func (x Handle) Startup() { + fmt.Printf("Starting up!\n") + log.Fatal(http.ListenAndServe(":8000", nil)) +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..398f70e --- /dev/null +++ b/main.go @@ -0,0 +1,26 @@ +package main + +import ( + "fmt" + "net/http" +) + +func main() { + fmt.Println("Starting server on :8000!") + + handle := Handle{} + + handle.New() + + handle.Get("login", func(mode AnswerType, w http.ResponseWriter, r *http.Request) *Error { + if mode == JSON { + return &Error{ + code: 404, + }; + } + LoadBasedOnAnswer(mode, w, "login.html", nil) + return nil; + }) + + handle.Startup() +} diff --git a/shell.nix b/shell.nix new file mode 100644 index 0000000..1cadf1c --- /dev/null +++ b/shell.nix @@ -0,0 +1,13 @@ +let + unstable = import (fetchTarball https://nixos.org/channels/nixos-unstable/nixexprs.tar.xz) { }; +in +{ pkgs ? import {} }: + pkgs.mkShell { + nativeBuildInputs = with unstable; [ + go + gopls + air + nodePackages.vscode-css-languageserver-bin + nodePackages.vscode-html-languageserver-bin + ]; +} diff --git a/templates/400.gohtml b/templates/400.gohtml new file mode 100644 index 0000000..c63c88e --- /dev/null +++ b/templates/400.gohtml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/templates/404.gohtml b/templates/404.gohtml new file mode 100644 index 0000000..c5126f7 --- /dev/null +++ b/templates/404.gohtml @@ -0,0 +1,3 @@ +

+ The page you were looking for could not be found! +

diff --git a/templates/index.gohtml b/templates/index.gohtml new file mode 100644 index 0000000..88331b1 --- /dev/null +++ b/templates/index.gohtml @@ -0,0 +1,10 @@ + + + + Stuff TODO change the name + + + + Hi Bitches + + diff --git a/views/404.html b/views/404.html new file mode 100644 index 0000000..e4f7950 --- /dev/null +++ b/views/404.html @@ -0,0 +1,15 @@ +{{ define "mainbody" }} +
+
+

+ 404 +

+

+ Page Not found +

+
+ The page you were looking for does not exist +
+
+
+{{ end }} diff --git a/views/500.html b/views/500.html new file mode 100644 index 0000000..fec8cfa --- /dev/null +++ b/views/500.html @@ -0,0 +1,6 @@ +{{ define "head" }} + + Error Page + +{{ end }} +{{ define "body" }}Heyyyyyy Err {{ end }} diff --git a/views/html.html b/views/html.html new file mode 100644 index 0000000..97328b6 --- /dev/null +++ b/views/html.html @@ -0,0 +1,19 @@ +{{ if .Full }} + + {{ block "body" . }} + {{ block "header.html" . }} {{end}} +
+ {{ block "mainbody" . }} {{end}} +
+ {{end}} + +{{ else }} + {{if .App }} +
+ {{ block "mainbody" . }} {{end}} +
+ {{ else }} + {{ block "mainbody" . }} {{end}} + {{end}} +{{end}} + diff --git a/views/index.html b/views/index.html new file mode 100644 index 0000000..05224e4 --- /dev/null +++ b/views/index.html @@ -0,0 +1,6 @@ +{{ define "title"}} Home : AI Stuff {{ end }} + +{{ define "mainbody" }} + hey bitches +{{ end }} + diff --git a/views/layout.html b/views/layout.html new file mode 100644 index 0000000..c27a00b --- /dev/null +++ b/views/layout.html @@ -0,0 +1,26 @@ + + + + {{ block "header" . }} + + {{ block "title" . }} + Ai stuff + {{ end }} + + {{ end }} + + + + + {{ block "other_imports" . }} {{end}} + + + + {{ block "body" . }} + {{ block "header.html" . }} {{end}} +
+ {{ block "mainbody" . }} {{end}} +
+ {{end}} + + diff --git a/views/login.html b/views/login.html new file mode 100644 index 0000000..51044c9 --- /dev/null +++ b/views/login.html @@ -0,0 +1,15 @@ +{{ define "title"}} Home : AI Stuff {{ end }} + +{{ define "mainbody" }} +
+
+ + +
+
+ + +
+
+{{ end }} + diff --git a/views/partials/header.html b/views/partials/header.html new file mode 100644 index 0000000..e21a461 --- /dev/null +++ b/views/partials/header.html @@ -0,0 +1,10 @@ + diff --git a/views/styles/main.css b/views/styles/main.css new file mode 100644 index 0000000..39e3a66 --- /dev/null +++ b/views/styles/main.css @@ -0,0 +1,57 @@ +* { + box-sizing: border-box; + font-family: 'Roboto', sans-serif; +} + +body { + margin: 0; + padding: 0; +} + +/* Nav bar */ + +nav { + background: #ececec; + margin: 0; + box-shadow: 0 0 8px 1px #888888ef; + height: 60px; +} + +nav ul { + display: flex; + margin: 0; + padding: 20px 40px; +} + +nav ul li { + list-style: none; +} + +nav ul .expand { + flex-grow: 1 +} + +nav ul li a { + text-decoration: none; + color: black; +} + +/* 404 page */ +.page404 { + display: grid; + place-items: center; + height: calc(100vh - 60px); + text-align: center; +} +.page404 h1 { + font-size: 10em; + margin: 0; +} +.page404 h2 { + font-size: 5em; + margin: 0; + margin-bottom: 0.3em; +} +.page404 div.description { + font-size: 1.5em; +}