new_theme.go (5422B)
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 "errors"
19 "path/filepath"
20 "strings"
21
22 "github.com/gohugoio/hugo/common/htime"
23 "github.com/gohugoio/hugo/helpers"
24 "github.com/gohugoio/hugo/hugofs"
25 "github.com/spf13/cobra"
26 jww "github.com/spf13/jwalterweatherman"
27 )
28
29 var _ cmder = (*newThemeCmd)(nil)
30
31 type newThemeCmd struct {
32 *baseBuilderCmd
33 }
34
35 func (b *commandsBuilder) newNewThemeCmd() *newThemeCmd {
36 cc := &newThemeCmd{}
37
38 cmd := &cobra.Command{
39 Use: "theme [name]",
40 Short: "Create a new theme",
41 Long: `Create a new theme (skeleton) called [name] in ./themes.
42 New theme is a skeleton. Please add content to the touched files. Add your
43 name to the copyright line in the license and adjust the theme.toml file
44 as you see fit.`,
45 RunE: cc.newTheme,
46 }
47
48 cc.baseBuilderCmd = b.newBuilderBasicCmd(cmd)
49
50 return cc
51 }
52
53 // newTheme creates a new Hugo theme template
54 func (n *newThemeCmd) newTheme(cmd *cobra.Command, args []string) error {
55 c, err := initializeConfig(false, false, false, &n.hugoBuilderCommon, n, nil)
56 if err != nil {
57 return err
58 }
59
60 if len(args) < 1 {
61 return newUserError("theme name needs to be provided")
62 }
63
64 createpath := c.hugo().PathSpec.AbsPathify(filepath.Join(c.Cfg.GetString("themesDir"), args[0]))
65 jww.FEEDBACK.Println("Creating theme at", createpath)
66
67 cfg := c.DepsCfg
68
69 if x, _ := helpers.Exists(createpath, cfg.Fs.Source); x {
70 return errors.New(createpath + " already exists")
71 }
72
73 mkdir(createpath, "layouts", "_default")
74 mkdir(createpath, "layouts", "partials")
75
76 touchFile(cfg.Fs.Source, createpath, "layouts", "index.html")
77 touchFile(cfg.Fs.Source, createpath, "layouts", "404.html")
78 touchFile(cfg.Fs.Source, createpath, "layouts", "_default", "list.html")
79 touchFile(cfg.Fs.Source, createpath, "layouts", "_default", "single.html")
80
81 baseofDefault := []byte(`<!DOCTYPE html>
82 <html>
83 {{- partial "head.html" . -}}
84 <body>
85 {{- partial "header.html" . -}}
86 <div id="content">
87 {{- block "main" . }}{{- end }}
88 </div>
89 {{- partial "footer.html" . -}}
90 </body>
91 </html>
92 `)
93 err = helpers.WriteToDisk(filepath.Join(createpath, "layouts", "_default", "baseof.html"), bytes.NewReader(baseofDefault), cfg.Fs.Source)
94 if err != nil {
95 return err
96 }
97
98 touchFile(cfg.Fs.Source, createpath, "layouts", "partials", "head.html")
99 touchFile(cfg.Fs.Source, createpath, "layouts", "partials", "header.html")
100 touchFile(cfg.Fs.Source, createpath, "layouts", "partials", "footer.html")
101
102 mkdir(createpath, "archetypes")
103
104 archDefault := []byte("+++\n+++\n")
105
106 err = helpers.WriteToDisk(filepath.Join(createpath, "archetypes", "default.md"), bytes.NewReader(archDefault), cfg.Fs.Source)
107 if err != nil {
108 return err
109 }
110
111 mkdir(createpath, "static", "js")
112 mkdir(createpath, "static", "css")
113
114 by := []byte(`The MIT License (MIT)
115
116 Copyright (c) ` + htime.Now().Format("2006") + ` YOUR_NAME_HERE
117
118 Permission is hereby granted, free of charge, to any person obtaining a copy of
119 this software and associated documentation files (the "Software"), to deal in
120 the Software without restriction, including without limitation the rights to
121 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
122 the Software, and to permit persons to whom the Software is furnished to do so,
123 subject to the following conditions:
124
125 The above copyright notice and this permission notice shall be included in all
126 copies or substantial portions of the Software.
127
128 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
129 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
130 FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
131 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
132 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
133 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
134 `)
135
136 err = helpers.WriteToDisk(filepath.Join(createpath, "LICENSE"), bytes.NewReader(by), cfg.Fs.Source)
137 if err != nil {
138 return err
139 }
140
141 n.createThemeMD(cfg.Fs, createpath)
142
143 return nil
144 }
145
146 func (n *newThemeCmd) createThemeMD(fs *hugofs.Fs, inpath string) (err error) {
147 by := []byte(`# theme.toml template for a Hugo theme
148 # See https://github.com/gohugoio/hugoThemes#themetoml for an example
149
150 name = "` + strings.Title(helpers.MakeTitle(filepath.Base(inpath))) + `"
151 license = "MIT"
152 licenselink = "https://github.com/yourname/yourtheme/blob/master/LICENSE"
153 description = ""
154 homepage = "http://example.com/"
155 tags = []
156 features = []
157 min_version = "0.41.0"
158
159 [author]
160 name = ""
161 homepage = ""
162
163 # If porting an existing theme
164 [original]
165 name = ""
166 homepage = ""
167 repo = ""
168 `)
169
170 err = helpers.WriteToDisk(filepath.Join(inpath, "theme.toml"), bytes.NewReader(by), fs.Source)
171 if err != nil {
172 return
173 }
174
175 return nil
176 }