Give that frontend a bit of a kick #2

Merged
sad merged 6 commits from css-update into main 2024-03-11 21:57:36 +00:00
3 changed files with 138 additions and 130 deletions
Showing only changes of commit 9bd35593fc - Show all commits

9
LICENSE Normal file
View File

@ -0,0 +1,9 @@
MIT License
Copyright (c) 2024 vxfemboy
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -5,53 +5,53 @@ import (
"fmt"
"log"
"net/http"
"path/filepath"
"os"
"os/signal"
"path/filepath"
"strings"
"syscall"
"time"
"github.com/BurntSushi/toml"
"github.com/go-git/go-git/v5"
"github.com/prologic/bitcask"
"github.com/BurntSushi/toml"
)
type Config struct {
Server struct {
Port string
}
Git struct {
UseGit bool
RepoURL string
Branch string
LocalPath string
}
Database struct {
Path string
}
Server struct {
Port string
}
Git struct {
UseGit bool
RepoURL string
Branch string
LocalPath string
}
Database struct {
Path string
}
}
var commentsDB *bitcask.Bitcask
func main() {
var config Config
if _, err := toml.DecodeFile("config.toml", &config); err != nil {
log.Fatalf("Failed to load config: %v", err)
}
var config Config
if _, err := toml.DecodeFile("config.toml", &config); err != nil {
log.Fatalf("Failed to load config: %v", err)
}
if config.Git.UseGit {
err := cloneRepository(config.Git.RepoURL, config.Git.LocalPath)
if err != nil && err != git.ErrRepositoryAlreadyExists {
log.Fatalf("Failed to clone repository: %v", err)
}
} else {
if _, err := os.Stat(config.Git.LocalPath); os.IsNotExist(err) {
os.MkdirAll(config.Git.LocalPath, os.ModePerm)
}
}
if config.Git.UseGit {
err := cloneRepository(config.Git.RepoURL, config.Git.LocalPath)
if err != nil && err != git.ErrRepositoryAlreadyExists {
log.Fatalf("Failed to clone repository: %v", err)
}
} else {
if _, err := os.Stat(config.Git.LocalPath); os.IsNotExist(err) {
os.MkdirAll(config.Git.LocalPath, os.ModePerm)
}
}
var err error
var err error
commentsDB, err = bitcask.Open(config.Database.Path)
if err != nil {
@ -59,13 +59,13 @@ func main() {
}
defer commentsDB.Close()
fs := http.FileServer(http.Dir("./assets"))
http.Handle("/assets/", http.StripPrefix("/assets/", fs))
fs := http.FileServer(http.Dir("./assets"))
http.Handle("/assets/", http.StripPrefix("/assets/", fs))
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
handler(&config, w, r)
})
handler(&config, w, r)
})
http.HandleFunc("/submit_comment", func(w http.ResponseWriter, r *http.Request) {
submitCommentHandler(w, r)
submitCommentHandler(w, r)
})
srv := &http.Server{Addr: config.Server.Port}
@ -98,14 +98,14 @@ func handler(config *Config, w http.ResponseWriter, r *http.Request) {
return
}
if config.Git.UseGit {
err := pullRepository(config.Git.LocalPath, config.Git.Branch)
if err != nil {
log.Printf("Failed to pull repository: %v", err)
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
return
}
}
if config.Git.UseGit {
err := pullRepository(config.Git.LocalPath, config.Git.Branch)
if err != nil {
log.Printf("Failed to pull repository: %v", err)
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
return
}
}
filePath := strings.TrimPrefix(r.URL.Path, "/")
if filePath == "" {
@ -117,38 +117,38 @@ func handler(config *Config, w http.ResponseWriter, r *http.Request) {
csp := "default-src 'self'; font-src 'self' data:; frame-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self';"
w.Header().Set("Content-Security-Policy", csp)
markdownFiles, err := listMarkdownFiles(config.Git.LocalPath)
if err != nil {
log.Printf("Error listing markdown files: %v", err)
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
return
}
markdownFiles, err := listMarkdownFiles(config.Git.LocalPath)
if err != nil {
log.Printf("Error listing markdown files: %v", err)
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
return
}
err = renderPage(w, r, config, filePath, commentsDB, markdownFiles)
if err != nil {
err = renderPage(w, r, config, filePath, commentsDB, markdownFiles)
if err != nil {
log.Printf("Failed to render page: %v", err)
http.Error(w, "File not found", http.StatusNotFound)
}
}
func listMarkdownFiles(localPath string) ([]string, error) {
var files []string
var files []string
err := filepath.Walk(localPath, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
err := filepath.Walk(localPath, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() && strings.HasSuffix(path, ".md") {
relPath, err := filepath.Rel(localPath, path)
if err != nil {
return err
}
if !info.IsDir() && strings.HasSuffix(path, ".md") {
relPath, err := filepath.Rel(localPath, path)
if err != nil {
return err
}
relPath = strings.Replace(relPath, string(os.PathSeparator), "/", -1)
files = append(files, relPath)
}
return nil
})
return files, err
relPath = strings.Replace(relPath, string(os.PathSeparator), "/", -1)
files = append(files, relPath)
}
return nil
})
return files, err
}

View File

@ -11,12 +11,12 @@ import (
"time"
"github.com/prologic/bitcask"
img64 "github.com/tenkoh/goldmark-img64"
"github.com/yuin/goldmark"
highlighting "github.com/yuin/goldmark-highlighting"
"github.com/yuin/goldmark/extension"
"github.com/yuin/goldmark/parser"
"github.com/yuin/goldmark/renderer/html"
img64 "github.com/tenkoh/goldmark-img64"
"github.com/yuin/goldmark/parser"
"github.com/yuin/goldmark/renderer/html"
)
type Page struct {
@ -27,74 +27,74 @@ type Page struct {
AuthoredDate *time.Time
LastModifier string
LastModifiedDate *time.Time
Pages []string
UseGit bool
Pages []string
UseGit bool
}
func renderPage(w http.ResponseWriter, r *http.Request, config *Config, filePath string, commentsDB *bitcask.Bitcask, pages []string) error {
var content []byte
var err error
var content []byte
var err error
if config.Git.UseGit {
content, err = readFileFromRepo(config.Git.LocalPath, filePath)
if err != nil {
return err
}
} else {
fullPath := filepath.Join(config.Git.LocalPath, filePath)
content, err = ioutil.ReadFile(fullPath)
if err != nil {
return err
}
}
if config.Git.UseGit {
content, err = readFileFromRepo(config.Git.LocalPath, filePath)
if err != nil {
return err
}
} else {
fullPath := filepath.Join(config.Git.LocalPath, filePath)
content, err = ioutil.ReadFile(fullPath)
if err != nil {
return err
}
}
ext := filepath.Ext(filePath)
switch ext {
case ".md":
renderMarkdown(w, r, content, commentsDB, filePath, pages, config)
case ".html", ".css":
renderStatic(w, content, ext)
default:
return fmt.Errorf("unsupported file format")
}
return nil
ext := filepath.Ext(filePath)
switch ext {
case ".md":
renderMarkdown(w, r, content, commentsDB, filePath, pages, config)
case ".html", ".css":
renderStatic(w, content, ext)
default:
return fmt.Errorf("unsupported file format")
}
return nil
}
func renderMarkdown(w http.ResponseWriter, r *http.Request, content []byte, commentsDB *bitcask.Bitcask, filePath string, pages []string, config *Config) {
md := goldmark.New(
goldmark.WithExtensions(
extension.GFM, // images should probably be base64 encoded https://github.com/tenkoh/goldmark-img64 for extra performance
extension.Table,
highlighting.NewHighlighting(
highlighting.WithStyle("monokai"),
extension.GFM, // images should probably be base64 encoded https://github.com/tenkoh/goldmark-img64 for extra performance
extension.Table,
highlighting.NewHighlighting(
highlighting.WithStyle("monokai"),
),
img64.Img64,
), // does this code below do anything useful?
goldmark.WithParserOptions(
parser.WithAutoHeadingID(),
),
goldmark.WithRendererOptions(
html.WithXHTML(),
html.WithHardWraps(),
goldmark.WithParserOptions(
parser.WithAutoHeadingID(),
),
goldmark.WithRendererOptions(
html.WithXHTML(),
html.WithHardWraps(),
img64.WithParentPath(config.Git.LocalPath),
),
),
)
var author, lastModifier string
var authoredDate, lastModifiedDate *time.Time
var err error
var author, lastModifier string
var authoredDate, lastModifiedDate *time.Time
var err error
if config.Git.UseGit {
var ad, lmd time.Time
author, ad, lastModifier, lmd, err = getAuthorAndLastModification(config.Git.LocalPath, filePath)
if err != nil {
http.Error(w, "Error fetching author and last modification date", http.StatusInternalServerError)
return
}
authoredDate = &ad
lastModifiedDate = &lmd
}
if config.Git.UseGit {
var ad, lmd time.Time
author, ad, lastModifier, lmd, err = getAuthorAndLastModification(config.Git.LocalPath, filePath)
if err != nil {
http.Error(w, "Error fetching author and last modification date", http.StatusInternalServerError)
return
}
authoredDate = &ad
lastModifiedDate = &lmd
}
var mdBuf bytes.Buffer
err = md.Convert(content, &mdBuf)
@ -103,13 +103,12 @@ func renderMarkdown(w http.ResponseWriter, r *http.Request, content []byte, comm
return
}
layout, err := ioutil.ReadFile("assets/_layout.html")
if err != nil {
log.Printf("Error reading _layout.html: %v", err)
http.Error(w, "Layout not found", http.StatusInternalServerError)
return
}
layout, err := ioutil.ReadFile("assets/_layout.html")
if err != nil {
log.Printf("Error reading _layout.html: %v", err)
http.Error(w, "Layout not found", http.StatusInternalServerError)
return
}
comments, err := getComments(commentsDB, r.URL.Path)
if err != nil && err != bitcask.ErrKeyNotFound {
@ -125,8 +124,8 @@ func renderMarkdown(w http.ResponseWriter, r *http.Request, content []byte, comm
AuthoredDate: authoredDate,
LastModifier: lastModifier,
LastModifiedDate: lastModifiedDate,
Pages: pages,
UseGit: config.Git.UseGit,
Pages: pages,
UseGit: config.Git.UseGit,
}
t, err := template.New("layout").Parse(string(layout))
@ -138,8 +137,8 @@ func renderMarkdown(w http.ResponseWriter, r *http.Request, content []byte, comm
var buf bytes.Buffer
err = t.Execute(&buf, page)
if err != nil {
log.Printf("Error executing template: %v", err)
http.Error(w, "Error rendering layout", http.StatusInternalServerError)
log.Printf("Error executing template: %v", err)
http.Error(w, "Error rendering layout", http.StatusInternalServerError)
return
}