pull/20/head
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(),
splited = value.split(":"),
filename = "",
archtype = "";
archetype = "";
if (value == "") {
notification({
@ -95,17 +95,17 @@ $(document).on('ready pjax:success', function() {
filename = value;
} else if (splited.length == 2) {
filename = splited[0];
archtype = splited[1];
archetype = splited[1];
} else {
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'
});
return false;
}
var content = '{"filename": "' + filename + '", "archtype": "' + archtype + '"}';
var content = '{"filename": "' + filename + '", "archetype": "' + archetype + '"}';
$.ajax({
type: 'POST',
@ -262,6 +262,10 @@ $(document).on('ready pjax:success', function() {
type = "object";
}
if (title.is('h2')) {
type = "object"
}
if (type == "object") {
title.after('<input id="new" placeholder="Write the field name and press enter..."></input>');
element = $("#new");

View File

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

View File

@ -4,7 +4,6 @@ import (
"bytes"
"encoding/json"
"errors"
"log"
"net/http"
"os"
"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
r.URL.Path = strings.Replace(r.URL.Path, "/admin/browse", "", 1)
// If the URL is blank now, replace it with a trailing slash
if r.URL.Path == "" {
r.URL.Path = "/"
switch r.Method {
case "DELETE":
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" {
// Remove both beginning and trailing slashes
r.URL.Path = strings.TrimPrefix(r.URL.Path, "/")
r.URL.Path = strings.TrimSuffix(r.URL.Path, "/")
func delete(w http.ResponseWriter, r *http.Request) (int, error) {
// Remove both beginning and trailing slashes
r.URL.Path = strings.TrimPrefix(r.URL.Path, "/")
r.URL.Path = strings.TrimSuffix(r.URL.Path, "/")
// Check if the file or directory exists
if stat, err := os.Stat(r.URL.Path); err == nil {
var err error
// If it's dir, remove all of the content inside
if stat.IsDir() {
err = os.RemoveAll(r.URL.Path)
} else {
err = os.Remove(r.URL.Path)
}
// Check for errors
if err != nil {
return 500, err
}
// Check if the file or directory exists
if stat, err := os.Stat(r.URL.Path); err == nil {
var err error
// If it's dir, remove all of the content inside
if stat.IsDir() {
err = os.RemoveAll(r.URL.Path)
} else {
return 404, nil
err = os.Remove(r.URL.Path)
}
w.Header().Set("Content-Type", "application/json")
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")
// Check for errors
if err != nil {
log.Print(err)
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)
} else {
return 404, nil
}
w.Header().Set("Content-Type", "application/json")
w.Write([]byte("{}"))
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"
"errors"
"io/ioutil"
"log"
"net/http"
"os"
"path/filepath"
@ -83,7 +82,7 @@ func servePost(w http.ResponseWriter, r *http.Request, filename string) (int, er
f = []byte(fString)
if err != nil {
log.Print(err)
w.Write([]byte(err.Error()))
return 500, err
}
@ -106,7 +105,7 @@ func servePost(w http.ResponseWriter, r *http.Request, filename string) (int, er
jsonFrontmatter, err := json.Marshal(rawFile)
if err != nil {
log.Print(err)
w.Write([]byte(err.Error()))
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)
if err != nil {
log.Print(err)
w.Write([]byte(err.Error()))
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
if _, err := os.Stat(filename); os.IsNotExist(err) {
log.Print(err)
w.Write([]byte(err.Error()))
return 404, nil
}
// Open the file and check if there was some error while opening
file, err := ioutil.ReadFile(filename)
if err != nil {
log.Print(err)
w.Write([]byte(err.Error()))
return 500, err
}
@ -173,7 +172,7 @@ func serveGet(w http.ResponseWriter, r *http.Request, c *config.Config, filename
buffer := bytes.NewBuffer(file)
file, err := parser.ReadFrom(buffer)
if err != nil {
log.Print(err)
w.Write([]byte(err.Error()))
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
if err != nil {
log.Print(err)
w.Write([]byte(err.Error()))
return 500, err
}
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")
if err != nil {
log.Print(err)
w.Write([]byte(err.Error()))
return 500, err
}

View File

@ -31,7 +31,11 @@
<div id="preview-area" class="scroll hidden"></div>
</div>
<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 }}
</div>
{{ end }}

View File

@ -2,8 +2,10 @@ package utils
import (
"errors"
"io"
"log"
"net/http"
"os"
"reflect"
"strings"
"text/template"
@ -12,6 +14,30 @@ import (
"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
func CanBeEdited(filename string) bool {
extensions := [...]string{".markdown", ".md",