main.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. package main
  2. import (
  3. "html/template"
  4. "os"
  5. "os/exec"
  6. "path/filepath"
  7. "runtime/pprof"
  8. "strconv"
  9. "strings"
  10. "time"
  11. "github.com/cdelorme/go-log"
  12. "github.com/cdelorme/go-maps"
  13. "github.com/cdelorme/go-option"
  14. )
  15. // check that a path exists
  16. // does not care if it is a directory
  17. // will not say whether user has rw access, but
  18. // will throw an error if the user cannot read the parent directory
  19. func exists(path string) (bool, error) {
  20. _, err := os.Stat(path)
  21. if err == nil {
  22. return true, nil
  23. }
  24. if os.IsNotExist(err) {
  25. return false, nil
  26. }
  27. return false, err
  28. }
  29. // if within a git repo, gets git version as a short-hash
  30. // otherwise falls back to a unix timestamp
  31. func version() string {
  32. version := strconv.FormatInt(time.Now().Unix(), 10)
  33. out, err := exec.Command("sh", "-c", "git rev-parse --short HEAD").Output()
  34. if err == nil {
  35. version = strings.Trim(string(out), "\n")
  36. }
  37. return version
  38. }
  39. // remove the path and extension from a given filename
  40. func basename(name string) string {
  41. return filepath.Base(strings.TrimSuffix(name, filepath.Ext(name)))
  42. }
  43. func main() {
  44. // get current directory
  45. cwd, _ := os.Getwd()
  46. // prepare staticmd with dependencies & defaults
  47. staticmd := Staticmd{
  48. Logger: log.Logger{},
  49. Version: version(),
  50. Input: cwd,
  51. Output: filepath.Join(cwd, "public/"),
  52. }
  53. // prepare cli options
  54. appOptions := option.App{Description: "command line tool for generating deliverable static content"}
  55. appOptions.Flag("template", "path to the template file", "--template", "-t")
  56. appOptions.Flag("input", "path to the markdown files", "--input", "-i")
  57. appOptions.Flag("output", "path to place generated content", "--output", "-o")
  58. appOptions.Flag("book", "combine all content into a single file", "--book", "-b")
  59. appOptions.Flag("relative", "use relative paths instead of absolute paths", "--relative", "-r")
  60. appOptions.Flag("profile", "produce profile output to supplied path", "--profile", "-p")
  61. appOptions.Example("-t template.tmpl -i . -b")
  62. appOptions.Example("-t template.tmpl -i src/ -o out/ -r")
  63. flags := appOptions.Parse()
  64. // apply flags
  65. t, _ := maps.String(flags, "", "template")
  66. if tmpl, err := template.ParseFiles(t); err != nil {
  67. staticmd.Logger.Error("Failed to open template: %s", err)
  68. os.Exit(1)
  69. } else {
  70. staticmd.Template = *tmpl
  71. }
  72. staticmd.Input, _ = maps.String(flags, staticmd.Input, "input")
  73. staticmd.Output, _ = maps.String(flags, staticmd.Output, "output")
  74. staticmd.Book, _ = maps.Bool(flags, staticmd.Book, "book")
  75. staticmd.Relative, _ = maps.Bool(flags, staticmd.Relative, "relative")
  76. // sanitize input & output
  77. staticmd.Input, _ = filepath.Abs(staticmd.Input)
  78. staticmd.Output, _ = filepath.Abs(staticmd.Output)
  79. // optionally enable profiling
  80. if profile, _ := maps.String(flags, "", "profile"); profile != "" {
  81. f, _ := os.Create(profile)
  82. pprof.StartCPUProfile(f)
  83. defer pprof.StopCPUProfile()
  84. }
  85. // sanitize & validate properties
  86. staticmd.Input = filepath.Clean(staticmd.Input)
  87. staticmd.Output = filepath.Clean(staticmd.Output)
  88. // print debug status
  89. staticmd.Logger.Debug("Staticmd State: %+v", staticmd)
  90. // walk the file system
  91. if err := filepath.Walk(staticmd.Input, staticmd.Walk); err != nil {
  92. staticmd.Logger.Error("failed to walk directory: %s", err)
  93. }
  94. staticmd.Logger.Debug("Pages: %+v", staticmd.Pages)
  95. // build
  96. if staticmd.Book {
  97. staticmd.Single()
  98. } else {
  99. staticmd.Multi()
  100. }
  101. }