This commit is contained in:
Henrique Dias 2015-09-20 20:42:22 +01:00
parent 69efc2d70f
commit 6df32165b1
8 changed files with 192 additions and 86 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -81,7 +81,7 @@ $(document).on('ready pjax:success', function() {
var value = $(this).val(), var value = $(this).val(),
splited = value.split(":"), splited = value.split(":"),
filename = "", filename = "",
archtype = ""; archetype = "";
if (value == "") { if (value == "") {
notification({ notification({
@ -95,17 +95,17 @@ $(document).on('ready pjax:success', function() {
filename = value; filename = value;
} else if (splited.length == 2) { } else if (splited.length == 2) {
filename = splited[0]; filename = splited[0];
archtype = splited[1]; archetype = splited[1];
} else { } else {
notification({ notification({
text: "Hmm... I don't understand you. Try writing something like 'name[:archtype]'.", text: "Hmm... I don't understand you. Try writing something like 'name[:archetype]'.",
type: 'error' type: 'error'
}); });
return false; return false;
} }
var content = '{"filename": "' + filename + '", "archtype": "' + archtype + '"}'; var content = '{"filename": "' + filename + '", "archetype": "' + archetype + '"}';
$.ajax({ $.ajax({
type: 'POST', type: 'POST',
@ -262,6 +262,10 @@ $(document).on('ready pjax:success', function() {
type = "object"; type = "object";
} }
if (title.is('h2')) {
type = "object"
}
if (type == "object") { if (type == "object") {
title.after('<input id="new" placeholder="Write the field name and press enter..."></input>'); title.after('<input id="new" placeholder="Write the field name and press enter..."></input>');
element = $("#new"); element = $("#new");

View File

@ -115,6 +115,7 @@ div[data-type="array-item"] {
label:hover > .actions, label:hover > .actions,
h1:hover > .actions, h1:hover > .actions,
h2:hover > .actions,
h3:hover > .actions, h3:hover > .actions,
div[data-type="array-item"]:hover .actions { div[data-type="array-item"]:hover .actions {
opacity: .7; opacity: .7;

View File

@ -4,7 +4,6 @@ import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"errors" "errors"
"log"
"net/http" "net/http"
"os" "os"
"strings" "strings"
@ -22,85 +21,157 @@ func ServeHTTP(w http.ResponseWriter, r *http.Request, c *config.Config) (int, e
// Removes the page main path from the URL // Removes the page main path from the URL
r.URL.Path = strings.Replace(r.URL.Path, "/admin/browse", "", 1) r.URL.Path = strings.Replace(r.URL.Path, "/admin/browse", "", 1)
// If the URL is blank now, replace it with a trailing slash switch r.Method {
if r.URL.Path == "" { case "DELETE":
r.URL.Path = "/" return delete(w, r)
case "POST":
return post(w, r)
case "GET":
return get(w, r, c)
default:
return 400, nil
} }
}
if r.Method == "DELETE" { func delete(w http.ResponseWriter, r *http.Request) (int, error) {
// Remove both beginning and trailing slashes // Remove both beginning and trailing slashes
r.URL.Path = strings.TrimPrefix(r.URL.Path, "/") r.URL.Path = strings.TrimPrefix(r.URL.Path, "/")
r.URL.Path = strings.TrimSuffix(r.URL.Path, "/") r.URL.Path = strings.TrimSuffix(r.URL.Path, "/")
// Check if the file or directory exists // Check if the file or directory exists
if stat, err := os.Stat(r.URL.Path); err == nil { if stat, err := os.Stat(r.URL.Path); err == nil {
var err error var err error
// If it's dir, remove all of the content inside // If it's dir, remove all of the content inside
if stat.IsDir() { if stat.IsDir() {
err = os.RemoveAll(r.URL.Path) err = os.RemoveAll(r.URL.Path)
} else {
err = os.Remove(r.URL.Path)
}
// Check for errors
if err != nil {
return 500, err
}
} else { } else {
return 404, nil err = os.Remove(r.URL.Path)
} }
w.Header().Set("Content-Type", "application/json") // Check for errors
w.Write([]byte("{}"))
} else if r.Method == "POST" {
// Get the JSON information sent using a buffer
buffer := new(bytes.Buffer)
buffer.ReadFrom(r.Body)
// Creates the raw file "map" using the JSON
var info map[string]interface{}
json.Unmarshal(buffer.Bytes(), &info)
// Check if filename and archtype are specified in
// the request
if _, ok := info["filename"]; !ok {
return 400, errors.New("Filename not specified.")
}
if _, ok := info["archtype"]; !ok {
return 400, errors.New("Archtype not specified.")
}
} else {
functions := template.FuncMap{
"CanBeEdited": utils.CanBeEdited,
"Defined": utils.Defined,
}
tpl, err := utils.GetTemplate(r, functions, "browse")
if err != nil { if err != nil {
log.Print(err) w.Write([]byte(err.Error()))
return 500, err return 500, err
} }
} else {
b := browse.Browse{ return 404, nil
Next: middleware.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
return 404, nil
}),
Root: "./",
Configs: []browse.Config{
browse.Config{
PathScope: "/",
Variables: c,
Template: tpl,
},
},
IgnoreIndexes: true,
}
return b.ServeHTTP(w, r)
} }
w.Header().Set("Content-Type", "application/json")
w.Write([]byte("{}"))
return 200, nil return 200, nil
} }
func post(w http.ResponseWriter, r *http.Request) (int, error) {
// Remove both beginning slashes
r.URL.Path = strings.TrimPrefix(r.URL.Path, "/")
// Get the JSON information sent using a buffer
buffer := new(bytes.Buffer)
buffer.ReadFrom(r.Body)
// Creates the raw file "map" using the JSON
var info map[string]interface{}
json.Unmarshal(buffer.Bytes(), &info)
// Check if filename and archetype are specified in
// the request
if _, ok := info["filename"]; !ok {
return 400, errors.New("Filename not specified.")
}
if _, ok := info["archetype"]; !ok {
return 400, errors.New("Archtype not specified.")
}
// Sanitize the file name path
filename := info["filename"].(string)
filename = strings.TrimPrefix(filename, "/")
filename = strings.TrimSuffix(filename, "/")
filename = r.URL.Path + filename
// Check if the archetype is defined
if info["archetype"] != "" {
// Sanitize the archetype path
archetype := info["archetype"].(string)
archetype = strings.Replace(archetype, "/archetypes", "", 1)
archetype = strings.Replace(archetype, "archetypes", "", 1)
archetype = strings.TrimPrefix(archetype, "/")
archetype = strings.TrimSuffix(archetype, "/")
archetype = "archetypes/" + archetype
// Check if the archetype ending with .markdown exists
if _, err := os.Stat(archetype + ".markdown"); err == nil {
err = utils.CopyFile(archetype+".markdown", filename)
if err != nil {
w.Write([]byte(err.Error()))
return 500, err
}
w.Header().Set("Location", "/admin/edit/"+filename)
w.Header().Set("Content-Type", "application/json")
w.Write([]byte("{}"))
return 201, nil
}
// Check if the archetype ending with .md exists
if _, err := os.Stat(archetype + ".md"); err == nil {
err = utils.CopyFile(archetype+".md", filename)
if err != nil {
w.Write([]byte(err.Error()))
return 500, err
}
w.Header().Set("Location", "/admin/edit/"+filename)
w.Header().Set("Content-Type", "application/json")
w.Write([]byte("{}"))
return 201, nil
}
}
wf, err := os.Create(filename)
if err != nil {
w.Write([]byte(err.Error()))
return 500, err
}
defer wf.Close()
w.Header().Set("Location", "/admin/edit/"+filename)
w.Header().Set("Content-Type", "application/json")
w.Write([]byte("{}"))
return 200, nil
}
func get(w http.ResponseWriter, r *http.Request, c *config.Config) (int, error) {
functions := template.FuncMap{
"CanBeEdited": utils.CanBeEdited,
"Defined": utils.Defined,
}
tpl, err := utils.GetTemplate(r, functions, "browse")
if err != nil {
w.Write([]byte(err.Error()))
return 500, err
}
b := browse.Browse{
Next: middleware.HandlerFunc(func(w http.ResponseWriter, r *http.Request) (int, error) {
return 404, nil
}),
Root: "./",
Configs: []browse.Config{
browse.Config{
PathScope: "/",
Variables: c,
Template: tpl,
},
},
IgnoreIndexes: true,
}
return b.ServeHTTP(w, r)
}

View File

@ -5,7 +5,6 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"io/ioutil" "io/ioutil"
"log"
"net/http" "net/http"
"os" "os"
"path/filepath" "path/filepath"
@ -83,7 +82,7 @@ func servePost(w http.ResponseWriter, r *http.Request, filename string) (int, er
f = []byte(fString) f = []byte(fString)
if err != nil { if err != nil {
log.Print(err) w.Write([]byte(err.Error()))
return 500, err return 500, err
} }
@ -106,7 +105,7 @@ func servePost(w http.ResponseWriter, r *http.Request, filename string) (int, er
jsonFrontmatter, err := json.Marshal(rawFile) jsonFrontmatter, err := json.Marshal(rawFile)
if err != nil { if err != nil {
log.Print(err) w.Write([]byte(err.Error()))
return 500, err return 500, err
} }
@ -127,7 +126,7 @@ func servePost(w http.ResponseWriter, r *http.Request, filename string) (int, er
err := ioutil.WriteFile(filename, file, 0666) err := ioutil.WriteFile(filename, file, 0666)
if err != nil { if err != nil {
log.Print(err) w.Write([]byte(err.Error()))
return 500, err return 500, err
} }
@ -145,14 +144,14 @@ func serveGet(w http.ResponseWriter, r *http.Request, c *config.Config, filename
// Check if the file exists. If it doesn't, send a "Not Found" message // Check if the file exists. If it doesn't, send a "Not Found" message
if _, err := os.Stat(filename); os.IsNotExist(err) { if _, err := os.Stat(filename); os.IsNotExist(err) {
log.Print(err) w.Write([]byte(err.Error()))
return 404, nil return 404, nil
} }
// Open the file and check if there was some error while opening // Open the file and check if there was some error while opening
file, err := ioutil.ReadFile(filename) file, err := ioutil.ReadFile(filename)
if err != nil { if err != nil {
log.Print(err) w.Write([]byte(err.Error()))
return 500, err return 500, err
} }
@ -173,7 +172,7 @@ func serveGet(w http.ResponseWriter, r *http.Request, c *config.Config, filename
buffer := bytes.NewBuffer(file) buffer := bytes.NewBuffer(file)
file, err := parser.ReadFrom(buffer) file, err := parser.ReadFrom(buffer)
if err != nil { if err != nil {
log.Print(err) w.Write([]byte(err.Error()))
return 500, err return 500, err
} }
@ -200,7 +199,7 @@ func serveGet(w http.ResponseWriter, r *http.Request, c *config.Config, filename
// Check if there were any errors // Check if there were any errors
if err != nil { if err != nil {
log.Print(err) w.Write([]byte(err.Error()))
return 500, err return 500, err
} }
default: default:
@ -217,8 +216,9 @@ func serveGet(w http.ResponseWriter, r *http.Request, c *config.Config, filename
} }
tpl, err := utils.GetTemplate(r, functions, "editor", "frontmatter") tpl, err := utils.GetTemplate(r, functions, "editor", "frontmatter")
if err != nil { if err != nil {
log.Print(err) w.Write([]byte(err.Error()))
return 500, err return 500, err
} }

View File

@ -31,7 +31,11 @@
<div id="preview-area" class="scroll hidden"></div> <div id="preview-area" class="scroll hidden"></div>
</div> </div>
<div class="frontmatter scroll"> <div class="frontmatter scroll">
<h2>Metadata</h2> <h2>Metadata
<span class="actions">
<button class="add"><i class="fa fa-plus"></i></button>
</span>
</h2>
{{ template "frontmatter" .FrontMatter }} {{ template "frontmatter" .FrontMatter }}
</div> </div>
{{ end }} {{ end }}

View File

@ -2,8 +2,10 @@ package utils
import ( import (
"errors" "errors"
"io"
"log" "log"
"net/http" "net/http"
"os"
"reflect" "reflect"
"strings" "strings"
"text/template" "text/template"
@ -12,6 +14,30 @@ import (
"github.com/hacdias/caddy-hugo/assets" "github.com/hacdias/caddy-hugo/assets"
) )
// CopyFile is used to copy a file
func CopyFile(old, new string) error {
// Open the file and create a new one
r, err := os.Open(old)
if err != nil {
return err
}
defer r.Close()
w, err := os.Create(new)
if err != nil {
return err
}
defer w.Close()
// Copy the content
_, err = io.Copy(w, r)
if err != nil {
return err
}
return nil
}
// CanBeEdited checks if a filename has a supported extension // CanBeEdited checks if a filename has a supported extension
func CanBeEdited(filename string) bool { func CanBeEdited(filename string) bool {
extensions := [...]string{".markdown", ".md", extensions := [...]string{".markdown", ".md",