2015-09-14 09:46:31 +00:00
|
|
|
package utils
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
2015-09-20 19:42:22 +00:00
|
|
|
"io"
|
2015-09-18 12:52:10 +00:00
|
|
|
"log"
|
2015-09-15 20:40:46 +00:00
|
|
|
"net/http"
|
2015-09-20 19:42:22 +00:00
|
|
|
"os"
|
2016-02-20 11:31:59 +00:00
|
|
|
"os/exec"
|
2015-09-14 09:46:31 +00:00
|
|
|
"reflect"
|
|
|
|
"strings"
|
2015-09-18 12:52:10 +00:00
|
|
|
"text/template"
|
2015-09-14 09:46:31 +00:00
|
|
|
"unicode"
|
2015-09-18 12:52:10 +00:00
|
|
|
|
2015-10-18 14:10:32 +00:00
|
|
|
"github.com/hacdias/caddy-hugo/assets"
|
|
|
|
"github.com/hacdias/caddy-hugo/config"
|
2015-09-14 09:46:31 +00:00
|
|
|
)
|
|
|
|
|
2016-02-07 15:14:56 +00:00
|
|
|
// CanBeEdited checks if the extension of a file is supported by the editor
|
2015-09-20 21:20:37 +00:00
|
|
|
func CanBeEdited(filename string) bool {
|
2016-02-07 09:09:22 +00:00
|
|
|
extensions := [...]string{
|
|
|
|
"md", "markdown", "mdown", "mmark",
|
|
|
|
"asciidoc", "adoc", "ad",
|
|
|
|
"rst",
|
2015-09-20 21:20:37 +00:00
|
|
|
".json", ".toml", ".yaml",
|
|
|
|
".css", ".sass", ".scss",
|
|
|
|
".js",
|
|
|
|
".html",
|
2016-02-07 15:14:56 +00:00
|
|
|
".txt",
|
2015-09-20 21:20:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, extension := range extensions {
|
|
|
|
if strings.HasSuffix(filename, extension) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
2015-09-20 21:00:25 +00:00
|
|
|
}
|
|
|
|
|
2015-09-20 19:42:22 +00:00
|
|
|
// 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
|
|
|
|
}
|
|
|
|
|
2015-09-20 21:20:37 +00:00
|
|
|
// 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
|
2015-09-20 08:15:21 +00:00
|
|
|
}
|
|
|
|
|
2015-09-20 21:20:37 +00:00
|
|
|
_, 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")
|
2015-09-20 08:15:21 +00:00
|
|
|
}
|
2015-09-20 21:20:37 +00:00
|
|
|
dict[key] = values[i+1]
|
2015-09-20 08:15:21 +00:00
|
|
|
}
|
2016-02-07 15:07:45 +00:00
|
|
|
|
2015-09-20 21:20:37 +00:00
|
|
|
return dict, nil
|
2015-09-20 08:15:21 +00:00
|
|
|
}
|
|
|
|
|
2015-09-18 12:52:10 +00:00
|
|
|
// GetTemplate is used to get a ready to use template based on the url and on
|
|
|
|
// other sent templates
|
|
|
|
func GetTemplate(r *http.Request, functions template.FuncMap, templates ...string) (*template.Template, error) {
|
|
|
|
// If this is a pjax request, use the minimal template to send only
|
|
|
|
// the main content
|
|
|
|
if r.Header.Get("X-PJAX") == "true" {
|
|
|
|
templates = append(templates, "base_minimal")
|
|
|
|
} else {
|
|
|
|
templates = append(templates, "base_full")
|
|
|
|
}
|
|
|
|
|
|
|
|
var tpl *template.Template
|
|
|
|
|
|
|
|
// For each template, add it to the the tpl variable
|
|
|
|
for i, t := range templates {
|
|
|
|
// Get the template from the assets
|
|
|
|
page, err := assets.Asset("templates/" + t + ".tmpl")
|
|
|
|
|
|
|
|
// Check if there is some error. If so, the template doesn't exist
|
|
|
|
if err != nil {
|
|
|
|
log.Print(err)
|
|
|
|
return new(template.Template), err
|
|
|
|
}
|
|
|
|
|
|
|
|
// If it's the first iteration, creates a new template and add the
|
|
|
|
// functions map
|
|
|
|
if i == 0 {
|
|
|
|
tpl, err = template.New(t).Funcs(functions).Parse(string(page))
|
|
|
|
} else {
|
|
|
|
tpl, err = tpl.Parse(string(page))
|
|
|
|
}
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
log.Print(err)
|
|
|
|
return new(template.Template), err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return tpl, nil
|
|
|
|
}
|
|
|
|
|
2015-09-18 08:47:02 +00:00
|
|
|
// IsMap checks if some variable is a map
|
2015-09-14 09:46:31 +00:00
|
|
|
func IsMap(sth interface{}) bool {
|
|
|
|
return reflect.ValueOf(sth).Kind() == reflect.Map
|
|
|
|
}
|
|
|
|
|
2015-09-18 08:47:02 +00:00
|
|
|
// IsSlice checks if some variable is a slice
|
2015-09-15 10:59:48 +00:00
|
|
|
func IsSlice(sth interface{}) bool {
|
|
|
|
return reflect.ValueOf(sth).Kind() == reflect.Slice
|
|
|
|
}
|
|
|
|
|
2015-09-20 21:20:37 +00:00
|
|
|
// ParseComponents parses the components of an URL creating an array
|
|
|
|
func ParseComponents(r *http.Request) []string {
|
|
|
|
//The URL that the user queried.
|
|
|
|
path := r.URL.Path
|
|
|
|
path = strings.TrimSpace(path)
|
|
|
|
//Cut off the leading and trailing forward slashes, if they exist.
|
|
|
|
//This cuts off the leading forward slash.
|
|
|
|
if strings.HasPrefix(path, "/") {
|
|
|
|
path = path[1:]
|
|
|
|
}
|
|
|
|
//This cuts off the trailing forward slash.
|
|
|
|
if strings.HasSuffix(path, "/") {
|
|
|
|
cutOffLastCharLen := len(path) - 1
|
|
|
|
path = path[:cutOffLastCharLen]
|
|
|
|
}
|
|
|
|
//We need to isolate the individual components of the path.
|
|
|
|
components := strings.Split(path, "/")
|
|
|
|
return components
|
|
|
|
}
|
|
|
|
|
2015-09-27 12:20:05 +00:00
|
|
|
// Run is used to run the static website generator
|
2016-02-20 12:04:12 +00:00
|
|
|
func Run(c *config.Config, force bool) {
|
2016-02-14 10:14:28 +00:00
|
|
|
os.RemoveAll(c.Path + "public")
|
|
|
|
|
2016-02-20 12:04:12 +00:00
|
|
|
// 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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-20 22:33:10 +00:00
|
|
|
if err := RunCommand(c.Hugo, c.Args, c.Path); err != nil {
|
2016-02-20 08:46:48 +00:00
|
|
|
log.Panic(err)
|
2015-12-13 10:06:02 +00:00
|
|
|
}
|
2015-09-20 21:20:37 +00:00
|
|
|
}
|
|
|
|
|
2016-02-20 11:31:59 +00:00
|
|
|
// RunCommand executes an external command
|
|
|
|
func RunCommand(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()
|
|
|
|
}
|
|
|
|
|
2016-02-20 12:04:12 +00:00
|
|
|
func stringInSlice(a string, list []string) (bool, int) {
|
|
|
|
for i, b := range list {
|
|
|
|
if b == a {
|
|
|
|
return true, i
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false, 0
|
|
|
|
}
|
|
|
|
|
2015-12-13 10:30:56 +00:00
|
|
|
var splitCapitalizeExceptions = map[string]string{
|
|
|
|
"youtube": "YouTube",
|
|
|
|
"github": "GitHub",
|
|
|
|
"googleplus": "Google Plus",
|
|
|
|
"linkedin": "LinkedIn",
|
|
|
|
}
|
|
|
|
|
2015-09-18 08:47:02 +00:00
|
|
|
// SplitCapitalize splits a string by its uppercase letters and capitalize the
|
|
|
|
// first letter of the string
|
2015-09-14 09:46:31 +00:00
|
|
|
func SplitCapitalize(name string) string {
|
2015-12-13 10:30:56 +00:00
|
|
|
if val, ok := splitCapitalizeExceptions[strings.ToLower(name)]; ok {
|
|
|
|
return val
|
|
|
|
}
|
|
|
|
|
2015-09-14 09:46:31 +00:00
|
|
|
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])
|
2015-09-26 20:39:27 +00:00
|
|
|
name = strings.ToUpper(string(name[0])) + name[1:]
|
2015-09-14 09:46:31 +00:00
|
|
|
|
|
|
|
return name
|
|
|
|
}
|