From c479f26d1dc77998b9582b3135424bfdae344be1 Mon Sep 17 00:00:00 2001 From: Stephen Searles Date: Wed, 14 Jun 2017 00:26:49 -0700 Subject: [PATCH] working on drafts. did a little cleanup --- caddyhugo.go | 114 +++++++++++++------ templates.go | 22 +++- testdir/testsite/archetypes/post.md | 3 - testdir/testsite/content/.md | 0 testdir/testsite/content/default/sdf.md | 7 ++ testdir/testsite/content/default/sdfs.md | 7 ++ testdir/testsite/content/post/asdf.md | 0 testdir/testsite/public/categories/index.xml | 14 +++ testdir/testsite/public/default/index.xml | 33 ++++++ testdir/testsite/public/index.xml | 14 +++ testdir/testsite/public/sitemap.xml | 20 ++++ testdir/testsite/public/tags/index.xml | 14 +++ 12 files changed, 211 insertions(+), 37 deletions(-) delete mode 100644 testdir/testsite/archetypes/post.md delete mode 100644 testdir/testsite/content/.md create mode 100644 testdir/testsite/content/default/sdf.md create mode 100644 testdir/testsite/content/default/sdfs.md delete mode 100644 testdir/testsite/content/post/asdf.md create mode 100644 testdir/testsite/public/categories/index.xml create mode 100644 testdir/testsite/public/default/index.xml create mode 100644 testdir/testsite/public/index.xml create mode 100644 testdir/testsite/public/sitemap.xml create mode 100644 testdir/testsite/public/tags/index.xml diff --git a/caddyhugo.go b/caddyhugo.go index a6ee1b4..524b169 100644 --- a/caddyhugo.go +++ b/caddyhugo.go @@ -1,12 +1,14 @@ package caddyhugo import ( + "encoding/base64" "errors" "fmt" "html/template" "io/ioutil" "net/http" "os" + "os/exec" "path" "path/filepath" "strings" @@ -21,6 +23,11 @@ import ( "github.com/mholt/caddy/caddyhttp/httpserver" ) +const ( + IdleWebsocketTimeout = 10 * time.Minute + WebsocketFileTicker = 1 * time.Second +) + func init() { plugin := CaddyHugo{} @@ -35,7 +42,9 @@ func init() { type docref struct { clients uint + name string doc *acedoc.Document + tmpdir string } type CaddyHugo struct { @@ -114,6 +123,9 @@ func (ch CaddyHugo) Middleware(c *caddy.Controller) httpserver.Middleware { if strings.HasPrefix(r.URL.Path, "/hugo/edit/") { return ch.Edit(c).ServeHTTP(w, r) } + if strings.HasPrefix(r.URL.Path, "/hugo/draft/") { + return ch.serveDraft(w, r) + } return http.StatusNotFound, errors.New("not found") }) @@ -177,7 +189,7 @@ func (ch *CaddyHugo) Edit(c *caddy.Controller) httpserver.Handler { return http.StatusNotFound, err } - err = ch.editTmpl.Execute(w, ch.TmplData(r, doc.doc)) + err = ch.editTmpl.Execute(w, ch.TmplData(r, doc)) if err != nil { fmt.Println(err) @@ -188,6 +200,44 @@ func (ch *CaddyHugo) Edit(c *caddy.Controller) httpserver.Handler { }) } +func (ch *CaddyHugo) serveDraft(w http.ResponseWriter, r *http.Request) (int, error) { + pathSegments := strings.SplitN(r.URL.Path, "/", 5) + if len(pathSegments) < 4 { + + return http.StatusNotFound, nil + } + + encoded := pathSegments[3] + + nameBytes, err := base64.RawURLEncoding.DecodeString(encoded) + if err != nil { + return http.StatusNotFound, err + } + + name := string(nameBytes) + + ch.mtx.Lock() + defer ch.mtx.Unlock() + + docref, ok := ch.docs[name] + + if !ok { + fmt.Println("DRAFT", name, ch.docs) + return http.StatusNotFound, fmt.Errorf("draft not found") + } + + filename := path.Join(docref.tmpdir, name) + + _, err = os.Stat(filename) + if err != nil { + fmt.Println("DRAFT", filename) + return http.StatusNotFound, fmt.Errorf("draft not found") + } + + http.FileServer(http.Dir(docref.tmpdir)).ServeHTTP(w, r) + return 200, nil +} + func (ch *CaddyHugo) doc(r *http.Request) (*docref, error) { ch.mtx.Lock() defer ch.mtx.Unlock() @@ -202,12 +252,19 @@ func (ch *CaddyHugo) doc(r *http.Request) (*docref, error) { return nil, err } - ref := &docref{doc: acedoc.NewString(string(contents))} + draftPrefix := fmt.Sprintf("draft-%s", base64.RawURLEncoding.EncodeToString([]byte(name))) + tmpdir := path.Join(os.TempDir(), draftPrefix) + + ref := &docref{ + name: name, + doc: acedoc.NewString(string(contents)), + tmpdir: tmpdir, + } ch.docs[name] = ref go func() { - ticker := time.NewTicker(1 * time.Minute) - idleMinutes := 0 + ticker := time.NewTicker(WebsocketFileTicker) + idleTicks := 0 for { <-ticker.C @@ -219,17 +276,25 @@ func (ch *CaddyHugo) doc(r *http.Request) (*docref, error) { fmt.Println("error saving document contents:", err) } + fmt.Println("rendering in", ref.tmpdir) + cmd := exec.Command("hugo", "-D", "-d", ref.tmpdir) + cmd.Dir = ch.Site.Root + if out, err := cmd.CombinedOutput(); err != nil { + fmt.Println("error rendering draft:", err, "output:", string(out)) + } + if ref.clients == 0 { - idleMinutes++ - if idleMinutes > 10 { - fmt.Println("idle for", idleMinutes, "minutes, quitting") + idleTicks++ + idleTime := time.Duration(idleTicks) * WebsocketFileTicker + if idleTime >= IdleWebsocketTimeout { + fmt.Printf("idle for %v, quitting\n", idleTime) + os.RemoveAll(tmpdir) delete(ch.docs, name) ch.mtx.Unlock() return } - fmt.Println("idle for", idleMinutes, "minutes") } else { - idleMinutes = 0 + idleTicks = 0 } ch.mtx.Unlock() } @@ -304,36 +369,21 @@ func (ch CaddyHugo) NewContent(w http.ResponseWriter, r *http.Request) (int, err name += ".md" } - filename := path.Join(ch.Site.Root, "content", ctype, name) + filename := path.Join(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() + cmd := exec.Command("hugo", "new", filename) + cmd.Dir = ch.Site.Root + out, err := cmd.CombinedOutput() if err != nil { - fmt.Println(err) + fmt.Println("error running hugo:\n", string(out)) return http.StatusInternalServerError, err } // serve redirect - http.Redirect(w, r, filepath.Join("/hugo/edit/", filename), http.StatusFound) + http.Redirect(w, r, filepath.Join("/hugo/edit/", ch.Site.Root, "content", filename), http.StatusFound) return http.StatusFound, nil } -func (ch CaddyHugo) TmplData(r *http.Request, doc *acedoc.Document) interface{} { - return tmplData{ch.Site, r, ch, doc} +func (ch CaddyHugo) TmplData(r *http.Request, docref *docref) interface{} { + return tmplData{ch.Site, r, ch, docref.doc, docref} } diff --git a/templates.go b/templates.go index 95fe730..aeb6ee4 100644 --- a/templates.go +++ b/templates.go @@ -1,6 +1,7 @@ package caddyhugo import ( + "encoding/base64" "fmt" "net/http" "os" @@ -58,13 +59,18 @@ type tmplData struct { Site *httpserver.SiteConfig R *http.Request CaddyHugo - Doc *acedoc.Document + Doc *acedoc.Document + docref *docref } func (t tmplData) LoadContent() (string, error) { return t.Doc.Contents(), nil } +func (t tmplData) IframeSource() string { + return fmt.Sprintf("/hugo/draft/%s/%s", base64.RawURLEncoding.EncodeToString([]byte(t.docref.name)), t.docref.name) +} + var EditPage = ` @@ -78,12 +84,21 @@ var EditPage = ` top: 50px; right: 0; bottom: 0; + left: 40%; +} +#draft { + position: absolute; + top: 50px; + right: 60%; + bottom: 0; left: 0; + }
{{ .LoadContent }}
+