filebrowser/editor.go

168 lines
4.1 KiB
Go
Raw Normal View History

2016-06-21 14:28:15 +00:00
package hugo
2015-09-26 21:02:49 +00:00
import (
"bytes"
2016-06-21 15:01:46 +00:00
"html/template"
2015-09-26 21:02:49 +00:00
"io/ioutil"
"net/http"
"os"
"path/filepath"
"strings"
2016-06-21 15:01:46 +00:00
"github.com/hacdias/caddy-filemanager"
2015-09-26 21:02:49 +00:00
"github.com/spf13/hugo/parser"
)
2015-09-27 18:49:58 +00:00
type editor struct {
Name string
Class string
IsPost bool
Mode string
Content string
FrontMatter interface{}
}
2015-09-26 21:02:49 +00:00
// GET handles the GET method on editor page
2016-06-21 15:01:46 +00:00
func (h Hugo) GET(w http.ResponseWriter, r *http.Request, c *Config, filename string) (int, error) {
2016-02-27 14:10:06 +00:00
// Check if the file exists.
2015-09-26 21:02:49 +00:00
if _, err := os.Stat(filename); os.IsNotExist(err) {
2016-03-12 13:03:31 +00:00
return http.StatusNotFound, err
2016-02-27 14:10:06 +00:00
} else if os.IsPermission(err) {
2016-03-12 13:03:31 +00:00
return http.StatusForbidden, err
2016-02-27 14:10:06 +00:00
} else if err != nil {
return http.StatusInternalServerError, err
2015-09-26 21:02:49 +00:00
}
// Open the file and check if there was some error while opening
file, err := ioutil.ReadFile(filename)
2016-02-27 14:10:06 +00:00
if os.IsPermission(err) {
2016-03-12 13:03:31 +00:00
return http.StatusForbidden, err
2016-02-27 14:10:06 +00:00
} else if err != nil {
2015-09-26 21:19:22 +00:00
return http.StatusInternalServerError, err
2015-09-26 21:02:49 +00:00
}
2016-06-21 15:01:46 +00:00
page := &filemanager.Page{
Info: &filemanager.PageInfo{
IsDir: false,
Config: &h.FileManager.Configs[0],
Name: strings.Replace(filename, c.Root, "", 1),
},
}
2015-09-26 21:02:49 +00:00
2016-06-21 15:01:46 +00:00
// Create a new editor variable and set the extension
data := new(editor)
data.Mode = strings.TrimPrefix(filepath.Ext(filename), ".")
data.Name = strings.Replace(filename, c.Root, "", 1)
data.IsPost = false
data.Mode = sanitizeMode(data.Mode)
2015-09-26 21:02:49 +00:00
2016-06-21 15:01:46 +00:00
var parserPage parser.Page
2016-06-16 15:52:37 +00:00
2015-09-26 21:02:49 +00:00
// Handle the content depending on the file extension
2016-06-21 15:01:46 +00:00
switch data.Mode {
case "markdown", "asciidoc", "rst":
2015-09-26 21:02:49 +00:00
if hasFrontMatterRune(file) {
// Starts a new buffer and parses the file using Hugo's functions
buffer := bytes.NewBuffer(file)
2016-06-21 15:01:46 +00:00
parserPage, err = parser.ReadFrom(buffer)
2015-09-26 21:02:49 +00:00
if err != nil {
2015-09-26 21:19:22 +00:00
return http.StatusInternalServerError, err
2015-09-26 21:02:49 +00:00
}
2016-06-21 15:01:46 +00:00
if strings.Contains(string(parserPage.FrontMatter()), "date") {
data.IsPost = true
2015-09-26 21:02:49 +00:00
}
// Parses the page content and the frontmatter
2016-06-21 15:01:46 +00:00
data.Content = strings.TrimSpace(string(parserPage.Content()))
data.FrontMatter, data.Name, err = Pretty(parserPage.FrontMatter())
data.Class = "complete"
2015-09-26 21:02:49 +00:00
} else {
// The editor will handle only content
2016-06-21 15:01:46 +00:00
data.Class = "content-only"
data.Content = string(file)
2015-09-26 21:02:49 +00:00
}
case "json", "toml", "yaml":
// Defines the class and declares an error
2016-06-21 15:01:46 +00:00
data.Class = "frontmatter-only"
2015-09-26 21:02:49 +00:00
// Checks if the file already has the frontmatter rune and parses it
if hasFrontMatterRune(file) {
2016-06-21 15:01:46 +00:00
data.FrontMatter, _, err = Pretty(file)
2015-09-26 21:02:49 +00:00
} else {
2016-06-21 15:01:46 +00:00
data.FrontMatter, _, err = Pretty(appendFrontMatterRune(file, data.Mode))
2015-09-26 21:02:49 +00:00
}
// Check if there were any errors
if err != nil {
2015-09-26 21:19:22 +00:00
return http.StatusInternalServerError, err
2015-09-26 21:02:49 +00:00
}
default:
// The editor will handle only content
2016-06-21 15:01:46 +00:00
data.Class = "content-only"
data.Content = string(file)
2015-09-26 21:02:49 +00:00
}
// Create the functions map, then the template, check for erros and
// execute the template if there aren't errors
functions := template.FuncMap{
2016-06-21 15:01:46 +00:00
"SplitCapitalize": SplitCapitalize,
"Defined": Defined,
2015-09-26 21:02:49 +00:00
}
2016-06-21 15:01:46 +00:00
var code int
page.Info.Data = data
code, err = page.AddTemplate("base", filemanager.Asset, functions)
2015-09-26 21:02:49 +00:00
if err != nil {
2016-06-21 15:01:46 +00:00
return code, err
}
templates := []string{"listing", "actions"}
for _, t := range templates {
code, err = page.AddTemplate(t, Asset, nil)
if err != nil {
return code, err
}
2015-09-26 21:02:49 +00:00
}
2016-06-21 15:01:46 +00:00
return page.PrintAsHTML(w)
2015-09-26 21:02:49 +00:00
}
func hasFrontMatterRune(file []byte) bool {
return strings.HasPrefix(string(file), "---") ||
strings.HasPrefix(string(file), "+++") ||
strings.HasPrefix(string(file), "{")
}
func appendFrontMatterRune(frontmatter []byte, language string) []byte {
switch language {
case "yaml":
return []byte("---\n" + string(frontmatter) + "\n---")
case "toml":
return []byte("+++\n" + string(frontmatter) + "\n+++")
case "json":
return frontmatter
}
return frontmatter
}
func sanitizeMode(extension string) string {
switch extension {
case "md", "markdown", "mdown", "mmark":
2015-09-26 21:02:49 +00:00
return "markdown"
case "asciidoc", "adoc", "ad":
return "asciidoc"
case "rst":
return "rst"
case "html", "htm":
return "html"
2015-09-26 21:02:49 +00:00
case "js":
return "javascript"
default:
return extension
}
}