massi-world

this website of mine
Log | Files | Refs

core.clj (6295B)


      1 (ns core
      2   (:require [hiccup2.core :as h]
      3             [clojure.java.io :as io]
      4             [clojure.string :as cstr]
      5             [clojure.java.shell :as shell]))
      6 
      7 (defn prnt [level emoji & words]
      8   (println (apply str
      9                   (apply str (repeat level "\t"))
     10                   "    "
     11                   emoji
     12                   "\t"
     13                   words)))
     14 
     15 (def VERBOSE (boolean (System/getenv "MW_VERBOSE")))
     16 (def WEB_ROOT (or (System/getenv "WEB_ROOT") ""))
     17 
     18 (defn without-index [path-vec]
     19   (if (= (last path-vec) "index.html")
     20     (butlast path-vec)
     21     path-vec))
     22 
     23 (defn dev?
     24   ([] (dev? (or (System/getenv "MW_ENV") "")))
     25   ([mw-env] (= "DEV" (cstr/upper-case mw-env))))
     26 
     27 (defmacro if-dev [a b]
     28   `(if (dev?)
     29      ~a
     30      ~b))
     31 
     32 (defn mk-path-fns [domain getspec]
     33   (letfn [(p
     34             ([] (p "" (dev?)))
     35             ([rest-str]
     36              (p rest-str (dev?)))
     37             ([rest-str is-dev]
     38              (str (if is-dev
     39                     (str "/" domain rest-str)
     40                     rest-str))))
     41           (network-path
     42             ([pg-key-or-spec]
     43              (network-path pg-key-or-spec (dev?)))
     44             ([pg-key-or-spec is-dev]
     45              (->> pg-key-or-spec
     46                   getspec
     47                   :path
     48                   (into (if is-dev ["localhost:8080" domain] [domain]))
     49                   without-index
     50                   (cstr/join "/"))))
     51           (url
     52             ([pg-key-or-spec] (url pg-key-or-spec (dev?)))
     53             ([pg-key-or-spec is-dev]
     54              (str "https://" (network-path pg-key-or-spec is-dev))))
     55           (path
     56             ([pg-key-or-spec]
     57              (path pg-key-or-spec (dev?)))
     58             ([pg-key-or-spec is-dev]
     59              (->> pg-key-or-spec
     60                   getspec
     61                   :path
     62                   without-index
     63                   (into (if is-dev [domain] []))
     64                   (cstr/join "/")
     65                   (str "/"))))
     66           (outfile [pg-key-or-spec]
     67             (->> pg-key-or-spec
     68                  getspec
     69                  :path
     70                  (into ["build" domain])
     71                  (cstr/join "/")))]
     72     (fn [& args] 
     73       (let [arg1 (first args)
     74             fns {:network-path network-path
     75                  :url url
     76                  :out outfile
     77                  :path path}
     78             result (cond
     79                      (some #(= % arg1) (keys fns))
     80                      (apply (arg1 fns) (rest args))
     81                      
     82                      (string? arg1)
     83                      (apply p args)
     84                      
     85                      (empty? args)
     86                      (p)
     87                      
     88                      :else
     89                      (throw (Exception. (str "⁉ invalid path call with args " args))))]
     90         (when VERBOSE
     91           (println "DEBUG: p" result "<-" args))
     92         
     93         result))))
     94 
     95 (defn p [path] (str WEB_ROOT path))
     96 (defn mk-p [domain] (if (= (clojure.string/upper-case (or (System/getenv "MW_ENV") "")) "DEV")
     97                       (fn [path] (str "/" domain path))
     98                       identity))
     99 
    100 (defn base-head-stuff [url {:keys [title desc img]}]
    101   (list [:meta {:charset "UTF-8"}]
    102         [:meta {:name "viewport"
    103                 :content "width=device-width"
    104                 :initial-screen-scale "1"}]
    105         [:title title]
    106         [:script {:type "module"} (h/raw "document.documentElement.classList.remove('no-js');
    107 document.documentElement.classList.add('js');")]
    108         [:meta {:name "description" :content desc}]
    109         [:meta {:property "og:title" :content title}]
    110         [:meta {:property "og:image" :content (get img :src)}]
    111         [:meta {:property "og:image:alt" :content (get img :desc)}]
    112         [:meta {:property "og:locale" :content "en_US"}]
    113         [:meta {:property "og:type" :content "website"}]
    114         [:meta {:property "og:url" :content url}]
    115         [:meta {:name "theme-color" :content "#000033"}]
    116         [:link {:rel "canonical" :href url}]))
    117 
    118 ;; todo figure out how to thread project-specific p stuff into this.
    119 (defn massi-world-domain-stuff [url p {:or {img {:src "https://massi.world/shared/assets/icon-180-180.png"
    120                                                  :desc "an undiscovered planet."}}
    121                                        :as argmap}]
    122   (concat
    123    (base-head-stuff url argmap)
    124    (list
    125     [:link {:rel "shortcut icon" :href (p "/favicon.ico")}]
    126     [:link {:rel "icon" :type "image/png" :sizes "16x16" :href (p "/shared/assets/icon-16-16.png")}]
    127     [:link {:rel "icon" :type "image/png" :sizes "32x32" :href (p "/shared/assets/icon-32-32.png")}]
    128     [:link {:rel "icon" :type "image/png" :sizes "48x48" :href (p "/shared/assets/icon-48-48.png")}]
    129     [:link {:rel "apple-touch-icon" :href (p "/shared/assets/icon-180-180.png")}])))
    130 
    131 (def linkback-footer
    132   (list [:footer "made by " [:a {:href "https://massi.world"} "massi"]]))
    133 
    134 (defn fill-templ [templstr hole-map]
    135   (clojure.string/replace
    136            templstr
    137            #"@\(([^\s\)]+)\)"
    138            (fn [match]
    139              (let [hole-filler (get hole-map (keyword (second match)))]
    140                (cond
    141                  (fn? hole-filler) (hole-filler)
    142                  (or (seq? hole-filler) (vector? hole-filler)) (str (h/html hole-filler))
    143                  (nil? hole-filler) (throw (Exception. (str "No filler for hole " (second match))))
    144                  true hole-filler)))))
    145 
    146 (defn process-templ [in-file out-file hole-map]
    147   (if (or (not (string? in-file))
    148           (= in-file out-file))
    149     (throw (Exception. "unable to process template. either in/out files not specified or they're the same. which would be weird.")))
    150   (let [out-str (fill-templ (slurp in-file) hole-map)]
    151     (if out-file
    152       (spit out-file out-str)
    153       out-str)))
    154 
    155 (defn md-hole [hole-map]
    156   (fn [text state]
    157     [(fill-templ text hole-map) state]))
    158 
    159 (defn md-to-html [in-str]
    160   (:out (shell/sh "bin/marked-custom.js" :in in-str)))
    161 
    162 (defn md
    163   ([file] (md file nil))
    164   ([file hole-fillers]
    165    (let [templ-str (slurp file)
    166          md-str (fill-templ templ-str hole-fillers)
    167          html-str (md-to-html md-str)]
    168      (h/raw html-str))))
    169 
    170 (defn prettify-html [html-str]
    171   (:out (shell/sh
    172          "prettier"
    173          "--stdin-filepath"
    174          "foo.html" ; just need to end in .html so prettier knows what to do.
    175          :in html-str)))