(import janet-html :as html) (import ./utils) # defining the basic structure of each page # thanks to https://css-tricks.com/emojis-as-favicons/ (defn as-html [h] (html/encode (html/doctype :html5) [:html h])) (def favicon "data:image/svg+xml,🌌") (defn html-head [data] [:head [:meta {:charset "utf-8"}] [:title (get-in data [:config :title])] [:link {:rel "icon" :href favicon}] [:link {:rel "stylesheet" :href (get-in data [:config :stylesheet])}]]) # below are some functions we need for the unique svgs generated for each page # arc drawing in svg is a bit messy. these two links helped me: # - http://xahlee.info/js/svg_circle_arc.html # - https://stackoverflow.com/a/18473154 (defn polar->cartesian ``` Given a pair of coordinates representing the center, returns the cartesian coordinate for a straight line drawn at radian angle `alpha` with length `len`. ``` [c-x c-y radius alpha] [(+ c-x (* radius (math/cos alpha))) (+ c-y (* radius (math/sin alpha)))]) (defn arc ``` Draws an svg arc with the given radius with a center at `c-x` and `c-y`. Note that `start` and `end` have to be given in radians. Due to limitations in SVG angles at exactly (* 2 math/pi) are not possible. ``` [c-x c-y radius start end] (let [large-arc? (<= (- end start) math/pi) [x1 y1] (polar->cartesian c-x c-y radius end) [x2 y2] (polar->cartesian c-x c-y radius start)] [:path {:d (string/format "M %.2f %.2f A %.2f %.2f 0 %.0f 0 %.2f %.2f" # starting point x1 y1 # defining the arc radius radius (if large-arc? 0 1) # end point x2 y2)}])) (def num-tiles 10) (def width 500) (def height 500) (def half-pi (/ math/pi 2)) (defn ten-print "Generates a unique SVG pattern for some given content." [content] (let [radius (/ width num-tiles 2) xs (map |(* width (/ $0 num-tiles)) (range (+ num-tiles 1))) ys (map |(* height (/ $0 num-tiles)) (range (+ num-tiles 1)))] (math/seedrandom (hash content)) [:svg.ten-print {:viewBox (string/format "%d %d %d %d" (- radius) (- radius) (+ width (* 2 radius)) (+ height (* 2 radius))) :xmlns "http://www.w3.org/2000/svg" :style "overflow: visible"} [:style "path { fill: none; stroke: none; }"] # avoid flash of unstyled content [:g {:transform "translate(0.5, 0.5"} (mapcat (fn [y] (map (fn [x] (let [rand (math/random) start-angle (if (< rand 0.5) half-pi 0)] (arc x y radius start-angle (+ start-angle (* 3 half-pi))))) xs)) ys)]])) (defn base ``` You can call this with some content and have it generate an entire HTML structure for you. ``` [page data nav body &opt raw?] (default raw? false) (as-html [(html-head data) [:body [:main {:class page} [:header (ten-print body)] [:nav [:h1 (get-in data [:config :title])] nav] [:article (if raw? (html/raw body) body)]]]])) # # different page types # (defn debug [jdn] (string/format "%j" jdn)) (defn home [data] (base "home" data [[:h2 "Recent Posts"] [:ul (map (fn [post] (let [{:published-at {:year y :month m :day d}} post] [:li " -- " [:a {:href (utils/slugify-content data post)} (post "title")]])) (data :posts))] [:h2 "Projects"] [:ul [:li "Berliner Winter"] [:li "Vanilla Sky"] [:li "All My Friends"] [:li "Kosmopolit"]] ] [])) (defn post [data item] (base "post" data [:ul [:li [:a {:href (get-in data [:config :base-url])} "Home"]] [:li [:a {:href "#"} "Projects"]] [:li [:a {:href "#"} "Posts"]] [:li [:a {:href "#"} "About"]]] (bagatto/mmarkdown->html (item :contents)) true))