From 83d9462ca172e087fb0378faf143ce1034c2091c Mon Sep 17 00:00:00 2001
From: Henrique Dias <hacdias@gmail.com>
Date: Tue, 28 Jun 2016 14:59:33 +0100
Subject: [PATCH] bootstrap new version

---
 .gitignore                      |   7 --
 assets/public/css/styles.css    |  97 ----------------
 assets/public/js/application.js |   6 +-
 assets/templates/editor.tmpl    |  62 ----------
 assets/templates/options.tmpl   |  50 --------
 binary.go                       |  67 -----------
 commands.go                     |  36 ------
 frontmatter.go                  | 172 ---------------------------
 get.go                          | 174 ---------------------------
 hugo.go                         | 109 ++++-------------
 installer/installer.go          |  27 +----
 post.go                         | 200 --------------------------------
 setup.go                        |  57 ++++-----
 utils/commands/commands.go      |  15 +++
 utils/files/files.go            |  30 +++++
 variables.go                    |  95 ---------------
 16 files changed, 93 insertions(+), 1111 deletions(-)
 delete mode 100644 .gitignore
 delete mode 100644 assets/public/css/styles.css
 delete mode 100644 assets/templates/editor.tmpl
 delete mode 100644 assets/templates/options.tmpl
 delete mode 100644 commands.go
 delete mode 100644 frontmatter.go
 delete mode 100644 get.go
 delete mode 100644 post.go
 create mode 100644 utils/commands/commands.go
 create mode 100644 utils/files/files.go
 delete mode 100644 variables.go

diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index d52f8163..00000000
--- a/.gitignore
+++ /dev/null
@@ -1,7 +0,0 @@
-assets.go
-node_modules
-.sass-cache
-temp
-copied_file.txt
-builds
-release
diff --git a/assets/public/css/styles.css b/assets/public/css/styles.css
deleted file mode 100644
index 79e570aa..00000000
--- a/assets/public/css/styles.css
+++ /dev/null
@@ -1,97 +0,0 @@
-.editor input[type="text"], .editor input[type="datetime-local"], .editor textarea {
-    background-color: #f5f3f3;
-    border-radius: .5em;
-    border: 1px solid #ccc;
-    outline: none;
-    padding: .5em;
-    line-height: 1.2em;
-    width: 100%;
-    font-size: 1rem;
-    margin: 0;
-    transition: all 0.3s;
-}
-input[type="text"]:focus {
-    border-bottom: 1px solid #26a69a;
-}
-.editor .block {
-    margin-bottom: 1em;
-}
-.editor fieldset {
-    border: 0;
-    margin: 0;
-    padding: 0;
-}
-.editor h1 textarea {
-    font-size: 2em;
-    font-weight: 400;
-    resize: none;
-    overflow: hidden;
-    padding: 0;
-    line-height: 1em;
-    height: 1em;
-    background-color: transparent;
-    border: 0;
-}
-.editor fieldset h3 {
-    display: inline-block
-}
-.editor label {
-    font-size: .8em;
-    color: #8b8b8b;
-    font-weight: 500;
-}
-.editor .options {
-    column-count: 2;
-    column-gap: 1em;
-}
-.editor .block {
-    break-inside: avoid;
-    position: relative;
-    z-index: 0;
-}
-.editor .block .delete {
-    position: absolute;
-    right: 0;
-    bottom: 1px;
-    height: 2.5em;
-    padding: 0 .7em;
-    background: transparent;
-    color: rgba(0, 0, 0, 0.5);
-}
-
-/* BUTTONS */
-
-.editor button, .editor input[type="submit"] {
-    box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12);
-    border: none;
-    border-radius: 2px;
-    height: 36px;
-    line-height: 36px;
-    outline: 0;
-    padding: 0 2rem;
-    text-transform: uppercase;
-    text-decoration: none;
-    color: #fff;
-    background-color: #26a69a;
-    text-align: center;
-    letter-spacing: .5px;
-    position: relative;
-    cursor: pointer;
-    display: inline-block;
-    overflow: hidden;
-    vertical-align: middle;
-    transition: all .3s ease-out;
-}
-
-/* TOOLBAR */
-
-.editor #actions {
-    display: flex;
-    margin: 1em 0;
-}
-.editor #actions> div {
-    flex-basis: 50%;
-}
-.editor #actions div:nth-child(2) {
-    text-align: right;
-}
diff --git a/assets/public/js/application.js b/assets/public/js/application.js
index d1e6eb60..ad9a93a7 100644
--- a/assets/public/js/application.js
+++ b/assets/public/js/application.js
@@ -1,5 +1 @@
-"use strict";
-
-var ace = document.createElement('script');
-ace.src = 'https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.3/ace.js';
-document.head.appendChild(ace);
+'use strict';
diff --git a/assets/templates/editor.tmpl b/assets/templates/editor.tmpl
deleted file mode 100644
index b2e4ae91..00000000
--- a/assets/templates/editor.tmpl
+++ /dev/null
@@ -1,62 +0,0 @@
-{{ define "content" }}
-<div class="container editor {{ .Class }}">
-{{ if eq .Class "complete" }}
-<h1>
-<textarea id="site-title">{{ .Name }}</textarea>
-</h1>
-
-<form method="POST" action=".">
-<div class="options">
-{{ template "frontmatter" .FrontMatter }}
-<button id="add-field">Add field</button>
-</div>
-
-<div class="main">
-{{ if eq .Mode "markdown" }}
-<nav>
-<a id="see-source" class="active">
-<i class="fa fa-code"></i>
-Source</a>
-<a id="see-preview">
-<i class="fa fa-eye"></i>
-Preview</a>
-</nav>
-{{ end}}
-
-<div id="editor-source" data-mode="{{ .Mode }}"></div>
-<textarea name="content">{{ .Content }}</textarea>
-<div id="editor-preview"></div>
-</form>
-{{ else if eq .Class "content-only" }}
-<form method="POST" action="">
-<h1 id="site-title">{{ .Name }}</h1>
-
-<div class="main">
-<div id="editor-source" data-mode="{{ .Mode }}"></div>
-<textarea name="content">{{ .Content }}</textarea>
-</div>
-</form>
-{{ else }}
-<form method="POST" action="">
-<h1 id="site-title">{{ .Name }}</h1>
-
-<div class="options">
-{{ template "frontmatter" .FrontMatter }}
-<button id="add-field">Add field</button>
-</div>
-</form>
-{{ end }}
-
-<div id="actions">
-<div>
-<input type="submit" data-type="{{ .Class }}" data-regenerate="false" data-schedule="false" value="Save">
-</div>
-<div>
-{{ if and (eq .Class "complete") ( .IsPost ) }}<input type="submit" data-type="{{ .Class }}" data-schedule="true" data-regenerate="false" value="Schedule">
-{{ end }}
-<input type="submit" data-type="{{ .Class }}" data-regenerate="true" data-schedule="false" class="default" value="Publish">
-</div>
-</div>
-</div>
-
-{{ end }}
diff --git a/assets/templates/options.tmpl b/assets/templates/options.tmpl
deleted file mode 100644
index e10b039b..00000000
--- a/assets/templates/options.tmpl
+++ /dev/null
@@ -1,50 +0,0 @@
-{{ define "frontmatter" }}
- {{ range $key, $value := . }}
-
-  {{ if or (eq $value.Type "object") (eq $value.Type "array") }}
-   <fieldset id="{{ $value.Name }}" data-type="{{ $value.Type }}">
-    <div class="title">
-     <h3>{{ SplitCapitalize $value.Title }}</h3>
-
-     <button class="delete" data-delete="{{ $value.Name }}">&#8722;</button>
-    </div>
-
-    <div class="columns">
-     {{ template "frontmatter" $value.Content }}
-     <button class="add">Add field</button>
-    </div>
-
-   </fieldset>
-   {{ else }}
-
-   {{ if not (eq $value.Parent.Type "array") }}
-    <div class="block" id="block-{{ $value.Name }}" data-content="{{ $value.Name }}">
-     <label for="{{ $value.Name }}">{{ SplitCapitalize $value.Title }}</label>
-     <button class="delete" data-delete="block-{{ $value.Name }}">&times;</button>
-
-    {{ end }}
-
-    {{ if eq $value.Parent.Type "array" }}
-     <div class="block" id="{{ $value.Name }}-{{ $key }}" data-type="array-item">
-     {{ end }}
-
-     {{ if eq $value.HTMLType "textarea" }}
-      <textarea class="scroll" name="{{ $value.Name }}:{{ $value.Type }}" id="{{ $value.Name }}" data-parent-type="{{ $value.Parent.Type }}">{{ $value.Content }}</textarea>
-      {{ else if eq $value.HTMLType "datetime" }}
-      <input name="{{ $value.Name }}:{{ $value.Type }}" id="{{ $value.Name }}" value="{{ $value.Content.Format " 2006-01-02T15:04" }}" type="datetime-local" data-parent-type="{{ $value.Parent.Type }}"></input>
-      {{ else }}
-      <input name="{{ $value.Name }}:{{ $value.Type }}" id="{{ $value.Name }}" value="{{ $value.Content }}" type="{{ $value.HTMLType }}" data-parent-type="{{ $value.Parent.Type }}"></input>
-     {{ end }}
-
-     {{ if not (eq $value.Parent.Type "array") }}
-     </div>
-    {{ end }}
-
-    {{ if eq $value.Parent.Type "array" }}
-     <button class="delete" data-delete="{{ $value.Name }}">&times;</button>
-    </div>
-   {{ end }}
-
-  {{ end }}
- {{ end }}
-{{ end }}
diff --git a/binary.go b/binary.go
index e8011866..3aabdc3e 100644
--- a/binary.go
+++ b/binary.go
@@ -1,9 +1,6 @@
 // Code generated by go-bindata.
 // sources:
-// assets/public/css/styles.css
 // assets/public/js/application.js
-// assets/templates/editor.tmpl
-// assets/templates/options.tmpl
 // DO NOT EDIT!
 
 package hugo
@@ -30,24 +27,6 @@ type asset struct {
 	info  os.FileInfo
 }
 
-// publicCssStylesCss reads file data from disk. It returns an error on failure.
-func publicCssStylesCss() (*asset, error) {
-	path := "D:\\Code\\Go\\src\\github.com\\hacdias\\caddy-hugo\\assets\\public\\css\\styles.css"
-	name := "public/css/styles.css"
-	bytes, err := bindataRead(path, name)
-	if err != nil {
-		return nil, err
-	}
-
-	fi, err := os.Stat(path)
-	if err != nil {
-		err = fmt.Errorf("Error reading asset info %s at %s: %v", name, path, err)
-	}
-
-	a := &asset{bytes: bytes, info: fi}
-	return a, err
-}
-
 // publicJsApplicationJs reads file data from disk. It returns an error on failure.
 func publicJsApplicationJs() (*asset, error) {
 	path := "D:\\Code\\Go\\src\\github.com\\hacdias\\caddy-hugo\\assets\\public\\js\\application.js"
@@ -66,42 +45,6 @@ func publicJsApplicationJs() (*asset, error) {
 	return a, err
 }
 
-// templatesEditorTmpl reads file data from disk. It returns an error on failure.
-func templatesEditorTmpl() (*asset, error) {
-	path := "D:\\Code\\Go\\src\\github.com\\hacdias\\caddy-hugo\\assets\\templates\\editor.tmpl"
-	name := "templates/editor.tmpl"
-	bytes, err := bindataRead(path, name)
-	if err != nil {
-		return nil, err
-	}
-
-	fi, err := os.Stat(path)
-	if err != nil {
-		err = fmt.Errorf("Error reading asset info %s at %s: %v", name, path, err)
-	}
-
-	a := &asset{bytes: bytes, info: fi}
-	return a, err
-}
-
-// templatesOptionsTmpl reads file data from disk. It returns an error on failure.
-func templatesOptionsTmpl() (*asset, error) {
-	path := "D:\\Code\\Go\\src\\github.com\\hacdias\\caddy-hugo\\assets\\templates\\options.tmpl"
-	name := "templates/options.tmpl"
-	bytes, err := bindataRead(path, name)
-	if err != nil {
-		return nil, err
-	}
-
-	fi, err := os.Stat(path)
-	if err != nil {
-		err = fmt.Errorf("Error reading asset info %s at %s: %v", name, path, err)
-	}
-
-	a := &asset{bytes: bytes, info: fi}
-	return a, err
-}
-
 // Asset loads and returns the asset for the given name.
 // It returns an error if the asset could not be found or
 // could not be loaded.
@@ -154,10 +97,7 @@ func AssetNames() []string {
 
 // _bindata is a table, holding each asset generator, mapped to its name.
 var _bindata = map[string]func() (*asset, error){
-	"public/css/styles.css": publicCssStylesCss,
 	"public/js/application.js": publicJsApplicationJs,
-	"templates/editor.tmpl": templatesEditorTmpl,
-	"templates/options.tmpl": templatesOptionsTmpl,
 }
 
 // AssetDir returns the file names below a certain
@@ -201,17 +141,10 @@ type bintree struct {
 }
 var _bintree = &bintree{nil, map[string]*bintree{
 	"public": &bintree{nil, map[string]*bintree{
-		"css": &bintree{nil, map[string]*bintree{
-			"styles.css": &bintree{publicCssStylesCss, map[string]*bintree{}},
-		}},
 		"js": &bintree{nil, map[string]*bintree{
 			"application.js": &bintree{publicJsApplicationJs, map[string]*bintree{}},
 		}},
 	}},
-	"templates": &bintree{nil, map[string]*bintree{
-		"editor.tmpl": &bintree{templatesEditorTmpl, map[string]*bintree{}},
-		"options.tmpl": &bintree{templatesOptionsTmpl, map[string]*bintree{}},
-	}},
 }}
 
 // RestoreAsset restores an asset under the given directory
diff --git a/commands.go b/commands.go
deleted file mode 100644
index 080cc187..00000000
--- a/commands.go
+++ /dev/null
@@ -1,36 +0,0 @@
-package hugo
-
-import (
-	"log"
-	"os"
-	"os/exec"
-)
-
-// Run executes an external command
-func Run(command string, args []string, path string) error {
-	cmd := exec.Command(command, args...)
-	cmd.Dir = path
-	cmd.Stdout = os.Stderr
-	cmd.Stderr = os.Stderr
-	return cmd.Run()
-}
-
-// RunHugo is used to run the static website generator
-func RunHugo(c *Config, force bool) {
-	os.RemoveAll(c.Public)
-
-	// Prevent running if watching is enabled
-	if b, pos := StringInSlice("--watch", c.Args); b && !force {
-		if len(c.Args) > pos && c.Args[pos+1] != "false" {
-			return
-		}
-
-		if len(c.Args) == pos+1 {
-			return
-		}
-	}
-
-	if err := Run(c.Hugo, c.Args, c.Root); err != nil {
-		log.Panic(err)
-	}
-}
diff --git a/frontmatter.go b/frontmatter.go
deleted file mode 100644
index 5fb3090e..00000000
--- a/frontmatter.go
+++ /dev/null
@@ -1,172 +0,0 @@
-package hugo
-
-import (
-	"log"
-	"reflect"
-	"sort"
-	"strings"
-
-	"github.com/spf13/cast"
-	"github.com/spf13/hugo/parser"
-)
-
-const (
-	mainName   = "#MAIN#"
-	objectType = "object"
-	arrayType  = "array"
-)
-
-var mainTitle = ""
-
-// Pretty creates a new FrontMatter object
-func Pretty(content []byte) (interface{}, string, error) {
-	frontType := parser.DetectFrontMatter(rune(content[0]))
-	front, err := frontType.Parse(content)
-
-	if err != nil {
-		return []string{}, mainTitle, err
-	}
-
-	object := new(frontmatter)
-	object.Type = objectType
-	object.Name = mainName
-
-	return rawToPretty(front, object), mainTitle, nil
-}
-
-type frontmatter struct {
-	Name     string
-	Title    string
-	Content  interface{}
-	Type     string
-	HTMLType string
-	Parent   *frontmatter
-}
-
-func rawToPretty(config interface{}, parent *frontmatter) interface{} {
-	objects := []*frontmatter{}
-	arrays := []*frontmatter{}
-	fields := []*frontmatter{}
-
-	cnf := map[string]interface{}{}
-
-	if reflect.TypeOf(config) == reflect.TypeOf(map[interface{}]interface{}{}) {
-		for key, value := range config.(map[interface{}]interface{}) {
-			cnf[key.(string)] = value
-		}
-	} else if reflect.TypeOf(config) == reflect.TypeOf([]interface{}{}) {
-		for key, value := range config.([]interface{}) {
-			cnf[string(key)] = value
-		}
-	} else {
-		cnf = config.(map[string]interface{})
-	}
-
-	for name, element := range cnf {
-		if IsMap(element) {
-			objects = append(objects, handleObjects(element, parent, name))
-		} else if IsSlice(element) {
-			arrays = append(arrays, handleArrays(element, parent, name))
-		} else {
-			if name == "title" && parent.Name == mainName {
-				mainTitle = element.(string)
-			}
-
-			fields = append(fields, handleFlatValues(element, parent, name))
-		}
-	}
-
-	sort.Sort(sortByTitle(objects))
-	sort.Sort(sortByTitle(arrays))
-	sort.Sort(sortByTitle(fields))
-
-	settings := []*frontmatter{}
-	settings = append(settings, fields...)
-	settings = append(settings, arrays...)
-	settings = append(settings, objects...)
-	return settings
-}
-
-type sortByTitle []*frontmatter
-
-func (f sortByTitle) Len() int      { return len(f) }
-func (f sortByTitle) Swap(i, j int) { f[i], f[j] = f[j], f[i] }
-func (f sortByTitle) Less(i, j int) bool {
-	return strings.ToLower(f[i].Name) < strings.ToLower(f[j].Name)
-}
-
-func handleObjects(content interface{}, parent *frontmatter, name string) *frontmatter {
-	c := new(frontmatter)
-	c.Parent = parent
-	c.Type = objectType
-	c.Title = name
-
-	if parent.Name == mainName {
-		c.Name = c.Title
-	} else if parent.Type == arrayType {
-		c.Name = parent.Name + "[]"
-	} else {
-		c.Name = parent.Name + "[" + c.Title + "]"
-	}
-
-	c.Content = rawToPretty(content, c)
-	return c
-}
-
-func handleArrays(content interface{}, parent *frontmatter, name string) *frontmatter {
-	c := new(frontmatter)
-	c.Parent = parent
-	c.Type = arrayType
-	c.Title = name
-
-	if parent.Name == mainName {
-		c.Name = name
-	} else {
-		c.Name = parent.Name + "[" + name + "]"
-	}
-
-	c.Content = rawToPretty(content, c)
-	return c
-}
-
-func handleFlatValues(content interface{}, parent *frontmatter, name string) *frontmatter {
-	c := new(frontmatter)
-	c.Parent = parent
-
-	switch reflect.ValueOf(content).Kind() {
-	case reflect.Bool:
-		c.Type = "boolean"
-	case reflect.Int, reflect.Float32, reflect.Float64:
-		c.Type = "number"
-	default:
-		c.Type = "string"
-	}
-
-	c.Content = content
-
-	switch strings.ToLower(name) {
-	case "description":
-		c.HTMLType = "textarea"
-	case "date", "publishdate":
-		c.HTMLType = "datetime"
-		c.Content = cast.ToTime(content)
-	default:
-		c.HTMLType = "text"
-	}
-
-	if parent.Type == arrayType {
-		c.Name = parent.Name + "[]"
-		c.Title = content.(string)
-	} else if parent.Type == objectType {
-		c.Title = name
-		c.Name = parent.Name + "[" + name + "]"
-
-		if parent.Name == mainName {
-			c.Name = name
-		}
-	} else {
-		log.Panic("Parent type not allowed in handleFlatValues.")
-	}
-
-	return c
-}
diff --git a/get.go b/get.go
deleted file mode 100644
index ac799485..00000000
--- a/get.go
+++ /dev/null
@@ -1,174 +0,0 @@
-package hugo
-
-import (
-	"bytes"
-	"fmt"
-	"html/template"
-	"io/ioutil"
-	"net/http"
-	"os"
-	"path/filepath"
-	"strings"
-
-	"github.com/hacdias/caddy-filemanager"
-	"github.com/spf13/hugo/parser"
-)
-
-type editor struct {
-	Name        string
-	Class       string
-	IsPost      bool
-	Mode        string
-	Content     string
-	BaseURL     string
-	FrontMatter interface{}
-}
-
-// GET handles the GET method on editor page
-func (h Hugo) GET(w http.ResponseWriter, r *http.Request, filename string) (int, error) {
-	// Check if the file exists.
-	if _, err := os.Stat(filename); os.IsNotExist(err) {
-		return http.StatusNotFound, err
-	} else if os.IsPermission(err) {
-		return http.StatusForbidden, err
-	} else if err != nil {
-		return http.StatusInternalServerError, err
-	}
-
-	// Open the file and check if there was some error while opening
-	file, err := ioutil.ReadFile(filename)
-	if os.IsPermission(err) {
-		return http.StatusForbidden, err
-	} else if err != nil {
-		return http.StatusInternalServerError, err
-	}
-
-	// Create a new editor variable and set the extension
-	data := new(editor)
-	data.Mode = strings.TrimPrefix(filepath.Ext(filename), ".")
-	data.Name = strings.Replace(filename, h.Config.Root, "", 1)
-	data.IsPost = false
-	data.BaseURL = h.Config.BaseURL
-	data.Mode = sanitizeMode(data.Mode)
-
-	var parserPage parser.Page
-
-	// Handle the content depending on the file extension
-	switch data.Mode {
-	case "markdown", "asciidoc", "rst":
-		if hasFrontMatterRune(file) {
-			// Starts a new buffer and parses the file using Hugo's functions
-			buffer := bytes.NewBuffer(file)
-			parserPage, err = parser.ReadFrom(buffer)
-			if err != nil {
-				return http.StatusInternalServerError, err
-			}
-
-			if strings.Contains(string(parserPage.FrontMatter()), "date") {
-				data.IsPost = true
-			}
-
-			// Parses the page content and the frontmatter
-			data.Content = strings.TrimSpace(string(parserPage.Content()))
-			data.FrontMatter, data.Name, err = Pretty(parserPage.FrontMatter())
-			data.Class = "complete"
-		} else {
-			// The editor will handle only content
-			data.Class = "content-only"
-			data.Content = string(file)
-		}
-	case "json", "toml", "yaml":
-		// Defines the class and declares an error
-		data.Class = "frontmatter-only"
-
-		// Checks if the file already has the frontmatter rune and parses it
-		if hasFrontMatterRune(file) {
-			data.FrontMatter, _, err = Pretty(file)
-		} else {
-			data.FrontMatter, _, err = Pretty(appendFrontMatterRune(file, data.Mode))
-		}
-
-		// Check if there were any errors
-		if err != nil {
-			return http.StatusInternalServerError, err
-		}
-	default:
-		// The editor will handle only content
-		data.Class = "content-only"
-		data.Content = string(file)
-	}
-
-	// Create the functions map, then the template, check for erros and
-	// execute the template if there aren't errors
-	functions := template.FuncMap{
-		"SplitCapitalize": SplitCapitalize,
-		"Defined":         Defined,
-	}
-
-	var code int
-
-	page := &filemanager.Page{
-		Info: &filemanager.PageInfo{
-			IsDir:  false,
-			Config: &h.FileManager.Configs[0],
-			Name:   data.Name,
-			Data:   data,
-		},
-	}
-
-	templates := []string{"options", "editor"}
-	for _, t := range templates {
-		code, err = page.AddTemplate(t, Asset, functions)
-		if err != nil {
-			return code, err
-		}
-	}
-
-	templates = []string{"actions", "base"}
-	for _, t := range templates {
-		code, err = page.AddTemplate(t, filemanager.Asset, nil)
-		if err != nil {
-			return code, err
-		}
-	}
-
-	code, err = page.PrintAsHTML(w)
-	fmt.Println(err)
-	return code, err
-}
-
-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":
-		return "markdown"
-	case "asciidoc", "adoc", "ad":
-		return "asciidoc"
-	case "rst":
-		return "rst"
-	case "html", "htm":
-		return "html"
-	case "js":
-		return "javascript"
-	default:
-		return extension
-	}
-}
diff --git a/hugo.go b/hugo.go
index d282973c..684b3a52 100644
--- a/hugo.go
+++ b/hugo.go
@@ -7,6 +7,7 @@
 package hugo
 
 import (
+	"log"
 	"mime"
 	"net/http"
 	"os"
@@ -14,120 +15,54 @@ import (
 	"strings"
 
 	"github.com/hacdias/caddy-filemanager"
+	"github.com/hacdias/caddy-filemanager/utils/variables"
+	"github.com/hacdias/caddy-hugo/utils/commands"
 	"github.com/mholt/caddy/caddyhttp/httpserver"
 )
 
-// AssetsURL is the base url of the assets
-const AssetsURL = "/_hugointernal"
-
-// Hugo contais the next middleware to be run and the configuration
-// of the current one.
+// Hugo is hugo
 type Hugo struct {
-	FileManager *filemanager.FileManager
 	Next        httpserver.Handler
 	Config      *Config
+	FileManager *filemanager.FileManager
 }
 
-// ServeHTTP is the main function of the whole plugin that routes every single
-// request to its function.
 func (h Hugo) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
-	// Check if the current request if for this plugin
 	if httpserver.Path(r.URL.Path).Matches(h.Config.BaseURL) {
-		// Check if we are asking for the assets
 		if httpserver.Path(r.URL.Path).Matches(h.Config.BaseURL + AssetsURL) {
-			return h.ServeAssets(w, r)
-		}
 
-		// If the url matches exactly with /{admin}/settings/, redirect
-		// to the page of the configuration file
-		if r.URL.Path == h.Config.BaseURL+"/settings/" {
-			var frontmatter string
-
-			if _, err := os.Stat(h.Config.Root + "config.yaml"); err == nil {
-				frontmatter = "yaml"
-			}
-
-			if _, err := os.Stat(h.Config.Root + "config.json"); err == nil {
-				frontmatter = "json"
-			}
-
-			if _, err := os.Stat(h.Config.Root + "config.toml"); err == nil {
-				frontmatter = "toml"
-			}
-
-			http.Redirect(w, r, h.Config.BaseURL+"/config."+frontmatter, http.StatusTemporaryRedirect)
-			return 0, nil
-		}
-
-		if strings.HasPrefix(r.URL.Path, h.Config.BaseURL+"/api/git/") && r.Method == http.MethodPost {
-			//return HandleGit(w, r, h.Config)
-			return 0, nil
-		}
-
-		if h.ShouldHandle(r) {
-			filename := strings.Replace(r.URL.Path, h.Config.BaseURL, h.Config.Root, 1)
-			switch r.Method {
-			case http.MethodGet:
-				return h.GET(w, r, filename)
-			case http.MethodPost:
-				return h.POST(w, r, filename)
-			default:
-				return h.FileManager.ServeHTTP(w, r)
-			}
 		}
 
 		return h.FileManager.ServeHTTP(w, r)
 	}
+
 	return h.Next.ServeHTTP(w, r)
 }
 
-var extensions = []string{
-	"md", "markdown", "mdown", "mmark",
-	"asciidoc", "adoc", "ad",
-	"rst",
-	"html", "htm",
-	"js",
-	"toml", "yaml", "json",
-}
+// RunHugo is used to run the static website generator
+func RunHugo(c *Config, force bool) {
+	os.RemoveAll(c.Root + "public")
 
-// ShouldHandle checks if this extension should be handled by this plugin
-func (h Hugo) ShouldHandle(r *http.Request) bool {
-	// Checks if the method is get or post
-	if r.Method != http.MethodGet && r.Method != http.MethodPost {
-		return false
-	}
+	// Prevent running if watching is enabled
+	if b, pos := variables.StringInSlice("--watch", c.Args); b && !force {
+		if len(c.Args) > pos && c.Args[pos+1] != "false" {
+			return
+		}
 
-	// Check if this request is for FileManager assets
-	if httpserver.Path(r.URL.Path).Matches(h.Config.BaseURL + filemanager.AssetsURL) {
-		return false
-	}
-
-	// If this request requires a raw file or a download, return the FileManager
-	query := r.URL.Query()
-	if val, ok := query["raw"]; ok && val[0] == "true" {
-		return false
-	}
-
-	if val, ok := query["download"]; ok && val[0] == "true" {
-		return false
-	}
-
-	// Check by file extension
-	extension := strings.TrimPrefix(filepath.Ext(r.URL.Path), ".")
-
-	for _, ext := range extensions {
-		if ext == extension {
-			return true
+		if len(c.Args) == pos+1 {
+			return
 		}
 	}
 
-	return false
+	if err := commands.Run(c.Hugo, c.Args, c.Root); err != nil {
+		log.Panic(err)
+	}
 }
 
-// ServeAssets provides the needed assets for the front-end
-func (h Hugo) ServeAssets(w http.ResponseWriter, r *http.Request) (int, error) {
+// serveAssets provides the needed assets for the front-end
+func serveAssets(w http.ResponseWriter, r *http.Request, c *Config) (int, error) {
 	// gets the filename to be used with Assets function
-	filename := strings.Replace(r.URL.Path, h.Config.BaseURL+AssetsURL, "public", 1)
+	filename := strings.Replace(r.URL.Path, c.BaseURL+AssetsURL, "public", 1)
 	file, err := Asset(filename)
 	if err != nil {
 		return http.StatusNotFound, nil
diff --git a/installer/installer.go b/installer/installer.go
index af77bb9b..2dc968dd 100644
--- a/installer/installer.go
+++ b/installer/installer.go
@@ -14,6 +14,7 @@ import (
 	"regexp"
 	"runtime"
 
+	"github.com/hacdias/caddy-hugo/utils/files"
 	"github.com/mitchellh/go-homedir"
 	"github.com/pivotal-golang/archiver/extractor"
 )
@@ -90,7 +91,7 @@ func GetPath() string {
 
 	// Copy the file
 	fmt.Print("Moving Hugo executable... ")
-	err = CopyFile(exetorename, hugo)
+	err = files.CopyFile(exetorename, hugo)
 	if err != nil {
 		fmt.Println(err)
 		os.Exit(-1)
@@ -213,27 +214,3 @@ func checkSHA256() {
 
 	fmt.Println("checked!")
 }
-
-// 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
-}
diff --git a/post.go b/post.go
deleted file mode 100644
index ecdf5744..00000000
--- a/post.go
+++ /dev/null
@@ -1,200 +0,0 @@
-package hugo
-
-import (
-	"bytes"
-	"encoding/json"
-	"errors"
-	"io/ioutil"
-	"net/http"
-	"path/filepath"
-	"strings"
-	"time"
-
-	"github.com/robfig/cron"
-	"github.com/spf13/cast"
-	"github.com/spf13/hugo/parser"
-)
-
-type info struct {
-	ContentType string
-	Schedule    bool
-	Regenerate  bool
-	Content     map[string]interface{}
-}
-
-type response struct {
-	Message string `json:"message"`
-}
-
-// POST handles the POST method on editor page
-func (h Hugo) POST(w http.ResponseWriter, r *http.Request, filename string) (int, error) {
-	var data info
-
-	// Get the JSON information sent using a buffer
-	rawBuffer := new(bytes.Buffer)
-	rawBuffer.ReadFrom(r.Body)
-	err := json.Unmarshal(rawBuffer.Bytes(), &data)
-
-	if err != nil {
-		return RespondJSON(w, &response{"Error decrypting json."}, http.StatusInternalServerError, err)
-	}
-
-	// Initializes the file content to write
-	var file []byte
-	var code int
-
-	switch data.ContentType {
-	case "frontmatter-only":
-		file, code, err = parseFrontMatterOnlyFile(data, filename)
-		if err != nil {
-			return RespondJSON(w, &response{err.Error()}, code, err)
-		}
-	case "content-only":
-		// The main content of the file
-		mainContent := data.Content["content"].(string)
-		mainContent = strings.TrimSpace(mainContent)
-
-		file = []byte(mainContent)
-	case "complete":
-		file, code, err = parseCompleteFile(data, filename, h.Config)
-		if err != nil {
-			return RespondJSON(w, &response{err.Error()}, code, err)
-		}
-	default:
-		return RespondJSON(w, &response{"Invalid content type."}, http.StatusBadRequest, nil)
-	}
-
-	// Write the file
-	err = ioutil.WriteFile(filename, file, 0666)
-
-	if err != nil {
-		return RespondJSON(w, &response{err.Error()}, http.StatusInternalServerError, err)
-	}
-
-	if data.Regenerate {
-		go RunHugo(h.Config, false)
-	}
-
-	return RespondJSON(w, nil, http.StatusOK, nil)
-}
-
-func parseFrontMatterOnlyFile(data info, filename string) ([]byte, int, error) {
-	frontmatter := strings.TrimPrefix(filepath.Ext(filename), ".")
-	var mark rune
-
-	switch frontmatter {
-	case "toml":
-		mark = rune('+')
-	case "json":
-		mark = rune('{')
-	case "yaml":
-		mark = rune('-')
-	default:
-		return []byte{}, http.StatusBadRequest, errors.New("Can't define the frontmatter.")
-	}
-
-	f, err := parser.InterfaceToFrontMatter(data.Content, mark)
-	fString := string(f)
-
-	// If it's toml or yaml, strip frontmatter identifier
-	if frontmatter == "toml" {
-		fString = strings.TrimSuffix(fString, "+++\n")
-		fString = strings.TrimPrefix(fString, "+++\n")
-	}
-
-	if frontmatter == "yaml" {
-		fString = strings.TrimSuffix(fString, "---\n")
-		fString = strings.TrimPrefix(fString, "---\n")
-	}
-
-	f = []byte(fString)
-
-	if err != nil {
-		return []byte{}, http.StatusInternalServerError, err
-	}
-
-	return f, http.StatusOK, nil
-}
-
-func parseCompleteFile(data info, filename string, c *Config) ([]byte, int, error) {
-	// The main content of the file
-	mainContent := data.Content["content"].(string)
-	mainContent = "\n\n" + strings.TrimSpace(mainContent) + "\n"
-
-	// Removes the main content from the rest of the frontmatter
-	delete(data.Content, "content")
-
-	if _, ok := data.Content["date"]; ok {
-		data.Content["date"] = data.Content["date"].(string) + ":00"
-	}
-
-	// Schedule the post
-	if data.Schedule {
-		t := cast.ToTime(data.Content["date"])
-
-		scheduler := cron.New()
-		scheduler.AddFunc(t.In(time.Now().Location()).Format("05 04 15 02 01 *"), func() {
-			// Set draft to false
-			data.Content["draft"] = false
-
-			// Converts the frontmatter in JSON
-			jsonFrontmatter, err := json.Marshal(data.Content)
-
-			if err != nil {
-				return
-			}
-
-			// Indents the json
-			frontMatterBuffer := new(bytes.Buffer)
-			json.Indent(frontMatterBuffer, jsonFrontmatter, "", "  ")
-
-			// Generates the final file
-			f := new(bytes.Buffer)
-			f.Write(frontMatterBuffer.Bytes())
-			f.Write([]byte(mainContent))
-			file := f.Bytes()
-
-			// Write the file
-			if err = ioutil.WriteFile(filename, file, 0666); err != nil {
-				return
-			}
-
-			go RunHugo(c, false)
-		})
-		scheduler.Start()
-	}
-
-	// Converts the frontmatter in JSON
-	jsonFrontmatter, err := json.Marshal(data.Content)
-
-	if err != nil {
-		return []byte{}, http.StatusInternalServerError, err
-	}
-
-	// Indents the json
-	frontMatterBuffer := new(bytes.Buffer)
-	json.Indent(frontMatterBuffer, jsonFrontmatter, "", "  ")
-
-	// Generates the final file
-	f := new(bytes.Buffer)
-	f.Write(frontMatterBuffer.Bytes())
-	f.Write([]byte(mainContent))
-	return f.Bytes(), http.StatusOK, nil
-}
-
-func RespondJSON(w http.ResponseWriter, message interface{}, code int, err error) (int, error) {
-	if message == nil {
-		message = map[string]string{}
-	}
-
-	msg, msgErr := json.Marshal(message)
-
-	if msgErr != nil {
-		return 500, msgErr
-	}
-
-	w.Header().Set("Content-Type", "application/json")
-	w.WriteHeader(code)
-	w.Write(msg)
-	return 0, err
-}
diff --git a/setup.go b/setup.go
index 8152cc88..b6f43708 100644
--- a/setup.go
+++ b/setup.go
@@ -5,15 +5,18 @@ import (
 	"log"
 	"net/http"
 	"os"
-	"path/filepath"
 	"strings"
 
 	"github.com/hacdias/caddy-filemanager"
+	"github.com/hacdias/caddy-filemanager/config"
 	"github.com/hacdias/caddy-hugo/installer"
+	"github.com/hacdias/caddy-hugo/utils/commands"
 	"github.com/mholt/caddy"
 	"github.com/mholt/caddy/caddyhttp/httpserver"
 )
 
+const AssetsURL = "/_hugointernal"
+
 func init() {
 	caddy.RegisterPlugin("hugo", caddy.Plugin{
 		ServerType: "http",
@@ -25,7 +28,7 @@ func init() {
 // middleware thing.
 func setup(c *caddy.Controller) error {
 	cnf := httpserver.GetConfig(c)
-	conf, _ := ParseHugo(c, cnf.Root)
+	conf, _ := parse(c, cnf.Root)
 
 	// Checks if there is an Hugo website in the path that is provided.
 	// If not, a new website will be created.
@@ -44,7 +47,7 @@ func setup(c *caddy.Controller) error {
 	}
 
 	if create {
-		err := Run(conf.Hugo, []string{"new", "site", conf.Root, "--force"}, ".")
+		err := commands.Run(conf.Hugo, []string{"new", "site", conf.Root, "--force"}, ".")
 		if err != nil {
 			log.Panic(err)
 		}
@@ -59,8 +62,8 @@ func setup(c *caddy.Controller) error {
 			Config: conf,
 			FileManager: &filemanager.FileManager{
 				Next: next,
-				Configs: []filemanager.Config{
-					filemanager.Config{
+				Configs: []config.Config{
+					config.Config{
 						HugoEnabled: true,
 						PathScope:   conf.Root,
 						Root:        http.Dir(conf.Root),
@@ -76,35 +79,27 @@ func setup(c *caddy.Controller) error {
 	return nil
 }
 
-// Config contains the configuration of hugo plugin
+// Config is a configuration for managing a particular hugo website.
 type Config struct {
-	Args    []string // Hugo arguments
-	Git     bool     // Is this site a git repository
-	BaseURL string   // Admin URL to listen on
-	Hugo    string   // Hugo executable path
-	Root    string   // Hugo website path
-	Public  string   // Public content path
-	Styles  string   // Admin stylesheet
+	Public      string   // Public content path
+	Root        string   // Hugo files path
+	Hugo        string   // Hugo executable location
+	Styles      string   // Admin styles path
+	Args        []string // Hugo arguments
+	BaseURL     string   // BaseURL of admin interface
+	FileManager *filemanager.FileManager
 }
 
-// ParseHugo parses the configuration file
-func ParseHugo(c *caddy.Controller, root string) (*Config, error) {
+// Parse parses the configuration set by the user so it can be
+// used by the middleware
+func parse(c *caddy.Controller, root string) (*Config, error) {
 	conf := &Config{
 		Public:  strings.Replace(root, "./", "", -1),
 		BaseURL: "/admin",
 		Root:    "./",
-		Git:     false,
-		Hugo:    installer.GetPath(),
 	}
 
-	stlsbytes, err := Asset("public/css/styles.css")
-
-	if err != nil {
-		return conf, err
-	}
-
-	conf.Styles = string(stlsbytes)
-
+	conf.Hugo = installer.GetPath()
 	for c.Next() {
 		args := c.RemainingArgs()
 
@@ -121,19 +116,17 @@ func ParseHugo(c *caddy.Controller, root string) (*Config, error) {
 				if !c.NextArg() {
 					return conf, c.ArgErr()
 				}
-				stylesheet, err := ioutil.ReadFile(c.Val())
+				tplBytes, err := ioutil.ReadFile(c.Val())
 				if err != nil {
 					return conf, err
 				}
-				conf.Styles += string(stylesheet)
+				conf.Styles = string(tplBytes)
 			case "admin":
 				if !c.NextArg() {
-					return nil, c.ArgErr()
+					return conf, c.ArgErr()
 				}
 				conf.BaseURL = c.Val()
-				// Remove the beginning slash if it exists or not
 				conf.BaseURL = strings.TrimPrefix(conf.BaseURL, "/")
-				// Add a beginning slash to make a
 				conf.BaseURL = "/" + conf.BaseURL
 			default:
 				key := "--" + c.Val()
@@ -148,9 +141,5 @@ func ParseHugo(c *caddy.Controller, root string) (*Config, error) {
 		}
 	}
 
-	if _, err := os.Stat(filepath.Join(conf.Root, ".git")); err == nil {
-		conf.Git = true
-	}
-
 	return conf, nil
 }
diff --git a/utils/commands/commands.go b/utils/commands/commands.go
new file mode 100644
index 00000000..2e8626d4
--- /dev/null
+++ b/utils/commands/commands.go
@@ -0,0 +1,15 @@
+package commands
+
+import (
+	"os"
+	"os/exec"
+)
+
+// Run executes an external command
+func Run(command string, args []string, path string) error {
+	cmd := exec.Command(command, args...)
+	cmd.Dir = path
+	cmd.Stdout = os.Stderr
+	cmd.Stderr = os.Stderr
+	return cmd.Run()
+}
diff --git a/utils/files/files.go b/utils/files/files.go
new file mode 100644
index 00000000..084259ca
--- /dev/null
+++ b/utils/files/files.go
@@ -0,0 +1,30 @@
+package files
+
+import (
+	"io"
+	"os"
+)
+
+// 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
+}
diff --git a/variables.go b/variables.go
deleted file mode 100644
index e361b612..00000000
--- a/variables.go
+++ /dev/null
@@ -1,95 +0,0 @@
-package hugo
-
-import (
-	"errors"
-	"log"
-	"reflect"
-	"strings"
-	"unicode"
-)
-
-// Defined checks if variable is defined in a struct
-func Defined(data interface{}, field string) bool {
-	t := reflect.Indirect(reflect.ValueOf(data)).Type()
-
-	if t.Kind() != reflect.Struct {
-		log.Print("Non-struct type not allowed.")
-		return false
-	}
-
-	_, b := t.FieldByName(field)
-	return b
-}
-
-// Dict allows to send more than one variable into a template
-func Dict(values ...interface{}) (map[string]interface{}, error) {
-	if len(values)%2 != 0 {
-		return nil, errors.New("invalid dict call")
-	}
-	dict := make(map[string]interface{}, len(values)/2)
-	for i := 0; i < len(values); i += 2 {
-		key, ok := values[i].(string)
-		if !ok {
-			return nil, errors.New("dict keys must be strings")
-		}
-		dict[key] = values[i+1]
-	}
-
-	return dict, nil
-}
-
-// IsMap checks if some variable is a map
-func IsMap(sth interface{}) bool {
-	return reflect.ValueOf(sth).Kind() == reflect.Map
-}
-
-// IsSlice checks if some variable is a slice
-func IsSlice(sth interface{}) bool {
-	return reflect.ValueOf(sth).Kind() == reflect.Slice
-}
-
-// StringInSlice checks if a slice contains a string
-func StringInSlice(a string, list []string) (bool, int) {
-	for i, b := range list {
-		if b == a {
-			return true, i
-		}
-	}
-	return false, 0
-}
-
-var splitCapitalizeExceptions = map[string]string{
-	"youtube":    "YouTube",
-	"github":     "GitHub",
-	"googleplus": "Google Plus",
-	"linkedin":   "LinkedIn",
-}
-
-// SplitCapitalize splits a string by its uppercase letters and capitalize the
-// first letter of the string
-func SplitCapitalize(name string) string {
-	if val, ok := splitCapitalizeExceptions[strings.ToLower(name)]; ok {
-		return val
-	}
-
-	var words []string
-	l := 0
-	for s := name; s != ""; s = s[l:] {
-		l = strings.IndexFunc(s[1:], unicode.IsUpper) + 1
-		if l <= 0 {
-			l = len(s)
-		}
-		words = append(words, s[:l])
-	}
-
-	name = ""
-
-	for _, element := range words {
-		name += element + " "
-	}
-
-	name = strings.ToLower(name[:len(name)-1])
-	name = strings.ToUpper(string(name[0])) + name[1:]
-
-	return name
-}