gitee.com/mirrors/Hugo-Go@v0.47.1/commands/new.go (about)

     1  // Copyright 2018 The Hugo Authors. All rights reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  // http://www.apache.org/licenses/LICENSE-2.0
     7  //
     8  // Unless required by applicable law or agreed to in writing, software
     9  // distributed under the License is distributed on an "AS IS" BASIS,
    10  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package commands
    15  
    16  import (
    17  	"bytes"
    18  	"os"
    19  	"path/filepath"
    20  	"strings"
    21  
    22  	"github.com/gohugoio/hugo/create"
    23  	"github.com/gohugoio/hugo/helpers"
    24  	"github.com/gohugoio/hugo/hugolib"
    25  	"github.com/spf13/afero"
    26  	"github.com/spf13/cobra"
    27  	jww "github.com/spf13/jwalterweatherman"
    28  )
    29  
    30  var _ cmder = (*newCmd)(nil)
    31  
    32  type newCmd struct {
    33  	hugoBuilderCommon
    34  	contentEditor string
    35  	contentType   string
    36  
    37  	*baseCmd
    38  }
    39  
    40  func newNewCmd() *newCmd {
    41  	cc := &newCmd{}
    42  	cc.baseCmd = newBaseCmd(&cobra.Command{
    43  		Use:   "new [path]",
    44  		Short: "Create new content for your site",
    45  		Long: `Create a new content file and automatically set the date and title.
    46  It will guess which kind of file to create based on the path provided.
    47  
    48  You can also specify the kind with ` + "`-k KIND`" + `.
    49  
    50  If archetypes are provided in your theme or site, they will be used.`,
    51  
    52  		RunE: cc.newContent,
    53  	})
    54  
    55  	cc.cmd.Flags().StringVarP(&cc.contentType, "kind", "k", "", "content type to create")
    56  	cc.cmd.PersistentFlags().StringVarP(&cc.source, "source", "s", "", "filesystem path to read files relative from")
    57  	cc.cmd.PersistentFlags().SetAnnotation("source", cobra.BashCompSubdirsInDir, []string{})
    58  	cc.cmd.Flags().StringVar(&cc.contentEditor, "editor", "", "edit new content with this editor, if provided")
    59  
    60  	cc.cmd.AddCommand(newNewSiteCmd().getCommand())
    61  	cc.cmd.AddCommand(newNewThemeCmd().getCommand())
    62  
    63  	return cc
    64  }
    65  
    66  func (n *newCmd) newContent(cmd *cobra.Command, args []string) error {
    67  	cfgInit := func(c *commandeer) error {
    68  		if cmd.Flags().Changed("editor") {
    69  			c.Set("newContentEditor", n.contentEditor)
    70  		}
    71  		return nil
    72  	}
    73  
    74  	c, err := initializeConfig(true, false, &n.hugoBuilderCommon, n, cfgInit)
    75  
    76  	if err != nil {
    77  		return err
    78  	}
    79  
    80  	if len(args) < 1 {
    81  		return newUserError("path needs to be provided")
    82  	}
    83  
    84  	createPath := args[0]
    85  
    86  	var kind string
    87  
    88  	createPath, kind = newContentPathSection(createPath)
    89  
    90  	if n.contentType != "" {
    91  		kind = n.contentType
    92  	}
    93  
    94  	cfg := c.DepsCfg
    95  
    96  	ps, err := helpers.NewPathSpec(cfg.Fs, cfg.Cfg)
    97  	if err != nil {
    98  		return err
    99  	}
   100  
   101  	// If a site isn't in use in the archetype template, we can skip the build.
   102  	siteFactory := func(filename string, siteUsed bool) (*hugolib.Site, error) {
   103  		if !siteUsed {
   104  			return hugolib.NewSite(*cfg)
   105  		}
   106  		var s *hugolib.Site
   107  
   108  		if err := c.hugo.Build(hugolib.BuildCfg{SkipRender: true}); err != nil {
   109  			return nil, err
   110  		}
   111  
   112  		s = c.hugo.Sites[0]
   113  
   114  		if len(c.hugo.Sites) > 1 {
   115  			// Find the best match.
   116  			for _, ss := range c.hugo.Sites {
   117  				if strings.Contains(createPath, "."+ss.Language.Lang) {
   118  					s = ss
   119  					break
   120  				}
   121  			}
   122  		}
   123  		return s, nil
   124  	}
   125  
   126  	return create.NewContent(ps, siteFactory, kind, createPath)
   127  }
   128  
   129  func mkdir(x ...string) {
   130  	p := filepath.Join(x...)
   131  
   132  	err := os.MkdirAll(p, 0777) // before umask
   133  	if err != nil {
   134  		jww.FATAL.Fatalln(err)
   135  	}
   136  }
   137  
   138  func touchFile(fs afero.Fs, x ...string) {
   139  	inpath := filepath.Join(x...)
   140  	mkdir(filepath.Dir(inpath))
   141  	err := helpers.WriteToDisk(inpath, bytes.NewReader([]byte{}), fs)
   142  	if err != nil {
   143  		jww.FATAL.Fatalln(err)
   144  	}
   145  }
   146  
   147  func newContentPathSection(path string) (string, string) {
   148  	// Forward slashes is used in all examples. Convert if needed.
   149  	// Issue #1133
   150  	createpath := filepath.FromSlash(path)
   151  	var section string
   152  	// assume the first directory is the section (kind)
   153  	if strings.Contains(createpath[1:], helpers.FilePathSeparator) {
   154  		parts := strings.Split(strings.TrimPrefix(createpath, helpers.FilePathSeparator), helpers.FilePathSeparator)
   155  		if len(parts) > 0 {
   156  			section = parts[0]
   157  		}
   158  
   159  	}
   160  
   161  	return createpath, section
   162  }