Created
April 27, 2024 09:16
-
-
Save TheCoreMan/fa528341dbff05d0fc37f4837fabb959 to your computer and use it in GitHub Desktop.
A short go script to refresh your Hugo post dates.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // 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