haunt.scm 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. ;;; 8sync's website
  2. ;;; Copyright © 2016 Christopher Allan Webber <cwebber@dustycloud.org>
  3. ;;;
  4. ;;; This program is free software: you can redistribute it and/or modify
  5. ;;; it under the terms of the GNU General Public License as published by
  6. ;;; the Free Software Foundation, either version 3 of the License, or
  7. ;;; (at your option) any later version.
  8. ;;;
  9. ;;; This program is distributed in the hope that it will be useful,
  10. ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. ;;; GNU General Public License for more details.
  13. ;;;
  14. ;;; You should have received a copy of the GNU General Public License
  15. ;;; along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. (use-modules (ice-9 match)
  17. (haunt asset)
  18. (haunt html)
  19. (haunt site)
  20. (haunt page)
  21. (haunt post)
  22. (haunt builder blog)
  23. (haunt builder atom)
  24. (haunt builder assets)
  25. (haunt reader)
  26. (haunt reader skribe)
  27. (syntax-highlight)
  28. (syntax-highlight scheme))
  29. ;;; Utilities
  30. ;;; ---------
  31. (define %site-prefix (make-parameter ""))
  32. (define (prefix-url url)
  33. (string-append (%site-prefix) url))
  34. ;;; Latest release info
  35. ;;; -------------------
  36. (define latest-version "0.1.0")
  37. (define main-download-url "ftp://ftp.gnu.org/gnu/8sync/")
  38. (define latest-filename
  39. (string-append "8sync-"
  40. latest-version
  41. ".tar.gz"))
  42. (define latest-release-url
  43. (string-append main-download-url
  44. latest-filename))
  45. (define latest-release-sig-url
  46. (string-append latest-release-url
  47. ".sig"))
  48. ;;; Templates
  49. ;;; ---------
  50. (define (stylesheet name)
  51. `(link (@ (rel "stylesheet")
  52. (href ,(prefix-url (string-append "/css/" name ".css"))))))
  53. (define (base-image image alt)
  54. `(img (@ (src ,(prefix-url (string-append "/images/" image)))
  55. (alt ,alt))))
  56. (define header-menu
  57. '(("docs" "/docs/")
  58. ("download" "/download/")
  59. ("community" "/community/")
  60. ("news" "/news/")))
  61. (define* (base-layout site body
  62. #:key title big-logo)
  63. `((doctype "html")
  64. (head
  65. (meta (@ (charset "utf-8")))
  66. (title ,(if title
  67. (string-append title " -- 8sync")
  68. (site-title site)))
  69. ;; css
  70. (link (@ (rel "stylesheet")
  71. (href ,(prefix-url "/css/main.css"))))
  72. (link (@ (rel "stylesheet")
  73. (href ,(prefix-url "/css/code.css"))))
  74. ;; atom feed
  75. (link (@ (rel "alternate")
  76. (title "8sync news")
  77. (type "application/atom+xml")
  78. (href ,(prefix-url "/feed.xml")))))
  79. (body
  80. (div (@ (class "main-wrapper"))
  81. (header (@ (id "site-header"))
  82. ;; 8sync logo
  83. (div (@ (class "header-logo-wrapper"))
  84. (a (@ (href ,(prefix-url "/"))
  85. (class "8sync-header-logo"))
  86. ,(base-image ;; "8sync-logo-header.png"
  87. (if big-logo
  88. "8sync-logo-500px.png"
  89. "8sync-logo-300px.png")
  90. "8sync logo")))
  91. ;; Header menu
  92. (div (@ ,(if big-logo
  93. '(class "navbar-menu big-navbar")
  94. '(class "navbar-menu small-navbar")))
  95. ,@(map
  96. (lambda (item)
  97. (match item
  98. ((name url)
  99. `(div
  100. (a (@ (href ,(prefix-url url)))
  101. ,name)))))
  102. header-menu)))
  103. (div (@ (class "site-main-content"))
  104. ,body))
  105. ;; TODO: Link to source.
  106. (div (@ (class "footer"))
  107. (a (@ (href "https://notabug.org/cwebber/8sync-website"))
  108. "Site contents")
  109. " dual licensed under "
  110. (a (@ (href "https://creativecommons.org/licenses/by-sa/4.0/"))
  111. "Creative Commons 4.0 International")
  112. " and "
  113. (a (@ (href "http://www.gnu.org/licenses/gpl-3.0.en.html"))
  114. "the GNU GPL, version 3 or any later version")
  115. ". Powered by "
  116. (a (@ (href "http://haunt.dthompson.us/"))
  117. "Haunt")
  118. "."))))
  119. (define* (post-template post #:key post-link)
  120. `(div (@ (class "content-box blogpost"))
  121. (h1 (@ (class "title"))
  122. ,(if post-link
  123. `(a (@ (href ,post-link))
  124. ,(post-ref post 'title))
  125. (post-ref post 'title)))
  126. (div (@ (class "post-about"))
  127. (span (@ (class "by-line"))
  128. ,(post-ref post 'author))
  129. " -- " ,(date->string* (post-date post)))
  130. (div (@ (class "post-body"))
  131. ,(post-sxml post))))
  132. (define (collection-template site title posts prefix)
  133. ;; In our case, we ignore the prefix argument because
  134. ;; the filename generated and the pathname might not be the same.
  135. ;; So we use (prefix-url) instead.
  136. (define (post-uri post)
  137. (prefix-url
  138. (string-append "/news/" (site-post-slug site post) ".html")))
  139. `((div (@ (class "news-header"))
  140. (h3 "recent news"))
  141. (div (@ (class "post-list"))
  142. ,@(map
  143. (lambda (post)
  144. (post-template post
  145. #:post-link (post-uri post)))
  146. posts))))
  147. (define 8sync-haunt-theme
  148. (theme #:name "8sync"
  149. #:layout
  150. (lambda (site title body)
  151. (base-layout
  152. site body
  153. #:title title
  154. #:big-logo #f))
  155. #:post-template post-template
  156. #:collection-template collection-template))
  157. ;;; Plain content pages
  158. ;;; -------------------
  159. (define code-snippet
  160. (string-join
  161. '("(define (site-user-view request db-conn)"
  162. " \"Display a list of all users registered on this site\""
  163. " (htmlize-response"
  164. " (list-users-template"
  165. " #:request request"
  166. " ;; Wrapping in 8sync \"suspends\" this function, running"
  167. " ;; fetch-active-users asynchronously, and \"wakes up\" the function"
  168. " ;; when ready, seamlessly passing back its result."
  169. " #:users (8sync"
  170. " (fetch-active-users db-conn)))")
  171. "\n"))
  172. (define (index-content posts)
  173. `(div
  174. ;; Main intro
  175. (div (@ (class "content-box bigger-text"))
  176. (h2 (@ (class "title"))
  177. "What's 8sync?")
  178. (p "8sync (pronounced \"eight-sync\") is an asynchronous "
  179. "programming library for "
  180. (a (@ (href "http://www.gnu.org/software/guile/"))
  181. "GNU Guile")
  182. ". It makes use of "
  183. (a (@ (href "https://www.gnu.org/software/guile/manual/html_node/Prompts.html"))
  184. "delimited continuations")
  185. " to avoid a mess of callbacks "
  186. "resulting in clean, easy to read non-blocking code.")
  187. (div (@ (class "code"))
  188. ,(highlights->sxml
  189. (highlight lex-scheme code-snippet))))
  190. ;; Video
  191. ;; News updates and etc
  192. ))
  193. (define (index-page site posts)
  194. (make-page
  195. "index.html"
  196. (base-layout site
  197. (index-content posts)
  198. #:big-logo #t)
  199. sxml->html))
  200. (define (docs-content posts)
  201. `(div (@ (class "content-box"))
  202. (h1 (@ (class "title"))
  203. "Documentation")
  204. (p
  205. "We haven't done a formal export yet! :) "
  206. "I suppose in the meanwhile we should add an appropriately oldschool "
  207. (a (@ (href "http://www.textfiles.com/underconstruction/"))
  208. "under construction gif")
  209. " here...")
  210. (p
  211. "In the meanwhile, you can read a "
  212. (a (@ (href "http://dustycloud.org/tmp/8sync-tutorial-part1.html"))
  213. "work in progress tutorial")
  214. ".")))
  215. (define (docs-page site posts)
  216. (make-page
  217. "docs/index.html"
  218. (base-layout site
  219. (docs-content posts)
  220. #:big-logo #f)
  221. sxml->html))
  222. (define (download-content posts)
  223. `(div (@ (class "content-box"))
  224. (h1 (@ (class "title"))
  225. "Download")
  226. (ul
  227. (li "Download the latest 8sync release: "
  228. (a (@ (href ,latest-release-url))
  229. ,latest-filename)
  230. " (" (a (@ (href ,latest-release-sig-url))
  231. "signature") ")")
  232. (li "See "
  233. (a (@ (href ,main-download-url))
  234. "all 8sync releases")))
  235. (p "For the latest code, we are "
  236. (a (@ (href "https://savannah.gnu.org/projects/8sync"))
  237. "hosted on Savannah. ")
  238. "Pull down our git repo:")
  239. (div (@ (class "code"))
  240. "git clone git://git.savannah.gnu.org/8sync.git")))
  241. (define (download-page site posts)
  242. (make-page
  243. "download/index.html"
  244. (base-layout site
  245. (download-content posts)
  246. #:big-logo #f)
  247. sxml->html))
  248. (define (community-content posts)
  249. `(div (@ (class "content-box"))
  250. (h1 (@ (class "title"))
  251. "Community")
  252. (p "Want to get involved in 8sync development? "
  253. "(Contributions of all kind are welcome!) "
  254. "Or maybe you're just a user looking for some help? "
  255. "We'd love to hear from you!")
  256. (ul
  257. (li (b "IRC:")
  258. " Chat with us on " (b "irc.freenode.net") " in "
  259. (a (@ (href "http://webchat.freenode.net/?channels=guile"))
  260. "#guile")
  261. " and "
  262. (a (@ (href "http://webchat.freenode.net/?channels=8sync"))
  263. "#8sync")
  264. ".")
  265. (li (b "Email:")
  266. " For now we're using the "
  267. (a (@ (href "https://lists.gnu.org/mailman/listinfo/guile-user"))
  268. "guile-user mailing list")
  269. " for most communication. "
  270. "You can also send patches there. "
  271. "Maybe in the future we'll get our own mailing lists..."))))
  272. (define (community-page site posts)
  273. (make-page
  274. "community/index.html"
  275. (base-layout site
  276. (community-content posts)
  277. #:big-logo #f)
  278. sxml->html))
  279. ;;; Site constructor
  280. ;;; ----------------
  281. (define* (make-site #:key
  282. site-prefix
  283. (build-directory "site"))
  284. (if site-prefix
  285. (%site-prefix site-prefix))
  286. (site #:title "8sync: Asynchronous Programming Made Awesome"
  287. #:domain "8sync.org"
  288. #:default-metadata
  289. '((author . "Christopher Allan Webber")
  290. (email . "cwebber@dustycloud.org"))
  291. #:readers (list (make-skribe-reader
  292. #:modules '((haunt skribe utils)
  293. (skribe-utils))))
  294. #:build-directory build-directory
  295. #:builders (list (blog #:theme 8sync-haunt-theme
  296. #:prefix "/news")
  297. index-page
  298. docs-page
  299. download-page
  300. community-page
  301. (atom-feed #:blog-prefix (prefix-url "/news"))
  302. (atom-feeds-by-tag #:blog-prefix (prefix-url "/news"))
  303. (static-directory "static/images" "images")
  304. (static-directory "static/css" "css")
  305. ;;; Not sure we'll ever need this
  306. ;; (static-directory "static/js" "js")
  307. (static-directory "static/fonts" "fonts"))))
  308. (make-site)