(ns sitetools.server
"Used to pre-render HTML files."
(:require [clojure.string :as string]
[goog.events :as evt]
[reagent.core :as r]
[reagent.dom.server :as server]
[reagent.debug :refer-macros [dbg log dev?]]
[reagent.interop :as i :refer-macros [$ $!]]
[sitetools.core :as tools]))
;;; Static site generation
(defn base [page]
(let [depth (->> page tools/to-relative (re-seq #"/") count)]
(->> "../" (repeat depth) (apply str))))
(defn danger [t s]
[t {:dangerouslySetInnerHTML {:__html s}}])
(defn html-template [{:keys [title body-html timestamp page-conf
js-file css-file main-div]}]
(let [main (str js-file timestamp)]
(server/render-to-static-markup
[:html
[:head
[:meta {:charset 'utf-8}]
[:meta {:name 'viewport
:content "width=device-width, initial-scale=1.0"}]
[:base {:href (-> page-conf :page-path base)}]
[:link {:href (str css-file timestamp) :rel 'stylesheet}]
[:title title]]
[:body
[:div {:id main-div} (danger :div body-html)]
(danger :script (str "var pageConfig = "
(-> page-conf clj->js js/JSON.stringify)))
[:script {:src main :type "text/javascript"}]]])))
(defn gen-page [page-path conf]
(tools/emit [:set-page page-path])
(let [conf (merge conf @tools/config)
b (:body conf)
bhtml (server/render-to-string b)]
(str "\n"
(html-template (assoc conf
:page-conf {:page-path page-path}
:body-html bhtml)))))
(defn fs [] (js/require "fs"))
(defn path [] (js/require "path"))
(defn mkdirs [f]
(doseq [d (reductions #(str %1 "/" %2)
(-> ($ (path) normalize f)
(string/split #"/")))]
(when-not ($ (fs) existsSync d)
($ (fs) mkdirSync d))))
(defn write-file [f content]
(mkdirs ($ (path) dirname f))
($ (fs) writeFileSync f content))
(defn path-join [& paths]
(apply ($ (path) :join) paths))
(defn write-resources [dir {:keys [css-file css-infiles]}]
(write-file (path-join dir css-file)
(->> css-infiles
(map #($ (fs) readFileSync %))
(string/join "\n"))))
;;; Main entry points
(defn ^:export genpages [opts]
(log "Generating site")
(let [conf (swap! tools/config merge (js->clj opts :keywordize-keys true))
conf (assoc conf :timestamp (str "?" (js/Date.now)))
{:keys [site-dir pages]} conf]
(doseq [f (keys pages)]
(write-file (->> f tools/to-relative (path-join site-dir))
(gen-page f conf)))
(write-resources site-dir conf))
(log "Wrote site"))