blog-renderer.rkt 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. #lang racket
  2. (require "../html-proc.rkt"
  3. "../utils/list-operations.rkt"
  4. "../utils/contract-predicates.rkt"
  5. "../parts/header.rkt"
  6. "post-renderer.rkt"
  7. (prefix-in gregor: gregor)
  8. (prefix-in xml: xml))
  9. (provide
  10. (contract-out
  11. [create-blog-renderer
  12. (->*
  13. ;; mandatory arguments (none are mandatory)
  14. ()
  15. ;; optional arguments (keywords are optional)
  16. (#:max-posts integer-or-infinity?
  17. #:min-date gregor:datetime?
  18. #:posts-per-page# integer-or-infinity?
  19. #:page-number integer?
  20. #:render-separators boolean?
  21. #:post-separator xml:xexpr?
  22. #:blog-title string?
  23. #:blog-language string?)
  24. (->
  25. ;; a procedure for rendering posts
  26. (-> Post? xml:xexpr?)
  27. ;; a procedure for rendering page
  28. (-> integer? integer-or-infinity? integer? xml:xexpr?)
  29. ;; list of posts
  30. (listof Post?)
  31. ;; active page
  32. integer?
  33. ;; returns rendered blog
  34. xml:xexpr?))]))
  35. (define (create-blog-renderer
  36. #:max-posts [max-posts +inf.0]
  37. #:min-date [min-date (gregor:->datetime/utc
  38. (gregor:with-timezone (gregor:datetime 2000)
  39. "Europe/Berlin"))]
  40. #:posts-per-page# [posts-per-page# +inf.0]
  41. #:page-number [page-number 0]
  42. #:render-separators [render-separators #t]
  43. #:post-separator [post-separator `(hr ((class "post-separator")))]
  44. #:blog-title [blog-title "Blog of Complaining"]
  45. #:blog-language [blog-language "en"])
  46. (λ (post-renderer
  47. page-links-renderer
  48. posts
  49. active-page#)
  50. (define (post-date<? post-1 post-2)
  51. (gregor:datetime<? (PostMetadata-creation-date (Post-metadata post-1))
  52. (PostMetadata-creation-date (Post-metadata post-2))))
  53. (define (post-date>min-date? a-post)
  54. (gregor:datetime>=? (PostMetadata-creation-date (Post-metadata a-post))
  55. min-date))
  56. (define (render-blog-page posts-for-page total-posts#)
  57. (finalize-html-content
  58. `(html ((lang ,blog-language))
  59. ,(render-header #:page-title blog-title)
  60. ,(render-page-body posts-for-page total-posts#))))
  61. (define (render-page-body posts total-posts#)
  62. ;; uses render-separators
  63. `(body (h1 ((class "blog-title")) ,blog-title)
  64. ,@(if render-separators
  65. (add-separators-between (render-posts posts))
  66. (render-posts posts))
  67. ,(page-links-renderer total-posts# posts-per-page# active-page#)))
  68. (define (add-separators-between posts)
  69. (list-join posts post-separator))
  70. (define (render-posts posts)
  71. (map post-renderer posts))
  72. (let* ([posts (filter post-date>min-date? posts)]
  73. [posts (sort posts post-date<?)]
  74. [posts (take-n-or-less posts max-posts)]
  75. [from-index (* posts-per-page# active-page# #;page-number )]
  76. [to-index (+ from-index posts-per-page#)]
  77. [posts-for-page (take-from-up-to posts from-index to-index)])
  78. (render-blog-page posts-for-page (length posts)))))