Blame


1 ddc03123 2020-03-28 op (ns blog.core
2 5e8f809e 2020-06-27 op (:require
3 5e8f809e 2020-06-27 op [blog.rss :as rss]
4 52f2ea18 2020-10-03 op [blog.http :as http]
5 52f2ea18 2020-10-03 op [blog.gemini :as gemini]
6 5e8f809e 2020-06-27 op [blog.time :as time]
7 5e8f809e 2020-06-27 op [clojure.edn :as edn]
8 5e8f809e 2020-06-27 op [clojure.java.io :as io]
9 5e8f809e 2020-06-27 op [clojure.java.shell :refer [sh]]
10 5e8f809e 2020-06-27 op [ring.adapter.jetty :as jetty]
11 5e8f809e 2020-06-27 op [ring.middleware.content-type :refer [wrap-content-type]]
12 5e8f809e 2020-06-27 op [ring.middleware.resource :refer [wrap-resource]])
13 5e8f809e 2020-06-27 op (:import (java.io File))
14 5e8f809e 2020-06-27 op (:gen-class))
15 ddc03123 2020-03-28 op
16 ddc03123 2020-03-28 op (defn copy-file [src dst]
17 ddc03123 2020-03-28 op (with-open [in (io/input-stream (io/file src))
18 ddc03123 2020-03-28 op out (io/output-stream (io/file dst))]
19 ddc03123 2020-03-28 op (io/copy in out)))
20 ddc03123 2020-03-28 op
21 52f2ea18 2020-10-03 op (defn post [{:keys [slug gemtext?] :as p}]
22 52f2ea18 2020-10-03 op (let [ext (if gemtext? ".gmi" ".md")]
23 52f2ea18 2020-10-03 op (-> p
24 52f2ea18 2020-10-03 op (assoc :body (-> (str "posts/" slug ext) io/resource slurp))
25 52f2ea18 2020-10-03 op (update :date time/parse))))
26 ddc03123 2020-03-28 op
27 d72c4e8f 2020-10-05 op (def pages (atom nil))
28 ddc03123 2020-03-28 op (def per-tag (atom {}))
29 ddc03123 2020-03-28 op (def posts (atom []))
30 ddc03123 2020-03-28 op
31 ddc03123 2020-03-28 op (defn add-post! [m]
32 ddc03123 2020-03-28 op (let [p (post m)]
33 ddc03123 2020-03-28 op (swap! posts conj p)
34 ddc03123 2020-03-28 op (doseq [t (:tags m)]
35 ddc03123 2020-03-28 op (swap! per-tag update t conj p))))
36 ddc03123 2020-03-28 op
37 5e8f809e 2020-06-27 op (defn load-posts! []
38 5e8f809e 2020-06-27 op (reset! per-tag {})
39 5e8f809e 2020-06-27 op (reset! posts [])
40 5e8f809e 2020-06-27 op (doseq [p (-> "posts.edn"
41 5e8f809e 2020-06-27 op io/resource
42 5e8f809e 2020-06-27 op slurp
43 5e8f809e 2020-06-27 op edn/read-string)]
44 5e8f809e 2020-06-27 op (add-post! p)))
45 ddc03123 2020-03-28 op
46 d72c4e8f 2020-10-05 op (defn load-pages! []
47 d72c4e8f 2020-10-05 op (reset! pages (->> "pages.edn"
48 d72c4e8f 2020-10-05 op io/resource
49 d72c4e8f 2020-10-05 op slurp
50 d72c4e8f 2020-10-05 op edn/read-string
51 d72c4e8f 2020-10-05 op (map (fn [{:keys [slug] :as p}]
52 d72c4e8f 2020-10-05 op (assoc p :body (as-> slug $
53 d72c4e8f 2020-10-05 op (str "pages/" $ ".gmi")
54 d72c4e8f 2020-10-05 op (io/resource $)
55 d72c4e8f 2020-10-05 op (slurp $))))))))
56 d72c4e8f 2020-10-05 op
57 ddc03123 2020-03-28 op (defn create-dirs! []
58 ddc03123 2020-03-28 op (doseq [d ["resources/out"
59 52f2ea18 2020-10-03 op "resources/out/gemini"
60 d72c4e8f 2020-10-05 op "resources/out/gemini/pages"
61 52f2ea18 2020-10-03 op "resources/out/gemini/post"
62 52f2ea18 2020-10-03 op "resources/out/gemini/tag"
63 9a594f34 2020-10-14 op "resources/out/gemini/img"
64 52f2ea18 2020-10-03 op "resources/out/http"
65 52f2ea18 2020-10-03 op "resources/out/http/css"
66 d72c4e8f 2020-10-05 op "resources/out/http/pages"
67 52f2ea18 2020-10-03 op "resources/out/http/post"
68 52f2ea18 2020-10-03 op "resources/out/http/tag"
69 52f2ea18 2020-10-03 op "resources/out/http/img"]]
70 ddc03123 2020-03-28 op (.. (File. d) mkdirs)))
71 ddc03123 2020-03-28 op
72 52f2ea18 2020-10-03 op (defn gemini-post [{? :gemtext?}] ?)
73 52f2ea18 2020-10-03 op
74 52f2ea18 2020-10-03 op (defn post-pages [{:keys [proto]}]
75 52f2ea18 2020-10-03 op (let [tags (keys @per-tag)
76 52f2ea18 2020-10-03 op ext (if (= proto :gemini) ".gmi" ".html")
77 52f2ea18 2020-10-03 op ffn (if (= proto :gemini) gemini-post identity)]
78 ddc03123 2020-03-28 op (map-indexed (fn [i posts]
79 ddc03123 2020-03-28 op {:filename (if (= i 0)
80 52f2ea18 2020-10-03 op (str "index" ext)
81 52f2ea18 2020-10-03 op (str (inc i) ext))
82 ddc03123 2020-03-28 op :tags tags
83 ddc03123 2020-03-28 op :nth (inc i)
84 ddc03123 2020-03-28 op :posts posts
85 ddc03123 2020-03-28 op :has-next true
86 ddc03123 2020-03-28 op :has-prev true})
87 52f2ea18 2020-10-03 op (partition-all 6 (filter ffn @posts)))))
88 ddc03123 2020-03-28 op
89 ddc03123 2020-03-28 op (defn fix-next-last
90 ddc03123 2020-03-28 op "Fix the :has-prev/:has-next for the post pages. This assumes
91 ddc03123 2020-03-28 op that `(not (empty? post-pages))`"
92 ddc03123 2020-03-28 op [post-pages]
93 ddc03123 2020-03-28 op (-> post-pages
94 ddc03123 2020-03-28 op (->> (into []))
95 ddc03123 2020-03-28 op (update 0 assoc :has-prev false)
96 ddc03123 2020-03-28 op (update (dec (count post-pages)) assoc :has-next false)))
97 ddc03123 2020-03-28 op
98 d72c4e8f 2020-10-05 op (defn render-pages [pagefn proto ext]
99 d72c4e8f 2020-10-05 op (doseq [page @pages
100 d72c4e8f 2020-10-05 op :let [{:keys [slug]} page
101 d72c4e8f 2020-10-05 op filename (str "resources/out/"
102 d72c4e8f 2020-10-05 op (name proto) "/pages/"
103 d72c4e8f 2020-10-05 op slug ext)]]
104 d72c4e8f 2020-10-05 op (spit filename
105 d72c4e8f 2020-10-05 op (pagefn page))))
106 d72c4e8f 2020-10-05 op
107 52f2ea18 2020-10-03 op (defn render-post-list [viewfn proto]
108 52f2ea18 2020-10-03 op (doseq [p (fix-next-last (post-pages {:proto proto}))
109 ddc03123 2020-03-28 op :let [{:keys [filename]} p]]
110 52f2ea18 2020-10-03 op (spit (str "resources/out/" (name proto) "/" filename)
111 52f2ea18 2020-10-03 op (viewfn p))))
112 ddc03123 2020-03-28 op
113 52f2ea18 2020-10-03 op (defn render-post [viewfn proto ext {s :slug, :as post}]
114 52f2ea18 2020-10-03 op (spit (str "resources/out/" (name proto) "/post/" s ext)
115 52f2ea18 2020-10-03 op (viewfn post)))
116 ddc03123 2020-03-28 op
117 52f2ea18 2020-10-03 op (defn render-tags [viewfn proto ext tags]
118 52f2ea18 2020-10-03 op (spit (str "resources/out/" (name proto) "/tags" ext)
119 52f2ea18 2020-10-03 op (viewfn tags)))
120 ddc03123 2020-03-28 op
121 52f2ea18 2020-10-03 op (defn render-tag [viewfn proto ext tag posts]
122 52f2ea18 2020-10-03 op (spit (str "resources/out/" (name proto) "/tag/" tag ext)
123 52f2ea18 2020-10-03 op (viewfn tag posts)))
124 ddc03123 2020-03-28 op
125 4f9bd2e2 2020-03-30 op (defn render-rss []
126 bade790b 2020-11-05 op (spit (str "resources/out/gemini/rss.xml")
127 bade790b 2020-11-05 op (rss/feed #(str "gemini://gemini.omarpolo.com/post/" % ".gmi")
128 bade790b 2020-11-05 op (->> @posts
129 bade790b 2020-11-05 op (filter gemini-post)
130 bade790b 2020-11-05 op (map #(dissoc % :body)))))
131 52f2ea18 2020-10-03 op (spit (str "resources/out/http/rss.xml")
132 bade790b 2020-11-05 op (rss/feed #(str "https://www.omarpolo.com/post/" % ".html") @posts)))
133 4f9bd2e2 2020-03-30 op
134 ddc03123 2020-03-28 op (defn copy-dir
135 9a594f34 2020-10-14 op "Copy the content of resources/`dir` to resources/out/`proto`/`dir`, assuming
136 ddc03123 2020-03-28 op these two directories exists. It does not copy recursively."
137 9a594f34 2020-10-14 op [dir proto]
138 ddc03123 2020-03-28 op (let [in (io/file (str "resources/" dir "/"))
139 9a594f34 2020-10-14 op out (str "resources/out/" proto "/" dir "/")]
140 ddc03123 2020-03-28 op (doseq [f (->> in file-seq (filter #(.isFile %)))]
141 ddc03123 2020-03-28 op (io/copy f (io/file (str out (.getName f)))))))
142 ddc03123 2020-03-28 op
143 ddc03123 2020-03-28 op (defn copy-assets
144 ddc03123 2020-03-28 op "Copy css and images to their places"
145 ddc03123 2020-03-28 op []
146 9a594f34 2020-10-14 op (copy-dir "img" "http")
147 9a594f34 2020-10-14 op (copy-dir "img" "gemini")
148 52f2ea18 2020-10-03 op (copy-file "resources/favicon.ico" "resources/out/http/favicon.ico")
149 52f2ea18 2020-10-03 op (copy-file "resources/css/style.css" "resources/out/http/css/style.css"))
150 ddc03123 2020-03-28 op
151 52f2ea18 2020-10-03 op (comment (build)
152 52f2ea18 2020-10-03 op (count (filter gemini-post @posts))
153 52f2ea18 2020-10-03 op (gemini/post-page (first @posts))
154 52f2ea18 2020-10-03 op )
155 52f2ea18 2020-10-03 op
156 5e8f809e 2020-06-27 op (defn build
157 ddc03123 2020-03-28 op "Build the blog"
158 ddc03123 2020-03-28 op []
159 ddc03123 2020-03-28 op (create-dirs!)
160 ddc03123 2020-03-28 op (copy-assets)
161 4f9bd2e2 2020-03-30 op (render-rss)
162 d72c4e8f 2020-10-05 op (doseq [[proto ffn ext homefn postfn tagsfn tagfn pagefn]
163 d72c4e8f 2020-10-05 op [[:http identity ".html" http/home-page http/post-page http/tags-page http/tag-page http/custom-page]
164 d72c4e8f 2020-10-05 op [:gemini gemini-post ".gmi" gemini/home-page gemini/post-page gemini/tags-page gemini/tag-page gemini/custom-page]]]
165 d72c4e8f 2020-10-05 op (render-pages pagefn proto ext)
166 52f2ea18 2020-10-03 op (render-post-list homefn proto)
167 52f2ea18 2020-10-03 op (doseq [p (filter ffn @posts)]
168 52f2ea18 2020-10-03 op (render-post postfn proto ext p))
169 52f2ea18 2020-10-03 op (render-tags tagsfn proto ext (keys @per-tag))
170 52f2ea18 2020-10-03 op (doseq [t @per-tag
171 52f2ea18 2020-10-03 op :let [[tag posts] t]]
172 52f2ea18 2020-10-03 op (render-tag tagfn proto ext (name tag) (filter ffn posts)))))
173 ddc03123 2020-03-28 op
174 ddc03123 2020-03-28 op (def j (atom nil))
175 ddc03123 2020-03-28 op
176 5e8f809e 2020-06-27 op (defn serve
177 ddc03123 2020-03-28 op "Serve a preview"
178 ddc03123 2020-03-28 op []
179 ddc03123 2020-03-28 op (reset!
180 ddc03123 2020-03-28 op j
181 ddc03123 2020-03-28 op (jetty/run-jetty (-> (fn [_] {:status 404, :body "not found"})
182 ddc03123 2020-03-28 op (wrap-resource "out")
183 ddc03123 2020-03-28 op (wrap-content-type))
184 30bd347e 2020-08-04 op {:port 3030
185 ddc03123 2020-03-28 op :join? false})))
186 ddc03123 2020-03-28 op
187 5e8f809e 2020-06-27 op (defn clean
188 60905fa3 2020-03-29 op "clean the output directory"
189 60905fa3 2020-03-29 op []
190 52f2ea18 2020-10-03 op (sh "rm" "-rf" "resources/out/http/")
191 52f2ea18 2020-10-03 op (sh "rm" "-rf" "resources/out/gemini/"))
192 60905fa3 2020-03-29 op
193 4696276a 2020-09-22 op (defn local-deploy
194 4696276a 2020-09-22 op "Copy the files to the local server"
195 4696276a 2020-09-22 op []
196 52f2ea18 2020-10-03 op (sh "rsync" "-r" "--delete" "resources/out/http/" "/var/www/omarpolo.local/"))
197 4696276a 2020-09-22 op
198 5e8f809e 2020-06-27 op (defn deploy
199 ddc03123 2020-03-28 op "Copy the files to the server"
200 ddc03123 2020-03-28 op []
201 52f2ea18 2020-10-03 op (sh "rsync" "-r" "--delete" "resources/out/http/" "op:sites/www.omarpolo.com/")
202 52f2ea18 2020-10-03 op (sh "rsync" "-r" "--delete" "resources/out/gemini/" "op:gemini"))
203 ddc03123 2020-03-28 op
204 ddc03123 2020-03-28 op (defn stop-jetty []
205 ddc03123 2020-03-28 op (.stop @j)
206 ddc03123 2020-03-28 op (reset! j nil))
207 ddc03123 2020-03-28 op
208 5e8f809e 2020-06-27 op (defn -main [& actions]
209 5e8f809e 2020-06-27 op (load-posts!)
210 d72c4e8f 2020-10-05 op (load-pages!)
211 5e8f809e 2020-06-27 op (doseq [action actions]
212 5e8f809e 2020-06-27 op (case action
213 5e8f809e 2020-06-27 op "clean" (clean)
214 5e8f809e 2020-06-27 op "build" (build)
215 5e8f809e 2020-06-27 op "deploy" (deploy)
216 5e8f809e 2020-06-27 op
217 5e8f809e 2020-06-27 op (println "unrecognized action" action))))
218 5e8f809e 2020-06-27 op
219 ddc03123 2020-03-28 op (comment
220 6776a2f2 2020-09-20 op (do
221 6776a2f2 2020-09-20 op (load-posts!)
222 d72c4e8f 2020-10-05 op (load-pages!)
223 d72c4e8f 2020-10-05 op ;; (clean)
224 4696276a 2020-09-22 op (build)
225 4696276a 2020-09-22 op (local-deploy))
226 ddc03123 2020-03-28 op (serve)
227 ddc03123 2020-03-28 op (stop-jetty)
228 4696276a 2020-09-22 op
229 4696276a 2020-09-22 op (do
230 4696276a 2020-09-22 op (deploy)
231 4696276a 2020-09-22 op (local-deploy))
232 ddc03123 2020-03-28 op )