From 924b11bebc61348d90efecb1a7dd338976643f58 Mon Sep 17 00:00:00 2001 From: Jan Tuomi Date: Fri, 9 Feb 2024 16:47:07 +0200 Subject: Add Dockerfile, improvements --- .gitignore | 1 + Dockerfile | 26 +++++++++++ README.md | 3 +- app.scm | 147 +++++++++++++++++++++++++++++++++++----------------------- template.html | 84 --------------------------------- 5 files changed, 119 insertions(+), 142 deletions(-) create mode 100644 Dockerfile delete mode 100644 template.html diff --git a/.gitignore b/.gitignore index d9df752..a9ec0be 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ dist dist/ pages pages/ +template.html diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..44b2559 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,26 @@ +FROM alpine:latest AS builder + +WORKDIR /app + +# Install deps +RUN apk add --no-cache chicken +COPY requirements.list ./requirements.list +RUN chicken-install -from-list requirements.list + +# Build app +COPY app.scm ./app.scm +RUN csc -static -o md-site-gen app.scm +RUN chmod +x md-site-gen + +FROM alpine:latest AS runner + +WORKDIR /app + +# Install runtime deps +RUN apk add --no-cache highlight inotify-tools + +# Run app +COPY --from=builder /app/md-site-gen /usr/bin/md-site-gen + +EXPOSE 8080 +CMD ["md-site-gen"] diff --git a/README.md b/README.md index f3554dd..44e923d 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,8 @@ Markdown -> HTML converter and HTTP server. | Variable | Description | | -------- | ----------- | -| `PORT` | HTTP server PORT (default: 8080) | +| `PORT` | HTTP server port. If not specified, will not start development HTTP server. | | `SRCROOT` | Relative markdown directory path (default: pages) | | `WEBROOT` | Relative output directory path (default: dist) | | `TEMPLATE` | Relative path to HTML file with a single `format` marker (default: template.html) | +| `NREPL_PORT` | nrepl port for remote debugging access (default: 1234) | diff --git a/app.scm b/app.scm index ffe8792..4491202 100644 --- a/app.scm +++ b/app.scm @@ -17,17 +17,18 @@ intarweb uri-common (chicken process) - (chicken process-context)) + (chicken process-context) + (chicken condition)) -(define *PORT* (string->number - (or (get-environment-variable "PORT") - "8080"))) +(define *PORT* (get-environment-variable "PORT")) (define *WEBROOT* (or (get-environment-variable "WEBROOT") "dist")) (define *SRCROOT* (or (get-environment-variable "SRCROOT") "pages")) (define *TEMPLATE* (or (get-environment-variable "TEMPLATE") - "template.html")) + "template.html")) +(define *NREPL-PORT* (string->number (or (get-environment-variable "NREPL_PORT") + "1234"))) (define (pipe x . fns) (match fns @@ -99,62 +100,89 @@ (format (read-string #f (open-input-file tmpl-path)) html)) -(define (compile-file filepath prev-result) - (define (inner return) - (define initial-srcroot (string-append "^" *SRCROOT*)) - (define replaced-filepath (replace initial-srcroot *WEBROOT* filepath)) +(define (system-has-fswatch?) + (call/cc (lambda (k) + (with-exception-handler + (lambda (exn) (k #f)) + (lambda () (system* "which fswatch") (k #t)))))) + +(define (system-has-inotifywait?) + (call/cc (lambda (k) + (with-exception-handler + (lambda (exn) (k #f)) + (lambda () (system* "which inotifywait") (k #t)))))) + +(define (compile-file-into outdir) + (lambda (filepath prev-result) + (define (inner return) + (define initial-srcroot (string-append "^" *SRCROOT*)) + (define replaced-filepath (replace initial-srcroot outdir filepath)) + + (if (directory-exists? filepath) + (begin + (print (format "Creating corresponding directory: ~A" filepath)) + (create-directory replaced-filepath #t) + (return (void)))) + + (if (not (irregex-search "\\.md$" filepath)) + (begin + (print (format "Copying non-md file: ~A" filepath)) + (copy-file filepath replaced-filepath) + (return (void)))) + + (print (format "Compiling markdown: ~A" filepath)) + (define out-path (pipe filepath + (@ replace "\\.md" ".html") + (@ replace initial-srcroot outdir))) + + (define out-content (pipe filepath + (@ convert-md-to-html) + (@ highlight-code-blocks) + (@ insert-to-page-tmpl *TEMPLATE*))) + + (with-output-to-file out-path + (thunk display out-content))) + + (call/cc inner))) - (if (directory-exists? filepath) - (begin - (print (format "Creating corresponding directory: ~A" filepath)) - (create-directory replaced-filepath #t) - (return (void)))) - - (if (not (irregex-search "\\.md$" filepath)) - (begin - (print (format "Copying non-md file: ~A" filepath)) - (copy-file filepath replaced-filepath) - (return (void)))) - - (print (format "Compiling markdown: ~A" filepath)) - (define out-path (pipe filepath - (@ replace "\\.md" ".html") - (@ replace initial-srcroot *WEBROOT*))) - - (define out-content (pipe filepath - (@ convert-md-to-html) - (@ highlight-code-blocks) - (@ insert-to-page-tmpl *TEMPLATE*))) - - (with-output-to-file out-path - (thunk display out-content))) +(define (recompile) + (define tmpdir (create-temporary-directory)) - (call/cc inner)) + (find-files *SRCROOT* + action: (compile-file-into tmpdir)) -(define (recompile) - (create-directory "dist" #t) + (system* (format "rm -r \"~A\" || true" *WEBROOT*)) + (system* (format "mv \"~A\" \"~A\"" tmpdir *WEBROOT*))) - (define (delete-path path) - (if (directory-exists? path) - (delete-directory path #t) - (delete-file path))) - (for-each delete-path (glob (string-append *WEBROOT* "/*"))) - (find-files "pages" - action: compile-file)) +(define (wait-for-filesystem-change stop-watching) + (cond ((system-has-fswatch?) (process (format "fswatch -r -L -1 ~A" *SRCROOT*))) + ((system-has-inotifywait?) (process (format "inotifywait -r -q -e create -e modify -e delete -e move ~A" *SRCROOT*))) + (else (begin (print "No file watching system installed") + (stop-watching (void)))))) +(define (watch-print . rest) (apply print "[watch] " rest)) (thread-start! (lambda () - (receive (input _ _) (process (format "fswatch -o ~A" *SRCROOT*)) - (let loop () - (print (format "Monitored directory has changed (# of changes: ~A)" (read-line input))) - (recompile) - (loop))))) + (watch-print "Starting watching source directory...") + + (call/cc + (lambda (stop-watching) + (let loop () + (watch-print "Calling file watching system...") + (receive (input _ _) (wait-for-filesystem-change stop-watching) + (watch-print "Waiting for filesystem changes...") + (watch-print (format "Monitored directory has changed (output: ~A)" (read-line input))) + (recompile) + (loop))))) + + (watch-print "Stopped watching source directory."))) +(define (nrepl-print . rest) (apply print "[nrepl] " rest)) (thread-start! (lambda () - (print "starting nrepl on port 1234") + (nrepl-print (format "Starting nrepl on port ~A" *NREPL-PORT*)) (nrepl-prompt (lambda () (display "#;0> "))) - (nrepl 1234))) + (nrepl *NREPL-PORT*))) (recompile) @@ -171,9 +199,9 @@ (define has-ext? (@ irregex-search "\\.\\S+$")) (match fragment ["" "index.html"] - ;; if path ends in an extension, do nothing + ;; if path ends in an extension, do nothing [(? has-ext?) fragment] - ;; otherwise, add .html + ;; otherwise, add .html [_ (string-append fragment ".html")])) (define (string-intercalate delim lst) @@ -187,8 +215,13 @@ (print (format "Serving file ~A" static-file-path)) (send-static-file static-file-path)) -(print (format "Serving ~A on port ~A, using ~A as html template" *WEBROOT* *PORT* *TEMPLATE*)) -(server-port *PORT*) -(root-path *WEBROOT*) -(vhost-map `((".*" . ,(@ app)))) -(start-server) +(if *PORT* + (begin (print (format "Serving ~A on port ~A, using ~A as html template" *WEBROOT* *PORT* *TEMPLATE*)) + (server-port (string->number *PORT*)) + (root-path *WEBROOT*) + (vhost-map `((".*" . ,(@ app)))) + (start-server)) + (begin (print "PORT not defined, not starting HTTP server. Putting main thread to sleep.") + (let loop () + (thread-sleep! 1) + (loop)))) diff --git a/template.html b/template.html deleted file mode 100644 index ce0fb2e..0000000 --- a/template.html +++ /dev/null @@ -1,84 +0,0 @@ - - - - jan.systems - - - - - - - - ~A - - -- cgit v1.3