(import (chicken base)
utf8
spiffy
nrepl
srfi-18
(chicken file)
(chicken io)
(chicken port)
(chicken format)
(chicken pretty-print)
lowdown
sxml-transforms
matchable
(chicken irregex)
shell
srfi-13
intarweb
html-parser
(chicken process))
(define (pipe x . fns)
(match fns
[() x]
[(fn . rest) (apply pipe (fn x) rest)]))
;; Convenience macro (@ expr ...) that expands to (lambda (x) (expr ... x))
(define-syntax @
(syntax-rules ()
((_ expr ...)
(lambda (x) (expr ... x)))))
(define-syntax thunk
(syntax-rules ()
((_ expr ...)
(lambda () (expr ...)))))
(define (replace from to str)
(irregex-replace/all from str to))
(define (html-unescape html)
(pipe html
(@ replace """ "\"")
(@ replace "'" "'")
(@ replace "&" "&")
(@ replace "<" "<")
(@ replace ">" ">")))
(define (highlight ext code)
(define tmp-file-path (create-temporary-file ext))
(with-output-to-file tmp-file-path
(lambda () (display code)))
(define result (capture ,(format "highlight ~A -O html -f" tmp-file-path)))
(delete-file tmp-file-path)
result)
(define (replace-code-block content return)
(define irx (irregex "^%lang (\\S+)%\\n?" 's))
(define lang-match
(irregex-search irx content))
(if (not lang-match)
(return content))
(define lang
(irregex-match-substring lang-match 1))
(pipe content
(@ replace irx "")
(@ html-unescape)
(@ highlight lang)
(@ string-trim-both)))
(define (convert-md-to-html filepath)
(with-output-to-string
(lambda () (markdown->html (open-input-file filepath)))))
(define (highlight-code-blocks html)
(define (highlight-match m)
(format "~A"
(call/cc (@ replace-code-block (irregex-match-substring m 1)))))
(irregex-replace/all (irregex "(.*?)" 's) html
highlight-match))
(define (insert-to-page-tmpl tmpl-path html)
(format (read-string #f (open-input-file tmpl-path))
html))
(define (app c)
(define html-text
(pipe "article.md"
(@ convert-md-to-html)
(@ highlight-code-blocks)
(@ insert-to-page-tmpl "index.html")))
(send-response body: html-text
headers: '((content-type #(text/html ((charset . utf-8)))))))
(define (compile-file filepath return)
(if (not (irregex-search "\\.md$" filepath))
(begin
(print (format "Copying non-md file: ~A" filepath))
(copy-file filepath
(replace "pages\\/" "dist/" filepath))
(return (void))))
(print (format "Compiling: ~A" filepath))
(define out-path (pipe filepath
(@ replace "\\.md" ".html")
(@ replace "pages\\/" "dist/")))
(define out-content (pipe filepath
(@ convert-md-to-html)
(@ highlight-code-blocks)
(@ insert-to-page-tmpl "index.html")))
(with-output-to-file out-path
(thunk display out-content)))
(define (recompile)
(create-directory "dist" #t)
(for-each (@ delete-file) (glob "dist/*"))
(find-files "pages"
action: (lambda (filepath prev-result) (call/cc (lambda (k) (compile-file filepath k))))))
(thread-start!
(lambda ()
(receive (input _ _) (process "fswatch -o pages")
(let loop ()
(print (format "Monitored directory has changed (# of changes: ~A)" (read-line input)))
(recompile)
(loop)))))
(thread-start!
(lambda ()
(print "starting nrepl on port 1234")
(nrepl-prompt (lambda () (display "#;0> ")))
(nrepl 1234)))
(recompile)
(vhost-map `((".*" . ,(lambda (c) (app c)))))
(start-server)