A blog and other things. https://etc.fsh.ee/
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.
 
 

242 lines
8.4 KiB

#lang racket
(require web-server/servlet
web-server/servlet-env
json
xml
css-expr
date
(prefix-in http- net/http-easy)
racket/match
racket/string
racket/promise
racket/list)
(require (prefix-in wp: "wp.rkt"))
(provide route-root)
(struct link (title href))
(define links
(list
(link "Home" "/")
(link "Quotes" "/quotes")
(link "Links" "/links")
(link "License" "/license")
(link "Search" "/search")
(link "Source" "https://git.fsh.ee/i/etc")))
(define css
(css-expr->css
(css-expr
(*
#:font-size .9rem)
(body
#:font-family monospace
#:line-height 1.5
#:max-width 80ch
#:margin-top 0
#:margin-right auto
#:margin-bottom 0
#:margin-left auto)
(.container
#:margin 1rem)
(a
#:text-decoration none)
(blockquote
#:display block
#:position relative
#:padding-left 1rem)
(blockquote:before
#:width 0;
#:content " "
#:position absolute
#:top 0
#:left 0
#:height 100%
#:display block
#:border-style inset
#:border-width 1px)
(pre ((& code)
#:display block
#:position relative
#:padding-left 1rem))
(pre ((& code:before)
#:width 0;
#:content " "
#:position absolute
#:top 0
#:left 0
#:height 100%
#:display block
#:border-style inset
#:border-width 1px))
(code:before code:after
#:content "`")
(pre ((& code:before)
#:content ""))
(pre ((& code:after)
#:content ""))
(blockquote
#:margin-left 0
#:margin-right 0)
(blockquote cite:before
#:content "")
(.comma:after
#:content ", ")
(span:last-of-type
((& .comma)
#:display none))
(@media (and screen (#:max-width 1000PX))
(pre ((& code)
#:max-width 100%
#:overflow-x auto
#:overflow-y hidden
#:-webkit-overflow-scrolling touch))))))
(define (tmpl post-cat c)
`(html
(head
(meta ((charset "utf-8")))
(meta ((name "viewport")
(content "width=device-width, initial-scale=1")))
(meta ((name "X-UA-Compatible")
(content "text/html; charset=utf-8")))
(meta ((name "Content-Type")
(content "text/html; charset=utf-8")))
(meta ((name "robots")
(content "all")))
(meta ((name "referrer")
(content "no-referrer-when-downgrade")))
(title ,(wp:content-title c)))
(body
(div ((class "container"))
(style ,css)
(header
(nav
,@(map
(lambda (link)
`(span (a ((href ,(link-href link))) ,(link-title link))
(span ((class "comma")))))
links))
(h1 ,(danger (wp:content-title c))))
,(if (> (length (wp:content-tags c)) 0)
`(div
,@(map
(lambda (tag)
`(span (a ((href ,(string-append "/subject/" (wp:tag-slug tag)))) ,(wp:tag-title tag))
(span ((class "comma")))))
(wp:content-tags c)))
`(span))
(article ,(danger (wp:content-desc c) "div")
,(if (> (length (wp:content-posts c)) 0)
`(div
(h2 "Posts")
,@(map
(lambda (post)
`(div (a ((href ,(string-append "/" (wp:content-slug post))))
,(danger (wp:content-title post))
(br)
(span "PUB " ,(wp:content-pub-fmt post)))
(br)
(br)))
(wp:content-posts c)))
`(span))
,(if (wp:content-is c post-cat)
`(div
,(if (wp:content-next c)
`(blockquote (p (span "Next")
(br)
(a ((href ,(string-append "/" (wp:content-slug (wp:content-next c)))))
,(danger (wp:content-title (wp:content-next c))))))
`(span))
,(if (wp:content-prev c)
`(blockquote (p (span "Prev")
(br)
(a ((href ,(string-append "/" (wp:content-slug (wp:content-prev c)))))
,(danger (wp:content-title (wp:content-prev c))))))
`(span)))
`(span)))
(footer
(pre
(span "PUB " ,(wp:content-pub-fmt c))
(br)
(span "MOD " ,(wp:content-mod-fmt c))))))))
(define (danger str (tag "span"))
(string->xexpr (string-append "<" tag ">" str "</" tag ">")))
(define (query-value sym q)
(foldl
(lambda (val ret)
(if (equal? (car val) sym)
(cdr val)
ret))
null
q))
(define (request->string-path req)
(foldl
(lambda (x y) (string-trim y x))
(path->string (url->path (request-uri req)))
(list "/" ".")))
(define (route-root cache wp-url home-content-slug post-cat page-cat req)
(with-handlers ((exn:fail? (lambda (exn)
(displayln exn)
(route-content post-cat (wp:dummy-err)))))
(let* ((uri (request->string-path req))
(uri-parts (string-split uri "/")))
(cond ((empty? uri-parts)
(route-content-list
post-cat
(lambda ()
(wp:fetch-post cache wp-url (list page-cat) home-content-slug))
(lambda ()
(wp:fetch-post-list cache wp-url (list post-cat) (list)))))
((equal? uri-parts (list home-content-slug))
(redirect-to "/"))
((equal? (first uri-parts) "search")
(let* ((term (query-value 'search (url-query (request-uri req))))
(func (if (null? term)
wp:dummy-search-init
(lambda ()
(wp:dummy-search-found
term
(wp:fetch-post-search cache wp-url (list post-cat page-cat) term))))))
(route-content post-cat (list (func)))))
((equal? (first uri-parts) "subject")
(let ((tag (wp:fetch-tag cache wp-url (string-trim uri "subject/" #:left? #t))))
(route-content-list
post-cat
(lambda () (map wp:tag->content tag))
(lambda () (wp:fetch-post-list cache wp-url (list post-cat) (map wp:tag-id tag))))))
(else (route-content post-cat (wp:fetch-post cache wp-url (list page-cat post-cat) uri)))))))
;; helpers
(define (route-content post-cat c)
(if (empty? c)
(response/xexpr (tmpl post-cat (wp:dummy-not-found)) #:code 404)
(response/xexpr (tmpl post-cat (car c)))))
(define (route-content-list post-cat make-content make-content-list)
(let ((content-list (make-content-list)))
(if (empty? content-list)
(route-content post-cat content-list)
(route-content post-cat
(map (lambda (c)
(wp:content (wp:content-title c)
(wp:content-desc c)
(wp:content-slug c)
(wp:content-excerpt c)
(wp:content-pub c)
(wp:content-mod c)
(wp:content-tags c)
content-list
(wp:content-next c)
(wp:content-prev c)
(wp:content-cats c)))
(make-content))))))