A simple blog generator for your ~
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

142 lines
2.8 KiB

  1. package main
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "time"
  6. "strconv"
  7. "text/template"
  8. "os"
  9. "bufio"
  10. "regexp"
  11. "flag"
  12. "encoding/json"
  13. )
  14. const entriesPath = "./entries/"
  15. const templatesPath = "./templates/"
  16. const outputPath = "./html/"
  17. const defaultTemplateFile = "log"
  18. type Entry struct {
  19. Date string
  20. Body []byte
  21. }
  22. func loadEntry(rawDate string) (*Entry, error) {
  23. filename := entriesPath + rawDate
  24. body, err := ioutil.ReadFile(filename)
  25. if err != nil {
  26. return nil, err
  27. }
  28. // Get raw date parts for formatting
  29. year := rawDate[:4]
  30. month, moErr := strconv.Atoi(rawDate[4:6])
  31. if moErr != nil {
  32. return nil, moErr
  33. }
  34. date, dateErr := strconv.Atoi(rawDate[6:8])
  35. if dateErr != nil {
  36. return nil, dateErr
  37. }
  38. formattedDate := fmt.Sprintf("%d %s %s", date, time.Month(month).String(), year)
  39. return &Entry{Date: formattedDate, Body: body}, nil
  40. }
  41. func main() {
  42. fmt.Println()
  43. fmt.Println(" ~log generator v1.0")
  44. fmt.Println()
  45. // Get any arguments
  46. templateFilePtr := flag.String("template", defaultTemplateFile, "Tildelog template file (defined name).")
  47. flag.Parse()
  48. c := configuration()
  49. if c = nil {
  50. c := configure()
  51. }
  52. if c != nil {
  53. templateFilePtr = c.TemplateFile
  54. }
  55. entryFiles := getEntries()
  56. entries := make([]Entry, len(*entryFiles))
  57. i := 0
  58. for _, file := range *entryFiles {
  59. entry, err := loadEntry(file)
  60. if err != nil {
  61. fmt.Printf("Error, skipping entry %s: %s\n", file, err)
  62. continue
  63. }
  64. fmt.Printf("Adding entry %s...\n", file)
  65. entries[i] = *entry
  66. i++
  67. }
  68. fmt.Printf("Using template %s...\n", *templateFilePtr)
  69. generateLog(entries, *templateFilePtr)
  70. fmt.Printf("Finished! Saved to %slog.html\n", outputPath)
  71. }
  72. type Config struct {
  73. EntriesPath string
  74. TemplateFile string
  75. }
  76. func configuration() *Config {
  77. file, err := os.Open(os.Getenv("HOME") + "/.tildelog")
  78. if err != nil {
  79. return nil
  80. }
  81. d := json.NewDecoder(file)
  82. c := Config{}
  83. err = d.Decode(&c)
  84. if err != nil {
  85. fmt.Printf("Couldn't decode configuration: %s\n", err)
  86. }
  87. return &c
  88. }
  89. var validFileFormat = regexp.MustCompile("^[0-9]{8}$")
  90. func getEntries() *[]string {
  91. files, _ := ioutil.ReadDir(entriesPath)
  92. fileList := make([]string, len(files))
  93. fileCount := 0
  94. // Traverse file list in reverse, i.e. newest to oldest
  95. for i := len(files)-1; i >= 0; i-- {
  96. file := files[i]
  97. if validFileFormat.Match([]byte(file.Name())) {
  98. fileList[fileCount] = file.Name()
  99. fileCount++
  100. }
  101. }
  102. fileList = fileList[:fileCount]
  103. return &fileList
  104. }
  105. func generateLog(entries []Entry, templateFile string) {
  106. file, err := os.Create(outputPath + "log.html")
  107. if err != nil {
  108. panic(err)
  109. }
  110. defer file.Close()
  111. writer := bufio.NewWriter(file)
  112. template, err := template.ParseGlob(templatesPath + "*.html")
  113. if err != nil {
  114. panic(err)
  115. }
  116. template.ExecuteTemplate(writer, templateFile, entries)
  117. writer.Flush()
  118. }