flounder

A simple gemini site builder
Log | Files | Refs | README | LICENSE

commit 803bb266d991ee8ddb1b7d977c7caa5bb361d399
parent b18554dca962686cbb07d660ec3bf2875bcd8f84
Author: alex wennerberg <alex@alexwennerberg.com>
Date:   Fri, 23 Oct 2020 23:56:38 -0700

serve static content and styles

Diffstat:
M.gitignore | 1+
MREADME.md | 4++++
Mconfig.go | 15++++++++-------
Mflounder.toml | 3+++
Mhttp.go | 41++++++++++++++++++++++++++++-------------
Mtemplates/header.html | 2+-
Atemplates/static/favicon.ico | 0
Atemplates/static/favicon.txt | 1+
Atemplates/static/robots.txt | 0
Atemplates/static/style.css | 66++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
10 files changed, 112 insertions(+), 21 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -1 +1,2 @@ files/ +tmpcerts/ diff --git a/README.md b/README.md @@ -8,3 +8,7 @@ Designed to help make the Gemini ecosystem more accessible. ## Hosting Very simple to host -- a single binary with a gemini server, http server included. + +## Customizing + +You can relatively easily change the style and layout of your instance if you'd like. diff --git a/config.go b/config.go @@ -5,13 +5,14 @@ import ( ) type Config struct { - FilesDirectory string - RootDomain string - SiteTitle string - Debug bool - SecretKey string - DBFile string - PasswdFile string // TODO remove + FilesDirectory string + TemplatesDirectory string + RootDomain string + SiteTitle string + Debug bool + SecretKey string + DBFile string + PasswdFile string // TODO remove } func getConfig(filename string) (Config, error) { diff --git a/flounder.toml b/flounder.toml @@ -1,4 +1,7 @@ SiteTitle="🐟flounder" RootDomain="localhost" FilesDirectory="./files" +# handles templates and static files +# everything in the static subfolder will be served at root +TemplatesDirectory="./templates" DBFile="./flounder.db" diff --git a/http.go b/http.go @@ -24,6 +24,12 @@ func renderError(w http.ResponseWriter, errorMsg string, statusCode int) { // TO } func indexHandler(w http.ResponseWriter, r *http.Request) { + // serve everything inside static directory + if r.URL.Path != "/" { + fileName := path.Join(c.TemplatesDirectory, "static", r.URL.Path) + http.ServeFile(w, r, fileName) + return + } indexFiles, err := getIndexFiles() if err != nil { log.Println(err) @@ -54,16 +60,24 @@ func indexHandler(w http.ResponseWriter, r *http.Request) { func editFileHandler(w http.ResponseWriter, r *http.Request) { // read file content. create if dne // authUser := "alex" - data := struct { - FileName string - FileText string - PageTitle string - }{"filename", "filetext", c.SiteTitle} - err := t.ExecuteTemplate(w, "edit_file.html", data) - if err != nil { - log.Println(err) - renderError(w, InternalServerErrorMsg, 500) - return + if r.Method == "GET" { + data := struct { + FileName string + FileText string + PageTitle string + }{"filename", "filetext", c.SiteTitle} + err := t.ExecuteTemplate(w, "edit_file.html", data) + if err != nil { + log.Println(err) + renderError(w, InternalServerErrorMsg, 500) + return + } + } else if r.Method == "POST" { + } +} + +func deleteFileHandler(w http.ResponseWriter, r *http.Request) { + if r.Method == "POST" { } } @@ -142,7 +156,9 @@ func userFile(w http.ResponseWriter, r *http.Request) { userName := strings.Split(r.Host, ".")[0] fileName := path.Join(c.FilesDirectory, userName, r.URL.Path) extension := path.Ext(fileName) - log.Println(extension) + if r.URL.Path == "/static/style.css" { + http.ServeFile(w, r, path.Join(c.TemplatesDirectory, "static/style.css")) + } if extension == ".gmi" || extension == ".gemini" { if strings.Contains(fileName, "..") { // prevent directory traversal TODO verify @@ -152,7 +168,6 @@ func userFile(w http.ResponseWriter, r *http.Request) { stat, _ := os.Stat(fileName) file, _ := os.Open(fileName) htmlString := gmi.Parse(file).HTML() - log.Println(htmlString) reader := strings.NewReader(htmlString) w.Header().Set("Content-Type", "text/html") http.ServeContent(w, r, fileName, stat.ModTime(), reader) @@ -175,7 +190,7 @@ func runHTTPServer() { http.HandleFunc(c.RootDomain+"/edit/", editFileHandler) http.HandleFunc(c.RootDomain+"/login", loginHandler) http.HandleFunc(c.RootDomain+"/register", registerHandler) - // http.HandleFunc("/delete/", deleteFileHandler) + http.HandleFunc(c.RootDomain+"/delete/", deleteFileHandler) // login+register functions // handle user files based on subdomain diff --git a/templates/header.html b/templates/header.html @@ -5,7 +5,7 @@ <meta charset="utf-8" /> <title>{{.PageTitle }}</title> <meta name="viewport" content="width=device-width" /> - <link rel="stylesheet" type="text/css" href="/static/style.css" /> + <link rel="stylesheet" type="text/css" href="/style.css" /> </head> <body> <main> diff --git a/templates/static/favicon.ico b/templates/static/favicon.ico diff --git a/templates/static/favicon.txt b/templates/static/favicon.txt @@ -0,0 +1 @@ +🐟 diff --git a/templates/static/robots.txt b/templates/static/robots.txt diff --git a/templates/static/style.css b/templates/static/style.css @@ -0,0 +1,66 @@ +main { + max-width: 70ch; + padding: 2ch; + margin: auto; + font-family: Helvetica, Arial, monospace; + word-wrap: break-word; +} + +.inline { + display: inline; +} + +img { + max-width: 100%; +} + +#editor { + width: 100%; + border: 1px solid #999999; + width: 100%; + margin: 5px 0; + padding: 3px; + resize: none; +} + +.status { + border: 1px solid black; + margin-top: 3px; + margin-bottom: 3px; + padding-left: 0.5ch; +} + +.status-text { + font-family: monospace; + padding: 0.5ch; +} + +.button { + background-color: white; /* Green */ + border: 1px solid black; + text-decoration: none; + padding: 2px 5px; + display: inline-block; + margin: 0px; + transition-duration: 0.2s; +} + +.button:hover { + background-color: black; + color: white; +} + +.error { + color: red; +} + +a { + color: black; + transition-duration: 0.2s; + font-weight: bold; +} + +a:hover { + background-color: black; + color: white; +}