Skip to content

Instantly share code, notes, and snippets.

@TheCoreMan
Created April 27, 2024 09:16
Show Gist options
  • Select an option

  • Save TheCoreMan/fa528341dbff05d0fc37f4837fabb959 to your computer and use it in GitHub Desktop.

Select an option

Save TheCoreMan/fa528341dbff05d0fc37f4837fabb959 to your computer and use it in GitHub Desktop.
A short go script to refresh your Hugo post dates.
// A short script to update the date in the frontmatter of a Hugo post.
// The date is updated to the current date and time.
// Run this script with `go run scripts/refresh-post-date/main.go -file path/to/post.md`,
// and you'll see:
// > ❯ go run main.go -file path/to/post.md
// > 12:10PM INF Refreshed by diff=1m55s
// > 12:10PM INF Successfully updated the date! 🎉 post=path/to/post.md
// You can add the `-verbose` flag to see more detailed logs.
package main
import (
"errors"
"flag"
"os"
"strings"
"time"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"gopkg.in/yaml.v3"
)
const (
FrontmatterSeparatorLength = 3
HugoTimeFormatAsGoFormat = "2006-01-02T15:04:05-07:00"
)
func parseFrontmatter(fullPost []byte) ([]byte, error) {
fullPostAsString := string(fullPost)
// The frontmatter is between two lines of `---`
startIndex := strings.Index(fullPostAsString, "---")
if startIndex == -1 {
return nil, errors.New("failed to find the start of the frontmatter")
}
endIndex := strings.Index(fullPostAsString[startIndex+FrontmatterSeparatorLength:], "---")
if endIndex == -1 {
return nil, errors.New("failed to find the end of the frontmatter")
}
endIndex += startIndex + FrontmatterSeparatorLength
return []byte(fullPostAsString[startIndex:endIndex]), nil
}
func parseFrontmatterFromFullPostToMap(fullPost []byte) (map[string]any, error) {
frontmatterMap := make(map[string]any)
frontmatterContent, err := parseFrontmatter(fullPost)
if err != nil {
return nil, err
}
yamlErr := yaml.Unmarshal(frontmatterContent, &frontmatterMap)
if yamlErr != nil {
return nil, errors.Join(yamlErr)
}
return frontmatterMap, nil
}
func main() {
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}) //nolint:exhaustruct
filePath := flag.String("file", "", "File path")
verbose := flag.Bool("verbose", false, "Verbose output")
flag.Parse()
if *filePath == "" {
flag.Usage()
log.Fatal().Msg("Please provide a file path")
}
if *verbose {
log.Logger = log.Level(zerolog.DebugLevel)
} else {
log.Logger = log.Level(zerolog.InfoLevel)
}
refreshDateInPost(*filePath)
}
// refreshDateInPost updates the date in the frontmatter of a Hugo post.
//
// Expects frontmatter in YAML format and between `---` separators.
// The date is updated to the current date and time, so make sure you're not in
// the middle of editing the post when running this script.
// See https://gohugo.io/content-management/front-matter/ for more information.
func refreshDateInPost(hugoPostFilePath string) {
content, err := os.ReadFile(hugoPostFilePath)
if err != nil {
log.Fatal().Err(err).Msg("Failed to read file")
}
currentFrontmatter, err := parseFrontmatterFromFullPostToMap(content)
if err != nil {
log.Fatal().Err(err).Msg("Failed to parse frontmatter")
}
currentDate := currentFrontmatter["date"]
log.Debug().Any("Date", currentDate).Msg("Current frontmatter")
newDate := time.Now().Format(HugoTimeFormatAsGoFormat)
currentFrontmatter["date"] = newDate
log.Debug().Any("date", currentFrontmatter["date"]).Msg("After editing frontmatter")
oldDateTime, err := time.Parse(HugoTimeFormatAsGoFormat, currentDate.(string))
if err != nil {
log.Fatal().Err(err).Msg("Failed to parse old date")
}
newDateTime, err := time.Parse(HugoTimeFormatAsGoFormat, newDate)
if err != nil {
log.Fatal().Err(err).Msg("Failed to parse new date")
}
diff := newDateTime.Sub(oldDateTime)
log.Info().Str("diff", diff.String()).Msg("Refreshed by")
newFrontmatter, err := yaml.Marshal(currentFrontmatter)
if err != nil {
log.Fatal().Err(err).Msg("Failed to marshal frontmatter")
}
oldFrontmatter, err := parseFrontmatter(content)
if err != nil {
log.Error().Err(err).Msg("Failed to parse frontmatter")
os.Exit(1)
}
newContent := strings.Replace(string(content), string(oldFrontmatter), "---\n"+string(newFrontmatter), 1)
err = os.WriteFile(hugoPostFilePath, []byte(newContent), 0o644) //nolint:gosec,gomnd
if err != nil {
log.Error().Err(err).Msg("Failed to write to file")
os.Exit(1)
}
log.Info().Str("post", hugoPostFilePath).Msg("Successfully updated the date! 🎉")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment