working on drafts. did a little cleanup

pull/8/head
Stephen Searles 8 years ago
parent 206032be6e
commit c479f26d1d
  1. 114
      caddyhugo.go
  2. 22
      templates.go
  3. 3
      testdir/testsite/archetypes/post.md
  4. 0
      testdir/testsite/content/.md
  5. 7
      testdir/testsite/content/default/sdf.md
  6. 7
      testdir/testsite/content/default/sdfs.md
  7. 0
      testdir/testsite/content/post/asdf.md
  8. 14
      testdir/testsite/public/categories/index.xml
  9. 33
      testdir/testsite/public/default/index.xml
  10. 14
      testdir/testsite/public/index.xml
  11. 20
      testdir/testsite/public/sitemap.xml
  12. 14
      testdir/testsite/public/tags/index.xml

@ -1,12 +1,14 @@
package caddyhugo package caddyhugo
import ( import (
"encoding/base64"
"errors" "errors"
"fmt" "fmt"
"html/template" "html/template"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"os" "os"
"os/exec"
"path" "path"
"path/filepath" "path/filepath"
"strings" "strings"
@ -21,6 +23,11 @@ import (
"github.com/mholt/caddy/caddyhttp/httpserver" "github.com/mholt/caddy/caddyhttp/httpserver"
) )
const (
IdleWebsocketTimeout = 10 * time.Minute
WebsocketFileTicker = 1 * time.Second
)
func init() { func init() {
plugin := CaddyHugo{} plugin := CaddyHugo{}
@ -35,7 +42,9 @@ func init() {
type docref struct { type docref struct {
clients uint clients uint
name string
doc *acedoc.Document doc *acedoc.Document
tmpdir string
} }
type CaddyHugo struct { type CaddyHugo struct {
@ -114,6 +123,9 @@ func (ch CaddyHugo) Middleware(c *caddy.Controller) httpserver.Middleware {
if strings.HasPrefix(r.URL.Path, "/hugo/edit/") { if strings.HasPrefix(r.URL.Path, "/hugo/edit/") {
return ch.Edit(c).ServeHTTP(w, r) 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") return http.StatusNotFound, errors.New("not found")
}) })
@ -177,7 +189,7 @@ func (ch *CaddyHugo) Edit(c *caddy.Controller) httpserver.Handler {
return http.StatusNotFound, err 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 { if err != nil {
fmt.Println(err) 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) { func (ch *CaddyHugo) doc(r *http.Request) (*docref, error) {
ch.mtx.Lock() ch.mtx.Lock()
defer ch.mtx.Unlock() defer ch.mtx.Unlock()
@ -202,12 +252,19 @@ func (ch *CaddyHugo) doc(r *http.Request) (*docref, error) {
return nil, err 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 ch.docs[name] = ref
go func() { go func() {
ticker := time.NewTicker(1 * time.Minute) ticker := time.NewTicker(WebsocketFileTicker)
idleMinutes := 0 idleTicks := 0
for { for {
<-ticker.C <-ticker.C
@ -219,17 +276,25 @@ func (ch *CaddyHugo) doc(r *http.Request) (*docref, error) {
fmt.Println("error saving document contents:", err) 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 { if ref.clients == 0 {
idleMinutes++ idleTicks++
if idleMinutes > 10 { idleTime := time.Duration(idleTicks) * WebsocketFileTicker
fmt.Println("idle for", idleMinutes, "minutes, quitting") if idleTime >= IdleWebsocketTimeout {
fmt.Printf("idle for %v, quitting\n", idleTime)
os.RemoveAll(tmpdir)
delete(ch.docs, name) delete(ch.docs, name)
ch.mtx.Unlock() ch.mtx.Unlock()
return return
} }
fmt.Println("idle for", idleMinutes, "minutes")
} else { } else {
idleMinutes = 0 idleTicks = 0
} }
ch.mtx.Unlock() ch.mtx.Unlock()
} }
@ -304,36 +369,21 @@ func (ch CaddyHugo) NewContent(w http.ResponseWriter, r *http.Request) (int, err
name += ".md" name += ".md"
} }
filename := path.Join(ch.Site.Root, "content", ctype, name) filename := path.Join(ctype, name)
dir := filepath.Dir(filename) cmd := exec.Command("hugo", "new", filename)
if _, err := os.Stat(dir); err != nil && os.IsNotExist(err) { cmd.Dir = ch.Site.Root
err = os.MkdirAll(dir, 0755) out, err := cmd.CombinedOutput()
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 { if err != nil {
fmt.Println(err) fmt.Println("error running hugo:\n", string(out))
return http.StatusInternalServerError, err return http.StatusInternalServerError, err
} }
// serve redirect // 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 return http.StatusFound, nil
} }
func (ch CaddyHugo) TmplData(r *http.Request, doc *acedoc.Document) interface{} { func (ch CaddyHugo) TmplData(r *http.Request, docref *docref) interface{} {
return tmplData{ch.Site, r, ch, doc} return tmplData{ch.Site, r, ch, docref.doc, docref}
} }

@ -1,6 +1,7 @@
package caddyhugo package caddyhugo
import ( import (
"encoding/base64"
"fmt" "fmt"
"net/http" "net/http"
"os" "os"
@ -58,13 +59,18 @@ type tmplData struct {
Site *httpserver.SiteConfig Site *httpserver.SiteConfig
R *http.Request R *http.Request
CaddyHugo CaddyHugo
Doc *acedoc.Document Doc *acedoc.Document
docref *docref
} }
func (t tmplData) LoadContent() (string, error) { func (t tmplData) LoadContent() (string, error) {
return t.Doc.Contents(), nil 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 = `<html> var EditPage = `<html>
<head> <head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.6/ace.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.6/ace.js"></script>
@ -78,12 +84,21 @@ var EditPage = `<html>
top: 50px; top: 50px;
right: 0; right: 0;
bottom: 0; bottom: 0;
left: 40%;
}
#draft {
position: absolute;
top: 50px;
right: 60%;
bottom: 0;
left: 0; left: 0;
} }
</style> </style>
<body> <body>
<div id="editor">{{ .LoadContent }}</div> <div id="editor">{{ .LoadContent }}</div>
<div id="draft"><iframe src="{{ .IframeSource }}">Loading draft...</iframe></div>
<script> <script>
var ltime = 0; var ltime = 0;
function getLtime() { function getLtime() {
@ -124,11 +139,14 @@ var EditPage = `<html>
console.log(err); console.log(err);
}); });
var cases = [];
session.on("change", function (delta) { session.on("change", function (delta) {
if (delta.dontreflect) { if (delta.dontreflect) {
return; return;
} }
console.log('sending', delta); cases.push({"delta":delta, "after":session.getDocument().getValue()});
console.log(JSON.stringify(cases));
socket.send(JSON.stringify({ socket.send(JSON.stringify({
"ltime": getLtime(), "ltime": getLtime(),
"deltas": [delta], "deltas": [delta],

@ -1,3 +0,0 @@
+++
title = ""
+++

@ -0,0 +1,7 @@
+++
date = "2017-06-13T23:13:42-07:00"
draft = true
title = "sdf"
+++

@ -0,0 +1,7 @@
+++
date = "2017-06-13T23:14:27-07:00"
draft = true
title = "sdfs"
+++

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Categories on My New Hugo Site</title>
<link>http://example.org/categories/</link>
<description>Recent content in Categories on My New Hugo Site</description>
<generator>Hugo -- gohugo.io</generator>
<language>en-us</language>
<atom:link href="http://example.org/categories/index.xml" rel="self" type="application/rss+xml" />
</channel>
</rss>

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Defaults on My New Hugo Site</title>
<link>http://example.org/default/</link>
<description>Recent content in Defaults on My New Hugo Site</description>
<generator>Hugo -- gohugo.io</generator>
<language>en-us</language>
<lastBuildDate>Tue, 13 Jun 2017 23:14:27 -0700</lastBuildDate>
<atom:link href="http://example.org/default/index.xml" rel="self" type="application/rss+xml" />
<item>
<title>sdfs</title>
<link>http://example.org/default/sdfs/</link>
<pubDate>Tue, 13 Jun 2017 23:14:27 -0700</pubDate>
<guid>http://example.org/default/sdfs/</guid>
<description></description>
</item>
<item>
<title>sdf</title>
<link>http://example.org/default/sdf/</link>
<pubDate>Tue, 13 Jun 2017 23:13:42 -0700</pubDate>
<guid>http://example.org/default/sdf/</guid>
<description></description>
</item>
</channel>
</rss>

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>My New Hugo Site</title>
<link>http://example.org/</link>
<description>Recent content on My New Hugo Site</description>
<generator>Hugo -- gohugo.io</generator>
<language>en-us</language>
<atom:link href="http://example.org/index.xml" rel="self" type="application/rss+xml" />
</channel>
</rss>

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xhtml="http://www.w3.org/1999/xhtml">
<url>
<loc>http://example.org/categories/</loc>
<priority>0</priority>
</url>
<url>
<loc>http://example.org/</loc>
<priority>0</priority>
</url>
<url>
<loc>http://example.org/tags/</loc>
<priority>0</priority>
</url>
</urlset>

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Tags on My New Hugo Site</title>
<link>http://example.org/tags/</link>
<description>Recent content in Tags on My New Hugo Site</description>
<generator>Hugo -- gohugo.io</generator>
<language>en-us</language>
<atom:link href="http://example.org/tags/index.xml" rel="self" type="application/rss+xml" />
</channel>
</rss>
Loading…
Cancel
Save