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.

270 lines
13KB

  1. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
  2. <!-- Created by htmlize-1.56 in css mode. -->
  3. <html>
  4. <head>
  5. <title>generate-blog.bash</title>
  6. <style type="text/css">
  7. <!--
  8. body {
  9. color: #f6f3e8;
  10. background-color: #242424;
  11. }
  12. .builtin {
  13. /* font-lock-builtin-face */
  14. color: #e5786d;
  15. }
  16. .comment {
  17. /* font-lock-comment-face */
  18. color: #99968b;
  19. }
  20. .comment-delimiter {
  21. /* font-lock-comment-delimiter-face */
  22. color: #99968b;
  23. }
  24. .function-name {
  25. /* font-lock-function-name-face */
  26. color: #cae682;
  27. }
  28. .keyword {
  29. /* font-lock-keyword-face */
  30. color: #8ac6f2;
  31. font-weight: bold;
  32. }
  33. .negation-char {
  34. }
  35. .sh-heredoc {
  36. /* sh-heredoc */
  37. color: #ffff00;
  38. font-weight: bold;
  39. }
  40. .sh-quoted-exec {
  41. /* sh-quoted-exec */
  42. color: #fa8072;
  43. }
  44. .string {
  45. /* font-lock-string-face */
  46. color: #95e454;
  47. }
  48. .variable-name {
  49. /* font-lock-variable-name-face */
  50. color: #cae682;
  51. }
  52. a {
  53. color: inherit;
  54. background-color: inherit;
  55. font: inherit;
  56. text-decoration: inherit;
  57. }
  58. a:hover {
  59. text-decoration: underline;
  60. }
  61. -->
  62. </style>
  63. </head>
  64. <body>
  65. <pre>
  66. <span class="comment-delimiter">#</span><span class="comment">!/bin/</span><span class="keyword">bash</span><span class="comment">
  67. </span><span class="comment-delimiter">##</span><span class="comment">
  68. </span><span class="comment-delimiter"># </span><span class="comment">Generate html page with blog article excerpts from ./posts.txt. Post file names should
  69. </span><span class="comment-delimiter"># </span><span class="comment">be added to ./posts.txt in the exact order that they are supposed to appear on the blog
  70. </span><span class="comment-delimiter"># </span><span class="comment">page.
  71. </span>
  72. <span class="comment-delimiter"># </span><span class="comment">Check if required executables can be found
  73. </span><span class="keyword">if ! </span><span class="builtin">type</span> readlink dirname html2text mv cat cksum base64; <span class="keyword">then</span>
  74. <span class="builtin">echo</span> <span class="string">'One or more required executables are not present. Generation cancelled'</span> &gt;&amp;2
  75. <span class="keyword">exit</span> 1
  76. <span class="keyword">fi</span>
  77. <span class="comment-delimiter"># </span><span class="comment">Determine script directory (requires GNU readlink)
  78. </span><span class="variable-name">here</span>=<span class="string">"$(</span><span class="sh-quoted-exec">dirname</span><span class="string"> "$(</span><span class="sh-quoted-exec">readlink</span><span class="string"> -f "${BASH_SOURCE[0]}")")"</span>
  79. <span class="builtin">printf</span> <span class="string">'Changing directory: '</span>
  80. <span class="builtin">pushd</span> <span class="string">"$here"</span> || <span class="keyword">exit</span> $<span class="variable-name">?</span>
  81. <span class="variable-name">posts_file</span>=<span class="string">"$here/posts.txt"</span>
  82. <span class="keyword">if</span> <span class="negation-char">!</span> [[ -f <span class="string">"$posts_file"</span> ]]; <span class="keyword">then</span>
  83. <span class="builtin">printf</span> <span class="string">'Posts file "%s" not found. Generation cancelled.\n'</span> <span class="string">"$posts_file"</span> &gt;&amp;2
  84. <span class="keyword">exit</span> 1
  85. <span class="keyword">fi</span>
  86. <span class="function-name">escape-html</span>() {
  87. sed <span class="string">'s/&amp;/\&amp;amp;/g; s/&lt;/\&amp;lt;/g; s/&gt;/\&amp;gt;/g; s/"/\&amp;quot;/g; s/'"'"'/\&amp;#39;/g'</span>
  88. }
  89. <span class="function-name">html-to-text</span>() {
  90. html2text -nobs -style compact <span class="string">"$@"</span>
  91. }
  92. <span class="function-name">print-blog-html-top</span>() {
  93. <span class="builtin">echo</span> <span class="string">'&lt;html&gt;
  94. &lt;head&gt;
  95. &lt;title&gt;Blog&lt;/title&gt;
  96. &lt;meta charset="UTF-8"&gt;
  97. &lt;/head&gt;
  98. &lt;style type="text/css"&gt;
  99. html {
  100. font-family: Helvetica, Arial, sans-serif;
  101. color: #5b4636;
  102. background-color: #f4ecd8;
  103. }
  104. body {
  105. padding: 1em;
  106. margin: auto;
  107. }
  108. @media only all and (pointer: coarse), (pointer: none) {
  109. body {
  110. font-size: 5.5vmin;
  111. }
  112. }
  113. @media only all and (pointer: fine) {
  114. body {
  115. font-size: calc(16px + 0.6vmin);
  116. min-width: 500px;
  117. max-width: 50em;
  118. }
  119. }
  120. &lt;/style&gt;
  121. &lt;body&gt;
  122. &lt;div style="display: flex; flex-direction: horizontal;"&gt;
  123. &lt;a href="index.html"&gt;Home&lt;/a&gt;
  124. &lt;span style="margin-left: 1em; margin-right: 1em;"&gt;|&lt;/span&gt;
  125. &lt;a href="feed.xml"&gt;RSS Feed&lt;/a&gt;
  126. &lt;/div&gt;
  127. &lt;h1&gt;Blog&lt;/h1&gt;
  128. '</span>
  129. }
  130. <span class="function-name">print-blog-html-bottom</span>() {
  131. <span class="builtin">echo</span> <span class="string">' &lt;/body&gt;
  132. &lt;/html&gt;'</span>
  133. }
  134. <span class="comment-delimiter"># </span><span class="comment">Note: pubDate and lastBuildDate are both set to the current time.
  135. </span><span class="function-name">print-blog-rss-top</span>() {
  136. cat &lt;&lt;EOF<span class="sh-heredoc">
  137. &lt;?xml version="1.0"?&gt;
  138. &lt;rss version="2.0"&gt;
  139. &lt;channel&gt;
  140. &lt;title&gt;Hugot Blog&lt;/title&gt;
  141. &lt;link&gt;https://hugot.nl/blog.html&lt;/link&gt;
  142. &lt;description&gt;Hugo's personal blog&lt;/description&gt;
  143. &lt;language&gt;en-us&lt;/language&gt;
  144. &lt;pubDate&gt;$(</span><span class="sh-quoted-exec">date</span><span class="sh-heredoc">)&lt;/pubDate&gt;
  145. &lt;lastBuildDate&gt;$(</span><span class="sh-quoted-exec">date</span><span class="sh-heredoc">)&lt;/lastBuildDate&gt;
  146. &lt;docs&gt;http://blogs.law.harvard.edu/tech/rss&lt;/docs&gt;
  147. &lt;generator&gt;Hugo's Custom Bash Script&lt;/generator&gt;
  148. &lt;managingEditor&gt;social@hugot.nl&lt;/managingEditor&gt;
  149. &lt;webMaster&gt;infra@hugot.nl&lt;/webMaster&gt;
  150. EOF
  151. </span>}
  152. <span class="function-name">print-blog-rss-bottom</span>() {
  153. <span class="builtin">echo</span> <span class="string">'&lt;/channel&gt;
  154. &lt;/rss&gt;'</span>
  155. }
  156. <span class="function-name">el</span>() {
  157. <span class="variable-name">format_string</span>=<span class="string">"$1"</span>
  158. <span class="builtin">shift</span>
  159. <span class="builtin">printf</span> <span class="string">"&lt;$format_string&gt;"</span> <span class="string">"$@"</span>
  160. }
  161. <span class="function-name">el-close</span>() {
  162. <span class="builtin">echo</span> <span class="string">"&lt;/$1&gt;"</span>
  163. }
  164. <span class="function-name">el-enclose</span>() {
  165. <span class="variable-name">element_name</span>=<span class="string">"$1"</span>
  166. <span class="builtin">shift</span>
  167. <span class="builtin">printf</span> <span class="string">'%s'</span> <span class="string">"&lt;$element_name&gt;"</span>
  168. <span class="builtin">printf</span> <span class="string">'%s'</span> <span class="string">"$@"</span>
  169. <span class="builtin">printf</span> <span class="string">'%s'</span> <span class="string">"&lt;/$element_name&gt;"</span>
  170. }
  171. <span class="variable-name">site_url</span>=<span class="string">"https://hugot.nl"</span>
  172. <span class="variable-name">blog_html</span>=<span class="string">"$here/blog.html"</span>
  173. <span class="variable-name">new_html</span>=<span class="string">"$blog_html.new"</span>
  174. <span class="variable-name">blog_rss</span>=<span class="string">"$here/feed.xml"</span>
  175. <span class="variable-name">new_rss</span>=<span class="string">"$blog_rss.new"</span>
  176. print-blog-html-top &gt; <span class="string">"$new_html"</span>
  177. print-blog-rss-top &gt; <span class="string">"$new_rss"</span>
  178. <span class="keyword">while </span><span class="builtin">read</span> -r post_html; <span class="keyword">do</span>
  179. <span class="comment-delimiter"># </span><span class="comment">Convert the post's html to text to make it easier to use the blog's text
  180. </span> <span class="variable-name">text</span>=<span class="string">"$(</span><span class="sh-quoted-exec">html-to-text</span><span class="string"> "$post_html" | escape-html)"</span> || <span class="keyword">exit</span> $<span class="variable-name">?</span>
  181. <span class="comment-delimiter"># </span><span class="comment">The title should be on the 2nd line of text, right after the link to the
  182. </span> <span class="comment-delimiter"># </span><span class="comment">homepage. This is a bit inflexible but it will do for now.
  183. </span> <span class="variable-name">title</span>=<span class="string">"$(</span><span class="sh-quoted-exec">tail</span><span class="string"> -n +2 &lt;&lt;&lt;"$text" | head -n 1 | tr -d '*')"</span> || <span class="keyword">exit</span> $<span class="variable-name">?</span>
  184. <span class="comment-delimiter"># </span><span class="comment">Use the first 5 lines after the title as post excerpt.
  185. </span> <span class="variable-name">excerpt</span>=<span class="string">"$(</span><span class="sh-quoted-exec">tail</span><span class="string"> -n +3 &lt;&lt;&lt;"$text" | head -n 5)"</span> || <span class="keyword">exit</span> $<span class="variable-name">?</span>
  186. <span class="comment-delimiter"># </span><span class="comment">Escape the post html file name to safely use it in the generated html.
  187. </span> <span class="variable-name">href</span>=<span class="string">"$(</span><span class="sh-quoted-exec">escape-html</span><span class="string"> &lt;&lt;&lt;"$post_html")"</span> || <span class="keyword">exit</span> $<span class="variable-name">?</span>
  188. <span class="variable-name">post_dir</span>=<span class="string">"$(</span><span class="sh-quoted-exec">dirname</span><span class="string"> "$post_html")"</span> || <span class="keyword">exit</span> $<span class="variable-name">?</span>
  189. <span class="variable-name">pubdate_file</span>=<span class="string">"$post_dir/publish_date.txt"</span>
  190. <span class="comment-delimiter"># </span><span class="comment">Determine a publishing date for the post
  191. </span> <span class="keyword">if</span> [[ -f <span class="string">"$pubdate_file"</span> ]]; <span class="keyword">then</span>
  192. <span class="builtin">read</span> -r pubdate &lt; <span class="string">"$pubdate_file"</span>
  193. <span class="keyword">else</span>
  194. <span class="variable-name">pubdate</span>=<span class="string">"$(</span><span class="sh-quoted-exec">date</span><span class="string">)"</span>
  195. <span class="builtin">echo</span> <span class="string">"$pubdate"</span> &gt; <span class="string">"$pubdate_file"</span>
  196. <span class="keyword">fi</span>
  197. {
  198. el div
  199. el <span class="string">'a href="%s"'</span> <span class="string">"$href"</span>
  200. <span class="builtin">printf</span> <span class="string">'&lt;h2 style="margin-bottom: 0.1em;"&gt;%s&lt;/h2&gt;'</span> <span class="string">"$title"</span>
  201. el-close a
  202. <span class="builtin">printf</span> <span class="string">'&lt;i style="font-size: 0.8em;"&gt;%s&lt;/i&gt;'</span> <span class="string">"$pubdate"</span>
  203. el <span class="string">'p style="margin-top: 0.5em;"'</span>
  204. <span class="builtin">printf</span> <span class="string">'%s ... &lt;a href="%s"&gt;Continue reading&lt;/a&gt;'</span> <span class="string">"$excerpt"</span> <span class="string">"$href"</span>
  205. el-close p
  206. el-close div
  207. el hr
  208. } &gt;&gt; <span class="string">"$new_html"</span>
  209. {
  210. el item
  211. el-enclose title <span class="string">"$title"</span>
  212. el-enclose link <span class="string">"$site_url/$href"</span>
  213. el-enclose description <span class="string">"$excerpt"</span>
  214. el-enclose pubDate <span class="string">"$pubdate"</span>
  215. <span class="builtin">echo</span> <span class="string">"&lt;guid isPermaLink=\"false\"&gt;$title$(</span><span class="sh-quoted-exec">base64</span><span class="string"> &lt;(cksum &lt;&lt;&lt;"$text"))&lt;/guid&gt;"</span>
  216. el-close item
  217. } &gt;&gt; <span class="string">"$new_rss"</span>
  218. <span class="keyword"> done</span> &lt; <span class="string">"$posts_file"</span>
  219. print-blog-html-bottom &gt;&gt; <span class="string">"$new_html"</span>
  220. print-blog-rss-bottom &gt;&gt; <span class="string">"$new_rss"</span>
  221. mv -v <span class="string">"$new_html"</span> <span class="string">"$blog_html"</span> || <span class="keyword">exit</span> $<span class="variable-name">?</span>
  222. mv -v <span class="string">"$new_rss"</span> <span class="string">"$blog_rss"</span> || <span class="keyword">exit</span> $<span class="variable-name">?</span>
  223. <span class="builtin"> echo</span> <span class="string">'SUCCESS!'</span>
  224. </pre>
  225. </body>
  226. </html>