diff --git a/lib/content.go b/lib/content.go new file mode 100644 index 0000000..3c4cd1f --- /dev/null +++ b/lib/content.go @@ -0,0 +1,88 @@ +package lib + +import ( + "encoding/json" + "errors" + "html/template" + "os" + "path" + "strings" +) + +const CONTENT_PATH string = "content" + +type Content struct{ + Dir string + Name string + + Title string `json:"title"` + ID string `json:"id"` + + Md string + HTML template.HTML + + Date string `json:"date"` + Author string `json:"author"` +} + +func ListContent(dir string) ([]Content, error) { + var res []Content + + dirpath := path.Join(CONTENT_PATH, dir) + entries, err := os.ReadDir(dirpath) + if err != nil { + return nil, errors.New("Cannot readdir: "+dirpath) + } + + for _, e := range entries { + if(!strings.HasSuffix(e.Name(), ".json")) { + continue + } + + var con Content + jsonfile := path.Join(dirpath, e.Name()) + jsoncon, err := os.ReadFile(jsonfile) + + if err != nil { + return nil, errors.New("Cannot get JSON: "+jsonfile) + } + + err = json.Unmarshal(jsoncon, &con) + if err != nil { + return nil, errors.New("Cannot parse JSON: "+jsonfile) + } + + con.Dir = dir + con.Name = strings.Split(e.Name(), ".")[0] + res = append(res, con) + } + + return res, nil +} + +func GetContent(dir string, name string) (Content, error) { + var res Content + jsonfile := path.Join(CONTENT_PATH, dir, name+".json") + mdfile := path.Join(CONTENT_PATH, dir, name+".md") + + res.Dir = dir + res.Name = name + + jsoncontent, err := os.ReadFile(jsonfile) + if err != nil { + return res, errors.New("Cannot read JSON file: "+jsonfile) + } + + rawcontent, err := os.ReadFile(mdfile) + if err != nil { + return res, errors.New("Cannot read markdown file: "+mdfile) + } + + if(json.Unmarshal(jsoncontent, &res)!= nil) { + return res, errors.New("Cannot parse JSON: "+jsonfile) + } + + res.Md = string(rawcontent) + res.HTML = template.HTML(ParseMarkdown(res.Md)) + return res, nil +} diff --git a/lib/util.go b/lib/util.go new file mode 100644 index 0000000..1c2f2cc --- /dev/null +++ b/lib/util.go @@ -0,0 +1,39 @@ +package lib + +import ( + "time" + + "github.com/gofiber/fiber/v2" + "github.com/russross/blackfriday/v2" +) + +func RenderError(c *fiber.Ctx, code int) error{ + var msg string = "Server Error" + c.Status(code) + + switch code { + case 404: + msg = "Not Found" + } + + return c.Render("error", fiber.Map{ + "msg": msg, + }) +} + +func TimeFromString(date string) (time.Time, error) { + res, err := time.Parse("02/01/06", date) + if err == nil { + return res, nil + } + return time.Now(), nil +} + +func ParseMarkdown(md string) string { + ext := blackfriday.FencedCode + ext |= blackfriday.BackslashLineBreak + ext |= blackfriday.Strikethrough + ext |= blackfriday.Tables + + return string(blackfriday.Run([]byte(md), blackfriday.WithExtensions(ext))) +} diff --git a/main.go b/main.go index bb736e4..d65b3b7 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,7 @@ package main import ( + "git.matterlinux.xyz/Matterlinux/website/lib" "git.matterlinux.xyz/Matterlinux/website/routes" "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/log" @@ -13,13 +14,18 @@ func main(){ Views: engine, }) app.Static("/", "./public") - app.Static("/images", "./content/images") + app.Static("/assets", "./content/assets") app.Get("/", routes.IndexRoute) + app.Get("/news", routes.NewsRoute) app.Get("/news/:id", routes.PostRoute) + + app.Get("/wiki", routes.WikiMainRoute) + app.Get("/wiki/:id", routes.WikiRoute) + app.Get("*", func(c *fiber.Ctx) error { - return routes.RenderError(c, 404) + return lib.RenderError(c, 404) }) log.Fatal(app.Listen(":9878")) diff --git a/public/font.css b/public/font.css new file mode 100644 index 0000000..0bbd929 --- /dev/null +++ b/public/font.css @@ -0,0 +1,9 @@ +@font-face { + font-family: Ubuntu; + src: url("fonts/ubuntu.ttf"); +} + +@font-face { + font-family: JetBrainsMono; + src: url("fonts/jetbrains.ttf"); +} diff --git a/public/md.css b/public/md.css index 8a071a6..1abfa02 100644 --- a/public/md.css +++ b/public/md.css @@ -22,6 +22,12 @@ font-size: 20px; color: var(--bright-second); line-height: 28px; + letter-spacing: .01em; +} + +.md strong { + font-weight: 900; + color: var(--bright-main); } .md a { @@ -43,5 +49,54 @@ .md code { font-family: JetBrainsMono; background: var(--dark-third); + color: var(--bright-main); border-radius: 5px; + font-size: 19px; +} + +.md pre { + margin-top: 0; + margin-bottom: 0; + font-family: JetBrainsMono; + font-size: 12px; + word-wrap: normal; + margin-bottom: 16px; + margin-top: 16px; + padding: 16px; + overflow: auto; + line-height: 1.45; + color: var(--bright-main); + background-color: var(--dark-third); + border-radius: 6px; +} + +.md table { + border-spacing: 0; + border-collapse: collapse; + display: block; + width: max-content; + max-width: 100%; + overflow: auto; + margin: 16px 0px 16px 0px; +} + +.md table th{ + font-weight: 900; + font-size: 20px; +} + +.md table th, +.md table td{ + font-size: 20px; + padding: 6px 13px; + border: 1px solid var(--bright-second); +} + +.markdown-body table tr { + background-color: var(--dark-second); + border-top: 1px solid var(--bright-second); +} + +.md a:hover { + color: var(--bright-main); } diff --git a/public/style.css b/public/style.css index c8ecc66..437898e 100644 --- a/public/style.css +++ b/public/style.css @@ -1,17 +1,9 @@ -@font-face { - font-family: Ubuntu; - src: url("fonts/ubuntu.ttf"); -} - -@font-face { - font-family: JetBrainsMono; - src: url("fonts/jetbrains.ttf"); -} +@import url("/font.css"); :root { --dark-main: black; --dark-second: #070707; - --dark-third: #101010; + --dark-third: #151515; --bright-main: white; --bright-second: #DFDFDF; } diff --git a/routes/index.go b/routes/index.go index 77c9a5f..19661bb 100644 --- a/routes/index.go +++ b/routes/index.go @@ -1,18 +1,19 @@ package routes import ( + "git.matterlinux.xyz/Matterlinux/website/lib" "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/log" ) func IndexRoute(c *fiber.Ctx) error{ - content, err := GetContent("content", "index") + con, err := lib.GetContent("", "index") if err != nil { - log.Error(err) - return RenderError(c, 500) + log.Error("GetContent -> ", err) + return lib.RenderError(c, 500) } return c.Render("index", fiber.Map{ - "readme": content, + "readme": con, }) } diff --git a/routes/news.go b/routes/news.go index 87567dc..172dd71 100644 --- a/routes/news.go +++ b/routes/news.go @@ -1,102 +1,69 @@ package routes import ( - "encoding/json" - "os" - "path" "sort" - "strings" + "git.matterlinux.xyz/Matterlinux/website/lib" "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/log" ) -var news_path = path.Join("content", "news") - func NewsRoute(c *fiber.Ctx) error { - var res []Content - entries, err := os.ReadDir(news_path) + contents, err := lib.ListContent("news") if err != nil { - log.Errorf("Cannot news dir: %s", err) - return RenderError(c, 500) + log.Errorf("ListContent -> %s", err.Error()) + return lib.RenderError(c, 500) } - for _, e := range entries { - if(!strings.HasSuffix(e.Name(), ".json")) { - continue + sort.Slice(contents, func(i, j int) bool { + time1, err := lib.TimeFromString(contents[i].Date) + if err != nil { + log.Errorf("Bad date while sorting: %s", err.Error()) + return false } - var con Content - jsonc, err := os.ReadFile(path.Join(news_path, e.Name())) - if err != nil { - log.Errorf("Cannot news JSON for %s: %s", e.Name(), err) - return RenderError(c, 500) + time2, err := lib.TimeFromString(contents[j].Date) + if err != nil { + log.Errorf("Bad date while sorting: %s", err.Error()) + return false } - err = json.Unmarshal(jsonc, &con) - if err != nil { - log.Errorf("Cannot parse news JSON for %s: %s", e.Name(), err) - return RenderError(c, 500) - } - - con.Time, err = TimeFromString(con.Date) - if err != nil { - log.Errorf("Cannot parse time for '%s': %s", con.Name, err) - } - res = append(res, con) - - } - - sort.Slice(res, func(i, j int) bool { - return res[i].Time.After(res[j].Time) + + return time1.After(time2) }) return c.Render("news", fiber.Map{ - "news": res, + "news": contents, }) } func PostRoute(c *fiber.Ctx) error { postid := c.Params("id") if len(postid) == 0 { - return RenderError(c, 404) + return lib.RenderError(c, 404) } - var res Content - entries, err := os.ReadDir(news_path) + contents, err := lib.ListContent("news") if err != nil { - log.Errorf("Cannot news dir: %s", err) - return RenderError(c, 500) + log.Errorf("ListContent -> %s", err.Error()) + return lib.RenderError(c, 500) } - for _, e := range entries { - if(!strings.HasSuffix(e.Name(), ".json")) { + for _, con := range contents { + if(con.ID != postid) { continue } - jsonc, err := os.ReadFile(path.Join(news_path, e.Name())) + con, err = lib.GetContent(con.Dir, con.Name) if err != nil { - log.Errorf("Cannot news JSON: %s", err) - return RenderError(c, 500) - } - - err = json.Unmarshal(jsonc, &res) - if err != nil { - log.Errorf("Cannot parse news JSON: %s", err) - return RenderError(c, 500) + log.Errorf("GetContent -> %s", err.Error()) + return lib.RenderError(c, 500) } - if(res.ID == postid) { - res, err = GetContent(news_path, strings.Split(e.Name(), ".json")[0]) - if err != nil { - log.Errorf("Cannot get content: %s", err) - return RenderError(c, 500) - } - - return c.Render("post", fiber.Map{ - "post": res, - }) - } + return c.Render("post", fiber.Map{ + "title": "News", + "post": con, + }) } - return RenderError(c, 404) + return lib.RenderError(c, 404) } diff --git a/routes/util.go b/routes/util.go deleted file mode 100644 index 6a70b1a..0000000 --- a/routes/util.go +++ /dev/null @@ -1,73 +0,0 @@ -package routes - -import ( - "encoding/json" - "errors" - "html/template" - "os" - "path" - "time" - - "github.com/gofiber/fiber/v2" - "github.com/russross/blackfriday/v2" -) - -type Content struct { - ID string `json:"id"` - Name string `json:"name"` - Date string `json:"date"` - Author string `json:"author"` - Content template.HTML `json:"content"` - Time time.Time -} - -func TimeFromString(date string) (time.Time, error) { - res, err := time.Parse("02/01/06", date) - if err == nil { - return res, nil - } - - return time.Now(), nil -} - -func GetContent(pth string, name string) (Content, error) { - var res Content - jsonfile := path.Join(pth, name+".json") - mdfile := path.Join(pth, name+".md") - - jsoncontent, err := os.ReadFile(jsonfile) - if err != nil { - return res, errors.New("Cannot read JSON file: "+jsonfile) - } - - mdcontent, err := os.ReadFile(mdfile) - if err != nil { - return res, errors.New("Cannot read markdown file: "+mdfile) - } - - if(json.Unmarshal(jsoncontent, &res)!= nil) { - return res, errors.New("Cannot parse JSON: "+jsonfile) - } - - ext := blackfriday.FencedCode - ext |= blackfriday.BackslashLineBreak - ext |= blackfriday.Strikethrough - - md := string(blackfriday.Run(mdcontent, blackfriday.WithExtensions(ext))) - res.Content = template.HTML(md) - return res, nil -} - -func RenderError(c *fiber.Ctx, code int) error{ - var msg string = "Server Error" - c.Status(code) - - switch code { - case 404: - msg = "Not Found" - } - - return c.Render("error", fiber.Map{ - "msg": msg, - }) -} diff --git a/routes/wiki.go b/routes/wiki.go new file mode 100644 index 0000000..db78f9e --- /dev/null +++ b/routes/wiki.go @@ -0,0 +1,53 @@ +package routes + +import ( + "git.matterlinux.xyz/Matterlinux/website/lib" + "github.com/gofiber/fiber/v2" + "github.com/gofiber/fiber/v2/log" +) + +func WikiMainRoute(c *fiber.Ctx) error { + con, err := lib.GetContent("wiki", "main") + if err != nil { + log.Error("GetContent -> ", err) + return lib.RenderError(c, 500) + } + + return c.Render("post", fiber.Map{ + "title": "Wiki", + "post": con, + }) +} + +func WikiRoute(c *fiber.Ctx) error{ + docid := c.Params("id") + if len(docid) == 0 { + return lib.RenderError(c, 404) + } + + contents, err := lib.ListContent("wiki") + if err != nil { + log.Errorf("ListContent -> %s", err.Error()) + return lib.RenderError(c, 500) + } + + for _, con := range contents { + if(con.ID != docid) { + continue + } + + con, err = lib.GetContent(con.Dir, con.Name) + if err != nil { + log.Errorf("GetContent -> %s", err.Error()) + return lib.RenderError(c, 500) + } + + con.Title = "Wiki: "+con.Title + return c.Render("post", fiber.Map{ + "title": "Wiki", + "post": con, + }) + } + + return lib.RenderError(c, 404) +} diff --git a/templates/error.html b/templates/error.html index 0da7dbd..49844c6 100644 --- a/templates/error.html +++ b/templates/error.html @@ -1,7 +1,7 @@ - Matter Linux + MatterLinux | Error diff --git a/templates/index.html b/templates/index.html index dbfdb67..e7f92d8 100644 --- a/templates/index.html +++ b/templates/index.html @@ -1,7 +1,7 @@ - Matter Linux + MatterLinux @@ -10,7 +10,7 @@ {{template "parts/bar" .}}
- {{.readme.Content}} + {{.readme.HTML}}
diff --git a/templates/news.html b/templates/news.html index d1de3ec..4430637 100644 --- a/templates/news.html +++ b/templates/news.html @@ -1,7 +1,7 @@ - Matter Linux + MatterLinux | News @@ -12,7 +12,7 @@ {{range $new := .news}}

{{$new.Date}}

-

{{$new.Name}}

+

{{$new.Title}}

{{end}} diff --git a/templates/parts/bar.html b/templates/parts/bar.html index f94f94f..19d42d3 100644 --- a/templates/parts/bar.html +++ b/templates/parts/bar.html @@ -3,7 +3,8 @@ diff --git a/templates/post.html b/templates/post.html index fabd646..da26e63 100644 --- a/templates/post.html +++ b/templates/post.html @@ -1,7 +1,7 @@ - Matter Linux + MatterLinux | {{.title}} @@ -10,10 +10,10 @@ {{template "parts/bar" .}}
-

{{.post.Name}}

+

{{.post.Title}}

{{.post.Date}} | by {{.post.Author}}

- {{.post.Content}} + {{.post.HTML}}