diff options
author | Bjørn Erik Pedersen <[email protected]> | 2023-06-26 20:48:44 +0200 |
---|---|---|
committer | Bjørn Erik Pedersen <[email protected]> | 2023-06-26 20:48:44 +0200 |
commit | bac03f40763e8b506d577e825d51df6b9a4c3f06 (patch) | |
tree | 242667d66df7efc8a47c080514b869bcde00e3d8 | |
parent | a018259bcf13eaa69c539e745aa1e1c6936d10ad (diff) | |
parent | cc14c6a52c215fc43716f7b266c4c340b3d28230 (diff) | |
download | hugo-bac03f40763e8b506d577e825d51df6b9a4c3f06.tar.gz hugo-bac03f40763e8b506d577e825d51df6b9a4c3f06.zip |
Merge branch 'master' of github.com:gohugoio/hugo
-rw-r--r-- | README.md | 1 | ||||
-rw-r--r-- | commands/new.go | 15 | ||||
-rw-r--r-- | config/allconfig/allconfig.go | 2 | ||||
-rw-r--r-- | config/allconfig/alldecoders.go | 43 | ||||
-rw-r--r-- | hugofs/files/classifier.go | 1 | ||||
-rw-r--r-- | hugolib/page__paths.go | 35 | ||||
-rw-r--r-- | resources/page/page_generate/generate_page_wrappers.go | 7 | ||||
-rw-r--r-- | resources/page/permalinks.go | 32 | ||||
-rw-r--r-- | resources/page/permalinks_test.go | 35 | ||||
-rw-r--r-- | resources/page/zero_file.autogen.go | 6 | ||||
-rw-r--r-- | source/fileInfo.go | 8 | ||||
-rw-r--r-- | testscripts/commands/new.txt | 5 | ||||
-rw-r--r-- | tpl/tplimpl/template.go | 6 |
13 files changed, 147 insertions, 49 deletions
@@ -41,6 +41,7 @@ Hugo is designed to work well for any kind of website including blogs, tumbles, <p> </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> + <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> </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 } |