commit b9566477009e4c688e92077e5a682f5890144d4b Author: Stephen Searles Date: Sun Jun 11 00:28:47 2017 -0700 initial commit diff --git a/caddyhugo.go b/caddyhugo.go new file mode 100644 index 0000000..da45969 --- /dev/null +++ b/caddyhugo.go @@ -0,0 +1,307 @@ +package caddyhugo + +import ( + "errors" + "fmt" + "html/template" + "io/ioutil" + "net/http" + "os" + "path" + "path/filepath" + "strings" + + "github.com/mholt/caddy" + "github.com/mholt/caddy/caddyhttp/httpserver" +) + +func init() { + plugin := CaddyHugo{} + + // register a "generic" plugin, like a directive or middleware + caddy.RegisterPlugin("hugo", caddy.Plugin{ + ServerType: "http", + Action: plugin.Setup, + }) + + // ... there are others. See the godoc. +} + +type CaddyHugo struct { + ServerType string + + authorTmpl, adminTmpl, editTmpl *template.Template +} + +func (c CaddyHugo) Name() string { + if c.ServerType == "" { + return "hugo" + } + return c.ServerType +} + +func (ch CaddyHugo) Setup(c *caddy.Controller) error { + + site := httpserver.GetConfig(c) + + var err error + + ch.authorTmpl, err = template.New("").Parse(AuthorPage) + if err != nil { + return fmt.Errorf("author template invalid: %v", err) + } + + ch.adminTmpl, err = template.New("").Parse(AdminPage) + if err != nil { + return fmt.Errorf("admin template invalid: %v", err) + } + + ch.editTmpl, err = template.New("").Parse(EditPage) + if err != nil { + return fmt.Errorf("edit template invalid: %v", err) + } + + // add a function that wraps listeners for the HTTP server + // (it's more common for a directive to call this rather than a standalone plugin) + site.AddMiddleware(ch.Middleware(c, site)) + + return nil +} + +func (ch CaddyHugo) Middleware(c *caddy.Controller, site *httpserver.SiteConfig) httpserver.Middleware { + return func(h httpserver.Handler) httpserver.Handler { + return httpserver.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) { + if !ch.Match(r) { + return h.ServeHTTP(w, r) + } + + if !ch.Auth(r) { + return http.StatusUnauthorized, errors.New("not authorized") + } + + if strings.HasPrefix(r.URL.Path, "/hugo/admin") { + return ch.Admin(site).ServeHTTP(w, r) + } + if strings.HasPrefix(r.URL.Path, "/hugo/author") { + return ch.AuthorHome(site).ServeHTTP(w, r) + } + if strings.HasPrefix(r.URL.Path, "/hugo/edit/") { + return ch.Edit(c, site).ServeHTTP(w, r) + } + + return http.StatusNotFound, errors.New("not found") + }) + } +} + +func (ch CaddyHugo) Auth(r *http.Request) bool { + return true +} + +func (ch CaddyHugo) Match(r *http.Request) bool { + if r.URL.Path == "/hugo" { + return true + } + + return strings.HasPrefix(r.URL.Path, "/hugo/") +} + +func (ch CaddyHugo) BasePath() string { + return "/hugo" +} + +func (ch CaddyHugo) Admin(site *httpserver.SiteConfig) httpserver.Handler { + return httpserver.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) { + err := ch.adminTmpl.Execute(w, ch.TmplData(r, site)) + if err != nil { + fmt.Println(err) + return http.StatusInternalServerError, err + } + + return http.StatusOK, nil + + }) +} + +func (ch CaddyHugo) AuthorHome(site *httpserver.SiteConfig) httpserver.Handler { + return httpserver.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) { + err := ch.authorTmpl.Execute(w, ch.TmplData(r, site)) + if err != nil { + fmt.Println(err) + return http.StatusInternalServerError, err + } + + return http.StatusOK, nil + }) +} + +func (ch CaddyHugo) Edit(c *caddy.Controller, site *httpserver.SiteConfig) httpserver.Handler { + return httpserver.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) { + if r.URL.Path == "/hugo/edit/new" { + + name := r.FormValue("name") + ctype := r.FormValue("type") + + if filepath.Ext(name) != ".md" { + name += ".md" + } + + filename := path.Join(site.Root, "content", ctype, name) + + dir := filepath.Dir(filename) + if _, err := os.Stat(dir); err != nil && os.IsNotExist(err) { + err = os.MkdirAll(dir, 0755) + if err != nil { + fmt.Println(err) + return http.StatusInternalServerError, err + } + } + + // create content + f, err := os.Create(filename) + if err != nil && !os.IsExist(err) { + fmt.Println(err) + return http.StatusInternalServerError, err + } + + // we only needed to make the file though + err = f.Close() + if err != nil { + fmt.Println(err) + return http.StatusInternalServerError, err + } + + // serve redirect + http.Redirect(w, r, filepath.Join("/hugo/edit/", filename), http.StatusFound) + return http.StatusFound, nil + } + + err := ch.editTmpl.Execute(w, ch.TmplData(r, site)) + if err != nil { + + fmt.Println(err) + return http.StatusInternalServerError, err + } + + return http.StatusOK, nil + }) +} + +func (t tmplData) Content() ([]string, error) { + var files []string + + err := filepath.Walk(path.Join(t.Site.Root, "content"), func(name string, fi os.FileInfo, err error) error { + if fi.IsDir() { + return nil + } + + files = append(files, name) + return nil + }) + + if err != nil { + fmt.Println(err) + return nil, err + } + + return files, nil +} + +func (ch CaddyHugo) TmplData(r *http.Request, site *httpserver.SiteConfig) interface{} { + return tmplData{site, r, ch} +} + +func (t tmplData) ContentTypes() ([]string, error) { + layoutDir, err := os.Open(path.Join(t.Site.Root, "archetypes")) + if err != nil { + fmt.Println("opening layout dir", err) + return nil, err + } + defer layoutDir.Close() + + names, err := layoutDir.Readdirnames(0) + if err != nil { + fmt.Println("reading dir", err) + return nil, err + } + + out := []string{"default"} + for _, name := range names { + out = append(out, name[:len(name)-len(filepath.Ext(name))]) + } + + return out, nil +} + +type tmplData struct { + Site *httpserver.SiteConfig + R *http.Request + CaddyHugo +} + +func (t tmplData) LoadContent() (string, error) { + path := t.R.URL.Path[len("/hugo/edit/"):] + f, err := os.Open(path) + if err != nil { + fmt.Println(err) + return "", err + } + out, err := ioutil.ReadAll(f) + return string(out), err +} + +var EditPage = ` + + + + + + + + + +
{{ .LoadContent }}
+ + +` + +var AdminPage = `not implemented` + +var AuthorPage = ` + + + +

Create content:

+
+ + + +
+ +

Edit content:

+ + +` diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..e2e4749 --- /dev/null +++ b/readme.md @@ -0,0 +1 @@ +author view diff --git a/testdir/caddyfile b/testdir/caddyfile new file mode 100644 index 0000000..ffe92de --- /dev/null +++ b/testdir/caddyfile @@ -0,0 +1,4 @@ +localhost:8080 { + hugo + errors { * } +} diff --git a/testdir/testsite/archetypes/post.md b/testdir/testsite/archetypes/post.md new file mode 100644 index 0000000..1259dc1 --- /dev/null +++ b/testdir/testsite/archetypes/post.md @@ -0,0 +1,3 @@ ++++ +title = "" ++++ diff --git a/testdir/testsite/config.toml b/testdir/testsite/config.toml new file mode 100644 index 0000000..e4b7418 --- /dev/null +++ b/testdir/testsite/config.toml @@ -0,0 +1,3 @@ +baseURL = "http://example.org/" +languageCode = "en-us" +title = "My New Hugo Site" diff --git a/testdir/testsite/content/post/asdf.md b/testdir/testsite/content/post/asdf.md new file mode 100644 index 0000000..e69de29