Merge pull request 'dynamic-pages' (#1) from dynamic-pages into main

Reviewed-on: s4d/tcp-wiki#1
This commit is contained in:
sad 2024-02-10 02:53:40 +00:00
commit 147ce945c3
5 changed files with 89 additions and 38 deletions

@ -57,7 +57,7 @@ change `main` to your specific repo's branch and you should be good to go!
## TODO ## TODO
- [ ] MANY FUCKING THINGS - [ ] config files
- [ ] Webhook support for auto pull on push/update of the git repo - [ ] Webhook support for auto pull on push/update of the git repo
- [x] Git Branch support - [x] Git Branch support
- [ ] add a star/upvote/like feature for pages - [ ] add a star/upvote/like feature for pages
@ -75,10 +75,8 @@ change `main` to your specific repo's branch and you should be good to go!
- [ ] reply to replies - [ ] reply to replies
- [ ] set security controls per page - [ ] set security controls per page
- [ ] auto refresh on post - [ ] auto refresh on post
- [ ] dynamically generated links for all avaiable pages - [x] dynamically generated links for all avaiable pages
- [ ] sitemap - [ ] sitemap
- [ ] anti robot shit here - [ ] anti robot shit here
- [ ] acual working pages!? - [x] acual working pages!?
- [ ] post quantum intergration and verification - [ ] image support
- [ ] BUILD UP THAT MARKDOWN SUPPORT
- [ ] fix whatever i did to fuck up design/layout/css???

@ -39,7 +39,8 @@
<p><small>{{ .Author }} at {{ .Date }}</small></p> <p><small>{{ .Author }} at {{ .Date }}</small></p>
</div> </div>
{{ end }} {{ end }}
</div> </div>
</main> </main>
<form method="POST" action="/submit_comment"> <form method="POST" action="/submit_comment">
<input type="hidden" name="path" value="{{ .Path }}"> <input type="hidden" name="path" value="{{ .Path }}">
@ -53,5 +54,13 @@
</div> </div>
<button type="submit">Submit</button> <button type="submit">Submit</button>
</form> </form>
<div class="sidebar">
<h2>Pages</h2>
<ul>
{{ range .Pages }}
<li><a href="/{{ . }}">{{ . }}</a></li>
{{ end }}
</ul>
</div>
</body> </body>
</html> </html>

@ -99,7 +99,6 @@ section h2 {
color: #999; color: #999;
} }
/* Added styles */
.page-info { .page-info {
font-size: 0.8em; font-size: 0.8em;
display: flex; display: flex;
@ -118,3 +117,16 @@ section h2 {
background-color: #555; background-color: #555;
margin-left: 5px; margin-left: 5px;
} }
.sidebar-toggle button {
background-color: #333;
color: #14ee00;
border: 1px solid #14ee00;
padding: 5px 10px;
cursor: pointer;
}
.sidebar-toggle button:hover {
background-color: #14ee00;
color: #131313;
}

@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"log" "log"
"net/http" "net/http"
"path/filepath"
"os" "os"
"os/signal" "os/signal"
"strings" "strings"
@ -33,6 +34,8 @@ func main() {
} }
defer commentsDB.Close() defer commentsDB.Close()
fs := http.FileServer(http.Dir("./assets"))
http.Handle("/assets/", http.StripPrefix("/assets/", fs))
http.HandleFunc("/", handler) http.HandleFunc("/", handler)
http.HandleFunc("/submit_comment", submitCommentHandler) http.HandleFunc("/submit_comment", submitCommentHandler)
@ -61,12 +64,10 @@ func main() {
} }
func handler(w http.ResponseWriter, r *http.Request) { func handler(w http.ResponseWriter, r *http.Request) {
//for debugging // For debugging
log.Printf("LOCAL PATH: %q", localPath) log.Printf("LOCAL PATH: %q", localPath)
//... if r.URL.Path == "./assets/favicon.ico" {
if r.URL.Path == "assets/favicon.ico" {
return return
} }
@ -85,10 +86,37 @@ func handler(w http.ResponseWriter, r *http.Request) {
csp := "default-src 'self'; img-src 'self'; script-src 'self'; style-src 'self';" csp := "default-src 'self'; img-src 'self'; script-src 'self'; style-src 'self';"
w.Header().Set("Content-Security-Policy", csp) w.Header().Set("Content-Security-Policy", csp)
err = renderPage(w, r, localPath, filePath, commentsDB) markdownFiles, err := listMarkdownFiles(localPath)
if err != nil { if err != nil {
log.Printf("Comment loading? %q", commentsDB.Path()) log.Printf("Error listing markdown files: %v", err)
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
return
}
err = renderPage(w, r, localPath, filePath, commentsDB, markdownFiles)
if err != nil {
log.Printf("Failed to render page: %v", err)
http.Error(w, "File not found", http.StatusNotFound) http.Error(w, "File not found", http.StatusNotFound)
} }
} }
func listMarkdownFiles(localPath string) ([]string, error) {
var files []string
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
}
// Ensure the path uses web-friendly slashes
relPath = strings.Replace(relPath, string(os.PathSeparator), "/", -1)
files = append(files, relPath)
}
return nil
})
return files, err
}

@ -24,29 +24,30 @@ type Page struct {
AuthoredDate time.Time AuthoredDate time.Time
LastModifier string LastModifier string
LastModifiedDate time.Time LastModifiedDate time.Time
Pages []string
} }
func renderPage(w http.ResponseWriter, r *http.Request, localPath, filePath string, commentsDB *bitcask.Bitcask) error { func renderPage(w http.ResponseWriter, r *http.Request, localPath, filePath string, commentsDB *bitcask.Bitcask, pages []string) error {
content, err := readFileFromRepo(localPath, filePath) content, err := readFileFromRepo(localPath, filePath)
if err != nil { if err != nil {
return err return err
} }
//log.Printf("Read file content: %s", content) ext := filepath.Ext(filePath)
switch ext {
ext := filepath.Ext(filePath) case ".md":
switch ext { renderMarkdown(w, r, content, commentsDB, localPath, filePath, pages) // Now correctly includes `pages`
case ".md": case ".html", ".css":
renderMarkdown(w, r, content, commentsDB, localPath, filePath) // Updated the call to include localPath and filePath renderStatic(w, content, ext)
case ".html", ".css": default:
renderStatic(w, content, ext) return fmt.Errorf("unsupported file format")
default: }
return fmt.Errorf("unsupported file format") return nil
}
return nil
} }
func renderMarkdown(w http.ResponseWriter, r *http.Request, content []byte, commentsDB *bitcask.Bitcask, localPath, filePath string) {
func renderMarkdown(w http.ResponseWriter, r *http.Request, content []byte, commentsDB *bitcask.Bitcask, localPath, filePath string, pages []string) {
md := goldmark.New( md := goldmark.New(
goldmark.WithExtensions( goldmark.WithExtensions(
extension.GFM, // GitHub Flavored Markdown extension.GFM, // GitHub Flavored Markdown
@ -69,11 +70,13 @@ func renderMarkdown(w http.ResponseWriter, r *http.Request, content []byte, comm
return return
} }
layout, err := ioutil.ReadFile(filepath.Join(localPath, "assets/_layout.html"))
if err != nil { layout, err := ioutil.ReadFile("assets/_layout.html")
http.Error(w, "Layout not found", http.StatusInternalServerError) if err != nil {
return log.Printf("Error reading _layout.html: %v", err)
} http.Error(w, "Layout not found", http.StatusInternalServerError)
return
}
comments, err := getComments(commentsDB, r.URL.Path) comments, err := getComments(commentsDB, r.URL.Path)
if err != nil && err != bitcask.ErrKeyNotFound { if err != nil && err != bitcask.ErrKeyNotFound {
@ -89,6 +92,7 @@ func renderMarkdown(w http.ResponseWriter, r *http.Request, content []byte, comm
AuthoredDate: authoredDate, AuthoredDate: authoredDate,
LastModifier: lastModifier, LastModifier: lastModifier,
LastModifiedDate: lastModifiedDate, LastModifiedDate: lastModifiedDate,
Pages: pages,
} }
t, err := template.New("layout").Parse(string(layout)) t, err := template.New("layout").Parse(string(layout))
if err != nil { if err != nil {