shithub: hugo

Download patch

ref: 28ffb92b36f1e6e3313797e3676d3601a5791c07
parent: 08c30b6e447921104516ef28e6dbc08b674c5354
author: spf13 <[email protected]>
date: Thu May 1 21:06:01 EDT 2014

Adding the new command and the create package

--- a/commands/hugo.go
+++ b/commands/hugo.go
@@ -62,6 +62,7 @@
 	HugoCmd.AddCommand(check)
 	HugoCmd.AddCommand(benchmark)
 	HugoCmd.AddCommand(convertCmd)
+	HugoCmd.AddCommand(newCmd)
 }
 
 func init() {
@@ -92,10 +93,12 @@
 
 	viper.RegisterAlias("taxonomies", "indexes")
 
+	viper.SetDefault("MetadataFormat", "toml")
 	viper.SetDefault("DisableRSS", false)
 	viper.SetDefault("ContentDir", "content")
 	viper.SetDefault("LayoutDir", "layouts")
 	viper.SetDefault("StaticDir", "static")
+	viper.SetDefault("ArchetypeDir", "archetypes")
 	viper.SetDefault("PublishDir", "public")
 	viper.SetDefault("DefaultLayout", "post")
 	viper.SetDefault("BuildDrafts", false)
--- /dev/null
+++ b/commands/new.go
@@ -1,0 +1,86 @@
+// Licensed under the Simple Public License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://opensource.org/licenses/Simple-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package commands
+
+import (
+	"fmt"
+	"strings"
+
+	"github.com/spf13/cobra"
+	"github.com/spf13/hugo/create"
+	"github.com/spf13/hugo/helpers"
+	jww "github.com/spf13/jwalterweatherman"
+)
+
+var siteType string
+var configFormat string
+var contentType string
+var contentFormat string
+var contentFrontMatter string
+
+func init() {
+	//newSiteCmd.Flags().StringVarP(&siteType, "type", "t", "blog", "What type of site to new")
+	newSiteCmd.Flags().StringVarP(&configFormat, "format", "f", "yaml", "Config file format")
+	newCmd.Flags().StringVarP(&contentType, "kind", "k", "", "Content type to create")
+	newCmd.AddCommand(newSiteCmd)
+}
+
+var newCmd = &cobra.Command{
+	Use:   "new [path]",
+	Short: "Create new content for your site",
+	Long: `Create will create a new content file and automatically set the date and title.
+It will guess which kind of file to create based on the path provided.
+You can also specify the kind with -k KIND
+If archetypes are provided in your theme or site, they will be used.
+`,
+	Run: NewContent,
+}
+
+func NewContent(cmd *cobra.Command, args []string) {
+	InitializeConfig()
+
+	if len(args) < 1 {
+		jww.FATAL.Fatalln("path needs to be provided")
+	}
+
+	createpath := args[0]
+
+	var kind string
+
+	// assume the first directory is the section (kind)
+	if strings.Contains(createpath[1:], "/") {
+		kind = helpers.GuessSection(createpath)
+	}
+
+	if contentType != "" {
+		kind = contentType
+	}
+
+	err := create.NewContent(kind, createpath)
+	if err != nil {
+		jww.ERROR.Println(err)
+	}
+}
+
+var newSiteCmd = &cobra.Command{
+	Use:   "site [type]",
+	Short: "Create a new site of [type]",
+	Long:  `Create a new site as a (blog, project, etc)`,
+	Run:   NewSite,
+}
+
+func NewSite(cmd *cobra.Command, args []string) {
+	InitializeConfig()
+
+	fmt.Println("new site called")
+	fmt.Println(args)
+}
--- /dev/null
+++ b/create/content.go
@@ -1,0 +1,128 @@
+// Copyright © 2014 Steve Francia <[email protected]>.
+//
+// Licensed under the Simple Public License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://opensource.org/licenses/Simple-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package create
+
+import (
+	"bytes"
+	"io/ioutil"
+	"os"
+	"path"
+	"strings"
+	"time"
+
+	"github.com/spf13/cast"
+	"github.com/spf13/hugo/helpers"
+	"github.com/spf13/hugo/hugolib"
+	"github.com/spf13/hugo/parser"
+	jww "github.com/spf13/jwalterweatherman"
+	"github.com/spf13/viper"
+)
+
+func NewContent(kind, name string) (err error) {
+	jww.INFO.Println("attempting to create", name, "of", kind)
+
+	location := FindArchetype(kind)
+
+	var by []byte
+
+	if location != "" {
+		by, err = ioutil.ReadFile(location)
+		if err != nil {
+			jww.ERROR.Println(err)
+		}
+	}
+	if location == "" || err != nil {
+		by = []byte("+++\n title = \"title\"\n draft = true \n+++\n")
+	}
+
+	psr, err := parser.ReadFrom(bytes.NewReader(by))
+	if err != nil {
+		return err
+	}
+	metadata, err := psr.Metadata()
+	if err != nil {
+		return err
+	}
+	newmetadata, err := cast.ToStringMapE(metadata)
+	if err != nil {
+		return err
+	}
+
+	for k, _ := range newmetadata {
+		switch strings.ToLower(k) {
+		case "date":
+			newmetadata[k] = time.Now()
+		case "title":
+			newmetadata[k] = helpers.MakeTitle(helpers.Filename(name))
+		}
+	}
+
+	caseimatch := func(m map[string]interface{}, key string) bool {
+		for k, _ := range m {
+			if strings.ToLower(k) == strings.ToLower(key) {
+				return true
+			}
+		}
+		return false
+	}
+
+	if !caseimatch(newmetadata, "date") {
+		newmetadata["date"] = time.Now()
+	}
+
+	if !caseimatch(newmetadata, "title") {
+		newmetadata["title"] = helpers.MakeTitle(helpers.Filename(name))
+	}
+
+	page, err := hugolib.NewPage(name)
+	if err != nil {
+		return err
+	}
+
+	page.Dir = viper.GetString("sourceDir")
+	page.SetSourceMetaData(newmetadata, parser.FormatToLeadRune(viper.GetString("MetaDataFormat")))
+
+	if err = page.SafeSaveSourceAs(path.Join(viper.GetString("contentDir"), name)); err != nil {
+		return
+	}
+	jww.FEEDBACK.Println(helpers.AbsPathify(path.Join(viper.GetString("contentDir"), name)), "created")
+
+	return nil
+}
+
+func FindArchetype(kind string) (outpath string) {
+	search := []string{helpers.AbsPathify(viper.GetString("archetypeDir"))}
+
+	if viper.GetString("theme") != "" {
+		themeDir := path.Join(helpers.AbsPathify("themes/"+viper.GetString("theme")), "/archetypes/")
+		if _, err := os.Stat(themeDir); os.IsNotExist(err) {
+			jww.ERROR.Println("Unable to find archetypes directory for theme :", viper.GetString("theme"), "in", themeDir)
+		} else {
+			search = append(search, themeDir)
+		}
+	}
+
+	for _, x := range search {
+		pathsToCheck := []string{kind + ".md", kind, "default.md", "default"}
+		for _, p := range pathsToCheck {
+			curpath := path.Join(x, p)
+			jww.DEBUG.Println("checking", curpath, "for archetypes")
+			if exists, _ := helpers.Exists(curpath); exists {
+				return curpath
+			}
+		}
+	}
+
+	return ""
+}