My personal website https://jonathanh.co.uk
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.
 
 
 
 
 
 

202 lines
6.4 KiB

  1. #!/usr/bin/env bash
  2. getBlogSlug(){
  3. echo "$1" | sed 's/^content\//\//' | sed 's/.md$/.html/' | sed -E 's/[0-9]+-//'
  4. }
  5. blog(){
  6. echo "Generating Blog pages"
  7. [ ! -f "tmp/templates/tagList.html" ] && echo "No taglist file" | tee "tmp/templates/tagList.html" > /dev/stderr
  8. local newer=""
  9. [ -f tmp/lastBlogUpdate ] && newer="-newer tmp/lastBlogUpdate"
  10. find content/ -type f -name '*.md' $newer | while read file; do
  11. newFileName=$(getBlogSlug "$file")
  12. mkdir -p "public_html/${newFileName%/*}"
  13. pandoc --template=templates/blog.html -f markdown -t html5 "$file" > "public_html/$newFileName"
  14. done
  15. touch tmp/lastBlogUpdate
  16. }
  17. makeIntro(){
  18. local file="$1"
  19. local output="tmp/intros/$file"
  20. local rssoutput="tmp/rss/$file"
  21. # We delete tmp each time the build script runs, so if the file exists, we have already generated one this time
  22. [ -f "$output" ] && return 1
  23. mkdir -p "${output%/*}"
  24. mkdir -p "${rssoutput%/*}"
  25. local info="$(sed -n '/---/,/---/p' "$file" | sed '/^$/,$d' | sed -n '1,/---/p' | sed '/^---$/d')"
  26. local slug=$(getBlogSlug "$file")
  27. local date="$(echo "$info" | yq -r .date)"
  28. local rfc822="$(date --utc -d "$date" "+%a, %d %b %Y %H:%M:%S") UT"
  29. local tags="$(echo "$info" | yq -r 'if ( .tags | type ) == "array" then .tags else [ .tags ] end | join("\n")' | awk '{print "<li>" $0 "</li>"}' )"
  30. local title="$(echo "$info" | yq -r .title)"
  31. local description="$(echo "$info" | yq -r .description)"
  32. echo "<article>
  33. <h2><a href='$slug'>$title</a></h2>
  34. <div class="article-details">
  35. <div class="date">
  36. $date
  37. </div>
  38. </div>
  39. <p>$description</p>
  40. <p><a href='$slug'>Read More</a></p>
  41. </article>" > "$output"
  42. echo "<item>
  43. <title>
  44. <![CDATA[$title]]></title>
  45. <link>https://jonathanh.co.uk/$slug</link>
  46. <guid isPermaLink=\"true\">https://jonathanh.co.uk/$slug</guid>
  47. <pubDate>$rfc822</pubDate>
  48. <description><![CDATA[$description]]></description>
  49. </item>" > "$rssoutput"
  50. }
  51. getIntro(){
  52. local file="$1"
  53. local output="tmp/intros/$file"
  54. if [ "$2" = "rss" ]; then
  55. local output="tmp/rss/$file"
  56. fi
  57. makeIntro "$file"
  58. cat "$output"
  59. }
  60. index(){
  61. echo "Generating Home Page"
  62. [ ! -f "tmp/templates/tagList.html" ] && echo "No taglist file" | tee "tmp/templates/tagList.html" > /dev/stderr
  63. local template="$(echo "" | pandoc --template=templates/blog.html -f markdown -t html5 -M frontpage 2> /dev/null )"
  64. # First loop makes all the intros needed and stores them in tmp/intros
  65. find content/blog/ -type f -name '*.md' | grep -v 'xxx' | sort -r | head -n 20 | while read file; do
  66. makeIntro "$file" &
  67. done
  68. wait
  69. # Once they are created, we will put them in, in order
  70. (
  71. echo "$template" | sed -n '1,/#CONTENT#/p' | head -n -1
  72. find content/blog/ -type f -name '*.md' | grep -v 'xxx' | sort -r | head -n 20 | while read file; do
  73. grep -Eq '^draft: true' "$file" || getIntro "$file"
  74. done
  75. echo "$template" | sed -n '/#CONTENT#/,$p' | sed '1d'
  76. ) > public_html/index.html
  77. }
  78. tagIndex(){
  79. local tag="$1"
  80. local title="$(basename "$tag")"
  81. [ ! -f "tmp/templates/tagList.html" ] && echo "No taglist file" | tee "tmp/templates/tagList.html" > /dev/stderr
  82. local template="$(echo "" | pandoc --template=templates/blog.html -f markdown -t html5 -M archive -M title:"$title Archive" 2> /dev/null )"
  83. cat "$1" | grep -v 'xxx' | sort -r | while read file; do
  84. makeIntro "$file" &
  85. done
  86. wait
  87. echo "$template" | sed -n '1,/#CONTENT#/p' | head -n -1
  88. cat "$1" | sort -r | while read file; do
  89. getIntro "$file"
  90. done
  91. echo "$template" | sed -n '/#CONTENT#/,$p' | sed '1d'
  92. }
  93. html_tag_list(){
  94. if [ -d "tmp/tag" ]; then
  95. echo "<ul class='taglist'>"
  96. wc -l tmp/tag/* | head -n -1 | sort -nr | while read line; do
  97. local link=$(echo "$line" | awk '{print $2 ".html"}' | sed 's/^tmp//' | tr '[A-Z]' '[a-z]' | tr ' ' '-')
  98. local name=$(echo "$line" | sed 's/tmp\/tag\///' | awk '{print $2 " (" $1 ")"}' | tr '_' ' ')
  99. echo "<li><a href='$link'>$name</a></li>"
  100. done
  101. echo "</ul>"
  102. else
  103. echo "Need to generate the taglist" > /dev/stderr
  104. fi
  105. }
  106. tags(){
  107. echo "Generating Tags"
  108. # Loops through each blog and puts it in tag lists, although only blogs that have changed
  109. local newer=""
  110. [ -f tmp/lastTagUpdate ] && newer="-newer tmp/lastTagUpdate"
  111. find content/blog/ -type f -name '*.md' -not -name 'xxx-*' $newer | while read file; do
  112. sed -n '/---/,/---/p' "$file" | sed -n '1,/---/p' | sed '/^---$/d' | sed '/^$/,$d' | yq -r 'if ( .tags | type ) == "array" then .tags else [ .tags ] end | join("\n")' | while read tag; do
  113. tag=$(echo "$tag" | tr ' ' '_')
  114. # Adds the file to the tags list if it's not already in there
  115. grep -q "$file" tmp/tag/"$tag" 2> /dev/null || echo "$file" >> tmp/tag/"$tag"
  116. done
  117. done
  118. echo "Generating Taglist HTML"
  119. html_tag_list > tmp/templates/tagList.html
  120. # We should now have a folder with a text file for each tag containing each blog
  121. echo "Generating Tag Index Pages"
  122. find tmp/tag/ -type f $newer | while read tag; do
  123. filename="$(echo $tag | sed 's/^tmp//' | tr '[A-Z]' '[a-z]').html"
  124. tagIndex "$tag" > "public_html/$filename"
  125. done
  126. touch tmp/lastTagUpdate
  127. }
  128. card(){
  129. echo "Generating Card"
  130. content/card.curl > public_html/card
  131. }
  132. rss(){
  133. echo "Generating RSS Feed"
  134. lastUpdate="$(date --utc "+%a, %d %b %Y %H:%M:%S") UT"
  135. # First loop makes all the intros needed and stores them in tmp/intros
  136. find content/blog/ -type f -name '*.md' | grep -v 'xxx' | sort -r | head -n 20 | while read file; do
  137. makeIntro "$file" &
  138. done
  139. wait
  140. (
  141. echo "<?xml version='1.0' encoding='UTF-8' ?>
  142. <rss xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:content=\"http://purl.org/rss/1.0/modules/content/\" xmlns:atom=\"http://www.w3.org/2005/Atom\" version=\"2.0\">
  143. <channel>
  144. <title><![CDATA[Jonathan Hodgson]]></title>
  145. <description><![CDATA[Jonathan Hodgson's Blog]]></description>
  146. <link>https://jonathanh.co.uk</link>
  147. <lastBuildDate>$lastUpdate</lastBuildDate>"
  148. find content/blog/ -type f -name '*.md' | grep -v 'xxx' | sort -r | head -n 20 | while read file; do
  149. grep -Eq '^draft: true' "$file" || getIntro "$file" rss
  150. done
  151. echo "</channel></rss>";
  152. ) > public_html/feed.rss
  153. }
  154. clean(){
  155. rm -rf tmp > /dev/null 2> /dev/null
  156. # Don't remove the public_html folder or docker won't re-attach it
  157. rm -rf public_html/*
  158. }
  159. # Make sure the folders we will need exist
  160. mkdir -p public_html/{blog,tag}
  161. mkdir -p tmp/{tag,templates,intros}
  162. case "$1" in
  163. clean) clean ;;
  164. index) index ;;
  165. blog) blog ;;
  166. tags) tags ;;
  167. card) card ;;
  168. rss) rss ;;
  169. all) tags && blog && index && rss && card ;;
  170. esac