Initial commit - read and serve markdown and static files
This commit is contained in:
commit
8daaa1b330
8 changed files with 180 additions and 0 deletions
15
README.md
Normal file
15
README.md
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
# Prose
|
||||||
|
|
||||||
|
Prose is a blogging platform written in Go, which I am building to serve my own blog.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Blog posts should be created in the format `DATE-title-slug.md`. Work in progress posts should be stored as `WIP-title-slug.md`. Static content should be stored in the `static/` folder, appropriately arranged.
|
||||||
|
|
||||||
|
Posts will be served as `/title-slug`, and files like `static/random/file/structure.txt` will be served as `/random/file/structure.txt`. When title slugs and static files conflict, slugs will have higher precdence.
|
||||||
|
|
||||||
|
To start the server:
|
||||||
|
|
||||||
|
go run .
|
||||||
|
|
||||||
|
Server will be live on port 8080.
|
5
go.mod
Normal file
5
go.mod
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
module prose
|
||||||
|
|
||||||
|
go 1.15
|
||||||
|
|
||||||
|
require github.com/yuin/goldmark v1.3.1
|
24
go.sum
Normal file
24
go.sum
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
||||||
|
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||||
|
github.com/russross/blackfriday v2.0.0+incompatible/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||||
|
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||||
|
github.com/yuin/goldmark v1.3.1 h1:eVwehsLsZlCJCwXyGLgg+Q4iFWE/eTIMG0e8waCmm/I=
|
||||||
|
github.com/yuin/goldmark v1.3.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
|
gitlab.com/golang-commonmark/html v0.0.0-20191124015941-a22733972181 h1:K+bMSIx9A7mLES1rtG+qKduLIXq40DAzYHtb0XuCukA=
|
||||||
|
gitlab.com/golang-commonmark/html v0.0.0-20191124015941-a22733972181/go.mod h1:dzYhVIwWCtzPAa4QP98wfB9+mzt33MSmM8wsKiMi2ow=
|
||||||
|
gitlab.com/golang-commonmark/linkify v0.0.0-20191026162114-a0c2df6c8f82 h1:oYrL81N608MLZhma3ruL8qTM4xcpYECGut8KSxRY59g=
|
||||||
|
gitlab.com/golang-commonmark/linkify v0.0.0-20191026162114-a0c2df6c8f82/go.mod h1:Gn+LZmCrhPECMD3SOKlE+BOHwhOYD9j7WT9NUtkCrC8=
|
||||||
|
gitlab.com/golang-commonmark/linkify v0.0.0-20200225224916-64bca66f6ad3 h1:1Coh5BsUBlXoEJmIEaNzVAWrtg9k7/eJzailMQr1grw=
|
||||||
|
gitlab.com/golang-commonmark/linkify v0.0.0-20200225224916-64bca66f6ad3/go.mod h1:Gn+LZmCrhPECMD3SOKlE+BOHwhOYD9j7WT9NUtkCrC8=
|
||||||
|
gitlab.com/golang-commonmark/markdown v0.0.0-20191127184510-91b5b3c99c19 h1:HsZm6XaTpEgZiZqcXZkUbG6BNtSZE3XyCTfo52YBoDY=
|
||||||
|
gitlab.com/golang-commonmark/markdown v0.0.0-20191127184510-91b5b3c99c19/go.mod h1:CRIzp0wh6PvKEAeEOtp9wEpNKJJ1VFTNfHO4+ToRgVA=
|
||||||
|
gitlab.com/golang-commonmark/mdurl v0.0.0-20191124015652-932350d1cb84 h1:qqjvoVXdWIcZCLPMlzgA7P9FZWdPGPvP/l3ef8GzV6o=
|
||||||
|
gitlab.com/golang-commonmark/mdurl v0.0.0-20191124015652-932350d1cb84/go.mod h1:IJZ+fdMvbW2qW6htJx7sLJ04FEs4Ldl/MDsJtMKywfw=
|
||||||
|
gitlab.com/golang-commonmark/puny v0.0.0-20191124015043-9f83538fa04f h1:Wku8eEdeJqIOFHtrfkYUByc4bCaTeA6fL0UJgfEiFMI=
|
||||||
|
gitlab.com/golang-commonmark/puny v0.0.0-20191124015043-9f83538fa04f/go.mod h1:Tiuhl+njh/JIg0uS/sOJVYi0x2HEa5rc1OAaVsb5tAs=
|
||||||
|
gitlab.com/opennota/wd v0.0.0-20180912061657-c5d65f63c638/go.mod h1:EGRJaqe2eO9XGmFtQCvV3Lm9NLico3UhFwUpCG/+mVU=
|
||||||
|
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||||
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
|
golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
|
||||||
|
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
37
page.go
Normal file
37
page.go
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
|
||||||
|
"github.com/yuin/goldmark"
|
||||||
|
"github.com/yuin/goldmark/extension"
|
||||||
|
"github.com/yuin/goldmark/renderer/html"
|
||||||
|
)
|
||||||
|
|
||||||
|
type page struct {
|
||||||
|
slug string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *page) render() ([]byte, error) {
|
||||||
|
data, err := ioutil.ReadFile("posts/" + p.slug + ".md")
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Could not read from %s.md: %s", p.slug, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
md := goldmark.New(
|
||||||
|
goldmark.WithExtensions(extension.Linkify),
|
||||||
|
goldmark.WithRendererOptions(
|
||||||
|
html.WithUnsafe(),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
var converted bytes.Buffer
|
||||||
|
err = md.Convert(data, &converted)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Could not parse markdown from %s.md: %s", p.slug, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return converted.Bytes(), nil
|
||||||
|
}
|
1
posts/.gitignore
vendored
Normal file
1
posts/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
WIP-*
|
20
prose.go
Normal file
20
prose.go
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
log.Printf("Hello, world! This is Prose.")
|
||||||
|
|
||||||
|
s, err := newServer()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
http.HandleFunc("/", s.router)
|
||||||
|
|
||||||
|
log.Fatal(http.ListenAndServe(":8080", nil))
|
||||||
|
}
|
78
server.go
Normal file
78
server.go
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type server struct {
|
||||||
|
pages []page
|
||||||
|
staticHandler http.Handler
|
||||||
|
}
|
||||||
|
|
||||||
|
func newServer() (*server, error) {
|
||||||
|
files, err := ioutil.ReadDir("posts/")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
s := &server{
|
||||||
|
pages: make([]page, 0, len(files)),
|
||||||
|
staticHandler: http.FileServer(http.Dir("static/")),
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, f := range files {
|
||||||
|
filename := f.Name()
|
||||||
|
|
||||||
|
if strings.HasSuffix(filename, ".md") {
|
||||||
|
s.pages = append(s.pages, page{slug: strings.TrimSuffix(filename, ".md")})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return s, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *server) logRequest(req *http.Request) {
|
||||||
|
log.Printf("%s %s from %s", req.Method, req.URL.Path, req.RemoteAddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *server) router(res http.ResponseWriter, req *http.Request) {
|
||||||
|
s.logRequest(req)
|
||||||
|
slug := req.URL.Path[1:]
|
||||||
|
|
||||||
|
if slug == "" {
|
||||||
|
s.homePage(res, req)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, p := range s.pages {
|
||||||
|
if p.slug == slug {
|
||||||
|
buf, err := p.render()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
res.WriteHeader(http.StatusInternalServerError)
|
||||||
|
res.Write([]byte("oh no"))
|
||||||
|
}
|
||||||
|
|
||||||
|
res.Write(buf)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s.staticHandler.ServeHTTP(res, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *server) homePage(res http.ResponseWriter, req *http.Request) {
|
||||||
|
res.Header().Add("content-type", "text/html")
|
||||||
|
|
||||||
|
res.Write([]byte("<h1>blog</h1>"))
|
||||||
|
|
||||||
|
for _, p := range s.pages {
|
||||||
|
fmt.Fprintf(res, "<a href=\"/%s\">%s</a><br>", p.slug, p.slug)
|
||||||
|
}
|
||||||
|
}
|
BIN
static/img/blog-init/line-height.png
Normal file
BIN
static/img/blog-init/line-height.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 103 KiB |
Loading…
Add table
Add a link
Reference in a new issue