2014-12-05 15:56:40 +00:00
|
|
|
(ns cryogen-core.compiler
|
2017-01-16 07:37:19 +00:00
|
|
|
(:require [clojure.java.io :as io]
|
2017-01-17 04:12:53 +00:00
|
|
|
[clojure.pprint :refer [pprint]]
|
2014-12-04 16:38:48 +00:00
|
|
|
[clojure.string :as s]
|
2017-01-16 07:37:19 +00:00
|
|
|
[io.aviso.exception :refer [write-exception]]
|
2017-01-15 08:30:25 +00:00
|
|
|
[net.cgrand.enlive-html :as enlive]
|
2017-01-16 07:37:19 +00:00
|
|
|
[selmer.parser :refer [cache-off! render-file]]
|
|
|
|
[selmer.util :refer [set-custom-resource-path!]]
|
2014-12-04 16:38:48 +00:00
|
|
|
[text-decoration.core :refer :all]
|
2017-01-16 07:37:19 +00:00
|
|
|
[cryogen-core.io :as cryogen-io]
|
2017-01-19 17:33:38 +00:00
|
|
|
[cryogen-core.klipse :as klipse]
|
2015-07-08 20:34:39 +00:00
|
|
|
[cryogen-core.markup :as m]
|
2017-01-04 08:33:34 +00:00
|
|
|
[cryogen-core.rss :as rss]
|
2017-01-16 07:37:19 +00:00
|
|
|
[cryogen-core.sass :as sass]
|
2015-07-08 20:34:39 +00:00
|
|
|
[cryogen-core.sitemap :as sitemap]
|
2017-02-08 08:13:45 +00:00
|
|
|
[clojure.inspector :as inspector]
|
2017-02-08 18:22:15 +00:00
|
|
|
[cryogen-core.toc :as toc]
|
|
|
|
[cryogen-core.navbar-model :as navbar-model])
|
2015-08-05 21:27:54 +00:00
|
|
|
(:import java.util.Locale))
|
2014-12-04 16:38:48 +00:00
|
|
|
|
|
|
|
(cache-off!)
|
|
|
|
|
2015-11-08 13:33:07 +00:00
|
|
|
(defn root-uri
|
2016-01-09 01:44:07 +00:00
|
|
|
"Creates the uri for posts and pages. Returns root-path by default"
|
2015-11-08 13:33:07 +00:00
|
|
|
[k config]
|
|
|
|
(if-let [uri (k config)]
|
|
|
|
uri
|
|
|
|
(config (-> k (name) (s/replace #"-uri$" "") (keyword)))))
|
2014-12-04 16:38:48 +00:00
|
|
|
|
2015-01-28 21:19:01 +00:00
|
|
|
(defn re-pattern-from-ext
|
|
|
|
"Creates a properly quoted regex pattern for the given file extension"
|
|
|
|
[ext]
|
|
|
|
(re-pattern (str (s/replace ext "." "\\.") "$")))
|
|
|
|
|
2016-05-24 05:20:36 +00:00
|
|
|
(defn find-entries
|
|
|
|
"Returns a list of files under the templates directory according to the
|
|
|
|
implemented Markup protocol and specified root directory. It defaults to
|
|
|
|
looking under the implemented protocol's subdirectory, but fallsback to look
|
|
|
|
at the templates directory."
|
|
|
|
[root mu ignored-files]
|
2017-01-16 07:37:19 +00:00
|
|
|
(let [assets (cryogen-io/find-assets
|
|
|
|
(cryogen-io/path "templates" (m/dir mu) root)
|
|
|
|
(m/ext mu)
|
|
|
|
ignored-files)]
|
2016-05-24 05:20:36 +00:00
|
|
|
(if (seq assets)
|
|
|
|
assets
|
2017-01-16 07:37:19 +00:00
|
|
|
(cryogen-io/find-assets
|
|
|
|
(cryogen-io/path "templates" root)
|
|
|
|
(m/ext mu)
|
|
|
|
ignored-files))))
|
2016-05-24 05:20:36 +00:00
|
|
|
|
2014-12-05 21:37:04 +00:00
|
|
|
(defn find-posts
|
2016-05-24 05:20:36 +00:00
|
|
|
"Returns a list of markdown files representing posts under the post root."
|
2014-12-30 12:31:46 +00:00
|
|
|
[{:keys [post-root ignored-files]} mu]
|
2016-05-24 05:20:36 +00:00
|
|
|
(find-entries post-root mu ignored-files))
|
2014-12-04 16:38:48 +00:00
|
|
|
|
2014-12-05 21:37:04 +00:00
|
|
|
(defn find-pages
|
2016-05-24 05:20:36 +00:00
|
|
|
"Returns a list of markdown files representing pages under the page root."
|
2014-12-30 12:31:46 +00:00
|
|
|
[{:keys [page-root ignored-files]} mu]
|
2016-05-24 05:20:36 +00:00
|
|
|
(find-entries page-root mu ignored-files))
|
2014-12-04 16:38:48 +00:00
|
|
|
|
2014-12-05 21:37:04 +00:00
|
|
|
(defn parse-post-date
|
|
|
|
"Parses the post date from the post's file name and returns the corresponding java date object"
|
2015-09-14 10:06:35 +00:00
|
|
|
[^String file-name date-fmt]
|
2014-12-04 16:38:48 +00:00
|
|
|
(let [fmt (java.text.SimpleDateFormat. date-fmt)]
|
|
|
|
(.parse fmt (.substring file-name 0 10))))
|
|
|
|
|
2014-12-05 21:37:04 +00:00
|
|
|
(defn page-uri
|
2016-02-12 02:04:56 +00:00
|
|
|
"Creates a URI from file name. `uri-type` is any of the uri types specified in config, e.g., `:post-root-uri`."
|
|
|
|
([file-name params]
|
|
|
|
(page-uri file-name nil params))
|
|
|
|
([file-name uri-type {:keys [blog-prefix clean-urls?] :as params}]
|
2017-01-16 07:37:19 +00:00
|
|
|
(let [page-uri (get params uri-type)
|
|
|
|
uri-end (if clean-urls? (s/replace file-name #"(index)?\.html" "/") file-name)]
|
|
|
|
(cryogen-io/path "/" blog-prefix page-uri uri-end))))
|
2014-12-04 16:38:48 +00:00
|
|
|
|
2014-12-05 21:37:04 +00:00
|
|
|
(defn read-page-meta
|
|
|
|
"Returns the clojure map from the top of a markdown page/post"
|
|
|
|
[page rdr]
|
2014-12-04 16:38:48 +00:00
|
|
|
(try
|
|
|
|
(read rdr)
|
|
|
|
(catch Exception _
|
|
|
|
(throw (IllegalArgumentException. (str "Malformed metadata on page: " page))))))
|
|
|
|
|
2014-12-30 12:31:46 +00:00
|
|
|
(defn page-content
|
|
|
|
"Returns a map with the given page's file-name, metadata and content parsed from
|
|
|
|
the file with the given markup."
|
2015-09-14 10:06:35 +00:00
|
|
|
[^java.io.File page config markup]
|
2017-01-16 07:37:19 +00:00
|
|
|
(with-open [rdr (java.io.PushbackReader. (io/reader page))]
|
|
|
|
(let [re-root (re-pattern (str "^.*?(" (:page-root config) "|" (:post-root config) ")/"))
|
|
|
|
page-fwd (s/replace (str page) "\\" "/") ;; make it work on Windows
|
2016-12-17 10:29:16 +00:00
|
|
|
page-name (s/replace page-fwd re-root "")
|
2015-01-28 21:19:01 +00:00
|
|
|
file-name (s/replace page-name (re-pattern-from-ext (m/ext markup)) ".html")
|
2014-12-04 16:38:48 +00:00
|
|
|
page-meta (read-page-meta page-name rdr)
|
2017-01-16 07:37:19 +00:00
|
|
|
content ((m/render-fn markup) rdr config)]
|
2014-12-30 12:31:46 +00:00
|
|
|
{:file-name file-name
|
|
|
|
:page-meta page-meta
|
2015-07-08 20:34:39 +00:00
|
|
|
:content content})))
|
2014-12-30 12:31:46 +00:00
|
|
|
|
|
|
|
(defn merge-meta-and-content
|
|
|
|
"Merges the page metadata and content maps, adding :toc if necessary."
|
|
|
|
[file-name page-meta content]
|
|
|
|
(merge
|
2015-07-08 20:34:39 +00:00
|
|
|
(update-in page-meta [:layout] #(str (name %) ".html"))
|
|
|
|
{:file-name file-name
|
|
|
|
:content content
|
2015-10-25 23:14:43 +00:00
|
|
|
:toc (if-let [toc (:toc page-meta)]
|
2017-01-16 07:37:19 +00:00
|
|
|
(toc/generate-toc content :list-type toc))}))
|
2014-12-30 12:31:46 +00:00
|
|
|
|
|
|
|
(defn parse-page
|
|
|
|
"Parses a page/post and returns a map of the content, uri, date etc."
|
|
|
|
[page config markup]
|
|
|
|
(let [{:keys [file-name page-meta content]} (page-content page config markup)]
|
|
|
|
(merge
|
2015-07-08 20:34:39 +00:00
|
|
|
(merge-meta-and-content file-name page-meta content)
|
2016-02-12 02:04:56 +00:00
|
|
|
{:uri (page-uri file-name :page-root-uri config)
|
2017-01-19 17:33:38 +00:00
|
|
|
:page-index (:page-index page-meta)
|
2017-01-27 05:57:33 +00:00
|
|
|
:klipse (klipse/merge-configs (:klipse config) (:klipse page-meta))})))
|
2014-12-30 12:31:46 +00:00
|
|
|
|
|
|
|
(defn parse-post
|
|
|
|
"Return a map with the given post's information."
|
|
|
|
[page config markup]
|
|
|
|
(let [{:keys [file-name page-meta content]} (page-content page config markup)]
|
|
|
|
(merge
|
2015-07-08 20:34:39 +00:00
|
|
|
(merge-meta-and-content file-name page-meta content)
|
2017-01-16 07:37:19 +00:00
|
|
|
(let [date (if (:date page-meta)
|
|
|
|
(.parse (java.text.SimpleDateFormat. (:post-date-format config)) (:date page-meta))
|
|
|
|
(parse-post-date file-name (:post-date-format config)))
|
|
|
|
archive-fmt (java.text.SimpleDateFormat. (:archive-group-format config "yyyy MMMM") (Locale/getDefault))
|
2015-07-08 20:34:39 +00:00
|
|
|
formatted-group (.format archive-fmt date)]
|
|
|
|
{:date date
|
|
|
|
:formatted-archive-group formatted-group
|
|
|
|
:parsed-archive-group (.parse archive-fmt formatted-group)
|
2016-02-12 02:04:56 +00:00
|
|
|
:uri (page-uri file-name :post-root-uri config)
|
2017-01-19 17:33:38 +00:00
|
|
|
:tags (set (:tags page-meta))
|
2017-01-27 05:57:33 +00:00
|
|
|
:klipse (klipse/merge-configs (:klipse config) (:klipse page-meta))}))))
|
2014-12-04 16:38:48 +00:00
|
|
|
|
2014-12-05 21:37:04 +00:00
|
|
|
(defn read-posts
|
|
|
|
"Returns a sequence of maps representing the data from markdown files of posts.
|
|
|
|
Sorts the sequence by post date."
|
|
|
|
[config]
|
2017-01-16 07:37:19 +00:00
|
|
|
(->> (m/markups)
|
|
|
|
(mapcat
|
2015-07-08 20:34:39 +00:00
|
|
|
(fn [mu]
|
|
|
|
(->>
|
|
|
|
(find-posts config mu)
|
2015-12-17 19:36:09 +00:00
|
|
|
(pmap #(parse-post % config mu))
|
2017-01-16 07:37:19 +00:00
|
|
|
(remove #(= (:draft? %) true)))))
|
2014-12-04 16:38:48 +00:00
|
|
|
(sort-by :date)
|
2016-12-13 20:59:09 +00:00
|
|
|
reverse
|
2016-12-19 00:22:29 +00:00
|
|
|
(drop-while #(and (:hide-future-posts? config) (.after (:date %) (java.util.Date.))))))
|
2014-12-04 16:38:48 +00:00
|
|
|
|
2014-12-05 21:37:04 +00:00
|
|
|
(defn read-pages
|
|
|
|
"Returns a sequence of maps representing the data from markdown files of pages.
|
2014-12-30 12:31:46 +00:00
|
|
|
Sorts the sequence by post date."
|
2014-12-05 21:37:04 +00:00
|
|
|
[config]
|
2017-01-16 07:37:19 +00:00
|
|
|
(->> (m/markups)
|
|
|
|
(mapcat
|
2015-07-08 20:34:39 +00:00
|
|
|
(fn [mu]
|
|
|
|
(->>
|
|
|
|
(find-pages config mu)
|
2017-01-16 07:37:19 +00:00
|
|
|
(map #(parse-page % config mu)))))
|
2014-12-04 16:38:48 +00:00
|
|
|
(sort-by :page-index)))
|
|
|
|
|
2014-12-05 21:37:04 +00:00
|
|
|
(defn tag-post
|
|
|
|
"Adds the uri and title of a post to the list of posts under each of its tags"
|
|
|
|
[tags post]
|
2014-12-04 16:38:48 +00:00
|
|
|
(reduce (fn [tags tag]
|
2015-09-03 16:27:55 +00:00
|
|
|
(update-in tags [tag] (fnil conj []) (select-keys post [:uri :title :content :date :enclosure])))
|
2017-01-16 07:37:19 +00:00
|
|
|
tags
|
|
|
|
(:tags post)))
|
2014-12-04 16:38:48 +00:00
|
|
|
|
2014-12-05 21:37:04 +00:00
|
|
|
(defn group-by-tags
|
|
|
|
"Maps all the tags with a list of posts that contain each tag"
|
|
|
|
[posts]
|
2014-12-04 16:38:48 +00:00
|
|
|
(reduce tag-post {} posts))
|
|
|
|
|
2014-12-05 21:37:04 +00:00
|
|
|
(defn group-for-archive
|
|
|
|
"Groups the posts by month and year for archive sorting"
|
|
|
|
[posts]
|
2014-12-04 16:38:48 +00:00
|
|
|
(->> posts
|
|
|
|
(map #(select-keys % [:title :uri :date :formatted-archive-group :parsed-archive-group]))
|
|
|
|
(group-by :formatted-archive-group)
|
|
|
|
(map (fn [[group posts]]
|
|
|
|
{:group group
|
|
|
|
:parsed-group (:parsed-archive-group (get posts 0))
|
|
|
|
:posts (map #(select-keys % [:title :uri :date]) posts)}))
|
|
|
|
(sort-by :parsed-group)
|
|
|
|
reverse))
|
|
|
|
|
2016-02-10 02:13:06 +00:00
|
|
|
(defn group-for-author
|
|
|
|
"Groups the posts by author. If no post author if found defaults `default-author`."
|
|
|
|
[posts default-author]
|
|
|
|
(->> posts
|
|
|
|
(map #(select-keys % [:title :uri :date :formatted-archive-group :parsed-archive-group :author]))
|
|
|
|
(map #(update % :author (fn [author] (or author default-author))))
|
|
|
|
(group-by :author)
|
|
|
|
(map (fn [[author posts]]
|
|
|
|
{:author author
|
|
|
|
:posts posts}))))
|
|
|
|
|
2014-12-05 21:37:04 +00:00
|
|
|
(defn tag-info
|
|
|
|
"Returns a map containing the name and uri of the specified tag"
|
2016-02-12 02:04:56 +00:00
|
|
|
[config tag]
|
2014-12-04 16:38:48 +00:00
|
|
|
{:name (name tag)
|
2016-02-12 02:04:56 +00:00
|
|
|
:uri (page-uri (str (name tag) ".html") :tag-root-uri config)})
|
2014-12-04 16:38:48 +00:00
|
|
|
|
2014-12-05 21:37:04 +00:00
|
|
|
(defn add-prev-next
|
2017-01-17 04:12:53 +00:00
|
|
|
"Adds a :prev and :next key to the page/post data containing the metadata of the prev/next
|
2014-12-05 21:37:04 +00:00
|
|
|
post/page if it exists"
|
|
|
|
[pages]
|
2014-12-04 16:38:48 +00:00
|
|
|
(map (fn [[prev target next]]
|
|
|
|
(assoc target
|
2017-01-17 04:12:53 +00:00
|
|
|
:prev (if prev (dissoc prev :content) nil)
|
|
|
|
:next (if next (dissoc next :content) nil)))
|
2014-12-04 16:38:48 +00:00
|
|
|
(partition 3 1 (flatten [nil pages nil]))))
|
|
|
|
|
2014-12-05 21:37:04 +00:00
|
|
|
(defn group-pages
|
|
|
|
"Separates the pages into links for the navbar and links for the sidebar"
|
|
|
|
[pages]
|
2014-12-04 16:38:48 +00:00
|
|
|
(let [{navbar-pages true
|
|
|
|
sidebar-pages false} (group-by #(boolean (:navbar? %)) pages)]
|
|
|
|
(map (partial sort-by :page-index) [navbar-pages sidebar-pages])))
|
|
|
|
|
2016-02-12 02:04:56 +00:00
|
|
|
(defn write-html
|
|
|
|
"When `clean-urls?` is set, appends `/index.html` before spit; otherwise just spits."
|
|
|
|
[file-uri {:keys [clean-urls?]} data]
|
|
|
|
(if clean-urls?
|
2017-01-16 07:37:19 +00:00
|
|
|
(cryogen-io/create-file-recursive (cryogen-io/path file-uri "index.html") data)
|
|
|
|
(cryogen-io/create-file file-uri data)))
|
2016-02-12 02:04:56 +00:00
|
|
|
|
2017-01-17 04:12:53 +00:00
|
|
|
(defn- print-debug-info [data]
|
|
|
|
(println "DEBUG:")
|
|
|
|
(pprint data))
|
2016-02-12 02:04:56 +00:00
|
|
|
|
2014-12-05 21:37:04 +00:00
|
|
|
(defn compile-pages
|
|
|
|
"Compiles all the pages into html and spits them out into the public folder"
|
2016-12-31 10:20:09 +00:00
|
|
|
[{:keys [blog-prefix page-root-uri debug?] :as params} pages]
|
2014-12-04 16:38:48 +00:00
|
|
|
(when-not (empty? pages)
|
|
|
|
(println (blue "compiling pages"))
|
2017-01-16 07:37:19 +00:00
|
|
|
(cryogen-io/create-folder (cryogen-io/path "/" blog-prefix page-root-uri))
|
2014-12-04 16:38:48 +00:00
|
|
|
(doseq [{:keys [uri] :as page} pages]
|
2017-01-17 04:12:53 +00:00
|
|
|
(println "-->" (cyan uri))
|
2016-12-31 10:20:09 +00:00
|
|
|
(when debug?
|
2017-01-17 04:12:53 +00:00
|
|
|
(print-debug-info page))
|
2016-02-12 02:04:56 +00:00
|
|
|
(write-html uri
|
|
|
|
params
|
|
|
|
(render-file (str "/html/" (:layout page))
|
|
|
|
(merge params
|
|
|
|
{:active-page "pages"
|
2016-12-30 22:43:13 +00:00
|
|
|
:home false
|
2017-01-16 07:37:19 +00:00
|
|
|
:servlet-context (cryogen-io/path "/" blog-prefix "/")
|
2016-02-12 02:04:56 +00:00
|
|
|
:page page
|
|
|
|
:uri uri}))))))
|
2014-12-04 16:38:48 +00:00
|
|
|
|
2014-12-05 21:37:04 +00:00
|
|
|
(defn compile-posts
|
|
|
|
"Compiles all the posts into html and spits them out into the public folder"
|
2016-12-31 14:48:52 +00:00
|
|
|
[{:keys [blog-prefix post-root-uri disqus-shortname debug?] :as params} posts]
|
2014-12-04 16:38:48 +00:00
|
|
|
(when-not (empty? posts)
|
|
|
|
(println (blue "compiling posts"))
|
2017-01-16 07:37:19 +00:00
|
|
|
(cryogen-io/create-folder (cryogen-io/path "/" blog-prefix post-root-uri))
|
|
|
|
(doseq [{:keys [uri] :as post} posts]
|
2017-01-17 04:12:53 +00:00
|
|
|
(println "-->" (cyan uri))
|
2016-12-31 14:48:52 +00:00
|
|
|
(when debug?
|
2017-01-17 04:12:53 +00:00
|
|
|
(print-debug-info post))
|
2017-01-16 07:37:19 +00:00
|
|
|
(write-html uri
|
2016-02-12 02:04:56 +00:00
|
|
|
params
|
|
|
|
(render-file (str "/html/" (:layout post))
|
|
|
|
(merge params
|
|
|
|
{:active-page "posts"
|
2017-01-16 07:37:19 +00:00
|
|
|
:servlet-context (cryogen-io/path "/" blog-prefix "/")
|
2016-02-12 02:04:56 +00:00
|
|
|
:post post
|
|
|
|
:disqus-shortname disqus-shortname
|
2017-01-16 07:37:19 +00:00
|
|
|
:uri uri}))))))
|
2014-12-04 16:38:48 +00:00
|
|
|
|
2014-12-05 21:37:04 +00:00
|
|
|
(defn compile-tags
|
|
|
|
"Compiles all the tag pages into html and spits them out into the public folder"
|
2015-11-08 13:33:07 +00:00
|
|
|
[{:keys [blog-prefix tag-root-uri] :as params} posts-by-tag]
|
2014-12-04 16:38:48 +00:00
|
|
|
(when-not (empty? posts-by-tag)
|
|
|
|
(println (blue "compiling tags"))
|
2017-01-16 07:37:19 +00:00
|
|
|
(cryogen-io/create-folder (cryogen-io/path "/" blog-prefix tag-root-uri))
|
2014-12-04 16:38:48 +00:00
|
|
|
(doseq [[tag posts] posts-by-tag]
|
2015-02-23 18:14:31 +00:00
|
|
|
(let [{:keys [name uri]} (tag-info params tag)]
|
2017-01-17 04:12:53 +00:00
|
|
|
(println "-->" (cyan uri))
|
2016-02-12 02:04:56 +00:00
|
|
|
(write-html uri
|
|
|
|
params
|
|
|
|
(render-file "/html/tag.html"
|
|
|
|
(merge params
|
|
|
|
{:active-page "tags"
|
2017-01-16 07:37:19 +00:00
|
|
|
:servlet-context (cryogen-io/path "/" blog-prefix "/")
|
2016-02-12 02:04:56 +00:00
|
|
|
:name name
|
|
|
|
:posts posts
|
|
|
|
:uri uri})))))))
|
2014-12-04 16:38:48 +00:00
|
|
|
|
2015-07-08 16:15:11 +00:00
|
|
|
(defn compile-tags-page [{:keys [blog-prefix] :as params}]
|
2017-01-16 07:37:19 +00:00
|
|
|
"Compiles a page with links to each tag page. Spits the page into the public folder"
|
2015-07-08 16:15:11 +00:00
|
|
|
(println (blue "compiling tags page"))
|
2016-02-12 02:04:56 +00:00
|
|
|
(let [uri (page-uri "tags.html" params)]
|
|
|
|
(write-html uri
|
|
|
|
params
|
|
|
|
(render-file "/html/tags.html"
|
|
|
|
(merge params
|
2017-01-16 07:37:19 +00:00
|
|
|
{:active-page "tags"
|
|
|
|
:servlet-context (cryogen-io/path "/" blog-prefix "/")
|
|
|
|
:uri uri})))))
|
2015-07-08 16:15:11 +00:00
|
|
|
|
2015-09-17 15:13:45 +00:00
|
|
|
(defn content-until-more-marker
|
2017-01-15 08:30:25 +00:00
|
|
|
"Returns the content until the <!--more--> special comment,
|
|
|
|
closing any unclosed tags. Returns nil if there's no such comment."
|
|
|
|
[content]
|
|
|
|
(when-let [index (s/index-of content "<!--more-->")]
|
|
|
|
(->> (subs content 0 index)
|
|
|
|
enlive/html-snippet
|
|
|
|
enlive/emit*
|
|
|
|
(apply str))))
|
2015-09-17 15:13:45 +00:00
|
|
|
|
2015-07-08 20:34:39 +00:00
|
|
|
(defn create-preview
|
|
|
|
"Creates a single post preview"
|
|
|
|
[blocks-per-preview post]
|
2017-01-15 08:30:25 +00:00
|
|
|
(update post :content
|
|
|
|
#(or (content-until-more-marker %)
|
|
|
|
(->> (enlive/html-snippet %)
|
|
|
|
(take blocks-per-preview)
|
|
|
|
enlive/emit*
|
|
|
|
(apply str)))))
|
2015-07-08 20:34:39 +00:00
|
|
|
|
|
|
|
(defn create-previews
|
|
|
|
"Returns a sequence of vectors, each containing a set of post previews"
|
2017-01-16 07:37:19 +00:00
|
|
|
[posts posts-per-page blocks-per-preview]
|
2015-07-08 20:34:39 +00:00
|
|
|
(->> posts
|
2015-09-18 20:22:40 +00:00
|
|
|
(map #(create-preview blocks-per-preview %))
|
2015-07-08 20:34:39 +00:00
|
|
|
(partition-all posts-per-page)
|
|
|
|
(map-indexed (fn [i v] {:index (inc i) :posts v}))))
|
|
|
|
|
|
|
|
(defn create-preview-links
|
|
|
|
"Turn each vector of previews into a map with :prev and :next keys that contain the uri of the
|
|
|
|
prev/next preview page"
|
2016-02-12 02:04:56 +00:00
|
|
|
[previews params]
|
2015-07-08 20:34:39 +00:00
|
|
|
(mapv (fn [[prev target next]]
|
|
|
|
(merge target
|
2017-01-16 07:37:19 +00:00
|
|
|
{:prev (if prev (page-uri (cryogen-io/path "p" (str (:index prev) ".html")) params) nil)
|
|
|
|
:next (if next (page-uri (cryogen-io/path "p" (str (:index next) ".html")) params) nil)}))
|
2015-07-08 20:34:39 +00:00
|
|
|
(partition 3 1 (flatten [nil previews nil]))))
|
|
|
|
|
|
|
|
(defn compile-preview-pages
|
|
|
|
"Compiles a series of pages containing 'previews' from each post"
|
|
|
|
[{:keys [blog-prefix posts-per-page blocks-per-preview] :as params} posts]
|
|
|
|
(when-not (empty? posts)
|
2017-01-16 07:37:19 +00:00
|
|
|
(let [previews (-> posts
|
|
|
|
(create-previews posts-per-page blocks-per-preview)
|
2016-02-12 02:04:56 +00:00
|
|
|
(create-preview-links params))
|
2017-01-16 07:37:19 +00:00
|
|
|
previews (if (> (count previews) 1)
|
|
|
|
(assoc-in previews [1 :prev] (page-uri "index.html" params))
|
|
|
|
previews)]
|
|
|
|
(cryogen-io/create-folder (cryogen-io/path "/" blog-prefix "p"))
|
2016-02-04 11:43:47 +00:00
|
|
|
(doseq [{:keys [index posts prev next]} previews
|
|
|
|
:let [index-page? (= 1 index)]]
|
2017-01-16 07:37:19 +00:00
|
|
|
(write-html
|
|
|
|
(if index-page? (page-uri "index.html" params)
|
|
|
|
(page-uri (cryogen-io/path "p" (str index ".html")) params))
|
|
|
|
params
|
|
|
|
(render-file "/html/previews.html"
|
|
|
|
(merge params
|
|
|
|
{:active-page "preview"
|
|
|
|
:home (when index-page? true)
|
|
|
|
:servlet-context (cryogen-io/path "/" blog-prefix "/")
|
|
|
|
:posts posts
|
|
|
|
:prev-uri prev
|
|
|
|
:next-uri next})))))))
|
2015-07-08 20:34:39 +00:00
|
|
|
|
2014-12-05 21:37:04 +00:00
|
|
|
(defn compile-index
|
|
|
|
"Compiles the index page into html and spits it out into the public folder"
|
2017-01-16 07:37:19 +00:00
|
|
|
[{:keys [disqus? debug? home-page] :as params}]
|
2014-12-04 16:38:48 +00:00
|
|
|
(println (blue "compiling index"))
|
2017-01-17 04:12:53 +00:00
|
|
|
(let [uri (page-uri "index.html" params)]
|
2016-12-31 10:20:09 +00:00
|
|
|
(when debug?
|
2017-01-17 04:12:53 +00:00
|
|
|
(print-debug-info meta))
|
2016-02-12 02:04:56 +00:00
|
|
|
(write-html uri
|
|
|
|
params
|
2016-12-30 22:43:13 +00:00
|
|
|
(render-file (str "/html/" (:layout home-page))
|
2016-02-12 02:04:56 +00:00
|
|
|
(merge params
|
2017-01-17 04:12:53 +00:00
|
|
|
{:active-page "home"
|
|
|
|
:home true
|
|
|
|
:disqus? disqus?
|
|
|
|
:uri uri
|
2017-01-17 06:56:14 +00:00
|
|
|
:post home-page
|
|
|
|
:page home-page})))))
|
2014-12-04 16:38:48 +00:00
|
|
|
|
2014-12-05 21:37:04 +00:00
|
|
|
(defn compile-archives
|
|
|
|
"Compiles the archives page into html and spits it out into the public folder"
|
2015-02-23 18:14:31 +00:00
|
|
|
[{:keys [blog-prefix] :as params} posts]
|
2014-12-04 16:38:48 +00:00
|
|
|
(println (blue "compiling archives"))
|
2016-02-12 02:04:56 +00:00
|
|
|
(let [uri (page-uri "archives.html" params)]
|
|
|
|
(write-html uri
|
|
|
|
params
|
|
|
|
(render-file "/html/archives.html"
|
|
|
|
(merge params
|
2017-01-16 07:37:19 +00:00
|
|
|
{:active-page "archives"
|
|
|
|
:archives true
|
|
|
|
:groups (group-for-archive posts)
|
|
|
|
:servlet-context (cryogen-io/path "/" blog-prefix "/")
|
|
|
|
:uri uri})))))
|
2014-12-04 16:38:48 +00:00
|
|
|
|
2016-02-10 02:13:06 +00:00
|
|
|
(defn compile-authors
|
|
|
|
"For each author, creates a page with filtered posts."
|
|
|
|
[{:keys [blog-prefix author-root-uri author] :as params} posts]
|
|
|
|
(println (blue "compiling authors"))
|
2017-01-16 07:37:19 +00:00
|
|
|
(cryogen-io/create-folder (cryogen-io/path "/" blog-prefix author-root-uri))
|
2016-02-10 02:13:06 +00:00
|
|
|
;; if the post author is empty defaults to config's :author
|
|
|
|
(doseq [{:keys [author posts]} (group-for-author posts author)]
|
2016-02-12 02:04:56 +00:00
|
|
|
(let [uri (page-uri (str author ".html") :author-root-uri params)]
|
2017-01-17 04:12:53 +00:00
|
|
|
(println "-->" (cyan uri))
|
2016-02-12 02:04:56 +00:00
|
|
|
(write-html uri
|
|
|
|
params
|
|
|
|
(render-file "/html/author.html"
|
|
|
|
(merge params
|
|
|
|
{:author author
|
|
|
|
:groups (group-for-archive posts)
|
2017-01-16 07:37:19 +00:00
|
|
|
:servlet-context (cryogen-io/path "/" blog-prefix "/")
|
2016-02-12 02:04:56 +00:00
|
|
|
:uri uri}))))))
|
2016-02-10 02:13:06 +00:00
|
|
|
|
2014-12-05 21:37:04 +00:00
|
|
|
(defn tag-posts
|
|
|
|
"Converts the tags in each post into links"
|
|
|
|
[posts config]
|
2014-12-04 16:38:48 +00:00
|
|
|
(map #(update-in % [:tags] (partial map (partial tag-info config))) posts))
|
|
|
|
|
2016-05-24 05:20:36 +00:00
|
|
|
(defn- template-dir?
|
|
|
|
"Checks that the dir exists in the templates directory."
|
|
|
|
[dir]
|
2017-01-16 07:37:19 +00:00
|
|
|
(.isDirectory (io/file (str "resources/templates/" dir))))
|
2016-05-24 05:20:36 +00:00
|
|
|
|
|
|
|
(defn- markup-entries [post-root page-root]
|
|
|
|
(let [entries (for [mu (m/markups)
|
2017-01-16 07:37:19 +00:00
|
|
|
t (distinct [post-root page-root])]
|
2016-05-24 05:20:36 +00:00
|
|
|
[(str (m/dir mu) "/" t) t])]
|
|
|
|
(apply concat entries)))
|
|
|
|
|
2015-06-14 15:16:35 +00:00
|
|
|
(defn copy-resources-from-markup-folders
|
2016-05-24 05:20:36 +00:00
|
|
|
"Copy resources from markup folders. This does not copy the markup entries."
|
2015-11-08 13:33:07 +00:00
|
|
|
[{:keys [post-root page-root] :as config}]
|
2016-05-24 05:20:36 +00:00
|
|
|
(let [folders (->> (markup-entries post-root page-root)
|
|
|
|
(filter template-dir?))]
|
2017-01-16 07:37:19 +00:00
|
|
|
(cryogen-io/copy-resources
|
2016-05-24 05:20:36 +00:00
|
|
|
(merge config
|
|
|
|
{:resources folders
|
|
|
|
:ignored-files (map #(re-pattern-from-ext (m/ext %)) (m/markups))}))))
|
2015-06-14 05:47:18 +00:00
|
|
|
|
2014-12-05 21:37:04 +00:00
|
|
|
(defn read-config
|
|
|
|
"Reads the config file"
|
|
|
|
[]
|
2015-04-03 02:22:17 +00:00
|
|
|
(try
|
|
|
|
(let [config (-> "templates/config.edn"
|
2017-01-16 07:37:19 +00:00
|
|
|
cryogen-io/get-resource
|
2015-04-03 02:22:17 +00:00
|
|
|
slurp
|
|
|
|
read-string
|
|
|
|
(update-in [:blog-prefix] (fnil str ""))
|
2015-11-08 13:33:07 +00:00
|
|
|
(update-in [:page-root] (fnil str ""))
|
|
|
|
(update-in [:post-root] (fnil str ""))
|
2016-01-09 01:44:07 +00:00
|
|
|
(update-in [:tag-root-uri] (fnil str ""))
|
2015-04-03 02:22:17 +00:00
|
|
|
(update-in [:rss-name] (fnil str "rss.xml"))
|
|
|
|
(update-in [:rss-filters] (fnil seq []))
|
|
|
|
(update-in [:sass-src] (fnil str "css"))
|
|
|
|
(update-in [:sass-dest] (fnil str "css"))
|
2016-12-17 10:29:16 +00:00
|
|
|
(update-in [:sass-path] (fnil str "sass"))
|
|
|
|
(update-in [:compass-path] (fnil str "compass"))
|
2015-04-03 02:22:17 +00:00
|
|
|
(update-in [:post-date-format] (fnil str "yyyy-MM-dd"))
|
|
|
|
(update-in [:keep-files] (fnil seq []))
|
2017-02-08 18:22:15 +00:00
|
|
|
(update-in [:ignored-files] (fnil seq [#"^\.#.*" #".*\.swp$"]))
|
2017-02-08 19:27:56 +00:00
|
|
|
(update-in [:navbar-model] (fnil str :flat))
|
2017-02-08 18:22:15 +00:00
|
|
|
)]
|
2015-04-03 02:22:17 +00:00
|
|
|
(merge
|
2015-07-08 20:34:39 +00:00
|
|
|
config
|
2015-11-08 13:33:07 +00:00
|
|
|
{:page-root-uri (root-uri :page-root-uri config)
|
2016-01-09 01:44:07 +00:00
|
|
|
:post-root-uri (root-uri :post-root-uri config)}))
|
2015-04-03 02:22:17 +00:00
|
|
|
(catch Exception _
|
|
|
|
(throw (IllegalArgumentException. "Failed to parse config.edn")))))
|
2014-12-04 16:38:48 +00:00
|
|
|
|
2017-02-02 03:49:51 +00:00
|
|
|
(defn klipsify
|
|
|
|
"Add the klipse html under the :klipse key and adds nohighlight
|
|
|
|
classes to any code blocks that are to be klipsified. Expects
|
|
|
|
configuration to be under :klipse, if there's none it does nothing."
|
|
|
|
[{:keys [klipse content] :as post-or-page}]
|
|
|
|
(-> post-or-page
|
|
|
|
(update :klipse klipse/emit content)
|
|
|
|
(update :content klipse/tag-nohighlight (:settings klipse))))
|
|
|
|
|
2014-12-05 21:37:04 +00:00
|
|
|
(defn compile-assets
|
|
|
|
"Generates all the html and copies over resources specified in the config"
|
|
|
|
[]
|
2014-12-04 16:38:48 +00:00
|
|
|
(println (green "compiling assets..."))
|
2017-02-08 08:53:15 +00:00
|
|
|
(let [{:keys [^String site-url blog-prefix rss-name recent-posts sass-dest keep-files ignored-files previews?
|
2017-02-08 18:22:15 +00:00
|
|
|
author-root-uri theme debug? navbar-model]
|
2017-02-08 08:13:45 +00:00
|
|
|
:as config} (read-config)
|
2017-02-02 03:49:51 +00:00
|
|
|
posts (map klipsify (add-prev-next (read-posts config)))
|
2014-12-04 16:38:48 +00:00
|
|
|
posts-by-tag (group-by-tags posts)
|
2017-01-17 04:12:53 +00:00
|
|
|
posts (tag-posts posts config)
|
2016-12-30 22:43:13 +00:00
|
|
|
latest-posts (->> posts (take recent-posts) vec)
|
2017-02-02 03:49:51 +00:00
|
|
|
pages (map klipsify (read-pages config))
|
2017-01-17 04:12:53 +00:00
|
|
|
home-page (->> pages
|
|
|
|
(filter #(boolean (:home? %)))
|
|
|
|
(first))
|
|
|
|
other-pages (->> pages
|
|
|
|
(remove #{home-page})
|
|
|
|
(add-prev-next))
|
|
|
|
[navbar-pages
|
|
|
|
sidebar-pages] (group-pages other-pages)
|
2015-02-23 18:14:31 +00:00
|
|
|
params (merge config
|
2016-09-03 19:33:37 +00:00
|
|
|
{:today (java.util.Date.)
|
|
|
|
:title (:site-title config)
|
2015-08-17 14:30:23 +00:00
|
|
|
:active-page "home"
|
2015-02-23 18:14:31 +00:00
|
|
|
:tags (map (partial tag-info config) (keys posts-by-tag))
|
2016-12-30 22:43:13 +00:00
|
|
|
:latest-posts latest-posts
|
2017-02-08 18:22:15 +00:00
|
|
|
:navbar-pages (cond
|
|
|
|
(= navbar-model :flat) navbar-pages
|
|
|
|
(= navbar-model :hierarchic) (navbar-model/build-nav-map navbar-pages)
|
|
|
|
)
|
|
|
|
:sidebar-pages (cond
|
|
|
|
(= navbar-model :flat) sidebar-pages
|
|
|
|
;(= navbar-model :hierarchic) (build-nav-map navbar-pages)
|
|
|
|
)
|
2017-02-08 08:13:45 +00:00
|
|
|
:home-page (if home-page
|
2017-01-17 04:12:53 +00:00
|
|
|
home-page
|
2017-02-08 08:13:45 +00:00
|
|
|
(assoc (first latest-posts) :layout "home.html"))
|
2016-02-12 02:04:56 +00:00
|
|
|
:archives-uri (page-uri "archives.html" config)
|
|
|
|
:index-uri (page-uri "index.html" config)
|
|
|
|
:tags-uri (page-uri "tags.html" config)
|
2017-02-08 08:13:45 +00:00
|
|
|
:rss-uri (cryogen-io/path "/" blog-prefix rss-name)
|
|
|
|
:site-url (if (.endsWith site-url "/") (.substring site-url 0 (dec (count site-url))) site-url)})]
|
2017-01-04 08:33:34 +00:00
|
|
|
(when debug?
|
|
|
|
(println (blue "debug: navbar-pages:"))
|
|
|
|
(println "\t-->" (cyan navbar-pages))
|
|
|
|
)
|
2017-01-17 04:12:53 +00:00
|
|
|
(set-custom-resource-path! (str "file:resources/templates/themes/" theme))
|
2017-01-16 07:37:19 +00:00
|
|
|
(cryogen-io/wipe-public-folder keep-files)
|
2015-06-14 10:23:58 +00:00
|
|
|
(println (blue "copying theme resources"))
|
2017-01-16 07:37:19 +00:00
|
|
|
(cryogen-io/copy-resources-from-theme config)
|
2014-12-04 16:38:48 +00:00
|
|
|
(println (blue "copying resources"))
|
2017-01-16 07:37:19 +00:00
|
|
|
(cryogen-io/copy-resources config)
|
2015-06-14 15:16:35 +00:00
|
|
|
(copy-resources-from-markup-folders config)
|
2017-01-17 04:12:53 +00:00
|
|
|
(compile-pages params other-pages)
|
2015-02-23 18:14:31 +00:00
|
|
|
(compile-posts params posts)
|
|
|
|
(compile-tags params posts-by-tag)
|
2015-07-08 16:15:11 +00:00
|
|
|
(compile-tags-page params)
|
2017-01-17 04:12:53 +00:00
|
|
|
(if previews?
|
|
|
|
(compile-preview-pages params posts)
|
2015-07-08 20:34:39 +00:00
|
|
|
(compile-index params))
|
2015-02-23 18:14:31 +00:00
|
|
|
(compile-archives params posts)
|
2016-02-10 02:13:06 +00:00
|
|
|
(when author-root-uri
|
|
|
|
(println (blue "generating authors views"))
|
|
|
|
(compile-authors params posts))
|
2014-12-04 16:38:48 +00:00
|
|
|
(println (blue "generating site map"))
|
2017-01-17 04:12:53 +00:00
|
|
|
(->> (sitemap/generate site-url ignored-files)
|
|
|
|
(cryogen-io/create-file (cryogen-io/path "/" blog-prefix "sitemap.xml")))
|
2015-01-04 01:36:30 +00:00
|
|
|
(println (blue "generating main rss"))
|
2017-01-17 04:12:53 +00:00
|
|
|
(->> (rss/make-channel config posts)
|
|
|
|
(cryogen-io/create-file (cryogen-io/path "/" blog-prefix rss-name)))
|
2015-01-04 01:36:30 +00:00
|
|
|
(println (blue "generating filtered rss"))
|
2015-11-08 13:33:07 +00:00
|
|
|
(rss/make-filtered-channels config posts-by-tag)
|
2014-12-04 16:38:48 +00:00
|
|
|
(println (blue "compiling sass"))
|
2014-12-25 16:24:25 +00:00
|
|
|
(sass/compile-sass->css!
|
2017-01-16 07:37:19 +00:00
|
|
|
(merge (select-keys config [:sass-path :compass-path :sass-src :ignored-files])
|
2017-01-18 04:44:37 +00:00
|
|
|
{:sass-dest (cryogen-io/path ".." "public" blog-prefix sass-dest)
|
2017-01-16 07:37:19 +00:00
|
|
|
:base-dir "resources/templates/"}))))
|
2014-12-04 16:38:48 +00:00
|
|
|
|
|
|
|
(defn compile-assets-timed []
|
|
|
|
(time
|
|
|
|
(try
|
|
|
|
(compile-assets)
|
|
|
|
(catch Exception e
|
2015-01-01 08:49:03 +00:00
|
|
|
(if (or (instance? IllegalArgumentException e)
|
|
|
|
(instance? clojure.lang.ExceptionInfo e))
|
2014-12-04 16:38:48 +00:00
|
|
|
(println (red "Error:") (yellow (.getMessage e)))
|
|
|
|
(write-exception e))))))
|