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
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}
}

@ -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 = `<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.6/ace.js"></script>
@ -78,12 +84,21 @@ var EditPage = `<html>
top: 50px;
right: 0;
bottom: 0;
left: 40%;
}
#draft {
position: absolute;
top: 50px;
right: 60%;
bottom: 0;
left: 0;
}
</style>
<body>
<div id="editor">{{ .LoadContent }}</div>
<div id="draft"><iframe src="{{ .IframeSource }}">Loading draft...</iframe></div>
<script>
var ltime = 0;
function getLtime() {
@ -124,11 +139,14 @@ var EditPage = `<html>
console.log(err);
});
var cases = [];
session.on("change", function (delta) {
if (delta.dontreflect) {
return;
}
console.log('sending', delta);
cases.push({"delta":delta, "after":session.getDocument().getValue()});
console.log(JSON.stringify(cases));
socket.send(JSON.stringify({
"ltime": getLtime(),
"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