diff --git a/project.clj b/project.clj index 4783506..789fe14 100644 --- a/project.clj +++ b/project.clj @@ -1,17 +1,17 @@ -(defproject cryogen-core "0.1.9" - :description "Cryogen's compiler" - :url "https://github.com/lacarmen/cryogen-core" - :license {:name "Eclipse Public License" - :url "http://www.eclipse.org/legal/epl-v10.html"} - :dependencies [[org.clojure/clojure "1.6.0"] - [clj-rss "0.1.9"] - [me.raynes/fs "1.4.6"] - [crouton "0.1.2"] - [cheshire "5.4.0"] - [clj-text-decoration "0.0.3"] - [io.aviso/pretty "0.1.13"] - [hiccup "1.0.5"] - [selmer "0.7.8"] - [markdown-clj "0.9.60" - :exclusions [com.keminglabs/cljx]] - [org.asciidoctor/asciidoctorj "1.5.2"]]) +(defproject cryogen-core "0.1.14" + :description "Cryogen's compiler" + :url "https://github.com/lacarmen/cryogen-core" + :license {:name "Eclipse Public License" + :url "http://www.eclipse.org/legal/epl-v10.html"} + :dependencies [[org.clojure/clojure "1.6.0"] + [clj-rss "0.1.9"] + [me.raynes/fs "1.4.6"] + [crouton "0.1.2"] + [cheshire "5.4.0"] + [clj-text-decoration "0.0.3"] + [io.aviso/pretty "0.1.13"] + [hiccup "1.0.5"] + [selmer "0.7.8"] + [markdown-clj "0.9.62"] + [pandect "0.4.1"] + [org.asciidoctor/asciidoctorj "1.5.2"]]) diff --git a/src/cryogen_core/compiler.clj b/src/cryogen_core/compiler.clj index e2a00dc..f126dea 100644 --- a/src/cryogen_core/compiler.clj +++ b/src/cryogen_core/compiler.clj @@ -184,7 +184,7 @@ (defn compile-pages "Compiles all the pages into html and spits them out into the public folder" - [default-params pages {:keys [blog-prefix page-root asset-url]}] + [default-params pages {:keys [blog-prefix page-root]}] (when-not (empty? pages) (println (blue "compiling pages")) (create-folder (str blog-prefix page-root)) @@ -195,11 +195,11 @@ (merge default-params {:servlet-context "../" :page page - :asset-url asset-url})))))) + :uri uri})))))) (defn compile-posts "Compiles all the posts into html and spits them out into the public folder" - [default-params posts {:keys [blog-prefix post-root disqus-shortname asset-url]}] + [default-params posts {:keys [blog-prefix post-root disqus-shortname]}] (when-not (empty? posts) (println (blue "compiling posts")) (create-folder (str blog-prefix post-root)) @@ -211,7 +211,7 @@ {:servlet-context "../" :post post :disqus-shortname disqus-shortname - :asset-url asset-url})))))) + :uri (:uri post)})))))) (defn compile-tags "Compiles all the tag pages into html and spits them out into the public folder" @@ -224,21 +224,23 @@ (println "\t-->" (cyan uri)) (spit (str public uri) (render-file "templates/html/layouts/tag.html" - (merge default-params {:servlet-context "../" - :name name - :posts posts}))))))) + (merge default-params + {:servlet-context "../" + :name name + :posts posts + :uri uri}))))))) (defn compile-index "Compiles the index page into html and spits it out into the public folder" - [default-params {:keys [blog-prefix disqus? asset-url]}] + [default-params {:keys [blog-prefix disqus?]}] (println (blue "compiling index")) (spit (str public blog-prefix "/index.html") (render-file "templates/html/layouts/home.html" (merge default-params - {:home true - :disqus? disqus? - :post (get-in default-params [:latest-posts 0]) - :asset-url asset-url})))) + {:home true + :disqus? disqus? + :post (get-in default-params [:latest-posts 0]) + :uri (str blog-prefix "/index.html")})))) (defn compile-archives "Compiles the archives page into html and spits it out into the public folder" @@ -248,7 +250,8 @@ (render-file "templates/html/layouts/archives.html" (merge default-params {:archives true - :groups (group-for-archive posts)})))) + :groups (group-for-archive posts) + :uri (str blog-prefix "/archives.html")})))) (defn tag-posts "Converts the tags in each post into links" @@ -264,20 +267,17 @@ read-string (update-in [:blog-prefix] (fnil str "")) (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")) (update-in [:post-date-format] (fnil str "yyyy-MM-dd")) (update-in [:keep-files] (fnil seq [])) - (update-in [:ignored-files] (fnil seq [#"^\.#.*" #".*\.swp$"]))) - site-url (:site-url config) - blog-prefix (:blog-prefix config)] + (update-in [:ignored-files] (fnil seq [#"^\.#.*" #".*\.swp$"])))] (merge config {:page-root (root-path :page-root config) :post-root (root-path :post-root config) - :tag-root (root-path :tag-root config) - :asset-root (str (if (.endsWith site-url "/") (apply str (butlast site-url)) site-url) - blog-prefix)}))) + :tag-root (root-path :tag-root config)}))) (defn compile-assets "Generates all the html and copies over resources specified in the config" @@ -296,7 +296,8 @@ :sidebar-pages sidebar-pages :archives-uri (str blog-prefix "/archives.html") :index-uri (str blog-prefix "/index.html") - :rss-uri (str blog-prefix "/" rss-name)}] + :rss-uri (str blog-prefix "/" rss-name) + :site-url (if (.endsWith site-url "/") (.substring site-url 0 (dec (count site-url))) site-url)}] (wipe-public-folder keep-files) (println (blue "copying resources")) @@ -309,20 +310,22 @@ (compile-archives default-params posts config) (println (blue "generating site map")) (spit (str public blog-prefix "/sitemap.xml") (sitemap/generate site-url ignored-files)) - (println (blue "generating rss")) + (println (blue "generating main rss")) (spit (str public blog-prefix "/" rss-name) (rss/make-channel config posts)) + (println (blue "generating filtered rss")) + (rss/make-filtered-channels public config posts-by-tag) (println (blue "compiling sass")) (sass/compile-sass->css! (str "resources/templates/" sass-src) - (str "resources/public" blog-prefix "/" sass-dest)))) + (str "resources/public" blog-prefix "/" sass-dest) + ignored-files))) (defn compile-assets-timed [] (time (try (compile-assets) (catch Exception e - (if - (or (instance? IllegalArgumentException e) - (instance? clojure.lang.ExceptionInfo e)) + (if (or (instance? IllegalArgumentException e) + (instance? clojure.lang.ExceptionInfo e)) (println (red "Error:") (yellow (.getMessage e))) (write-exception e)))))) diff --git a/src/cryogen_core/io.clj b/src/cryogen_core/io.clj index 691003e..e554111 100644 --- a/src/cryogen_core/io.clj +++ b/src/cryogen_core/io.clj @@ -4,12 +4,17 @@ (def public "resources/public") +(defn re-filter [bool-fn re & other-res] + (let [res (conj other-res re)] + (reify java.io.FilenameFilter + (accept [this _ name] + (bool-fn (some #(re-find % name) res)))))) + +(def match-re-filter (partial re-filter some?)) +(def reject-re-filter (partial re-filter nil?)) + (defn get-resource [resource] - (-> (Thread/currentThread) - (.getContextClassLoader) - (.getResource resource) - (.toURI) - (io/file))) + (-> resource io/resource io/file)) (defn ignore [ignored-files] (fn [file] @@ -37,14 +42,24 @@ (doseq [asset (fs/find-files "resources/templates/md" #".+(jpg|jpeg|png|gif)")] (io/copy asset (io/file (str public blog-prefix "/img/" (.getName asset)))))) -(defn copy-resources [{:keys [blog-prefix resources]}] +(defn copy-dir [src target ignored-files] + (fs/mkdirs target) + (let [filename-filter (apply reject-re-filter ignored-files) + files (.listFiles (io/file src) filename-filter)] + (doseq [f files] + (let [out (io/file target (.getName f))] + (if (.isDirectory f) + (copy-dir f out ignored-files) + (io/copy f out)))))) + +(defn copy-resources [{:keys [blog-prefix resources ignored-files]}] (doseq [resource resources] (let [src (str "resources/templates/" resource) - target (str public blog-prefix "/" resource)] + target (str public blog-prefix "/" resource)] (cond (not (.exists (io/file src))) (throw (IllegalArgumentException. (str "resource " src " not found"))) (.isDirectory (io/file src)) - (fs/copy-dir src target) + (copy-dir src target ignored-files) :else (fs/copy src target))))) diff --git a/src/cryogen_core/rss.clj b/src/cryogen_core/rss.clj index 26856fa..eca46fe 100644 --- a/src/cryogen_core/rss.clj +++ b/src/cryogen_core/rss.clj @@ -1,6 +1,7 @@ (ns cryogen-core.rss (:require [clj-rss.core :as rss] - [clojure.xml :refer [emit]]) + [clojure.xml :refer [emit]] + [text-decoration.core :refer :all]) (:import java.util.Date)) @@ -25,4 +26,10 @@ :description (:description config) :lastBuildDate (Date.) :author (:author config)}) - (posts-to-items (:site-url config) (:author config) posts))) \ No newline at end of file + (posts-to-items (:site-url config) (:author config) posts))) + +(defn make-filtered-channels [public {:keys [rss-filters blog-prefix] :as config} posts-by-tag] + (doseq [filter rss-filters] + (let [uri (str public blog-prefix "/" (name filter) ".xml")] + (println "\t-->" (cyan uri)) + (spit uri (make-channel config (get posts-by-tag filter)))))) \ No newline at end of file diff --git a/src/cryogen_core/sass.clj b/src/cryogen_core/sass.clj index 85df024..93d2c2c 100644 --- a/src/cryogen_core/sass.clj +++ b/src/cryogen_core/sass.clj @@ -1,6 +1,7 @@ (ns cryogen-core.sass (:require [clojure.java.shell :refer [sh]] - [clojure.java.io :as io])) + [clojure.java.io :as io] + [cryogen-core.io :refer [ignore match-re-filter]])) (defn sass-installed? "Checks for the installation of Sass." @@ -8,11 +9,14 @@ (= 0 (:exit (sh "sass" "--version")))) (defn find-sass-files - "Given a Diretory, gets files, filtered to those having scss or sass extention" - [dir] - (->> (.list (io/file dir)) - (seq) - (filter (comp not nil? (partial re-find #"(?i:s[ca]ss$)"))))) + "Given a Diretory, gets files, Filtered to those having scss or sass + extention. Ignores files matching any ignored regexps." + [dir ignored-files] + (let [filename-filter (match-re-filter #"(?i:s[ca]ss$)")] + (->> (.listFiles (io/file dir) filename-filter) + (filter #(not (.isDirectory %))) + (filter (ignore ignored-files)) + (map #(.getName %))))) (defn compile-sass-file! "Given a sass file which might be in src-sass directory, @@ -31,8 +35,9 @@ dest-sass. Prompts you to install sass if he finds sass files and can't find the command. Shows you any problems it comes across when compiling. " [src-sass - dest-sass] - (let [sass-files (find-sass-files src-sass)] + dest-sass + ignored-files] + (let [sass-files (find-sass-files src-sass ignored-files)] (if (seq sass-files) ;; I found sass files, ;; If sass is installed diff --git a/src/cryogen_core/watcher.clj b/src/cryogen_core/watcher.clj index 43d478f..0694fcf 100644 --- a/src/cryogen_core/watcher.clj +++ b/src/cryogen_core/watcher.clj @@ -1,24 +1,33 @@ (ns cryogen-core.watcher (:require [clojure.java.io :refer [file]] - [cryogen-core.io :refer [ignore]])) + [cryogen-core.io :refer [ignore]] + [pandect.core :refer [md5]] + [clojure.set :as set])) -(defn get-assets [root ignored-files] - (->> root +(defn get-assets [path ignored-files] + (->> path file file-seq (filter #(not (.isDirectory %))) (filter (ignore ignored-files)))) -(defn sum-times [path ignored-files] - (->> (get-assets path ignored-files) (map #(.lastModified %)) (reduce +))) +(defn checksums [path ignored-files] + (let [files (get-assets path ignored-files)] + (zipmap (map md5 files) files))) + +(defn find-changes [old-sums new-sums] + (let [old-sum-set (-> old-sums keys set) + new-sum-set (-> new-sums keys set)] + (when-some [changes (set/difference new-sum-set old-sum-set)] + (vals (select-keys new-sums changes))))) (defn watch-assets [root ignored-files action] - (loop [times (sum-times root ignored-files)] + (loop [sums (checksums root ignored-files)] (Thread/sleep 300) - (let [new-times (sum-times root ignored-files)] - (when-not (= times new-times) + (let [new-sums (checksums root ignored-files)] + (when (find-changes sums new-sums) (action)) - (recur new-times)))) + (recur new-sums)))) (defn start-watcher! [root ignored-files action] (doto (Thread. #(watch-assets root ignored-files action))