massi-world

this website of mine
Log | Files | Refs

commit 9928b8a4878b4e1b27e6ce0b44dfda199d577246
parent 84b9da46983ece285801189ae7b613b074485d82
Author: massi <mdsiboldi@gmail.com>
Date:   Wed, 31 Jul 2024 22:01:52 -0700

organization, disorganization, link fns

Diffstat:
M.gitignore | 5+++--
MMakefile | 2+-
AREADME.org | 36++++++++++++++++++++++++++++++++++++
Msite/manifest.templ.json | 4++--
Msrc/core.clj | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
Msrc/site.clj | 129++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------
Msrc/swatchbuckler.clj | 17+++++++++++++----
Mswatchbuckler/manifest.templ.json | 4++--
8 files changed, 217 insertions(+), 55 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -4,4 +4,6 @@ build **/*.draft .cpcache .nrepl-port -node_modules -\ No newline at end of file +node_modules +/cert.pem +/key.pem diff --git a/Makefile b/Makefile @@ -22,7 +22,7 @@ build: serve: make clean MW_ENV=dev make build - http-server build -p 8080 & while true; do \ + http-server build -p 8080 -S -C cert.pem & while true; do \ inotifywait @./build -qre close_write .; \ make clean; \ MW_ENV=dev make build; \ diff --git a/README.org b/README.org @@ -0,0 +1,36 @@ +* massi-world 🌎 +It's my website. It's a work in progress. I'm building up a static +site generator in clojure from the ground up becuse it's interesting +and I've been meaning to use a lisp more. clojure is pretty cool so +far. + +* Tips ‼ +** SSL on dev +Run this in project root for ssl on dev server (so we can keep +https:// hardcoded): + +=openssl req -newkey rsa:2048 -new -nodes -x509 +-days 3650 -keyout key.pem -out cert.pem= + +However, there's a warning about self-signing the cert and i'm not +sure how to get that to go away. +https://www.npmjs.com/package/http-server seems like it has some +advice. + +** Publishing +Edit =~/.ssh/config= like so the Makefile and your computer are in +agreement about where to push. +#+BEGIN_SRC +Host mw + Hostname ssh.xyz.example.net + User xxx +#+END_SRC + +* Notes ✍ +- Running make build will build using the prod env +- Make serve will build using dev +- To make a one-off dev build, run =MW_ENV=dev make build= + +* Todo 😴 +- Split out js in swatchbuckler +- Finish the website diff --git a/site/manifest.templ.json b/site/manifest.templ.json @@ -2,10 +2,10 @@ "name": "massi world", "icons": [ { - "src": "@(web-root)/shared-assets/icon-192-192.png", + "src": "@(icon-192)", "type": "image/png", "sizes": "192x192" } ], - "start_url": "@(web-root)/index.html" + "start_url": "@(index-url)" } diff --git a/src/core.clj b/src/core.clj @@ -5,11 +5,73 @@ [clojure.string :as cstr])) (def WEB_ROOT (or (System/getenv "WEB_ROOT") "")) -(println WEB_ROOT) + +(defn without-index [path-vec] + (if (= (last path-vec) "index.html") + (butlast path-vec) + path-vec)) + +(defn dev? + ([] (dev? (or (System/getenv "MW_ENV") ""))) + ([mw-env] (= "DEV" (cstr/upper-case mw-env)))) + +(defn mk-path-fns [domain getspec] + (letfn [(p + ([rest-str] + (p rest-str (dev?))) + ([rest-str is-dev] + (str (if is-dev + (str "/" domain rest-str) + rest-str)))) + (network-path + ([pg-key-or-spec] + (network-path pg-key-or-spec (dev?))) + ([pg-key-or-spec is-dev] + (->> pg-key-or-spec + getspec + :path + (into [domain]) + (into (if is-dev ["localhost:8080"] [])) + without-index + (cstr/join "/")))) + (url + ([pg-key-or-spec] (url pg-key-or-spec (dev?))) + ([pg-key-or-spec is-dev] + (str "https://" (network-path pg-key-or-spec is-dev)))) + (path + ([pg-key-or-spec] + (path pg-key-or-spec (dev?))) + ([pg-key-or-spec is-dev] + (->> pg-key-or-spec + getspec + :path + without-index + (into (if is-dev [domain] [])) + (cstr/join "/") + (str "/")))) + (outfile [pg-key-or-spec] + (->> pg-key-or-spec + getspec + :path + (into ["build" domain]) + (cstr/join "/")))] + {:p p + :p-network-path network-path + :p-url url + :p-out outfile + :p-path path})) + + +(defn inject-path-fns [domain getspec] + (doseq [[k v] (mk-path-fns domain getspec)] + (eval `(def ~(symbol k) ~v)))) (defn p [path] (str WEB_ROOT path)) +(defn mk-p [domain] (if (= (clojure.string/upper-case (or (System/getenv "MW_ENV") "")) "DEV") + (fn [path] (str "/" domain path)) + identity)) -(defn base-head-stuff [ {:keys [path title desc img]}] +(defn base-head-stuff [url {:keys [title desc img]}] (list [:meta {:charset "UTF-8"}] [:meta {:name "viewport" :content "width=device-width" @@ -23,14 +85,15 @@ document.documentElement.classList.add('js');")] [:meta {:property "og:image:alt" :content (get img :desc)}] [:meta {:property "og:locale" :content "en_US"}] [:meta {:property "og:type" :content "website"}] - [:meta {:property "og:url" :content path}] + [:meta {:property "og:url" :content url}] [:meta {:name "theme-color" :content "#000033"}] - [:link {:rel "canonical" :href path}])) + [:link {:rel "canonical" :href url}])) -(defn massi-world-domain-stuff [{:or {img {:src "https://massi.world/shared-assets/icon-180-180.png" +;; todo figure out how to thread project-specific p stuff into this. +(defn massi-world-domain-stuff [url p {:or {img {:src "https://massi.world/shared-assets/icon-180-180.png" :desc "an undiscovered planet."}} :as argmap}] - (concat (base-head-stuff argmap) + (concat (base-head-stuff url argmap) (list [:link {:rel "shortcut icon" :href (p "/favicon.ico")}] [:link {:rel "icon" :type "image/png" :sizes "16x16" :href (p "/shared-assets/icon-16-16.png")}] [:link {:rel "icon" :type "image/png" :sizes "32x32" :href (p "/shared-assets/icon-32-32.png")}] diff --git a/src/site.clj b/src/site.clj @@ -5,21 +5,65 @@ [clojure.string :as cstr] [core])) -(defn site-header [argmap] - (concat (core/massi-world-domain-stuff argmap) - (list [:link {:rel "stylesheet" :href (core/p "/style.css")}] - [:link {:rel "manifest" :href (core/p "/manifest.json")}]))) +(def domain "massi.world") +(def pages {}) +(defn getspec [key-or-spec] + (if (map? key-or-spec) + key-or-spec + (if (nil? (pages key-or-spec)) + (throw (Exception. (str "ensure check failed! page " key-or-spec " not found."))) + (pages key-or-spec)))) -(defn with-page [argmap & body] +(core/inject-path-fns domain getspec) + +(defn test-path [pgkey] + (println) + (println (str "paths for " pgkey ":\n")) + (letfn [(mypp [obj] + (doseq [[k v] obj] + (println (str " " k)) + (println (str " " v))) + )] + (println "dev:") + (mypp {:p (p "/is/a/path.txt" true) + :network-path (p-network-path pgkey true) + :url (p-url pgkey true) + :path (p-path pgkey true)}) + + (println "prod:") + (mypp {:p (p "/is/a/path.txt") + :network-path (p-network-path pgkey) + :url (p-url pgkey) + :path (p-path pgkey)}) + + (println "other:") + (mypp + {:outfile (p-out pgkey)}))) + +(defn site-header [spec] + (concat (core/massi-world-domain-stuff (p-url spec) p spec) + (list [:link {:rel "stylesheet" :href (p "/style.css")}] + [:link {:rel "manifest" :href (p "/manifest.json")}]))) + +(defn with-head [pg-key-or-spec & body] (h/html (h/raw "<!DOCTYPE html>") [:html.no-js [:head (site-header - (merge argmap - {:path (str "https://massi.world" (get argmap :path))}))]] + (merge (getspec pg-key-or-spec) + {:path (p-url pg-key-or-spec)}))]] [:body (seq body)])) +(defmacro defpage [key spec & render] + `(def pages + (merge pages + {~key (merge {:render + (fn [] + (with-head ~spec + ~@render))} ~spec)}))) + + (defn header [] [:header "massi world 🦝"]) (defn footer [] @@ -28,17 +72,6 @@ (.format (java.text.SimpleDateFormat. "MM/dd/yyyy hh:mm:ssa z") (new java.util.Date))]) -(defn mk-home [path] - (with-page {:path path - :title "massi world" - :desc "home"} - (header) - [:section - [:h1 "projects"] - [:ul - [:li [:a {:href (core/p "/projects/color-synth.html")} "color-synth"]]] - (footer)])) - (defn mk-page [{:keys [path fn]}] (let* [out-dir "build/massi.world" out-file (str out-dir path) @@ -51,7 +84,8 @@ (defn build-manifest [] (core/process-templ "site/manifest.templ.json" "build/massi.world/manifest.json" - {:web-root core/WEB_ROOT}) + {:icon-192 (p "/shared-assets/icon-192-192.png") + :index-url (p-url :home)}) (println "wrote manifest.")) (defn build-css [] @@ -60,6 +94,41 @@ {:web-root core/WEB_ROOT}) (println "wrote style.css")) +(defn render-page [pgkey] + (let* [out-file (p-out pgkey) + out-str (str ((-> pgkey getspec :render)))] + (io/make-parents out-file) + (spit out-file out-str) + (println "wrote" out-file))) + +(defpage :home {:path ["index.html"] + :title "massi world" + :desc "a website"} + (header) + [:section + [:h1 "projects"] + [:ul + [:li [:a {:href (p-path :color-synth)} "color-synth"]]]] + (footer)) + +(defpage :color-synth {:path ["projects" + "color-synth.html"] + :title "color-synth" + :desc "a modular digital video synthesizer on the web"} + (header) + [:main.color-synth + [:div.md (core/md "site/md/color-synth.templ.md" + {:samples [:div.samples + [:img {:src (p "/assets/color-synth-sample-1.webp") + :alt "a pixelated wobbling smiley face"}] + [:img {:src (p "/assets/color-synth-sample-2.webp") + :alt "jagged vibrant waves"}] + [:img {:src (p "/assets/color-synth-sample-3.webp") + :alt "a complicated animation. fuzzy, sharp, and checkered"}] + [:img {:src (p "/assets/color-synth-sample-4.webp") + :alt "mellow swampy waves"}]]})]] + (footer)) + ;; _ arg is so we can call this with clj -X massi-world/build ;; _ is expected to be a map, and clojure complains if we don't accept it (defn build [_] @@ -67,23 +136,7 @@ (build-manifest) (build-css) (time - (doseq [spec [{:path "/index.html" :fn mk-home} - {:path "/projects/color-synth.html" - :fn #(with-page {:path % - :title "projects -> color-synth" - :desc "a digital video synthesizer on the web"} - (header) - [:main.color-synth - [:div.md (core/md "site/md/color-synth.templ.md" - {:samples [:div.samples - [:img {:src (core/p "/assets/color-synth-sample-1.webp") - :alt "a pixelated wobbling smiley face"}] - [:img {:src (core/p "/assets/color-synth-sample-2.webp") - :alt "jagged vibrant waves"}] - [:img {:src (core/p "/assets/color-synth-sample-3.webp") - :alt "a complicated animation. fuzzy, sharp, and checkered"}] - [:img {:src (core/p "/assets/color-synth-sample-4.webp") - :alt "mellow swampy waves"}]]})]] - (footer))}]] - (mk-page spec)))) + (doseq [pgkey (keys pages)] + (render-page pgkey)))) +(build nil) diff --git a/src/swatchbuckler.clj b/src/swatchbuckler.clj @@ -1,16 +1,25 @@ (ns swatchbuckler (:require [core])) +(def domain "swatchbuckler.massi.world") +(core/inject-path-fns domain identity) + +(def spec {:path ["index.html"] + :title "swatchbuckler" + :desc "generate fg/bg pairs from a midtone"}) + (defn build [_] (core/process-templ "swatchbuckler/index.templ.html" "build/swatchbuckler.massi.world/index.html" - {:head-content (core/massi-world-domain-stuff {:path "https://swatchbuckler.massi.world" - :title "swatchbuckler" - :desc "generate fg/bg pairs from a midtone"})}) + {:head-content (core/massi-world-domain-stuff + (p-url spec) + p + spec)}) (println "wrote build/swatchbuckler.massi.world/index.html") (core/process-templ "swatchbuckler/manifest.templ.json" "build/swatchbuckler.massi.world/manifest.json" - {:web-root core/WEB_ROOT})) + {:icon-192 (p "/shared-assets/icon-192-192.png") + :index-url (p-url spec)})) diff --git a/swatchbuckler/manifest.templ.json b/swatchbuckler/manifest.templ.json @@ -2,10 +2,10 @@ "name": "swatchbuckler", "icons": [ { - "src": "@(web-root)/shared-assets/icon-192-192.png", + "src": "@(icon-192)", "type": "image/png", "sizes": "192x192" } ], - "start_url": "@(web-root)/index.html" + "start_url": "@(index-url)" }