|  |  |  | @ -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 = `<html> | 
			
		
	
		
			
				
					|  |  |  |  | <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/ext-settings_menu.js"></script> | 
			
		
	
		
			
				
					|  |  |  |  | <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.6/ext-keybinding_menu.js"></script> | 
			
		
	
		
			
				
					|  |  |  |  | <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.6/keybinding-vim.js"></script> | 
			
		
	
		
			
				
					|  |  |  |  | <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.6/mode-markdown.js"></script> | 
			
		
	
		
			
				
					|  |  |  |  | <style type="text/css" media="screen"> | 
			
		
	
		
			
				
					|  |  |  |  | #editor { 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	position: absolute; | 
			
		
	
		
			
				
					|  |  |  |  | 	top: 50px; | 
			
		
	
		
			
				
					|  |  |  |  | 	right: 0; | 
			
		
	
		
			
				
					|  |  |  |  | 	bottom: 0; | 
			
		
	
		
			
				
					|  |  |  |  | 	left: 0; | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | </style> | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | <body> | 
			
		
	
		
			
				
					|  |  |  |  | 	<div id="editor">{{ .LoadContent }}</div> | 
			
		
	
		
			
				
					|  |  |  |  | <script> | 
			
		
	
		
			
				
					|  |  |  |  |     var editor = ace.edit("editor"); | 
			
		
	
		
			
				
					|  |  |  |  |     editor.setTheme("ace/theme/monokai"); | 
			
		
	
		
			
				
					|  |  |  |  |     var session = editor.getSession(); | 
			
		
	
		
			
				
					|  |  |  |  |     session.setMode("ace/mode/markdown"); | 
			
		
	
		
			
				
					|  |  |  |  |     session.on("change", function (delta) { | 
			
		
	
		
			
				
					|  |  |  |  | 	    console.log(delta); | 
			
		
	
		
			
				
					|  |  |  |  |     }) | 
			
		
	
		
			
				
					|  |  |  |  | </script> | 
			
		
	
		
			
				
					|  |  |  |  | </body> | 
			
		
	
		
			
				
					|  |  |  |  | </html>` | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | var AdminPage = `<html><body>not implemented</body></html>` | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | var AuthorPage = `<html> | 
			
		
	
		
			
				
					|  |  |  |  | <head> | 
			
		
	
		
			
				
					|  |  |  |  | </head> | 
			
		
	
		
			
				
					|  |  |  |  | <body> | 
			
		
	
		
			
				
					|  |  |  |  | 	<p>Create content:</p> | 
			
		
	
		
			
				
					|  |  |  |  | 	<form action="/hugo/edit/new" method="POST"> | 
			
		
	
		
			
				
					|  |  |  |  | 		<label>Name: <input type="text" name="name" /></label> | 
			
		
	
		
			
				
					|  |  |  |  | 		<select name="type"> | 
			
		
	
		
			
				
					|  |  |  |  | 		    {{- range .ContentTypes }} | 
			
		
	
		
			
				
					|  |  |  |  | 			<option value="{{ . }}">{{ . }}</option> | 
			
		
	
		
			
				
					|  |  |  |  | 		    {{- end }} | 
			
		
	
		
			
				
					|  |  |  |  | 		</select> | 
			
		
	
		
			
				
					|  |  |  |  | 		<input type="submit" /> | 
			
		
	
		
			
				
					|  |  |  |  | 	</form> | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	<p>Edit content:</p> | 
			
		
	
		
			
				
					|  |  |  |  | 	<ul>{{ range .Content }} | 
			
		
	
		
			
				
					|  |  |  |  | 		<li><a href="/hugo/edit/{{ . }}">{{ . }}</a></li> | 
			
		
	
		
			
				
					|  |  |  |  | 	    {{- end }} | 
			
		
	
		
			
				
					|  |  |  |  | 	</ul> | 
			
		
	
		
			
				
					|  |  |  |  | </body> | 
			
		
	
		
			
				
					|  |  |  |  | </html>` |