]> git.maquefel.me Git - brevno-suite/hugo/commitdiff
hugolib: Add support for gitpurism
authorNikita Shubin <nikita.shubin@maquefel.me>
Sun, 26 Apr 2026 10:07:31 +0000 (13:07 +0300)
committerNikita Shubin <nikita.shubin@maquefel.me>
Sun, 26 Apr 2026 10:12:12 +0000 (13:12 +0300)
Add possibility to extract and use tags and categories coming from git
notes.

NOTE: I have no idea of what this is, just mimicking some stuff found
here.

TODO:
- specify git notes branches to scan in config file
- actually all meta can be taken from git notes
- add condition in config to affect either meta appended or rewritten

Signed-off-by: Nikita Shubin <nikita.shubin@maquefel.me>
commands/commandeer.go
config/allconfig/allconfig.go
hugolib/hugo_sites.go
hugolib/page.go
hugolib/page__common.go
hugolib/page__meta.go
hugolib/page__new.go
hugolib/site.go

index 6b222fe9b5d51d951ae0094b435ae239c3f2e73f..9678ff40fddf4a45770331bd1e9400863e72f8c6 100644 (file)
@@ -615,6 +615,7 @@ func applyLocalFlagsBuild(cmd *cobra.Command, r *rootCommand) {
        cmd.Flags().BoolP("buildExpired", "E", false, "include expired content")
        cmd.Flags().BoolP("ignoreCache", "", false, "ignores the cache directory")
        cmd.Flags().Bool("enableGitInfo", false, "add Git revision, date, author, and CODEOWNERS info to the pages")
+       cmd.Flags().Bool("enableGitPurismInfo", false, "grab meta (tags, categories) from Git notes")
        cmd.Flags().StringP("layoutDir", "l", "", "filesystem path to layout directory")
        _ = cmd.MarkFlagDirname("layoutDir")
        cmd.Flags().BoolVar(&r.gc, "gc", false, "enable to run some cleanup tasks (remove unused cache files) after the build")
index 75613e0de691fa718988a5c5ce53ef773346b359..cdfd42825771dfc65ed293a265da3c1b0afb698e 100644 (file)
@@ -703,6 +703,10 @@ type RootConfig struct {
        // <docsmeta>{"identifiers": ["Page"] }</docsmeta>
        EnableGitInfo bool
 
+       // When enabled, Hugo will attempt to grab tags and categories from Git notes.
+       // <docsmeta>{"identifiers": ["Page"] }</docsmeta>
+       EnableGitPurismInfo bool
+
        // Enable to track, calculate and print metrics.
        TemplateMetrics bool
 
index eea3583a562cf14fa2c99406716aa51908170222..59c5b459563be97d0b241c6c321d69dcea3878ed 100644 (file)
@@ -86,6 +86,8 @@ type HugoSites struct {
 
        markdownTitleInfo *markdownTitleInfo
 
+       gitPurismInfo *gitPurismInfo
+
        // As loaded from the /data dirs
        data map[string]any
 
@@ -336,6 +338,8 @@ type hugoSitesInit struct {
        gitInfo hsync.FuncResetter
 
        markdownTitleInfo hsync.FuncResetter
+
+       gitPurismInfo hsync.FuncResetter
 }
 
 func (h *HugoSites) Data() map[string]any {
@@ -417,6 +421,18 @@ func (h *HugoSites) markdownTitleInfoForPage(p page.Page) (*MarkdownTitleInfo, e
        return h.markdownTitleInfo.forPage(p), nil
 }
 
+func (h *HugoSites) gitPurismInfoForPage(p page.Page) (*GitPurismInfo, error) {
+       if err := h.init.gitPurismInfo.Do(context.Background()); err != nil {
+               return nil, err
+       }
+
+       if h.gitPurismInfo == nil {
+               return nil, nil
+       }
+
+       return h.gitPurismInfo.forPage(p), nil
+}
+
 func (h *HugoSites) reportProgress(f func() (state terminal.ProgressState, progress float64)) {
        h.progressReporter.mu.Lock()
        defer h.progressReporter.mu.Unlock()
@@ -587,12 +603,6 @@ func (h *HugoSites) loadGitInfo() error {
 func (h *HugoSites) loadMarkdownTitleInfo() error {
        // TODO: Make it configurable
        // if h.Configs.Base.EnableMarkdownTitle {
-       //      cfg := gitInfoConfig{
-       //              Deps:         h.Deps,
-       //              Modules:      h.Configs.Modules,
-       //              GitInfoCache: h.Configs.FileCaches.ModuleGitInfoCache(),
-       //              Logger:       h.Log,
-       //      }
                mt, err := newMarkdownTitleInfo(h.Deps.Conf.DirsBase().ContentDir)
                if err != nil {
                        return err
@@ -603,6 +613,18 @@ func (h *HugoSites) loadMarkdownTitleInfo() error {
        return nil
 }
 
+func (h *HugoSites) loadGitPurismInfo() error {
+       if h.Configs.Base.EnableGitPurismInfo {
+               gpi, err := newGitPurismInfo(h.Deps.Conf.DirsBase().ContentDir)
+               if err != nil {
+                       return err
+               } else {
+                       h.gitPurismInfo = gpi
+               }
+       }
+       return nil
+}
+
 // Reset resets the sites and template caches etc., making it ready for a full rebuild.
 func (h *HugoSites) reset() {
        h.fatalErrorHandler = &fatalErrorHandler{
index 742ff343d8ab52843b39540ba62ecf47c6677d0f..81759da6d0468d4f3f8a1e3880a5d90ba13210be 100644 (file)
@@ -329,6 +329,10 @@ func (p *pageState) MarkdownTitleInfo() *MarkdownTitleInfo {
        return p.markdownTitleInfo
 }
 
+func (p *pageState) GitPurismInfo() *GitPurismInfo {
+       return p.gitPurismInfo
+}
+
 // GetTerms gets the terms defined on this page in the given taxonomy.
 // The pages returned will be ordered according to the front matter.
 func (ps *pageState) GetTerms(taxonomy string) page.Pages {
index 42965e8a07525b77e2eda180786cd165d9fe4188..69458a0973d9a280c96803530d2f896157b80b3e 100644 (file)
@@ -88,6 +88,7 @@ type pageCommon struct {
        codeowners []string
 
        markdownTitleInfo    *MarkdownTitleInfo
+       gitPurismInfo    *GitPurismInfo
 
        // Positional navigation
        posNextPrev        *nextPrev
index 7253be4aa7ec786e10807d6181fc76302a4f0751..e290c19d2f39cd470b7540d2773f176fe4f11faa 100644 (file)
@@ -820,6 +820,50 @@ params:
                }
        }
 
+       if ps.gitPurismInfo != nil {
+               if len(ps.gitPurismInfo.Categories) > 0 {
+                       if existing, ok := pcfg.Params["categories"]; ok {
+                               switch v := existing.(type) {
+                               case []string:
+                                       pcfg.Params["categories"] = append(v, ps.gitPurismInfo.Categories...)
+                               case []interface{}:
+                                       existingStrings := make([]string, 0, len(v))
+                                       for _, iv := range v {
+                                               if s, ok := iv.(string); ok {
+                                                       existingStrings = append(existingStrings, s)
+                                               }
+                                       }
+                                       pcfg.Params["categories"] = append(existingStrings, ps.gitPurismInfo.Categories...)
+                               default:
+                                       pcfg.Params["categories"] = ps.gitPurismInfo.Categories
+                               }
+                       } else {
+                               pcfg.Params["categories"] = ps.gitPurismInfo.Categories
+                       }
+               }
+
+               if len(ps.gitPurismInfo.Tags) > 0 {
+                       if existing, ok := pcfg.Params["tags"]; ok {
+                               switch v := existing.(type) {
+                               case []string:
+                                       pcfg.Params["tags"] = append(v, ps.gitPurismInfo.Tags...)
+                               case []interface{}:
+                                       existingStrings := make([]string, 0, len(v))
+                                       for _, iv := range v {
+                                               if s, ok := iv.(string); ok {
+                                                       existingStrings = append(existingStrings, s)
+                                               }
+                                       }
+                                       pcfg.Params["tags"] = append(existingStrings, ps.gitPurismInfo.Tags...)
+                               default:
+                                       pcfg.Params["tags"] = ps.gitPurismInfo.Tags
+                               }
+                       } else {
+                               pcfg.Params["tags"] = ps.gitPurismInfo.Tags
+                       }
+               }
+       }
+
        for k, v := range userParams {
                pcfg.Params[strings.ToLower(k)] = v
        }
index 70925e3b8d3146181c547e2e6524b5384434d25c..aff95e5db59a681a7b08a9f7bd220732d192f44f 100644 (file)
@@ -101,6 +101,13 @@ func (s *Site) doNewPageFromPageMeta(m *pageMeta, cascades *page.PageMatcherPara
                        return nil, fmt.Errorf("failed to load MarkdownTitle data: %w", err)
                }
                ps.markdownTitleInfo = mt
+
+               gpi, err := s.h.gitPurismInfoForPage(ps)
+               if err != nil {
+                       return nil, fmt.Errorf("failed to load GitPurism data: %w", err)
+
+               }
+               ps.gitPurismInfo = gpi
        }
 
        ps.pageMenus = &pageMenus{p: ps}
index d0431d701816ba0062b4a2266bf680bddc9328ac..b201d6e7a073ed931f66d0319ddd494e0cd94475 100644 (file)
@@ -599,6 +599,9 @@ func newHugoSites(
                return h.loadMarkdownTitleInfo()
        })
 
+       h.init.gitPurismInfo = hsync.OnceMoreFunc(func(ctx context.Context) error {
+               return h.loadGitPurismInfo()
+       })
        return h, nil
 }