my CMS/Blog engine
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.

tpldata.go 3.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. package main
  2. /*
  3. * This is freesofware under 2-clause BSD license, See LICENSE file
  4. * Copyright (c) 2013, Martin Angers
  5. */
  6. import (
  7. "bufio"
  8. _ "bytes"
  9. "fmt"
  10. "html/template"
  11. _ "os"
  12. "path/filepath"
  13. "regexp"
  14. "strings"
  15. "time"
  16. "github.com/russross/blackfriday"
  17. )
  18. var (
  19. ErrEmptyPost = fmt.Errorf("empty post file")
  20. ErrInvalidFrontMatter = fmt.Errorf("invalid front matter")
  21. ErrMissingFrontMatter = fmt.Errorf("missing front matter")
  22. bfExtensions = 0
  23. bfRender blackfriday.Renderer
  24. // Lookup table to find the format based on the length of the date in the front matter
  25. pubDtFmt = map[int]string{
  26. 10: "2006-01-02",
  27. 13: "2006-01-02 15h",
  28. 14: "2006-01-02 15h",
  29. 15: "2006-01-02 15:04",
  30. 16: "2006-01-02 15:04",
  31. 25: time.RFC3339,
  32. }
  33. )
  34. // The TemplateData structure contains all the relevant information passed to the
  35. // template to generate the static HTML file.
  36. type TemplateData map[string]string
  37. // Post data contains all the relevant information about a post (ie. meta data)
  38. // and also a TemplateData
  39. type PostData struct {
  40. PubTime time.Time
  41. ModTime time.Time
  42. Prev *PostData
  43. Next *PostData
  44. D TemplateData
  45. Content template.HTML
  46. }
  47. // Initialize a custom HTML render
  48. func initBF() {
  49. bfExtensions |= blackfriday.EXTENSION_NO_INTRA_EMPHASIS
  50. bfExtensions |= blackfriday.EXTENSION_TABLES
  51. bfExtensions |= blackfriday.EXTENSION_FENCED_CODE
  52. bfExtensions |= blackfriday.EXTENSION_AUTOLINK
  53. bfExtensions |= blackfriday.EXTENSION_STRIKETHROUGH
  54. bfExtensions |= blackfriday.EXTENSION_SPACE_HEADERS
  55. htmlFlags := 0
  56. htmlFlags |= blackfriday.HTML_USE_XHTML
  57. htmlFlags |= blackfriday.HTML_USE_SMARTYPANTS
  58. htmlFlags |= blackfriday.HTML_SMARTYPANTS_FRACTIONS
  59. bfRender = blackfriday.HtmlRenderer(htmlFlags, "", "")
  60. }
  61. // All Posts readed, ready to be generated, make site Index (inter-link) here
  62. // `all` is an ordered array of all posts to generate
  63. // return the index post
  64. func siteIndex(all []*PostData) (index int) {
  65. index = 0
  66. l := len(all)
  67. for i := l - 1; i >= 0; i-- {
  68. if i > 0 {
  69. all[i].Prev = all[i-1]
  70. }
  71. if i < l-1 {
  72. all[i].Next = all[i+1]
  73. }
  74. if _, ex := all[i].D["IndexPage"]; ex {
  75. index = i
  76. }
  77. }
  78. return
  79. }
  80. // Replace special characters to form a valid slug (post path)
  81. var rxSlug = regexp.MustCompile(`[^a-zA-Z\-_0-9]`)
  82. // Return a valid slug from the file name of the post.
  83. func getSlug(fnm string) string {
  84. return rxSlug.ReplaceAllString(strings.Replace(fnm, filepath.Ext(fnm), "", 1), "-")
  85. }
  86. // Read the front matter from the post. If there is no front matter, this is
  87. // not a valid post.
  88. func readFrontMatter(s *bufio.Scanner) (TemplateData, error) {
  89. // make a clone of SiteData
  90. m := make(TemplateData)
  91. for k, v := range SiteMeta.meta {
  92. m[k] = v
  93. }
  94. // defaut template name if not specified
  95. m["Template"] = "default"
  96. // scan the front matter
  97. infm := false
  98. for s.Scan() {
  99. l := strings.Trim(s.Text(), " ")
  100. if l == "---" { // The front matter is delimited by 3 dashes
  101. if infm {
  102. // This signals the end of the front matter
  103. return m, nil
  104. } else {
  105. // This is the start of the front matter
  106. infm = true
  107. }
  108. } else if infm {
  109. sections := strings.SplitN(l, ":", 2)
  110. if len(sections) != 2 {
  111. // Invalid front matter line
  112. return nil, ErrInvalidFrontMatter
  113. }
  114. m[sections[0]] = strings.Trim(sections[1], " ")
  115. } else if l != "" {
  116. // No front matter, quit
  117. return nil, ErrMissingFrontMatter
  118. }
  119. }
  120. if err := s.Err(); err != nil {
  121. return nil, err
  122. }
  123. return nil, ErrEmptyPost
  124. }