Blame


1 d5c213d1 2020-10-03 op (ns blog.http
2 d5c213d1 2020-10-03 op (:require
3 d5c213d1 2020-10-03 op [blog.time :as time]
4 d5c213d1 2020-10-03 op [blog.gemtext :as gemtext]
5 d72c4e8f 2020-10-05 op [clojure.string :as str]
6 d72c4e8f 2020-10-05 op [clojure.walk :as walk]
7 d5c213d1 2020-10-03 op [hiccup.page :refer [html5 include-css]]
8 d5c213d1 2020-10-03 op [commonmark-hiccup.core :refer [markdown->hiccup default-config]]))
9 d5c213d1 2020-10-03 op
10 fe64383e 2020-10-14 op (defn link-item [{:keys [url text title]}]
11 fe64383e 2020-10-14 op [:li [:a (cond-> {:href url}
12 fe64383e 2020-10-14 op title (assoc :title title))
13 fe64383e 2020-10-14 op text]])
14 d5c213d1 2020-10-03 op
15 fe64383e 2020-10-14 op (defn header [{:keys [skip-banner?]}]
16 d5c213d1 2020-10-03 op (list
17 d5c213d1 2020-10-03 op [:header
18 d5c213d1 2020-10-03 op [:nav
19 d5c213d1 2020-10-03 op [:ul
20 d5c213d1 2020-10-03 op (link-item {:url "/", :text "Home"})
21 d5c213d1 2020-10-03 op (link-item {:url "/tags.html", :text "All Tags"})
22 d72c4e8f 2020-10-05 op (link-item {:url "/pages/projects.html", :text "Projects"})
23 4ba399c0 2021-08-03 op #_(link-item {:url "/dots", :text "dotfiles"})
24 fe64383e 2020-10-14 op (link-item {:url "gemini://gemini.omarpolo.com" :text "gemini://"
25 fe64383e 2020-10-14 op :title "This website in the gemini space."})]]
26 fe64383e 2020-10-14 op (when-not skip-banner?
27 fe64383e 2020-10-14 op [:div
28 fe64383e 2020-10-14 op [:h1 [:a {:href "/"} "yumh"]]
29 fe64383e 2020-10-14 op [:p "writing about things, sometimes."]])]))
30 d5c213d1 2020-10-03 op
31 d5c213d1 2020-10-03 op (defn with-page
32 fe64383e 2020-10-14 op [{:keys [title class description skip-banner?], :as d} & body]
33 d5c213d1 2020-10-03 op (html5 {:lang "en"}
34 d5c213d1 2020-10-03 op [:head
35 d5c213d1 2020-10-03 op [:meta {:charset "utf8"}]
36 d5c213d1 2020-10-03 op [:meta {:name "viewport", :content "width=device-width, initial-scale=1"}]
37 d5c213d1 2020-10-03 op [:link {:rel "shortcut icon", :href "/favicon.ico"}]
38 d5c213d1 2020-10-03 op [:link {:rel "alternative" :type "application/rss+xml" :href "https://www.omarpolo.com/rss.xml"}]
39 d5c213d1 2020-10-03 op (when description
40 d5c213d1 2020-10-03 op [:meta {:name "description" :content description}])
41 d5c213d1 2020-10-03 op [:title title]
42 d5c213d1 2020-10-03 op (include-css "/css/style.css")]
43 d5c213d1 2020-10-03 op [:body {:class (or class "")}
44 d5c213d1 2020-10-03 op (header d)
45 d5c213d1 2020-10-03 op [:main body]
46 d5c213d1 2020-10-03 op [:footer
47 a358af7f 2020-12-12 op [:p "text: CC-BY-SA-4.0; code: MIT (unless specified otherwise)"]
48 d5c213d1 2020-10-03 op [:p "Blog proudly generated with "
49 d5c213d1 2020-10-03 op [:a {:href "https://git.omarpolo.com/blog/"}
50 d5c213d1 2020-10-03 op [:code "(clojure)"]]]]
51 d5c213d1 2020-10-03 op [:noscript
52 d5c213d1 2020-10-03 op [:img {:src "https://goatcounter.omarpolo.com/count?p=/test-img"}]]
53 d5c213d1 2020-10-03 op [:script "
54 d5c213d1 2020-10-03 op ;(function () {
55 4ba399c0 2021-08-03 op if (window.location.host !== 'www.omarpolo.com')
56 d5c213d1 2020-10-03 op window.goatcounter = {no_onload: true}
57 d5c213d1 2020-10-03 op })();"]
58 d5c213d1 2020-10-03 op [:script {:data-goatcounter "https://goatcounter.omarpolo.com/count"
59 d5c213d1 2020-10-03 op :async true
60 d5c213d1 2020-10-03 op :src "//goatcounter.omarpolo.com/count.js"}]]))
61 d5c213d1 2020-10-03 op
62 fe64383e 2020-10-14 op (defn link->images
63 fe64383e 2020-10-14 op "traverse `doc` and replace every link to an image to an `img` tag."
64 fe64383e 2020-10-14 op [doc]
65 fe64383e 2020-10-14 op (walk/prewalk
66 fe64383e 2020-10-14 op (fn [item]
67 fe64383e 2020-10-14 op (if-not (and (vector? item) (= (first item) :a))
68 fe64383e 2020-10-14 op item
69 fe64383e 2020-10-14 op (let [[_ {:keys [href] :as attrs} text] item]
70 fe64383e 2020-10-14 op [:p
71 fe64383e 2020-10-14 op [:a attrs
72 fe64383e 2020-10-14 op [:img {:src href
73 fe64383e 2020-10-14 op :alt text}]]])))))
74 fe64383e 2020-10-14 op
75 d5c213d1 2020-10-03 op (defn post-fragment
76 d5c213d1 2020-10-03 op [{:keys [full? title-with-link?]}
77 d5c213d1 2020-10-03 op {:keys [title date slug tags short body toot music xkcd gemtext?], :as post}]
78 d5c213d1 2020-10-03 op [:article
79 d5c213d1 2020-10-03 op [:header
80 d5c213d1 2020-10-03 op [(if full?
81 d5c213d1 2020-10-03 op :h1
82 d5c213d1 2020-10-03 op :h2.fragment)
83 d5c213d1 2020-10-03 op (if title-with-link?
84 d5c213d1 2020-10-03 op [:a {:href (str "/post/" slug ".html")} title]
85 d5c213d1 2020-10-03 op title)]
86 d5c213d1 2020-10-03 op [:p.author "Written by " [:em "Omar Polo"] " on " (time/fmt-loc date)
87 d5c213d1 2020-10-03 op (list
88 d5c213d1 2020-10-03 op (when music
89 20b38ec1 2020-12-26 op (let [b (list "“" [:em (:title music)] "”"
90 20b38ec1 2020-12-26 op (when-let [by (:by music)]
91 20b38ec1 2020-12-26 op (list " by " [:em by])))]
92 20b38ec1 2020-12-26 op (list " while listening to "
93 20b38ec1 2020-12-26 op (if-let [url (:url music)]
94 20b38ec1 2020-12-26 op [:a {:href url
95 20b38ec1 2020-12-26 op :target "_blank"
96 20b38ec1 2020-12-26 op :rel "noopener"}
97 20b38ec1 2020-12-26 op b]
98 20b38ec1 2020-12-26 op [:span b]))))
99 d5c213d1 2020-10-03 op ".")]
100 d5c213d1 2020-10-03 op [:ul.tags (map #(vector :li [:a {:href (str "/tag/" (name %) ".html")}
101 d5c213d1 2020-10-03 op (str "#" (name %))])
102 40ca3ee3 2020-12-28 op (sort tags))]
103 d5c213d1 2020-10-03 op (when xkcd
104 d5c213d1 2020-10-03 op [:p [:a {:href (str "https://xkcd.com/" xkcd)
105 d5c213d1 2020-10-03 op :target "_blank"
106 d5c213d1 2020-10-03 op :rel "noopener"}
107 d5c213d1 2020-10-03 op "Related XKCD"]])
108 d5c213d1 2020-10-03 op (when toot
109 d5c213d1 2020-10-03 op [:p [:a {:href toot,
110 d5c213d1 2020-10-03 op :target "_blank"
111 d5c213d1 2020-10-03 op :rel "noopener"} "Comments over ActivityPub"]])]
112 d5c213d1 2020-10-03 op [:section
113 d5c213d1 2020-10-03 op (if full?
114 d5c213d1 2020-10-03 op (if gemtext?
115 d5c213d1 2020-10-03 op (-> body gemtext/parse gemtext/to-hiccup)
116 d5c213d1 2020-10-03 op (markdown->hiccup default-config body))
117 d5c213d1 2020-10-03 op [:p short])]])
118 d5c213d1 2020-10-03 op
119 d5c213d1 2020-10-03 op (defn home-page
120 d5c213d1 2020-10-03 op [{:keys [posts has-next has-prev nth]}]
121 d5c213d1 2020-10-03 op (with-page {:title "Home"}
122 d5c213d1 2020-10-03 op (map (partial post-fragment {:title-with-link? true})
123 d5c213d1 2020-10-03 op posts)
124 d5c213d1 2020-10-03 op [:nav.post-navigation
125 d5c213d1 2020-10-03 op (if has-prev
126 d5c213d1 2020-10-03 op [:a.prev {:href (str "/" (if (= (dec nth) 1)
127 d5c213d1 2020-10-03 op "index"
128 d5c213d1 2020-10-03 op (dec nth)) ".html")}
129 d5c213d1 2020-10-03 op "« Newer Posts"])
130 d5c213d1 2020-10-03 op (if has-next
131 d5c213d1 2020-10-03 op [:a.next {:href (str "/" (inc nth) ".html")}
132 d5c213d1 2020-10-03 op "Older Posts »"])]))
133 d5c213d1 2020-10-03 op
134 d72c4e8f 2020-10-05 op (defn custom-page [{:keys [title body]}]
135 fe64383e 2020-10-14 op (with-page {:title title
136 fe64383e 2020-10-14 op :skip-banner? true}
137 d72c4e8f 2020-10-05 op ;; warning: hack ahead
138 d72c4e8f 2020-10-05 op (walk/prewalk
139 d72c4e8f 2020-10-05 op (fn [item]
140 d72c4e8f 2020-10-05 op (if-not (and (vector? item) (= (first item) :a))
141 d72c4e8f 2020-10-05 op item
142 d72c4e8f 2020-10-05 op (let [[_ attrs & body] item]
143 d72c4e8f 2020-10-05 op [:a (update attrs :href str/replace #"\.gmi$" ".html")
144 d72c4e8f 2020-10-05 op body])))
145 d72c4e8f 2020-10-05 op (-> body gemtext/parse gemtext/to-hiccup))))
146 d72c4e8f 2020-10-05 op
147 d5c213d1 2020-10-03 op (defn post-page
148 d5c213d1 2020-10-03 op [{:keys [title short], :as post}]
149 d5c213d1 2020-10-03 op (with-page {:title title
150 d5c213d1 2020-10-03 op :class "article"
151 d5c213d1 2020-10-03 op :description short}
152 d5c213d1 2020-10-03 op (post-fragment {:full? true}
153 d5c213d1 2020-10-03 op post)))
154 d5c213d1 2020-10-03 op
155 d5c213d1 2020-10-03 op (defn tags-page
156 d5c213d1 2020-10-03 op [tags]
157 d5c213d1 2020-10-03 op (with-page {:title "All tags"
158 d5c213d1 2020-10-03 op :class "tags"}
159 d5c213d1 2020-10-03 op [:h2 "All tags"]
160 d5c213d1 2020-10-03 op [:nav
161 d5c213d1 2020-10-03 op [:ul
162 d5c213d1 2020-10-03 op (map #(vector :li [:a {:href (str "/tag/" (name %) ".html")} (str "#" (name %))])
163 d5c213d1 2020-10-03 op (sort (fn [a b]
164 d5c213d1 2020-10-03 op (compare (.toLowerCase (name a))
165 d5c213d1 2020-10-03 op (.toLowerCase (name b)))) tags))]]))
166 d5c213d1 2020-10-03 op
167 d5c213d1 2020-10-03 op (defn tag-page
168 d5c213d1 2020-10-03 op [tag posts]
169 d5c213d1 2020-10-03 op (with-page {:title (str "Posts tagged with #" tag)
170 d5c213d1 2020-10-03 op :class "tag"}
171 d5c213d1 2020-10-03 op [:h2 "Posts tagged with " [:code "#" tag]]
172 d5c213d1 2020-10-03 op (map (partial post-fragment {:title-with-link? true})
173 d5c213d1 2020-10-03 op (->> posts
174 d5c213d1 2020-10-03 op (sort-by :date)
175 d5c213d1 2020-10-03 op (reverse)))))