structure changes
							parent
							
								
									3f36200862
								
							
						
					
					
						commit
						1375038a66
					
				
							
								
								
									
										14
									
								
								Gruntfile.js
								
								
								
								
							
							
						
						
									
										14
									
								
								Gruntfile.js
								
								
								
								
							|  | @ -8,11 +8,11 @@ module.exports = function(grunt) { | |||
|   grunt.initConfig({ | ||||
|     watch: { | ||||
|       sass: { | ||||
|         files: ['assets/src/css/**/*.css'], | ||||
|         files: ['assets/public_src/css/**/*.css'], | ||||
|         tasks: ['concat', 'cssmin'] | ||||
|       }, | ||||
|       js: { | ||||
|         files: ['assets/src/js/**/*.js'], | ||||
|         files: ['assets/public_src/js/**/*.js'], | ||||
|         tasks: ['uglify:main'] | ||||
|       }, | ||||
|     }, | ||||
|  | @ -24,7 +24,7 @@ module.exports = function(grunt) { | |||
|           'node_modules/animate.css/source/bouncing_entrances/bounceInRight.css', | ||||
|           'node_modules/animate.css/source/fading_entrances/fadeIn.css', | ||||
|           'node_modules/animate.css/source/fading_exits/fadeOut.css', | ||||
|           'assets/src/css/main.css' | ||||
|           'assets/public_src/css/main.css' | ||||
|         ], | ||||
|         dest: 'temp/css/main.css', | ||||
|       }, | ||||
|  | @ -35,7 +35,7 @@ module.exports = function(grunt) { | |||
|           expand: true, | ||||
|           flatten: true, | ||||
|           src: ['node_modules/font-awesome/fonts/**'], | ||||
|           dest: 'assets/fonts' | ||||
|           dest: 'assets/public/fonts' | ||||
|         }], | ||||
|       }, | ||||
|     }, | ||||
|  | @ -48,7 +48,7 @@ module.exports = function(grunt) { | |||
|           expand: true, | ||||
|           cwd: 'temp/css/', | ||||
|           src: ['*.css', '!*.min.css'], | ||||
|           dest: 'assets/css/', | ||||
|           dest: 'assets/public/css/', | ||||
|           ext: '.min.css' | ||||
|         }] | ||||
|       } | ||||
|  | @ -56,7 +56,7 @@ module.exports = function(grunt) { | |||
|     uglify: { | ||||
|       plugins: { | ||||
|         files: { | ||||
|           'assets/js/plugins.min.js': ['node_modules/jquery/dist/jquery.min.js', | ||||
|           'assets/public/js/plugins.min.js': ['node_modules/jquery/dist/jquery.min.js', | ||||
|             'node_modules/perfect-scrollbar/dist/js/min/perfect-scrollbar.jquery.min.js', | ||||
|             'node_modules/showdown/dist/showdown.min.js', | ||||
|             'node_modules/noty/js/noty/packaged/jquery.noty.packaged.min.js', | ||||
|  | @ -67,7 +67,7 @@ module.exports = function(grunt) { | |||
|       }, | ||||
|       main: { | ||||
|         files: { | ||||
|           'assets/js/app.min.js': ['assets/src/js/**/*.js'] | ||||
|           'assets/public/js/app.min.js': ['assets/src/js/**/*.js'] | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|  |  | |||
| Before Width: | Height: | Size: 357 KiB After Width: | Height: | Size: 357 KiB | 
|  | @ -5,7 +5,6 @@ import ( | |||
| 	"path/filepath" | ||||
| 	"strings" | ||||
| 
 | ||||
| 	"github.com/hacdias/caddy-hugo/tools/hugo" | ||||
| 	"github.com/mholt/caddy/caddy/setup" | ||||
| ) | ||||
| 
 | ||||
|  | @ -27,7 +26,7 @@ func ParseHugo(c *setup.Controller) (*Config, error) { | |||
| 		Git:    false, | ||||
| 	} | ||||
| 
 | ||||
| 	conf.Hugo = hugo.GetPath() | ||||
| 	conf.Hugo = GetPath() | ||||
| 
 | ||||
| 	for c.Next() { | ||||
| 		args := c.RemainingArgs() | ||||
|  |  | |||
|  | @ -0,0 +1,211 @@ | |||
| package config | ||||
| 
 | ||||
| import ( | ||||
| 	"crypto/sha256" | ||||
| 	"encoding/hex" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"io/ioutil" | ||||
| 	"log" | ||||
| 	"net/http" | ||||
| 	"os" | ||||
| 	"os/exec" | ||||
| 	"path/filepath" | ||||
| 	"runtime" | ||||
| 
 | ||||
| 	"github.com/hacdias/caddy-hugo/tools/files" | ||||
| 	"github.com/mitchellh/go-homedir" | ||||
| 	"github.com/pivotal-golang/archiver/extractor" | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	version = "0.15" | ||||
| 	baseurl = "https://github.com/spf13/hugo/releases/download/v" + version + "/" | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
| 	caddy, bin, temp, hugo, tempfile, zipname, exename string | ||||
| 	sha256Hash                                         = map[string]string{ | ||||
| 		"hugo_0.15_darwin_386.zip":              "f9b7353f9b64e7aece5f7981e5aa97dc4b31974ce76251edc070e77691bc03e2", | ||||
| 		"hugo_0.15_darwin_amd64.zip":            "aeecd6a12d86ab920f5b04e9486474bbe478dc246cdc2242799849b84c61c6f1", | ||||
| 		"hugo_0.15_dragonfly_amd64.zip":         "e380343789f2b2e0c366c8e1eeb251ccd90eea53dac191ff85d8177b130e53bc", | ||||
| 		"hugo_0.15_freebsd_386.zip":             "98f9210bfa3dcb48bd154879ea1cfe1b0ed8a3d891fdeacbdb4c3fc69b72aac4", | ||||
| 		"hugo_0.15_freebsd_amd64.zip":           "aa6a3028899e76e6920b9b5a64c29e14017ae34120efa67276e614e3a69cb100", | ||||
| 		"hugo_0.15_freebsd_arm.zip":             "de52e1b07caf778bdc3bdb07f39119cd5a1739c8822ebe311cd4f667c43588ac", | ||||
| 		"hugo_0.15_linux_386.tar.gz":            "af28c4cbb16db765535113f361a38b2249c634ce2d3798dcf5b795de6e4b7ecf", | ||||
| 		"hugo_0.15_linux_amd64.tar.gz":          "32a6335bd76f72867efdec9306a8a7eb7b9498a2e0478105efa96c1febadb09b", | ||||
| 		"hugo_0.15_linux_arm.tar.gz":            "886dd1a843c057a46c541011183dd558469250580e81450eedbd1a4d041e9234", | ||||
| 		"hugo_0.15_netbsd_386.zip":              "6245f5db16b33a09466f149d5b7b68a7899d6d624903de9e7e70c4b6ea869a72", | ||||
| 		"hugo_0.15_netbsd_amd64.zip":            "103ea8d81d2a3d707c05e3dd68c98fcf8146ddd36b49bf0e65d9874cee230c88", | ||||
| 		"hugo_0.15_netbsd_arm.zip":              "9c9b5cf4ea3b6169be1b5fc924251a247d9c140dd8a45aa5175031878585ff0a", | ||||
| 		"hugo_0.15_openbsd_386.zip":             "81dfdb3048a27a61b249650241fe4e8da1eda31a3a7311c615eb419f1cdd06b1", | ||||
| 		"hugo_0.15_openbsd_amd64.zip":           "e7447cde0dd7628b05b25b86938018774d8db8156ab1330b364e0e2c6501ad87", | ||||
| 		"hugo_0.15_windows_386_32-bit-only.zip": "0a72f9a1a929f36c0e52fb1c6272b4d37a2bd1a6bd19ce57a6e7b6803b434756", | ||||
| 		"hugo_0.15_windows_amd64.zip":           "9f03602e48ae2199e06431d7436fb3b9464538c0d44aac9a76eb98e1d4d5d727", | ||||
| 	} | ||||
| ) | ||||
| 
 | ||||
| // GetPath retrives the Hugo path for the user or install it if it's not found
 | ||||
| func GetPath() string { | ||||
| 	initializeVariables() | ||||
| 
 | ||||
| 	var err error | ||||
| 
 | ||||
| 	// Check if Hugo is already on $PATH
 | ||||
| 	if hugo, err := exec.LookPath("hugo"); err == nil { | ||||
| 		return hugo | ||||
| 	} | ||||
| 
 | ||||
| 	// Check if Hugo is on $HOME/.caddy/bin
 | ||||
| 	if _, err = os.Stat(hugo); err == nil { | ||||
| 		return hugo | ||||
| 	} | ||||
| 
 | ||||
| 	fmt.Println("Unable to find Hugo on your computer.") | ||||
| 
 | ||||
| 	// Create the neccessary folders
 | ||||
| 	os.MkdirAll(caddy, 0774) | ||||
| 	os.Mkdir(bin, 0774) | ||||
| 
 | ||||
| 	if temp, err = ioutil.TempDir("", "caddy-hugo"); err != nil { | ||||
| 		fmt.Println(err) | ||||
| 		os.Exit(-1) | ||||
| 	} | ||||
| 
 | ||||
| 	downloadHugo() | ||||
| 	checkSHA256() | ||||
| 
 | ||||
| 	fmt.Print("Unzipping... ") | ||||
| 
 | ||||
| 	// Unzip or Ungzip the file
 | ||||
| 	switch runtime.GOOS { | ||||
| 	case "darwin", "windows": | ||||
| 		zp := extractor.NewZip() | ||||
| 		err = zp.Extract(tempfile, temp) | ||||
| 	default: | ||||
| 		gz := extractor.NewTgz() | ||||
| 		err = gz.Extract(tempfile, temp) | ||||
| 	} | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		fmt.Println(err) | ||||
| 		os.Exit(-1) | ||||
| 	} | ||||
| 
 | ||||
| 	fmt.Println("done.") | ||||
| 
 | ||||
| 	var exetorename string | ||||
| 
 | ||||
| 	err = filepath.Walk(temp, func(path string, f os.FileInfo, err error) error { | ||||
| 		if f.Name() == exename { | ||||
| 			exetorename = path | ||||
| 		} | ||||
| 
 | ||||
| 		return nil | ||||
| 	}) | ||||
| 
 | ||||
| 	// Copy the file
 | ||||
| 	fmt.Print("Moving Hugo executable... ") | ||||
| 	err = files.CopyFile(exetorename, hugo) | ||||
| 	if err != nil { | ||||
| 		fmt.Println(err) | ||||
| 		os.Exit(-1) | ||||
| 	} | ||||
| 
 | ||||
| 	err = os.Chmod(hugo, 0755) | ||||
| 	if err != nil { | ||||
| 		fmt.Println(err) | ||||
| 		os.Exit(-1) | ||||
| 	} | ||||
| 
 | ||||
| 	fmt.Println("done.") | ||||
| 	fmt.Println("Hugo installed at " + hugo) | ||||
| 	defer os.RemoveAll(temp) | ||||
| 	return hugo | ||||
| } | ||||
| 
 | ||||
| func initializeVariables() { | ||||
| 	exename = "hugo_" + version + "_" + runtime.GOOS + "_" + runtime.GOARCH | ||||
| 	zipname = exename | ||||
| 
 | ||||
| 	homedir, err := homedir.Dir() | ||||
| 	if err != nil { | ||||
| 		fmt.Println(err) | ||||
| 		os.Exit(-1) | ||||
| 	} | ||||
| 
 | ||||
| 	caddy = filepath.Join(homedir, ".caddy") | ||||
| 	bin = filepath.Join(caddy, "bin") | ||||
| 	hugo = filepath.Join(bin, "hugo") | ||||
| 
 | ||||
| 	switch runtime.GOOS { | ||||
| 	case "darwin": | ||||
| 		zipname += ".zip" | ||||
| 	case "windows": | ||||
| 		// At least for v0.15 version
 | ||||
| 		if runtime.GOARCH == "386" { | ||||
| 			zipname += "32-bit-only" | ||||
| 		} | ||||
| 
 | ||||
| 		zipname += ".zip" | ||||
| 		exename += ".exe" | ||||
| 		hugo += ".exe" | ||||
| 	default: | ||||
| 		zipname += ".tar.gz" | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func downloadHugo() { | ||||
| 	tempfile = filepath.Join(temp, zipname) | ||||
| 
 | ||||
| 	fmt.Print("Downloading Hugo from GitHub releases... ") | ||||
| 
 | ||||
| 	// Create the file
 | ||||
| 	out, err := os.Create(tempfile) | ||||
| 	out.Chmod(0774) | ||||
| 	if err != nil { | ||||
| 		defer os.RemoveAll(temp) | ||||
| 		fmt.Println(err) | ||||
| 		os.Exit(-1) | ||||
| 	} | ||||
| 	defer out.Close() | ||||
| 
 | ||||
| 	// Get the data
 | ||||
| 	resp, err := http.Get(baseurl + zipname) | ||||
| 	if err != nil { | ||||
| 		fmt.Println("An error ocurred while downloading. If this error persists, try downloading Hugo from \"https://github.com/spf13/hugo/releases/\" and put the executable in " + bin + " and rename it to 'hugo' or 'hugo.exe' if you're on Windows.") | ||||
| 		fmt.Println(err) | ||||
| 		os.Exit(-1) | ||||
| 	} | ||||
| 	defer resp.Body.Close() | ||||
| 
 | ||||
| 	// Writer the body to file
 | ||||
| 	_, err = io.Copy(out, resp.Body) | ||||
| 	if err != nil { | ||||
| 		fmt.Println(err) | ||||
| 		os.Exit(-1) | ||||
| 	} | ||||
| 
 | ||||
| 	fmt.Println("downloaded.") | ||||
| } | ||||
| 
 | ||||
| func checkSHA256() { | ||||
| 	fmt.Print("Checking SHA256...") | ||||
| 
 | ||||
| 	hasher := sha256.New() | ||||
| 	f, err := os.Open(tempfile) | ||||
| 	if err != nil { | ||||
| 		log.Fatal(err) | ||||
| 	} | ||||
| 	defer f.Close() | ||||
| 	if _, err := io.Copy(hasher, f); err != nil { | ||||
| 		log.Fatal(err) | ||||
| 	} | ||||
| 
 | ||||
| 	if hex.EncodeToString(hasher.Sum(nil)) != sha256Hash[zipname] { | ||||
| 		fmt.Println("can't verify SHA256.") | ||||
| 		os.Exit(-1) | ||||
| 	} | ||||
| 
 | ||||
| 	fmt.Println("checked!") | ||||
| } | ||||
							
								
								
									
										13
									
								
								hugo.go
								
								
								
								
							
							
						
						
									
										13
									
								
								hugo.go
								
								
								
								
							|  | @ -1,6 +1,6 @@ | |||
| //go:generate go get github.com/jteeuwen/go-bindata
 | ||||
| //go:generate go install github.com/jteeuwen/go-bindata/go-bindata
 | ||||
| //go:generate go-bindata -pkg assets -o assets/assets.go templates/ assets/css/ assets/js/ assets/fonts/
 | ||||
| //go:generate go-bindata -prefix assets/ -pkg assets -o routes/assets/assets.go assets/templates/ assets/public/...
 | ||||
| 
 | ||||
| // Package hugo makes the bridge between the static website generator Hugo
 | ||||
| // and the webserver Caddy, also providing an administrative user interface.
 | ||||
|  | @ -14,13 +14,14 @@ import ( | |||
| 	"path/filepath" | ||||
| 	"strings" | ||||
| 
 | ||||
| 	"github.com/hacdias/caddy-hugo/assets" | ||||
| 	"github.com/hacdias/caddy-hugo/config" | ||||
| 	"github.com/hacdias/caddy-hugo/routes/assets" | ||||
| 	"github.com/hacdias/caddy-hugo/routes/browse" | ||||
| 	"github.com/hacdias/caddy-hugo/routes/editor" | ||||
| 	"github.com/hacdias/caddy-hugo/routes/git" | ||||
| 	"github.com/hacdias/caddy-hugo/tools/commands" | ||||
| 	"github.com/hacdias/caddy-hugo/tools/hugo" | ||||
| 	"github.com/hacdias/caddy-hugo/tools/server" | ||||
| 	"github.com/mholt/caddy/caddy/setup" | ||||
| 	"github.com/mholt/caddy/middleware" | ||||
| ) | ||||
|  | @ -79,10 +80,10 @@ func (h CaddyHugo) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error | |||
| 
 | ||||
| 		// If the length of the components string is less than one, the variable
 | ||||
| 		// page will always be "admin"
 | ||||
| 		if len(utils.ParseComponents(r)) > 1 { | ||||
| 			page = utils.ParseComponents(r)[1] | ||||
| 		if len(server.ParseURLComponents(r)) > 1 { | ||||
| 			page = server.ParseURLComponents(r)[1] | ||||
| 		} else { | ||||
| 			page = utils.ParseComponents(r)[0] | ||||
| 			page = server.ParseURLComponents(r)[0] | ||||
| 		} | ||||
| 
 | ||||
| 		// If the page isn't "assets" neither "edit", it should always put a
 | ||||
|  | @ -145,7 +146,7 @@ func (h CaddyHugo) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error | |||
| 		// Whenever the header "X-Regenerate" is true, the website should be
 | ||||
| 		// regenerated. Used in edit and settings, for example.
 | ||||
| 		if r.Header.Get("X-Regenerate") == "true" { | ||||
| 			go utils.Run(h.Config, false) | ||||
| 			go hugo.Run(h.Config, false) | ||||
| 		} | ||||
| 
 | ||||
| 		if err != nil { | ||||
|  |  | |||
|  | @ -6,7 +6,7 @@ import ( | |||
| 	"strings" | ||||
| 
 | ||||
| 	"github.com/hacdias/caddy-hugo/config" | ||||
| 	"github.com/hacdias/caddy-hugo/tools/utils" | ||||
| 	"github.com/hacdias/caddy-hugo/tools/server" | ||||
| ) | ||||
| 
 | ||||
| // DELETE handles the delete requests on browse pages
 | ||||
|  | @ -32,17 +32,17 @@ func DELETE(w http.ResponseWriter, r *http.Request, c *config.Config) (int, erro | |||
| 
 | ||||
| 		// Check for errors
 | ||||
| 		if err != nil { | ||||
| 			return utils.RespondJSON(w, map[string]string{ | ||||
| 			return server.RespondJSON(w, map[string]string{ | ||||
| 				"message": "Something went wrong.", | ||||
| 			}, 500, nil) | ||||
| 		} | ||||
| 	} else { | ||||
| 		return utils.RespondJSON(w, map[string]string{ | ||||
| 		return server.RespondJSON(w, map[string]string{ | ||||
| 			"message": "File not found.", | ||||
| 		}, 404, nil) | ||||
| 	} | ||||
| 
 | ||||
| 	return utils.RespondJSON(w, map[string]string{ | ||||
| 	return server.RespondJSON(w, map[string]string{ | ||||
| 		"message": message, | ||||
| 	}, 200, nil) | ||||
| } | ||||
|  |  | |||
|  | @ -6,6 +6,7 @@ import ( | |||
| 
 | ||||
| 	"github.com/hacdias/caddy-hugo/config" | ||||
| 	"github.com/hacdias/caddy-hugo/tools/templates" | ||||
| 	"github.com/hacdias/caddy-hugo/tools/variables" | ||||
| 	"github.com/mholt/caddy/middleware" | ||||
| 	"github.com/mholt/caddy/middleware/browse" | ||||
| ) | ||||
|  | @ -15,7 +16,7 @@ import ( | |||
| func GET(w http.ResponseWriter, r *http.Request, c *config.Config) (int, error) { | ||||
| 	functions := template.FuncMap{ | ||||
| 		"CanBeEdited": templates.CanBeEdited, | ||||
| 		"Defined":     templates.Defined, | ||||
| 		"Defined":     variables.Defined, | ||||
| 	} | ||||
| 
 | ||||
| 	tpl, err := templates.Get(r, functions, "browse") | ||||
|  |  | |||
|  | @ -12,7 +12,7 @@ import ( | |||
| 
 | ||||
| 	"github.com/hacdias/caddy-hugo/config" | ||||
| 	"github.com/hacdias/caddy-hugo/tools/commands" | ||||
| 	"github.com/hacdias/caddy-hugo/tools/utils" | ||||
| 	"github.com/hacdias/caddy-hugo/tools/server" | ||||
| ) | ||||
| 
 | ||||
| // POST handles the POST method on browse page. It's used to create new files,
 | ||||
|  | @ -37,13 +37,13 @@ func POST(w http.ResponseWriter, r *http.Request, c *config.Config) (int, error) | |||
| 	// Check if filename and archetype are specified in
 | ||||
| 	// the request
 | ||||
| 	if _, ok := info["filename"]; !ok { | ||||
| 		return utils.RespondJSON(w, map[string]string{ | ||||
| 		return server.RespondJSON(w, map[string]string{ | ||||
| 			"message": "Filename not specified.", | ||||
| 		}, 500, nil) | ||||
| 	} | ||||
| 
 | ||||
| 	if _, ok := info["archetype"]; !ok { | ||||
| 		return utils.RespondJSON(w, map[string]string{ | ||||
| 		return server.RespondJSON(w, map[string]string{ | ||||
| 			"message": "Archtype not specified.", | ||||
| 		}, 500, nil) | ||||
| 	} | ||||
|  | @ -67,7 +67,7 @@ func POST(w http.ResponseWriter, r *http.Request, c *config.Config) (int, error) | |||
| 		} | ||||
| 
 | ||||
| 		if err := commands.Run(c.Hugo, args, c.Path); err != nil { | ||||
| 			return utils.RespondJSON(w, map[string]string{ | ||||
| 			return server.RespondJSON(w, map[string]string{ | ||||
| 				"message": "Something went wrong.", | ||||
| 			}, 500, err) | ||||
| 		} | ||||
|  | @ -84,14 +84,14 @@ func POST(w http.ResponseWriter, r *http.Request, c *config.Config) (int, error) | |||
| 		} | ||||
| 
 | ||||
| 		if err != nil { | ||||
| 			return utils.RespondJSON(w, map[string]string{ | ||||
| 			return server.RespondJSON(w, map[string]string{ | ||||
| 				"message": "Something went wrong.", | ||||
| 			}, 500, err) | ||||
| 		} | ||||
| 
 | ||||
| 	} | ||||
| 
 | ||||
| 	return utils.RespondJSON(w, map[string]string{ | ||||
| 	return server.RespondJSON(w, map[string]string{ | ||||
| 		"location": url, | ||||
| 		"message":  "File created.", | ||||
| 	}, 200, nil) | ||||
|  | @ -101,7 +101,7 @@ func upload(w http.ResponseWriter, r *http.Request, c *config.Config) (int, erro | |||
| 	// Parse the multipart form in the request
 | ||||
| 	err := r.ParseMultipartForm(100000) | ||||
| 	if err != nil { | ||||
| 		return utils.RespondJSON(w, map[string]string{ | ||||
| 		return server.RespondJSON(w, map[string]string{ | ||||
| 			"message": "Something went wrong.", | ||||
| 		}, 500, err) | ||||
| 	} | ||||
|  | @ -113,7 +113,7 @@ func upload(w http.ResponseWriter, r *http.Request, c *config.Config) (int, erro | |||
| 			// Open the first file
 | ||||
| 			var infile multipart.File | ||||
| 			if infile, err = hdr.Open(); nil != err { | ||||
| 				return utils.RespondJSON(w, map[string]string{ | ||||
| 				return server.RespondJSON(w, map[string]string{ | ||||
| 					"message": "Something went wrong.", | ||||
| 				}, 500, err) | ||||
| 			} | ||||
|  | @ -121,14 +121,14 @@ func upload(w http.ResponseWriter, r *http.Request, c *config.Config) (int, erro | |||
| 			// Create the file
 | ||||
| 			var outfile *os.File | ||||
| 			if outfile, err = os.Create(c.Path + r.URL.Path + hdr.Filename); nil != err { | ||||
| 				return utils.RespondJSON(w, map[string]string{ | ||||
| 				return server.RespondJSON(w, map[string]string{ | ||||
| 					"message": "Something went wrong.", | ||||
| 				}, 500, err) | ||||
| 			} | ||||
| 
 | ||||
| 			// Copy the file content
 | ||||
| 			if _, err = io.Copy(outfile, infile); nil != err { | ||||
| 				return utils.RespondJSON(w, map[string]string{ | ||||
| 				return server.RespondJSON(w, map[string]string{ | ||||
| 					"message": "Something went wrong.", | ||||
| 				}, 500, err) | ||||
| 			} | ||||
|  | @ -137,5 +137,5 @@ func upload(w http.ResponseWriter, r *http.Request, c *config.Config) (int, erro | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return utils.RespondJSON(w, nil, 200, nil) | ||||
| 	return server.RespondJSON(w, nil, 200, nil) | ||||
| } | ||||
|  |  | |||
|  | @ -8,7 +8,7 @@ import ( | |||
| 	"strings" | ||||
| 
 | ||||
| 	"github.com/hacdias/caddy-hugo/config" | ||||
| 	"github.com/hacdias/caddy-hugo/tools/utils" | ||||
| 	"github.com/hacdias/caddy-hugo/tools/server" | ||||
| ) | ||||
| 
 | ||||
| // PUT handles the HTTP PUT request for all /admin/browse related requests.
 | ||||
|  | @ -31,7 +31,7 @@ func PUT(w http.ResponseWriter, r *http.Request, c *config.Config) (int, error) | |||
| 	// Check if filename and archetype are specified in
 | ||||
| 	// the request
 | ||||
| 	if _, ok := info["filename"]; !ok { | ||||
| 		return utils.RespondJSON(w, map[string]string{ | ||||
| 		return server.RespondJSON(w, map[string]string{ | ||||
| 			"message": "Filename not specified.", | ||||
| 		}, 400, nil) | ||||
| 	} | ||||
|  | @ -44,12 +44,12 @@ func PUT(w http.ResponseWriter, r *http.Request, c *config.Config) (int, error) | |||
| 
 | ||||
| 	// Renames the file/folder
 | ||||
| 	if err := os.Rename(old, new); err != nil { | ||||
| 		return utils.RespondJSON(w, map[string]string{ | ||||
| 		return server.RespondJSON(w, map[string]string{ | ||||
| 			"message": "Something went wrong.", | ||||
| 		}, 500, err) | ||||
| 	} | ||||
| 
 | ||||
| 	return utils.RespondJSON(w, map[string]string{ | ||||
| 	return server.RespondJSON(w, map[string]string{ | ||||
| 		"message": "File renamed.", | ||||
| 	}, 200, nil) | ||||
| } | ||||
|  |  | |||
|  | @ -13,6 +13,7 @@ import ( | |||
| 	"github.com/hacdias/caddy-hugo/config" | ||||
| 	"github.com/hacdias/caddy-hugo/tools/frontmatter" | ||||
| 	"github.com/hacdias/caddy-hugo/tools/templates" | ||||
| 	"github.com/hacdias/caddy-hugo/tools/variables" | ||||
| 	"github.com/spf13/hugo/parser" | ||||
| ) | ||||
| 
 | ||||
|  | @ -110,8 +111,8 @@ func GET(w http.ResponseWriter, r *http.Request, c *config.Config, filename stri | |||
| 	// Create the functions map, then the template, check for erros and
 | ||||
| 	// execute the template if there aren't errors
 | ||||
| 	functions := template.FuncMap{ | ||||
| 		"SplitCapitalize": templates.SplitCapitalize, | ||||
| 		"Defined":         templates.Defined, | ||||
| 		"SplitCapitalize": variables.SplitCapitalize, | ||||
| 		"Defined":         variables.Defined, | ||||
| 	} | ||||
| 
 | ||||
| 	tpl, err := templates.Get(r, functions, "editor", "frontmatter") | ||||
|  |  | |||
|  | @ -11,7 +11,7 @@ import ( | |||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/hacdias/caddy-hugo/config" | ||||
| 	"github.com/hacdias/caddy-hugo/tools/commands" | ||||
| 	"github.com/hacdias/caddy-hugo/tools/hugo" | ||||
| 	"github.com/robfig/cron" | ||||
| 	"github.com/spf13/cast" | ||||
| 	"github.com/spf13/hugo/parser" | ||||
|  | @ -144,7 +144,7 @@ func parseCompleteFile(r *http.Request, c *config.Config, rawFile map[string]int | |||
| 				return | ||||
| 			} | ||||
| 
 | ||||
| 			go commands.Run(c, false) | ||||
| 			go hugo.Run(c, false) | ||||
| 		}) | ||||
| 		scheduler.Start() | ||||
| 	} | ||||
|  |  | |||
|  | @ -8,14 +8,14 @@ import ( | |||
| 	"strings" | ||||
| 
 | ||||
| 	"github.com/hacdias/caddy-hugo/config" | ||||
| 	"github.com/hacdias/caddy-hugo/tools/utils" | ||||
| 	"github.com/hacdias/caddy-hugo/tools/server" | ||||
| ) | ||||
| 
 | ||||
| // POST handles the POST method on GIT page which is only an API.
 | ||||
| func POST(w http.ResponseWriter, r *http.Request, c *config.Config) (int, error) { | ||||
| 	// Check if git is installed on the computer
 | ||||
| 	if _, err := exec.LookPath("git"); err != nil { | ||||
| 		return utils.RespondJSON(w, map[string]string{ | ||||
| 		return server.RespondJSON(w, map[string]string{ | ||||
| 			"message": "Git is not installed on your computer.", | ||||
| 		}, 400, nil) | ||||
| 	} | ||||
|  | @ -30,7 +30,7 @@ func POST(w http.ResponseWriter, r *http.Request, c *config.Config) (int, error) | |||
| 
 | ||||
| 	// Check if command was sent
 | ||||
| 	if _, ok := info["command"]; !ok { | ||||
| 		return utils.RespondJSON(w, map[string]string{ | ||||
| 		return server.RespondJSON(w, map[string]string{ | ||||
| 			"message": "Command not specified.", | ||||
| 		}, 400, nil) | ||||
| 	} | ||||
|  | @ -43,7 +43,7 @@ func POST(w http.ResponseWriter, r *http.Request, c *config.Config) (int, error) | |||
| 	} | ||||
| 
 | ||||
| 	if len(args) == 0 { | ||||
| 		return utils.RespondJSON(w, map[string]string{ | ||||
| 		return server.RespondJSON(w, map[string]string{ | ||||
| 			"message": "Command not specified.", | ||||
| 		}, 400, nil) | ||||
| 	} | ||||
|  | @ -53,12 +53,12 @@ func POST(w http.ResponseWriter, r *http.Request, c *config.Config) (int, error) | |||
| 	output, err := cmd.CombinedOutput() | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		return utils.RespondJSON(w, map[string]string{ | ||||
| 		return server.RespondJSON(w, map[string]string{ | ||||
| 			"message": err.Error(), | ||||
| 		}, 500, err) | ||||
| 	} | ||||
| 
 | ||||
| 	return utils.RespondJSON(w, map[string]string{ | ||||
| 	return server.RespondJSON(w, map[string]string{ | ||||
| 		"message": string(output), | ||||
| 	}, 200, nil) | ||||
| } | ||||
|  |  | |||
|  | @ -5,7 +5,7 @@ import ( | |||
| 	"os/exec" | ||||
| ) | ||||
| 
 | ||||
| // RunCommand executes an external command
 | ||||
| // Run executes an external command
 | ||||
| func Run(command string, args []string, path string) error { | ||||
| 	cmd := exec.Command(command, args...) | ||||
| 	cmd.Dir = path | ||||
|  |  | |||
|  | @ -6,7 +6,7 @@ import ( | |||
| 	"sort" | ||||
| 	"strings" | ||||
| 
 | ||||
| 	"github.com/hacdias/caddy-hugo/tools/types" | ||||
| 	"github.com/hacdias/caddy-hugo/tools/variables" | ||||
| 	"github.com/spf13/cast" | ||||
| 	"github.com/spf13/hugo/parser" | ||||
| ) | ||||
|  | @ -60,9 +60,9 @@ func rawToPretty(config interface{}, parent *frontmatter) interface{} { | |||
| 	} | ||||
| 
 | ||||
| 	for name, element := range cnf { | ||||
| 		if types.IsMap(element) { | ||||
| 		if variables.IsMap(element) { | ||||
| 			objects = append(objects, handleObjects(element, parent, name)) | ||||
| 		} else if types.IsSlice(element) { | ||||
| 		} else if variables.IsSlice(element) { | ||||
| 			arrays = append(arrays, handleArrays(element, parent, name)) | ||||
| 		} else { | ||||
| 			if name == "title" && parent.Name == mainName { | ||||
|  |  | |||
|  | @ -1,48 +1,11 @@ | |||
| package hugo | ||||
| 
 | ||||
| import ( | ||||
| 	"crypto/sha256" | ||||
| 	"encoding/hex" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"io/ioutil" | ||||
| 	"log" | ||||
| 	"net/http" | ||||
| 	"os" | ||||
| 	"os/exec" | ||||
| 	"path/filepath" | ||||
| 	"runtime" | ||||
| 
 | ||||
| 	"github.com/hacdias/caddy-hugo/config" | ||||
| 	"github.com/mitchellh/go-homedir" | ||||
| 	"github.com/pivotal-golang/archiver/extractor" | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	version = "0.15" | ||||
| 	baseurl = "https://github.com/spf13/hugo/releases/download/v" + version + "/" | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
| 	caddy, bin, temp, hugo, tempfile, zipname, exename string | ||||
| 	sha256Hash                                         = map[string]string{ | ||||
| 		"hugo_0.15_darwin_386.zip":              "f9b7353f9b64e7aece5f7981e5aa97dc4b31974ce76251edc070e77691bc03e2", | ||||
| 		"hugo_0.15_darwin_amd64.zip":            "aeecd6a12d86ab920f5b04e9486474bbe478dc246cdc2242799849b84c61c6f1", | ||||
| 		"hugo_0.15_dragonfly_amd64.zip":         "e380343789f2b2e0c366c8e1eeb251ccd90eea53dac191ff85d8177b130e53bc", | ||||
| 		"hugo_0.15_freebsd_386.zip":             "98f9210bfa3dcb48bd154879ea1cfe1b0ed8a3d891fdeacbdb4c3fc69b72aac4", | ||||
| 		"hugo_0.15_freebsd_amd64.zip":           "aa6a3028899e76e6920b9b5a64c29e14017ae34120efa67276e614e3a69cb100", | ||||
| 		"hugo_0.15_freebsd_arm.zip":             "de52e1b07caf778bdc3bdb07f39119cd5a1739c8822ebe311cd4f667c43588ac", | ||||
| 		"hugo_0.15_linux_386.tar.gz":            "af28c4cbb16db765535113f361a38b2249c634ce2d3798dcf5b795de6e4b7ecf", | ||||
| 		"hugo_0.15_linux_amd64.tar.gz":          "32a6335bd76f72867efdec9306a8a7eb7b9498a2e0478105efa96c1febadb09b", | ||||
| 		"hugo_0.15_linux_arm.tar.gz":            "886dd1a843c057a46c541011183dd558469250580e81450eedbd1a4d041e9234", | ||||
| 		"hugo_0.15_netbsd_386.zip":              "6245f5db16b33a09466f149d5b7b68a7899d6d624903de9e7e70c4b6ea869a72", | ||||
| 		"hugo_0.15_netbsd_amd64.zip":            "103ea8d81d2a3d707c05e3dd68c98fcf8146ddd36b49bf0e65d9874cee230c88", | ||||
| 		"hugo_0.15_netbsd_arm.zip":              "9c9b5cf4ea3b6169be1b5fc924251a247d9c140dd8a45aa5175031878585ff0a", | ||||
| 		"hugo_0.15_openbsd_386.zip":             "81dfdb3048a27a61b249650241fe4e8da1eda31a3a7311c615eb419f1cdd06b1", | ||||
| 		"hugo_0.15_openbsd_amd64.zip":           "e7447cde0dd7628b05b25b86938018774d8db8156ab1330b364e0e2c6501ad87", | ||||
| 		"hugo_0.15_windows_386_32-bit-only.zip": "0a72f9a1a929f36c0e52fb1c6272b4d37a2bd1a6bd19ce57a6e7b6803b434756", | ||||
| 		"hugo_0.15_windows_amd64.zip":           "9f03602e48ae2199e06431d7436fb3b9464538c0d44aac9a76eb98e1d4d5d727", | ||||
| 	} | ||||
| 	"github.com/hacdias/caddy-hugo/tools/commands" | ||||
| ) | ||||
| 
 | ||||
| // Run is used to run the static website generator
 | ||||
|  | @ -60,7 +23,7 @@ func Run(c *config.Config, force bool) { | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if err := RunCommand(c.Hugo, c.Args, c.Path); err != nil { | ||||
| 	if err := commands.Run(c.Hugo, c.Args, c.Path); err != nil { | ||||
| 		log.Panic(err) | ||||
| 	} | ||||
| } | ||||
|  | @ -73,185 +36,3 @@ func stringInSlice(a string, list []string) (bool, int) { | |||
| 	} | ||||
| 	return false, 0 | ||||
| } | ||||
| 
 | ||||
| // GetPath retrives the Hugo path for the user or install it if it's not found
 | ||||
| func GetPath() string { | ||||
| 	initializeVariables() | ||||
| 
 | ||||
| 	var err error | ||||
| 
 | ||||
| 	// Check if Hugo is already on $PATH
 | ||||
| 	if hugo, err := exec.LookPath("hugo"); err == nil { | ||||
| 		return hugo | ||||
| 	} | ||||
| 
 | ||||
| 	// Check if Hugo is on $HOME/.caddy/bin
 | ||||
| 	if _, err = os.Stat(hugo); err == nil { | ||||
| 		return hugo | ||||
| 	} | ||||
| 
 | ||||
| 	fmt.Println("Unable to find Hugo on your computer.") | ||||
| 
 | ||||
| 	// Create the neccessary folders
 | ||||
| 	os.MkdirAll(caddy, 0774) | ||||
| 	os.Mkdir(bin, 0774) | ||||
| 
 | ||||
| 	if temp, err = ioutil.TempDir("", "caddy-hugo"); err != nil { | ||||
| 		fmt.Println(err) | ||||
| 		os.Exit(-1) | ||||
| 	} | ||||
| 
 | ||||
| 	downloadHugo() | ||||
| 	checkSHA256() | ||||
| 
 | ||||
| 	fmt.Print("Unzipping... ") | ||||
| 
 | ||||
| 	// Unzip or Ungzip the file
 | ||||
| 	switch runtime.GOOS { | ||||
| 	case "darwin", "windows": | ||||
| 		zp := extractor.NewZip() | ||||
| 		err = zp.Extract(tempfile, temp) | ||||
| 	default: | ||||
| 		gz := extractor.NewTgz() | ||||
| 		err = gz.Extract(tempfile, temp) | ||||
| 	} | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		fmt.Println(err) | ||||
| 		os.Exit(-1) | ||||
| 	} | ||||
| 
 | ||||
| 	fmt.Println("done.") | ||||
| 
 | ||||
| 	var exetorename string | ||||
| 
 | ||||
| 	err = filepath.Walk(temp, func(path string, f os.FileInfo, err error) error { | ||||
| 		if f.Name() == exename { | ||||
| 			exetorename = path | ||||
| 		} | ||||
| 
 | ||||
| 		return nil | ||||
| 	}) | ||||
| 
 | ||||
| 	// Copy the file
 | ||||
| 	fmt.Print("Moving Hugo executable... ") | ||||
| 	r, err := os.Open(exetorename) | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	defer r.Close() | ||||
| 
 | ||||
| 	w, err := os.Create(hugo) | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	defer w.Close() | ||||
| 
 | ||||
| 	_, err = io.Copy(w, r) | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		fmt.Println(err) | ||||
| 		os.Exit(-1) | ||||
| 	} | ||||
| 
 | ||||
| 	err = os.Chmod(hugo, 0755) | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		fmt.Println(err) | ||||
| 		os.Exit(-1) | ||||
| 	} | ||||
| 
 | ||||
| 	fmt.Println("done.") | ||||
| 	fmt.Println("Hugo installed at " + hugo) | ||||
| 	defer os.RemoveAll(temp) | ||||
| 	return hugo | ||||
| } | ||||
| 
 | ||||
| func initializeVariables() { | ||||
| 	exename = "hugo_" + version + "_" + runtime.GOOS + "_" + runtime.GOARCH | ||||
| 	zipname = exename | ||||
| 
 | ||||
| 	homedir, err := homedir.Dir() | ||||
| 	if err != nil { | ||||
| 		fmt.Println(err) | ||||
| 		os.Exit(-1) | ||||
| 	} | ||||
| 
 | ||||
| 	caddy = filepath.Join(homedir, ".caddy") | ||||
| 	bin = filepath.Join(caddy, "bin") | ||||
| 	hugo = filepath.Join(bin, "hugo") | ||||
| 
 | ||||
| 	switch runtime.GOOS { | ||||
| 	case "darwin": | ||||
| 		zipname += ".zip" | ||||
| 	case "windows": | ||||
| 		// At least for v0.15 version
 | ||||
| 		if runtime.GOARCH == "386" { | ||||
| 			zipname += "32-bit-only" | ||||
| 		} | ||||
| 
 | ||||
| 		zipname += ".zip" | ||||
| 		exename += ".exe" | ||||
| 		hugo += ".exe" | ||||
| 	default: | ||||
| 		zipname += ".tar.gz" | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func downloadHugo() { | ||||
| 	tempfile = filepath.Join(temp, zipname) | ||||
| 
 | ||||
| 	fmt.Print("Downloading Hugo from GitHub releases... ") | ||||
| 
 | ||||
| 	// Create the file
 | ||||
| 	out, err := os.Create(tempfile) | ||||
| 	out.Chmod(0774) | ||||
| 	if err != nil { | ||||
| 		defer os.RemoveAll(temp) | ||||
| 		fmt.Println(err) | ||||
| 		os.Exit(-1) | ||||
| 	} | ||||
| 	defer out.Close() | ||||
| 
 | ||||
| 	// Get the data
 | ||||
| 	resp, err := http.Get(baseurl + zipname) | ||||
| 	if err != nil { | ||||
| 		fmt.Println("An error ocurred while downloading. If this error persists, try downloading Hugo from \"https://github.com/spf13/hugo/releases/\" and put the executable in " + bin + " and rename it to 'hugo' or 'hugo.exe' if you're on Windows.") | ||||
| 		fmt.Println(err) | ||||
| 		os.Exit(-1) | ||||
| 	} | ||||
| 	defer resp.Body.Close() | ||||
| 
 | ||||
| 	// Writer the body to file
 | ||||
| 	_, err = io.Copy(out, resp.Body) | ||||
| 	if err != nil { | ||||
| 		fmt.Println(err) | ||||
| 		os.Exit(-1) | ||||
| 	} | ||||
| 
 | ||||
| 	fmt.Println("downloaded.") | ||||
| } | ||||
| 
 | ||||
| func checkSHA256() { | ||||
| 	fmt.Print("Checking SHA256...") | ||||
| 
 | ||||
| 	hasher := sha256.New() | ||||
| 	f, err := os.Open(tempfile) | ||||
| 	if err != nil { | ||||
| 		log.Fatal(err) | ||||
| 	} | ||||
| 	defer f.Close() | ||||
| 	if _, err := io.Copy(hasher, f); err != nil { | ||||
| 		log.Fatal(err) | ||||
| 	} | ||||
| 
 | ||||
| 	if hex.EncodeToString(hasher.Sum(nil)) != sha256Hash[zipname] { | ||||
| 		fmt.Println("can't verify SHA256.") | ||||
| 		os.Exit(-1) | ||||
| 	} | ||||
| 
 | ||||
| 	fmt.Println("checked!") | ||||
| } | ||||
|  |  | |||
|  | @ -0,0 +1,25 @@ | |||
| package server | ||||
| 
 | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"errors" | ||||
| 	"net/http" | ||||
| ) | ||||
| 
 | ||||
| // RespondJSON
 | ||||
| func RespondJSON(w http.ResponseWriter, message map[string]string, code int, err error) (int, error) { | ||||
| 	msg, msgErr := json.Marshal(message) | ||||
| 
 | ||||
| 	if msgErr != nil { | ||||
| 		return 500, msgErr | ||||
| 	} | ||||
| 
 | ||||
| 	if code == 500 && err != nil { | ||||
| 		err = errors.New(message["message"]) | ||||
| 	} | ||||
| 
 | ||||
| 	w.Header().Set("Content-Type", "application/json") | ||||
| 	w.WriteHeader(code) | ||||
| 	w.Write(msg) | ||||
| 	return 0, err | ||||
| } | ||||
|  | @ -1,14 +1,12 @@ | |||
| package utils | ||||
| package server | ||||
| 
 | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"errors" | ||||
| 	"net/http" | ||||
| 	"strings" | ||||
| ) | ||||
| 
 | ||||
| // ParseComponents parses the components of an URL creating an array
 | ||||
| func ParseComponents(r *http.Request) []string { | ||||
| // ParseURLComponents parses the components of an URL creating an array
 | ||||
| func ParseURLComponents(r *http.Request) []string { | ||||
| 	//The URL that the user queried.
 | ||||
| 	path := r.URL.Path | ||||
| 	path = strings.TrimSpace(path) | ||||
|  | @ -26,20 +24,3 @@ func ParseComponents(r *http.Request) []string { | |||
| 	components := strings.Split(path, "/") | ||||
| 	return components | ||||
| } | ||||
| 
 | ||||
| func RespondJSON(w http.ResponseWriter, message map[string]string, code int, err error) (int, error) { | ||||
| 	msg, msgErr := json.Marshal(message) | ||||
| 
 | ||||
| 	if msgErr != nil { | ||||
| 		return 500, msgErr | ||||
| 	} | ||||
| 
 | ||||
| 	if code == 500 && err != nil { | ||||
| 		err = errors.New(message["message"]) | ||||
| 	} | ||||
| 
 | ||||
| 	w.Header().Set("Content-Type", "application/json") | ||||
| 	w.WriteHeader(code) | ||||
| 	w.Write(msg) | ||||
| 	return 0, err | ||||
| } | ||||
|  | @ -1,15 +1,12 @@ | |||
| package templates | ||||
| 
 | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"html/template" | ||||
| 	"log" | ||||
| 	"net/http" | ||||
| 	"reflect" | ||||
| 	"strings" | ||||
| 	"unicode" | ||||
| 	"text/template" | ||||
| 
 | ||||
| 	"github.com/hacdias/caddy-hugo/assets" | ||||
| 	"github.com/hacdias/caddy-hugo/routes/assets" | ||||
| ) | ||||
| 
 | ||||
| // CanBeEdited checks if the extension of a file is supported by the editor
 | ||||
|  | @ -34,36 +31,6 @@ func CanBeEdited(filename string) bool { | |||
| 	return false | ||||
| } | ||||
| 
 | ||||
| // 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 | ||||
| } | ||||
| 
 | ||||
| // Get is used to get a ready to use template based on the url and on
 | ||||
| // other sent templates
 | ||||
| func Get(r *http.Request, functions template.FuncMap, templates ...string) (*template.Template, error) { | ||||
|  | @ -104,39 +71,3 @@ func Get(r *http.Request, functions template.FuncMap, templates ...string) (*tem | |||
| 
 | ||||
| 	return tpl, nil | ||||
| } | ||||
| 
 | ||||
| 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 | ||||
| } | ||||
|  |  | |||
|  | @ -75,31 +75,3 @@ func TestDefined(t *testing.T) { | |||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| type testSplitCapitalize struct { | ||||
| 	name   string | ||||
| 	result string | ||||
| } | ||||
| 
 | ||||
| var testSplitCapitalizeCases = []testSplitCapitalize{ | ||||
| 	{"loremIpsum", "Lorem ipsum"}, | ||||
| 	{"LoremIpsum", "Lorem ipsum"}, | ||||
| 	{"loremipsum", "Loremipsum"}, | ||||
| 	{"YouTube", "YouTube"}, | ||||
| 	{"GitHub", "GitHub"}, | ||||
| 	{"GooglePlus", "Google Plus"}, | ||||
| 	{"Facebook", "Facebook"}, | ||||
| } | ||||
| 
 | ||||
| func TestSplitCapitalize(t *testing.T) { | ||||
| 	for _, pair := range testSplitCapitalizeCases { | ||||
| 		v := SplitCapitalize(pair.name) | ||||
| 		if v != pair.result { | ||||
| 			t.Error( | ||||
| 				"For", pair.name, | ||||
| 				"expected", pair.result, | ||||
| 				"got", v, | ||||
| 			) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -0,0 +1,42 @@ | |||
| package variables | ||||
| 
 | ||||
| import ( | ||||
| 	"strings" | ||||
| 	"unicode" | ||||
| ) | ||||
| 
 | ||||
| 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 | ||||
| } | ||||
|  | @ -0,0 +1,31 @@ | |||
| package variables | ||||
| 
 | ||||
| import "testing" | ||||
| 
 | ||||
| type testSplitCapitalize struct { | ||||
| 	name   string | ||||
| 	result string | ||||
| } | ||||
| 
 | ||||
| var testSplitCapitalizeCases = []testSplitCapitalize{ | ||||
| 	{"loremIpsum", "Lorem ipsum"}, | ||||
| 	{"LoremIpsum", "Lorem ipsum"}, | ||||
| 	{"loremipsum", "Loremipsum"}, | ||||
| 	{"YouTube", "YouTube"}, | ||||
| 	{"GitHub", "GitHub"}, | ||||
| 	{"GooglePlus", "Google Plus"}, | ||||
| 	{"Facebook", "Facebook"}, | ||||
| } | ||||
| 
 | ||||
| func TestSplitCapitalize(t *testing.T) { | ||||
| 	for _, pair := range testSplitCapitalizeCases { | ||||
| 		v := SplitCapitalize(pair.name) | ||||
| 		if v != pair.result { | ||||
| 			t.Error( | ||||
| 				"For", pair.name, | ||||
| 				"expected", pair.result, | ||||
| 				"got", v, | ||||
| 			) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | @ -1,4 +1,4 @@ | |||
| package types | ||||
| package variables | ||||
| 
 | ||||
| import "reflect" | ||||
| 
 | ||||
|  | @ -0,0 +1,37 @@ | |||
| package variables | ||||
| 
 | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"log" | ||||
| 	"reflect" | ||||
| ) | ||||
| 
 | ||||
| // 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 | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	 Henrique Dias
						Henrique Dias