aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <[email protected]>2023-06-26 20:48:44 +0200
committerBjørn Erik Pedersen <[email protected]>2023-06-26 20:48:44 +0200
commitbac03f40763e8b506d577e825d51df6b9a4c3f06 (patch)
tree242667d66df7efc8a47c080514b869bcde00e3d8
parenta018259bcf13eaa69c539e745aa1e1c6936d10ad (diff)
parentcc14c6a52c215fc43716f7b266c4c340b3d28230 (diff)
downloadhugo-bac03f40763e8b506d577e825d51df6b9a4c3f06.tar.gz
hugo-bac03f40763e8b506d577e825d51df6b9a4c3f06.zip
Merge branch 'master' of github.com:gohugoio/hugo
-rw-r--r--README.md1
-rw-r--r--commands/new.go15
-rw-r--r--config/allconfig/allconfig.go2
-rw-r--r--config/allconfig/alldecoders.go43
-rw-r--r--hugofs/files/classifier.go1
-rw-r--r--hugolib/page__paths.go35
-rw-r--r--resources/page/page_generate/generate_page_wrappers.go7
-rw-r--r--resources/page/permalinks.go32
-rw-r--r--resources/page/permalinks_test.go35
-rw-r--r--resources/page/zero_file.autogen.go6
-rw-r--r--source/fileInfo.go8
-rw-r--r--testscripts/commands/new.txt5
-rw-r--r--tpl/tplimpl/template.go6
13 files changed, 147 insertions, 49 deletions
diff --git a/README.md b/README.md
index e5e8ad0ee..745c70fd9 100644
--- a/README.md
+++ b/README.md
@@ -41,6 +41,7 @@ Hugo is designed to work well for any kind of website including blogs, tumbles,
<p>&nbsp;</p>
<p float="left">
<a href="https://www.linode.com/?utm_campaign=hugosponsor&utm_medium=banner&utm_source=hugogithub" target="_blank"><img src="https://raw.githubusercontent.com/gohugoio/gohugoioTheme/master/assets/images/sponsors/linode-logo_standard_light_medium.png" width="200" alt="Linode"></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ <a href="https://cloudcannon.com/?utm_campaign=HugoSponsorship&utm_source=sponsor&utm_content=gohugo" target="_blank"><img src="https://raw.githubusercontent.com/gohugoio/gohugoioTheme/master/assets/images/sponsors/cloudcannon-blue.svg" width="220" alt="CloudCannon"></a>
<p>&nbsp;</p>
## Supported Architectures
diff --git a/commands/new.go b/commands/new.go
index 1b2a412fd..b5c4d2152 100644
--- a/commands/new.go
+++ b/commands/new.go
@@ -47,13 +47,13 @@ func newNewCommand() *newCommand {
use: "content [path]",
short: "Create new content for your site",
long: `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.
-
- Ensure you run this within the root directory of your site.`,
+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.
+
+Ensure you run this within the root directory of your site.`,
run: func(ctx context.Context, cd *simplecobra.Commandeer, r *rootCommand, args []string) error {
if len(args) < 1 {
return errors.New("path needs to be provided")
@@ -150,6 +150,7 @@ Use ` + "`hugo new [contentPath]`" + ` to create new content.`,
},
withc: func(cmd *cobra.Command, r *rootCommand) {
cmd.Flags().BoolVarP(&force, "force", "f", false, "init inside non-empty directory")
+ cmd.Flags().StringVar(&format, "format", "toml", "preferred file format (toml, yaml or json)")
},
},
&simpleCommand{
diff --git a/config/allconfig/allconfig.go b/config/allconfig/allconfig.go
index 9079e2ce3..2dc409be7 100644
--- a/config/allconfig/allconfig.go
+++ b/config/allconfig/allconfig.go
@@ -150,7 +150,7 @@ type Config struct {
Minify minifiers.MinifyConfig `mapstructure:"-"`
// Permalink configuration.
- Permalinks map[string]string `mapstructure:"-"`
+ Permalinks map[string]map[string]string `mapstructure:"-"`
// Taxonomy configuration.
Taxonomies map[string]string `mapstructure:"-"`
diff --git a/config/allconfig/alldecoders.go b/config/allconfig/alldecoders.go
index 1c8573f3d..4d9ef4f85 100644
--- a/config/allconfig/alldecoders.go
+++ b/config/allconfig/alldecoders.go
@@ -206,7 +206,48 @@ var allDecoderSetups = map[string]decodeWeight{
"permalinks": {
key: "permalinks",
decode: func(d decodeWeight, p decodeConfig) error {
- p.c.Permalinks = maps.CleanConfigStringMapString(p.p.GetStringMapString(d.key))
+ p.c.Permalinks = make(map[string]map[string]string)
+
+ p.c.Permalinks["page"] = make(map[string]string)
+ p.c.Permalinks["section"] = make(map[string]string)
+ p.c.Permalinks["taxonomy"] = make(map[string]string)
+ p.c.Permalinks["term"] = make(map[string]string)
+
+ config := maps.CleanConfigStringMap(p.p.GetStringMap(d.key))
+ for k, v := range config {
+ switch v := v.(type) {
+ case string:
+ // [permalinks]
+ // key = '...'
+
+ // To sucessfully be backward compatible, "default" patterns need to be set for both page and term
+ p.c.Permalinks["page"][k] = v;
+ p.c.Permalinks["term"][k] = v;
+
+ case maps.Params:
+ // [permalinks.key]
+ // xyz = ???
+
+ if (k == "page") || (k == "section") || (k == "taxonomy") || (k == "term") {
+ // TODO: warn if we overwrite an already set value
+ for k2, v2 := range v {
+ switch v2 := v2.(type) {
+ case string:
+ p.c.Permalinks[k][k2] = v2
+
+ default:
+ return fmt.Errorf("permalinks configuration invalid: unknown value %q for key %q for kind %q", v2, k2, k)
+ }
+ }
+ } else {
+ return fmt.Errorf("permalinks configuration only allows per-kind configuration 'page', 'section', 'taxonomy' and 'term'; unknown kind: %q", k)
+ }
+
+ default:
+ return fmt.Errorf("permalinks configuration invalid: unknown value %q for key %q", v, k)
+ }
+ }
+
return nil
},
},
diff --git a/hugofs/files/classifier.go b/hugofs/files/classifier.go
index 09b239c21..5690795ed 100644
--- a/hugofs/files/classifier.go
+++ b/hugofs/files/classifier.go
@@ -93,6 +93,7 @@ const (
ContentClassBranch ContentClass = "branch"
ContentClassFile ContentClass = "zfile" // Sort below
ContentClassContent ContentClass = "zcontent"
+ ContentClassZero ContentClass = "zero" // Special value for zeroFile
)
func (c ContentClass) IsBundle() bool {
diff --git a/hugolib/page__paths.go b/hugolib/page__paths.go
index 72eac3182..f98531c10 100644
--- a/hugolib/page__paths.go
+++ b/hugolib/page__paths.go
@@ -18,6 +18,7 @@ import (
"strings"
"github.com/gohugoio/hugo/helpers"
+ "github.com/gohugoio/hugo/hugofs/files"
"github.com/gohugoio/hugo/resources/page"
)
@@ -108,14 +109,16 @@ func createTargetPathDescriptor(s *Site, p page.Page, pm *pageMeta) (page.Target
)
d := s.Deps
+ classifier := files.ContentClassZero
if !p.File().IsZero() {
dir = p.File().Dir()
baseName = p.File().TranslationBaseName()
contentBaseName = p.File().ContentBaseName()
+ classifier = p.File().Classifier()
}
- if baseName != contentBaseName {
+ if classifier == files.ContentClassLeaf {
// See https://github.com/gohugoio/hugo/issues/4870
// A leaf bundle
dir = strings.TrimSuffix(dir, contentBaseName+helpers.FilePathSeparator)
@@ -143,22 +146,26 @@ func createTargetPathDescriptor(s *Site, p page.Page, pm *pageMeta) (page.Target
desc.PrefixFilePath = s.getLanguageTargetPathLang(alwaysInSubDir)
desc.PrefixLink = s.getLanguagePermalinkLang(alwaysInSubDir)
- // Expand only page.KindPage and page.KindTaxonomy; don't expand other Kinds of Pages
- // like page.KindSection or page.KindTaxonomyTerm because they are "shallower" and
- // the permalink configuration values are likely to be redundant, e.g.
- // naively expanding /category/:slug/ would give /category/categories/ for
- // the "categories" page.KindTaxonomyTerm.
- if p.Kind() == page.KindPage || p.Kind() == page.KindTerm {
- opath, err := d.ResourceSpec.Permalinks.Expand(p.Section(), p)
- if err != nil {
- return desc, err
- }
+ opath, err := d.ResourceSpec.Permalinks.Expand(p.Section(), p)
+ if err != nil {
+ return desc, err
+ }
- if opath != "" {
- opath, _ = url.QueryUnescape(opath)
- desc.ExpandedPermalink = opath
+ if opath != "" {
+ opath, _ = url.QueryUnescape(opath)
+ if strings.HasSuffix(opath, "//") {
+ // When rewriting the _index of the section the permalink config is applied to,
+ // we get douple slashes at the end sometimes; clear them up here
+ opath = strings.TrimSuffix(opath, "/")
}
+ desc.ExpandedPermalink = opath
+
+ if !p.File().IsZero() {
+ s.Log.Debugf("Set expanded permalink path for %s %s to %#v", p.Kind(), p.File().Path(), opath)
+ } else {
+ s.Log.Debugf("Set expanded permalink path for %s in %v to %#v", p.Kind(), desc.Sections, opath)
+ }
}
return desc, nil
diff --git a/resources/page/page_generate/generate_page_wrappers.go b/resources/page/page_generate/generate_page_wrappers.go
index f4b40f717..c034bc002 100644
--- a/resources/page/page_generate/generate_page_wrappers.go
+++ b/resources/page/page_generate/generate_page_wrappers.go
@@ -221,7 +221,7 @@ func generateFileIsZeroWrappers(c *codegen.Inspector) error {
methods := c.MethodsFromTypes([]reflect.Type{reflect.TypeOf((*source.File)(nil)).Elem()}, nil)
for _, m := range methods {
- if m.Name == "IsZero" {
+ if m.Name == "IsZero" || m.Name == "Classifier" {
continue
}
fmt.Fprint(&buff, m.DeclarationNamed("zeroFile"))
@@ -255,6 +255,11 @@ func (zeroFile) IsZero() bool {
return true
}
+func (z zeroFile) Classifier() files.ContentClass {
+ z.log.Warnln(".File.Classifier on zero object. Wrap it in if or with: {{ with .File }}{{ .Classifier }}{{ end }}")
+ return files.ContentClassZero
+}
+
%s
`, header, importsString(pkgImports), buff.String())
diff --git a/resources/page/permalinks.go b/resources/page/permalinks.go
index 3dfc36937..ab418a20b 100644
--- a/resources/page/permalinks.go
+++ b/resources/page/permalinks.go
@@ -26,6 +26,7 @@ import (
"errors"
"github.com/gohugoio/hugo/helpers"
+
)
// PermalinkExpander holds permalin mappings per section.
@@ -35,7 +36,7 @@ type PermalinkExpander struct {
// to be used to replace that tag.
knownPermalinkAttributes map[string]pageToPermaAttribute
- expanders map[string]func(Page) (string, error)
+ expanders map[string]map[string]func(Page) (string, error)
urlize func(uri string) string
}
@@ -68,7 +69,7 @@ func (p PermalinkExpander) callback(attr string) (pageToPermaAttribute, bool) {
// NewPermalinkExpander creates a new PermalinkExpander configured by the given
// urlize func.
-func NewPermalinkExpander(urlize func(uri string) string, patterns map[string]string) (PermalinkExpander, error) {
+func NewPermalinkExpander(urlize func(uri string) string, patterns map[string]map[string]string) (PermalinkExpander, error) {
p := PermalinkExpander{urlize: urlize}
p.knownPermalinkAttributes = map[string]pageToPermaAttribute{
@@ -87,12 +88,15 @@ func NewPermalinkExpander(urlize func(uri string) string, patterns map[string]st
"filename": p.pageToPermalinkFilename,
}
- e, err := p.parse(patterns)
- if err != nil {
- return p, err
- }
+ p.expanders = make(map[string]map[string]func(Page) (string, error))
- p.expanders = e
+ for kind, patterns := range patterns {
+ e, err := p.parse(patterns)
+ if err != nil {
+ return p, err
+ }
+ p.expanders[kind] = e
+ }
return p, nil
}
@@ -100,7 +104,13 @@ func NewPermalinkExpander(urlize func(uri string) string, patterns map[string]st
// Expand expands the path in p according to the rules defined for the given key.
// If no rules are found for the given key, an empty string is returned.
func (l PermalinkExpander) Expand(key string, p Page) (string, error) {
- expand, found := l.expanders[key]
+ expanders, found := l.expanders[p.Kind()]
+
+ if !found {
+ return "", nil
+ }
+
+ expand, found := expanders[key]
if !found {
return "", nil
@@ -242,6 +252,10 @@ func (l PermalinkExpander) pageToPermalinkDate(p Page, dateField string) (string
// pageToPermalinkTitle returns the URL-safe form of the title
func (l PermalinkExpander) pageToPermalinkTitle(p Page, _ string) (string, error) {
+ if p.File().TranslationBaseName() == "_index" {
+ return "", nil
+ }
+
return l.urlize(p.Title()), nil
}
@@ -252,6 +266,8 @@ func (l PermalinkExpander) pageToPermalinkFilename(p Page, _ string) (string, er
// Page bundles; the directory name will hopefully have a better name.
dir := strings.TrimSuffix(p.File().Dir(), helpers.FilePathSeparator)
_, name = filepath.Split(dir)
+ } else if name == "_index" {
+ return "", nil
}
return l.urlize(name), nil
diff --git a/resources/page/permalinks_test.go b/resources/page/permalinks_test.go
index b9c0ca9cb..24eb27f5b 100644
--- a/resources/page/permalinks_test.go
+++ b/resources/page/permalinks_test.go
@@ -69,6 +69,7 @@ func TestPermalinkExpansion(t *testing.T) {
page.date = d
page.section = "blue"
page.slug = "The Slug"
+ page.kind = "page"
for _, item := range testdataPermalinks {
if !item.valid {
@@ -79,8 +80,10 @@ func TestPermalinkExpansion(t *testing.T) {
name := specNameCleaner.ReplaceAllString(item.spec, "")
c.Run(name, func(c *qt.C) {
- patterns := map[string]string{
- "posts": item.spec,
+ patterns := map[string]map[string]string{
+ "page": {
+ "posts": item.spec,
+ },
}
expander, err := NewPermalinkExpander(urlize, patterns)
c.Assert(err, qt.IsNil)
@@ -103,14 +106,18 @@ func TestPermalinkExpansionMultiSection(t *testing.T) {
page.date = d
page.section = "blue"
page.slug = "The Slug"
+ page.kind = "page"
page_slug_fallback := newTestPageWithFile("/page-filename/index.md")
page_slug_fallback.title = "Page Title"
-
- permalinksConfig := map[string]string{
- "posts": "/:slug",
- "blog": "/:section/:year",
- "recipes": "/:slugorfilename",
+ page_slug_fallback.kind = "page"
+
+ permalinksConfig := map[string]map[string]string{
+ "page": {
+ "posts": "/:slug",
+ "blog": "/:section/:year",
+ "recipes": "/:slugorfilename",
+ },
}
expander, err := NewPermalinkExpander(urlize, permalinksConfig)
c.Assert(err, qt.IsNil)
@@ -137,8 +144,10 @@ func TestPermalinkExpansionConcurrent(t *testing.T) {
c := qt.New(t)
- permalinksConfig := map[string]string{
- "posts": "/:slug/",
+ permalinksConfig := map[string]map[string]string{
+ "page": {
+ "posts": "/:slug/",
+ },
}
expander, err := NewPermalinkExpander(urlize, permalinksConfig)
@@ -151,6 +160,7 @@ func TestPermalinkExpansionConcurrent(t *testing.T) {
go func(i int) {
defer wg.Done()
page := newTestPage()
+ page.kind = "page"
for j := 1; j < 20; j++ {
page.slug = fmt.Sprintf("slug%d", i+j)
expanded, err := expander.Expand("posts", page)
@@ -209,9 +219,12 @@ func BenchmarkPermalinkExpand(b *testing.B) {
page.title = "Hugo Rocks"
d, _ := time.Parse("2006-01-02", "2019-02-28")
page.date = d
+ page.kind = "page"
- permalinksConfig := map[string]string{
- "posts": "/:year-:month-:title",
+ permalinksConfig := map[string]map[string]string{
+ "page": {
+ "posts": "/:year-:month-:title",
+ },
}
expander, err := NewPermalinkExpander(urlize, permalinksConfig)
if err != nil {
diff --git a/resources/page/zero_file.autogen.go b/resources/page/zero_file.autogen.go
index 72d98998e..979f92a0f 100644
--- a/resources/page/zero_file.autogen.go
+++ b/resources/page/zero_file.autogen.go
@@ -18,6 +18,7 @@ package page
import (
"github.com/gohugoio/hugo/common/loggers"
"github.com/gohugoio/hugo/hugofs"
+ "github.com/gohugoio/hugo/hugofs/files"
"github.com/gohugoio/hugo/source"
)
@@ -34,6 +35,11 @@ func (zeroFile) IsZero() bool {
return true
}
+func (z zeroFile) Classifier() files.ContentClass {
+ z.log.Warnln(".File.Classifier on zero object. Wrap it in if or with: {{ with .File }}{{ .Classifier }}{{ end }}")
+ return files.ContentClassZero
+}
+
func (z zeroFile) Path() (o0 string) {
z.log.Warnln(".File.Path on zero object. Wrap it in if or with: {{ with .File }}{{ .Path }}{{ end }}")
return
diff --git a/source/fileInfo.go b/source/fileInfo.go
index c58a0c3b9..03bb1b16c 100644
--- a/source/fileInfo.go
+++ b/source/fileInfo.go
@@ -92,6 +92,9 @@ type FileWithoutOverlap interface {
// if file is a leaf bundle.
ContentBaseName() string
+ // Classifier is the ContentClass of the file
+ Classifier() files.ContentClass
+
// UniqueID is the MD5 hash of the file's path and is for most practical applications,
// Hugo content files being one of them, considered to be unique.
UniqueID() string
@@ -170,6 +173,11 @@ func (fi *FileInfo) ContentBaseName() string {
return fi.contentBaseName
}
+// Classifier is the ContentClass of the file
+func (fi *FileInfo) Classifier() files.ContentClass {
+ return fi.classifier;
+}
+
// Section returns a file's section.
func (fi *FileInfo) Section() string {
fi.init()
diff --git a/testscripts/commands/new.txt b/testscripts/commands/new.txt
index aad0d80f6..92cc3b7da 100644
--- a/testscripts/commands/new.txt
+++ b/testscripts/commands/new.txt
@@ -2,6 +2,8 @@
hugo new site -h
stdout 'Create a new site in the provided directory'
+hugo new site my-yaml-site --format yml
+checkfile my-yaml-site/hugo.yml
hugo new site mysite -f
stdout 'Congratulations! Your new Hugo site is created in'
cd mysite
@@ -45,6 +47,3 @@ draft: true
---
Dummy content.
-
-
-
diff --git a/tpl/tplimpl/template.go b/tpl/tplimpl/template.go
index e706bca4c..ba5e861af 100644
--- a/tpl/tplimpl/template.go
+++ b/tpl/tplimpl/template.go
@@ -754,15 +754,15 @@ func (t *templateHandler) applyTemplateTransformers(ns *templateNamespace, ts *t
//go:embed embedded/templates/*
//go:embed embedded/templates/_default/*
//go:embed embedded/templates/_server/*
-var embededTemplatesFs embed.FS
+var embeddedTemplatesFs embed.FS
func (t *templateHandler) loadEmbedded() error {
- return fs.WalkDir(embededTemplatesFs, ".", func(path string, d fs.DirEntry, err error) error {
+ return fs.WalkDir(embeddedTemplatesFs, ".", func(path string, d fs.DirEntry, err error) error {
if d == nil || d.IsDir() {
return nil
}
- templb, err := embededTemplatesFs.ReadFile(path)
+ templb, err := embeddedTemplatesFs.ReadFile(path)
if err != nil {
return err
}