massi-world

this website of mine
Log | Files | Refs

commit 3544b46ca917de42b17dcb039e39a68d5ed05d31
parent 2b54915fd106c0df96475298fa0a37afa610e21a
Author: massi <mdsiboldi@gmail.com>
Date:   Fri,  2 Aug 2024 06:14:55 -0700

path fn updates, styling sesh

Diffstat:
Mshared/static/shared-assets/spiral-for-dark-mode.svg | 4++--
Mshared/static/shared-assets/spiral-for-light-mode.svg | 4++--
Msite/md/color-synth.templ.md | 23+++++++++++++++--------
Msite/style.templ.css | 97+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
Msrc/core.clj | 34++++++++++++++++++++++++----------
Msrc/site.clj | 64+++++++++++++++++++++++++++++++++++++++++-----------------------
Msrc/swatchbuckler.clj | 6+++---
7 files changed, 175 insertions(+), 57 deletions(-)

diff --git a/shared/static/shared-assets/spiral-for-dark-mode.svg b/shared/static/shared-assets/spiral-for-dark-mode.svg @@ -2,8 +2,8 @@ <!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools --> <svg - width="1rem" - height="1rem" + width="0.8rem" + height="0.8rem" viewBox="-1 0 20 20" version="1.1" id="svg1" diff --git a/shared/static/shared-assets/spiral-for-light-mode.svg b/shared/static/shared-assets/spiral-for-light-mode.svg @@ -2,8 +2,8 @@ <!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools --> <svg - width="1rem" - height="1rem" + width="0.8em" + height="0.8em" viewBox="-1 0 20 20" version="1.1" id="svg1" diff --git a/site/md/color-synth.templ.md b/site/md/color-synth.templ.md @@ -1,26 +1,27 @@ -# color-synth +@(samples) - [git repo here](https://git.massi.world/color-synth) - [check out color-synth here!](https://color-synth.massi.world) -@(samples) - -## About +# About Color-synth is a virtual modular [video synthesizer](https://en.wikipedia.org/wiki/Video_synthesizer). Add and hook up various signal-generating modules, connect them to the video output channels, and watch the colors start dancing in your eyes. -## Current State +# Current State Color-synth is under __active development__. Everything is subject to change, and any programs you save to url may become invalid in the future. -## How To Synthesize +# How To Synthesize - Add a module using the buttons on the bottom right. + - To connect a module, drag from its purple connector on the top-right of the module, to either a green input port of another module, or the video output channels (lightness, chroma, hue) on the top right of the screen. + - To disconnect a module, do the same thing you did to connect it. + - When you've made something you want to share, click on the `save` button at the bottom right corner. This will save your patch to the url. -## The Modules +# The Modules - The __oscillator__ module generates a waveform signal. In the audio realm, you usually have knobs to control an oscillator's octave, semitone, and cents. Each knob is more precise than the last, and accomplishes different effects - pitching up or down an octave, transposing, and fine-tuning. In the video realm, there are some similarities to this system. Three knobs working at different harmonic levels. `Coarse` controls how the waveform repeats over the entire screen. For example, `coarse` set to `1` means that from the first pixel drawn on the screen to the last, the waveform will go through one cycle. `Fine` works on the row level - each increment of the fine knob will cycle the waveform once per row of pixels. `Superfine` is akin to cents. It enables movement by slightly adjusting the frequency of the wave so that it doesn't perfectly line up with the screen. Finally, you can select between a sine, square, or sawtooth wave with `waveform`. @@ -34,12 +35,18 @@ Color-synth is under __active development__. Everything is subject to change, an - The __image oscillator__ module currently adds a smiley face. In the _future_, you'll be able provide an image of your own! It has one control, `speed`, that is probably confusing right now. Basically, you can think of the color values of an image as a complicated waveform. That waveform has a frequency. In the current state of this module, a speed of `100,000` will display the image at full size. `200,000` will display a 2x2 grid of the image. `300,000`, 3x3. Etc. -## Roadmap +# Roadmap - Better inputs. There is much to do here. The current ones are imprecise and unwieldy. + - Image module overhaul. Having inputs for scaleX, scaleY, and image URL would be a good start. + - Workspace improvements. There are a lot of impactful things here. The ability to hide all modules! The ability to move all modules at once and/or pan the workspace. Improvements to the initial positioning of new modules. + - Workflow improvements. Undo/Redo! The ability to delete modules! Adding a module in between two connected modules! Better disconnect ergonomics! + - Module design overhaul. My long-term goal is to style each module in its own unique way, as a nod to all the unique modular synthesis gear out there. + - Mobile support. + - MIDI support, so you can route midi to your browser and sync color-synth with your music! diff --git a/site/style.templ.css b/site/style.templ.css @@ -1,14 +1,40 @@ :root { --dark-bg: #1d2c3a; --dark-fg: #acbdcf; + --dark-link: white; + --light-bg: #def0ff; --light-fg: #455564; + --light-link: black; + + --bg: var(--light-bg); + --fg: var(--light-fg); + --link: var(--light-link); + +} + +@media (prefers-color-scheme: dark) { + :root { + --bg: var(--dark-bg); + --fg: var(--dark-fg); + --link: var(--dark-link); + } +} + +@media (max-width: 600px) { + header { + line-height: 1.2; + } + header > *:nth-child(2n)::after { + content: "\A"; + white-space: pre; + } } html { - font-size: 24px; - color: var(--light-fg); - background: var(--light-bg); + font-size: 20px; + color: var(--fg); + background: var(--bg); } @@ -19,8 +45,65 @@ body { padding: 0.75rem; } -h1 { - font-size: 2rem; +a { + color: var(--link); + text-decoration: 1px underline; + text-underline-offset: 0.1em; +} + +.md h1 { + font-size: 1.4rem; + font-weight: normal; + margin: 0.5rem 0; +} + +.md p, .md ul, .md ol { + margin-top: 0; +} + +h1 > a, h2 > a, h3 > a, h4 > a { + color: inherit; + text-decoration: none; + position: relative; + left: -1.2rem; + padding-left: 1.2rem; +} + +#svg-arrow { + vertical-align: middle; + width: 1em; + height: 1em; + padding: 0 0.4em; +} + +header { + font-size: 1.2rem; + padding-bottom: 0.8rem; +} + +header a { + color: inherit; +} + +header a:last-child { + text-decoration: none; +} + +ul { + margin-left: -1rem; +} + +h1:hover > a::after, +h2:hover > a::after, +h3:hover > a::after, +h4:hover > a::after { + content: "🔗"; + position: absolute; + right: -1.2rem; + font-size: 0.8rem; + top: 0; + bottom: 0; + align-content: center; } ul > li { @@ -28,10 +111,6 @@ ul > li { } @media (prefers-color-scheme: dark) { - html { - background: var(--dark-bg); - color: var(--dark-fg); - } ul > li { list-style: url("@(web-root)/shared-assets/spiral-for-dark-mode.svg") } diff --git a/src/core.clj b/src/core.clj @@ -12,6 +12,7 @@ "\t" words))) +(def VERBOSE (boolean (System/getenv "MW_VERBOSE"))) (def WEB_ROOT (or (System/getenv "WEB_ROOT") "")) (defn without-index [path-vec] @@ -25,6 +26,7 @@ (defn mk-path-fns [domain getspec] (letfn [(p + ([] (p "" (dev?))) ([rest-str] (p rest-str (dev?))) ([rest-str is-dev] @@ -62,16 +64,28 @@ :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)))) + (fn [& args] + (let [arg1 (first args) + fns {:network-path network-path + :url url + :out outfile + :path path} + result (cond + (some #(= % arg1) (keys fns)) + (apply (arg1 fns) (rest args)) + + (string? arg1) + (apply p args) + + (empty? args) + (p) + + :else + (throw (Exception. (str "⁉ invalid path call with args " args))))] + (when VERBOSE + (println "DEBUG: p" result "<-" args)) + + result)))) (defn p [path] (str WEB_ROOT path)) (defn mk-p [domain] (if (= (clojure.string/upper-case (or (System/getenv "MW_ENV") "")) "DEV") diff --git a/src/site.clj b/src/site.clj @@ -14,34 +14,34 @@ (throw (Exception. (str "ensure check failed! page " key-or-spec " not found."))) (pages key-or-spec)))) -(core/inject-path-fns domain getspec) +(def p (core/mk-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 (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)}) + :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)}) + :network-path (p :network-path pgkey) + :url (p :url pgkey) + :path (p :path pgkey)}) (println "other:") (mypp - {:outfile (p-out pgkey)}))) + {:outfile (p :out pgkey)}))) (defn site-header [spec] - (concat (core/massi-world-domain-stuff (p-url spec) p 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")}]))) @@ -61,31 +61,50 @@ (with-head ~spec ~@render))} ~spec)}))) +(defn page-identifier? [thing] + (or (map? thing) (keyword? thing))) + +(def svg-arrow + [:svg {:viewBox "0 0 16 16" :id "svg-arrow"} + [:path {:style "fill:var(--fg)" :d "M 9.3370298,4.2576328 8.9740248,4.8872198 13.221,7.329 H 0.72416487 V 8.032 H 13.221 l -4.2469782,2.442097 0.363005,0.629587 5.9300332,-3.4230256 z"}]]) + +(defn header [& crumbs] + (letfn [(mkcrumb + ([pg] + (cond (page-identifier? pg) + [:a {:href (p :path pg)} + (:title (getspec pg))] + + (string? pg) + [:span pg] + + :else + (throw (Exception. "header got wrong stuff.")))))] + [:header + (interpose [:span {:class "crumb-interposer"} svg-arrow] (map mkcrumb (conj crumbs :home)))])) -(defn header [] - [:header "massi world 🦝"]) (defn footer [] [:footer - "Last generated: " - (.format (java.text.SimpleDateFormat. "MM/dd/yyyy hh:mm:ssa z") - (new java.util.Date))]) + "Last generated: " + (.format (java.text.SimpleDateFormat. "MM/dd/yyyy hh:mm:ssa z") + (new java.util.Date))]) (defn build-manifest [] (core/prnt 1 "🤖" "writing build/massi.world/manifest.json") (core/process-templ "site/manifest.templ.json" "build/massi.world/manifest.json" {:icon-192 (p "/shared-assets/icon-192-192.png") - :index-url (p-url :home)})) + :index-url (p :url :home)})) (defn build-css [] (core/prnt 1 "🖼" "writing build/massi.world/style.css") (core/process-templ "site/style.templ.css" "build/massi.world/style.css" - {:web-root core/WEB_ROOT})) + {:web-root (p "")})) (defn render-page [pgkey] (core/prnt 1 "👉" pgkey) - (let [out-file (p-out pgkey) + (let [out-file (p :out pgkey) out-str (do (core/prnt 2 "🌀" "rendering " pgkey) (str ((-> pgkey getspec :render)))) out-str (if (cstr/ends-with? out-file ".html") @@ -106,14 +125,13 @@ [:section [:h1 "projects"] [:ul - [:li [:a {:href (p-path :color-synth)} "color-synth"]]]] + [:li [:a {:href (p :path :color-synth)} "color-synth"]]]] (footer)) -(defpage :color-synth {:path ["projects" - "color-synth.html"] +(defpage :color-synth {:path ["projects" "color-synth.html"] :title "color-synth" :desc "a modular digital video synthesizer on the web"} - (header) + (header "projects" :color-synth) [:main.color-synth [:div.md (core/md "site/md/color-synth.templ.md" {:samples [:div.samples diff --git a/src/swatchbuckler.clj b/src/swatchbuckler.clj @@ -2,7 +2,7 @@ (:require [core])) (def domain "swatchbuckler.massi.world") -(core/inject-path-fns domain identity) +(def p (core/mk-path-fns domain identity)) (def spec {:path ["index.html"] :title "swatchbuckler" @@ -21,7 +21,7 @@ (core/fill-templ (slurp templ-file) {:head-content (core/massi-world-domain-stuff - (p-url spec) + (p :url spec) p spec)})) html-str (do @@ -36,7 +36,7 @@ "swatchbuckler/manifest.templ.json" "build/swatchbuckler.massi.world/manifest.json" {:icon-192 (p "/shared-assets/icon-192-192.png") - :index-url (p-url spec)}) + :index-url (p :url spec)}) (core/prnt 1 "🤖" "wrote build/massi.world/manifest.json") (print "\t 🕜\t"))) (println))