diff --git a/go.mod b/go.mod index a1c6c76..e9fd53c 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,7 @@ require ( require golang.org/x/crypto v0.27.0 // indirect require ( + github.com/gomarkdown/markdown v0.0.0-20250311123330-531bef5e742b // indirect github.com/gorilla/websocket v1.5.3 // indirect github.com/pelletier/go-toml/v2 v2.2.3 // indirect github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // indirect diff --git a/go.sum b/go.sum index f2ec7e7..d817720 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,8 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= +github.com/gomarkdown/markdown v0.0.0-20250311123330-531bef5e742b h1:EY/KpStFl60qA17CptGXhwfZ+k1sFNJIUNR8DdbcuUk= +github.com/gomarkdown/markdown v0.0.0-20250311123330-531bef5e742b/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= diff --git a/main.go b/main.go index 2252622..8de29a3 100644 --- a/main.go +++ b/main.go @@ -448,6 +448,7 @@ func createServeMux(app *model.AppState) *http.ServeMux { mux.Handle("/admin/", http.StripPrefix("/admin", admin.Handler(app))) mux.Handle("/api/", http.StripPrefix("/api", api.Handler(app))) mux.Handle("/music/", http.StripPrefix("/music", view.MusicHandler(app))) + mux.Handle("/blog/", http.StripPrefix("/blog", view.BlogHandler(app))) mux.Handle("/uploads/", http.StripPrefix("/uploads", staticHandler(filepath.Join(app.Config.DataDirectory, "uploads")))) mux.Handle("/cursor-ws", cursor.Handler(app)) mux.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { diff --git a/model/blog.go b/model/blog.go new file mode 100644 index 0000000..89f37a0 --- /dev/null +++ b/model/blog.go @@ -0,0 +1,39 @@ +package model + +import ( + "fmt" + "html/template" + "regexp" + "strings" + "time" +) + +type ( + Blog struct { + Title string `db:"title"` + Description string `db:"description"` + Visible bool `db:"visible"` + Date time.Time `db:"date"` + AuthorID string `db:"author"` + Markdown string `db:"markdown"` + HTML template.HTML `db:"html"` + } +) + +func (b *Blog) TitleNormalised() string { + rgx := regexp.MustCompile(`[^a-z0-9\-]`) + return rgx.ReplaceAllString( + strings.ReplaceAll( + strings.ToLower(b.Title), " ", "-", + ), + "", + ) +} + +func (b *Blog) GetMonth() string { + return fmt.Sprintf("%02d", int(b.Date.Month())) +} + +func (b *Blog) PrintDate() string { + return b.Date.Format("02 January 2006") +} diff --git a/public/img/aridoodle.png b/public/img/aridoodle.png new file mode 100644 index 0000000..c8328b5 Binary files /dev/null and b/public/img/aridoodle.png differ diff --git a/public/script/blog.js b/public/script/blog.js new file mode 100644 index 0000000..e69de29 diff --git a/public/style/blog.css b/public/style/blog.css new file mode 100644 index 0000000..a333120 --- /dev/null +++ b/public/style/blog.css @@ -0,0 +1,46 @@ +main { + margin: 0 auto 1rem auto; +} + +article.blog { + font-family: 'Lora', serif; +} + +.blog-date { + margin-top: -1em; + opacity: .75; +} + +.blog p { + line-height: 1.5em; +} + +.blog p:hover { + background: inherit; +} + +.blog sub { + opacity: .75; +} + +.blog img { + margin: 0 auto; + max-height: 50%; + max-width: 100%; + + display: block; +} + +.blog i.end-mark { + width: 1.2em; + height: 1.2em; + margin-top: -.2em; + + display: inline-block; + transform: translateY(.2em); + + background: url("/img/aridoodle.png"); + background-size: contain; + background-repeat: no-repeat; + background-position: center; +} diff --git a/view/blog.go b/view/blog.go new file mode 100644 index 0000000..85da400 --- /dev/null +++ b/view/blog.go @@ -0,0 +1,86 @@ +package view + +import ( + "html/template" + "net/http" + "time" + + "arimelody-web/model" + "arimelody-web/templates" + + "github.com/gomarkdown/markdown" + "github.com/gomarkdown/markdown/html" + "github.com/gomarkdown/markdown/parser" +) + +var mdRenderer = html.NewRenderer(html.RendererOptions{ + Flags: html.CommonFlags | html.HrefTargetBlank, +}) + +func BlogHandler(app *model.AppState) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + blog := model.Blog{ + Title: "hello world!~", + Description: "lorem ipsum yadda yadda something boobies babababababababa", + Visible: true, + Date: time.Now(), + AuthorID: "ari", + Markdown: +` +# hello, world! + +i'm ari! + +she/her 🏳️‍⚧️🏳️‍🌈💫🦆🇮🇪 + +i'm a musician, developer, streamer, youtuber, and probably a bunch of other things i forgot to mention! + +you're very welcome to take a look around my little space on the internet here, or explore any of the other parts i inhabit! + +if you're looking to support me financially, that's so cool of you!! if you like, you can buy some of my music over on bandcamp so you can at least get something for your money. thank you very much either way!! 💕 + +for anything else, you can reach me for any and all communications through ari@arimelody.me. if your message contains anything beyond a silly gag, i strongly recommend encrypting your message using my public pgp key, listed below! + +thank you for stopping by- i hope you have a lovely rest of your day! 💫 + +## metadata + +**my colours 🌈** + +- primary: #b7fd49 +- secondary: #f8e05b +- tertiary: #f788fe + +**my keys 🔑** + +- pgp: [[link]](/keys/ari%20melody_0x92678188_public.asc) +- ssh (ed25519): [[link]](/keys/id_ari_ed25519.pub) + +**where to find me 🛰️** + +- youtube +- twitch +- spotify +- bandcamp +- github + +**projects i've worked on 🛠️** + +- catdance +- pride flag +- ipaddrgen +- impact meme +- OpenTerminal +- Silver.js +`, + } + + // blog.Markdown += " " + + mdParser := parser.NewWithExtensions(parser.CommonExtensions | parser.AutoHeadingIDs) + md := mdParser.Parse([]byte(blog.Markdown)) + blog.HTML = template.HTML(markdown.Render(md, mdRenderer)) + + templates.BlogTemplate.Execute(w, &blog) + }) +} diff --git a/view/blog.html b/view/blog.html new file mode 100644 index 0000000..60f3c4b --- /dev/null +++ b/view/blog.html @@ -0,0 +1,34 @@ +{{define "head"}} +{{.Title}} - ari melody 💫 + + + + + + + + + + + + + + +{{end}} + +{{define "content"}} +
+
+

{{.Title}}

+

Posted by {{.AuthorID}} @ {{.PrintDate}}

+ +
+ {{.HTML}} +
+ + +
+ + +
+{{end}}