Created
June 5, 2023 12:11
-
-
Save exupero/469496ac7bb179199b8714d96bc2aae4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bb | |
(require '[babashka.deps :as deps]) | |
(deps/add-deps '{:deps {org.clojars.askonomm/ruuter {:mvn/version "1.3.2"}}}) | |
(require '[clojure.java.browse :as browse] | |
'[clojure.string :as str] | |
'[cheshire.core :as json] | |
'[org.httpkit.server :as srv] | |
'[ruuter.core :as ruuter] | |
'[hiccup.core :as h]) | |
(import '[java.net URLDecoder]) | |
(defn re-map [re f s & ss] | |
(remove #{"" ::padding} | |
(interleave | |
(str/split s re) | |
(concat (apply map f (re-seq re s) ss) [::padding])))) | |
(defn render [dom & [status]] | |
{:status (or status 200) | |
:body (h/html dom)}) | |
(def style | |
"body {max-width: 800px; margin: 0 auto} | |
body, textarea {font-size: 18pt; line-height: 1.5; font-family: 'PT Sans'} | |
section {margin-bottom: 2rem; display: flex} | |
ol {padding: 0 0 0 2.5rem; margin: 0 2rem 0 0} | |
strong {color: red}") | |
(defn template [dom] | |
(list | |
"<!DOCTYPE html>" | |
(h/html | |
[:head | |
[:meta {:charset "UTF-8"}] | |
[:meta {:content "width=device-width, initial-scale=1" :name "viewport"}] | |
[:title "Wish Lab Mad Lib"] | |
[:script {:src "https://unpkg.com/[email protected]/dist/htmx.min.js" :defer true}] | |
[:script {:src "https://unpkg.com/[email protected]/dist/ext/json-enc.js" :defer true}] | |
[:style {:type "text/css"} style]] | |
[:body | |
dom]))) | |
(defn wordlist [s] | |
(map second (re-seq #"\[([^\]]+)\]" s))) | |
(defn selections [] | |
[:textarea | |
{:name :selections | |
:hx-post "/madlib" | |
:hx-target "#madlib" | |
:hx-ext "json-enc"}]) | |
(defn word-count [s] | |
(let [c (count (re-seq #"\[[^\[]+\]|[A-Za-z'-]+" s))] | |
[:em "(" c " words)"])) | |
(defn madlib-content | |
([s] (madlib-content s nil)) | |
([s words] | |
[:div | |
(-> s | |
(str/replace #"___" "") | |
(as-> $ (re-map #"\[[^\[]+\]" | |
#(do [:strong (or %2 %1)]) | |
$ | |
(concat words (repeat nil)))))])) | |
(defn index [script-file _] | |
(let [s (slurp script-file)] | |
(render | |
(template | |
[:div | |
[:section | |
[:ol | |
(for [word (wordlist s)] | |
[:li word])] | |
(selections)] | |
[:section | |
[:div | |
(word-count s) | |
[:br] | |
[:div#madlib | |
(madlib-content s)]]]])))) | |
(defn madlib [script-file {:keys [body]}] | |
(let [s (slurp script-file) | |
{:keys [selections]} (json/parse-string (slurp body) true) | |
words (map str/trim (str/split-lines selections))] | |
(render | |
(madlib-content s words)))) | |
(defn routes [script-file] | |
[{:path "/" | |
:method :get | |
:response (partial index script-file)} | |
{:path "/madlib" | |
:method :post | |
:response (partial madlib script-file)}]) | |
(defonce server (atom nil)) | |
(defn start-server [port routes] | |
(when-let [s @server] | |
(s :timeout 100) | |
(reset! server nil)) | |
(let [s (srv/run-server #(ruuter/route (routes) %) {:port port})] | |
(reset! server s))) | |
(when (= *file* (System/getProperty "babashka.file")) | |
(let [[script-file] *command-line-args* | |
port 9999 | |
url (str "http://localhost:" port "/")] | |
(start-server port #(routes script-file)) | |
(println "serving" url) | |
(browse/browse-url url) | |
@(promise))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment