From 9c7c935d665a87e6d12fc5fe53171e631b06cc71 Mon Sep 17 00:00:00 2001 From: Aleksander Madland Stapnes Date: Sun, 15 Jan 2017 05:17:48 -0300 Subject: [PATCH 01/15] Style pedantry: Remove trailing whitespace. My emacs did it... --- src/cryogen_core/compiler.clj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cryogen_core/compiler.clj b/src/cryogen_core/compiler.clj index 018b606..e71bf2c 100644 --- a/src/cryogen_core/compiler.clj +++ b/src/cryogen_core/compiler.clj @@ -481,10 +481,10 @@ :latest-posts latest-posts :navbar-pages navbar-pages :sidebar-pages sidebar-pages - :home-page (if (not-empty home-pages) - (first home-pages) + :home-page (if (not-empty home-pages) + (first home-pages) (merge (first latest-posts) - {:layout "home.html"})) + {:layout "home.html"})) :archives-uri (page-uri "archives.html" config) :index-uri (page-uri "index.html" config) :tags-uri (page-uri "tags.html" config) From dbd5caaf1f90075e4b65b982ff5498450a3dcd21 Mon Sep 17 00:00:00 2001 From: Aleksander Madland Stapnes Date: Sun, 15 Jan 2017 05:30:25 -0300 Subject: [PATCH 02/15] Replace tagsoup dependency with enlive Tagsoup depends on an old version of clojure.data.xml, which doesn't compile with clojure 1.9.0-alpha12. Enlive seems more actively maintained and used. --- project.clj | 2 +- src/cryogen_core/compiler.clj | 30 ++++++++++++++--------------- test/cryogen_core/compiler_test.clj | 3 ++- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/project.clj b/project.clj index 5fd0ff8..c938571 100644 --- a/project.clj +++ b/project.clj @@ -14,6 +14,6 @@ [selmer "1.10.3"] [pandect "0.6.1"] [hawk "0.2.11"] - [clj-tagsoup "0.3.0" :exclusions [org.clojure/clojure]]] + [enlive "1.1.6"]] :deploy-repositories [["snapshots" :clojars] ["releases" :clojars]]) diff --git a/src/cryogen_core/compiler.clj b/src/cryogen_core/compiler.clj index e71bf2c..1b6d63c 100644 --- a/src/cryogen_core/compiler.clj +++ b/src/cryogen_core/compiler.clj @@ -5,8 +5,7 @@ [clojure.java.io :refer [copy file reader writer]] [clojure.string :as s] [text-decoration.core :refer :all] - [pl.danieljanus.tagsoup :as tagsoup] - [hiccup.core :as hiccup] + [net.cgrand.enlive-html :as enlive] [cryogen-core.toc :refer [generate-toc]] [cryogen-core.sass :as sass] [cryogen-core.markup :as m] @@ -295,23 +294,24 @@ :uri uri}))))) (defn content-until-more-marker - [^String content] - (let [index (.indexOf content "")] - (if (pos? index) - (let [s (subs content 0 index)] - (->> ((tagsoup/parse-string s) 2) - (drop 2) - hiccup/html))))) + "Returns the content until the special comment, + closing any unclosed tags. Returns nil if there's no such comment." + [content] + (when-let [index (s/index-of content "")] + (->> (subs content 0 index) + enlive/html-snippet + enlive/emit* + (apply str)))) (defn create-preview "Creates a single post preview" [blocks-per-preview post] - (merge post - {:content (or (content-until-more-marker (:content post)) - (->> ((tagsoup/parse-string (:content post)) 2) - (drop 2) - (take blocks-per-preview) - hiccup/html))})) + (update post :content + #(or (content-until-more-marker %) + (->> (enlive/html-snippet %) + (take blocks-per-preview) + enlive/emit* + (apply str))))) (defn create-previews "Returns a sequence of vectors, each containing a set of post previews" diff --git a/test/cryogen_core/compiler_test.clj b/test/cryogen_core/compiler_test.clj index 2d76c8d..46a5a55 100644 --- a/test/cryogen_core/compiler_test.clj +++ b/test/cryogen_core/compiler_test.clj @@ -22,7 +22,8 @@ and more content. ") - "
+ "
+
this post has more marker
"))) From dec80185e5fa4e906a9073a1a5fba0184b153bd5 Mon Sep 17 00:00:00 2001 From: Carmen La Date: Mon, 16 Jan 2017 02:37:19 -0500 Subject: [PATCH 03/15] A big ol' cleanup --- project.clj | 16 +- src/cryogen_core/compiler.clj | 246 ++++++++++++++-------------- src/cryogen_core/github.clj | 37 ----- src/cryogen_core/markup.clj | 5 +- src/cryogen_core/plugins.clj | 3 +- src/cryogen_core/rss.clj | 6 +- src/cryogen_core/sass.clj | 63 +++---- src/cryogen_core/sitemap.clj | 4 +- src/cryogen_core/watcher.clj | 14 +- test/cryogen_core/compiler_test.clj | 5 +- test/cryogen_core/toc_test.clj | 102 ++++++------ 11 files changed, 223 insertions(+), 278 deletions(-) delete mode 100644 src/cryogen_core/github.clj diff --git a/project.clj b/project.clj index c938571..7540783 100644 --- a/project.clj +++ b/project.clj @@ -4,16 +4,16 @@ :license {:name "Eclipse Public License" :url "http://www.eclipse.org/legal/epl-v10.html"} :dependencies [[org.clojure/clojure "1.8.0"] - [clj-rss "0.2.3"] - [me.raynes/fs "1.4.6"] - [crouton "0.1.2"] [cheshire "5.6.3"] + [clj-rss "0.2.3"] [clj-text-decoration "0.0.3"] - [io.aviso/pretty "0.1.33"] - [hiccup "1.0.5"] - [selmer "1.10.3"] - [pandect "0.6.1"] + [crouton "0.1.2"] + [enlive "1.1.6"] [hawk "0.2.11"] - [enlive "1.1.6"]] + [hiccup "1.0.5"] + [io.aviso/pretty "0.1.33"] + [me.raynes/fs "1.4.6"] + [pandect "0.6.1"] + [selmer "1.10.3"]] :deploy-repositories [["snapshots" :clojars] ["releases" :clojars]]) diff --git a/src/cryogen_core/compiler.clj b/src/cryogen_core/compiler.clj index 1b6d63c..fd92eb6 100644 --- a/src/cryogen_core/compiler.clj +++ b/src/cryogen_core/compiler.clj @@ -1,19 +1,17 @@ (ns cryogen-core.compiler - (:require [selmer.parser :refer [cache-off! render-file]] - [selmer.util :refer [set-custom-resource-path!]] - [io.aviso.exception :refer [write-exception]] - [clojure.java.io :refer [copy file reader writer]] + (:require [clojure.java.io :as io] [clojure.string :as s] - [text-decoration.core :refer :all] + [io.aviso.exception :refer [write-exception]] [net.cgrand.enlive-html :as enlive] - [cryogen-core.toc :refer [generate-toc]] - [cryogen-core.sass :as sass] + [selmer.parser :refer [cache-off! render-file]] + [selmer.util :refer [set-custom-resource-path!]] + [text-decoration.core :refer :all] + [cryogen-core.io :as cryogen-io] [cryogen-core.markup :as m] - [cryogen-core.io :refer - [get-resource find-assets create-folder create-file-recursive create-file wipe-public-folder - copy-resources copy-resources-from-theme path]] + [cryogen-core.rss :as rss] + [cryogen-core.sass :as sass] [cryogen-core.sitemap :as sitemap] - [cryogen-core.rss :as rss]) + [cryogen-core.toc :as toc]) (:import java.util.Locale)) (cache-off!) @@ -36,14 +34,16 @@ looking under the implemented protocol's subdirectory, but fallsback to look at the templates directory." [root mu ignored-files] - (let [assets (find-assets (path "templates" (m/dir mu) root) - (m/ext mu) - ignored-files)] + (let [assets (cryogen-io/find-assets + (cryogen-io/path "templates" (m/dir mu) root) + (m/ext mu) + ignored-files)] (if (seq assets) assets - (find-assets (path "templates" root) - (m/ext mu) - ignored-files)))) + (cryogen-io/find-assets + (cryogen-io/path "templates" root) + (m/ext mu) + ignored-files)))) (defn find-posts "Returns a list of markdown files representing posts under the post root." @@ -66,9 +66,9 @@ ([file-name params] (page-uri file-name nil params)) ([file-name uri-type {:keys [blog-prefix clean-urls?] :as params}] - (let [page-uri (params uri-type) - uri-end (if clean-urls? (s/replace file-name #"(index)?\.html" "/") file-name)] - (path "/" blog-prefix page-uri uri-end)))) + (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)))) (defn read-page-meta "Returns the clojure map from the top of a markdown page/post" @@ -82,13 +82,13 @@ "Returns a map with the given page's file-name, metadata and content parsed from the file with the given markup." [^java.io.File page config markup] - (with-open [rdr (java.io.PushbackReader. (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 + (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 page-name (s/replace page-fwd re-root "") file-name (s/replace page-name (re-pattern-from-ext (m/ext markup)) ".html") page-meta (read-page-meta page-name rdr) - content ((m/render-fn markup) rdr config)] + content ((m/render-fn markup) rdr config)] {:file-name file-name :page-meta page-meta :content content}))) @@ -101,7 +101,7 @@ {:file-name file-name :content content :toc (if-let [toc (:toc page-meta)] - (generate-toc content :list-type toc))})) + (toc/generate-toc content :list-type toc))})) (defn parse-page "Parses a page/post and returns a map of the content, uri, date etc." @@ -118,10 +118,10 @@ (let [{:keys [file-name page-meta content]} (page-content page config markup)] (merge (merge-meta-and-content file-name page-meta content) - (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. (get config :archive-group-format "yyyy MMMM") (Locale/getDefault)) + (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)) formatted-group (.format archive-fmt date)] {:date date :formatted-archive-group formatted-group @@ -133,13 +133,13 @@ "Returns a sequence of maps representing the data from markdown files of posts. Sorts the sequence by post date." [config] - (->> (mapcat + (->> (m/markups) + (mapcat (fn [mu] (->> (find-posts config mu) (pmap #(parse-post % config mu)) - (remove #(= (:draft? %) true)))) - (m/markups)) + (remove #(= (:draft? %) true))))) (sort-by :date) reverse (drop-while #(and (:hide-future-posts? config) (.after (:date %) (java.util.Date.)))))) @@ -148,12 +148,12 @@ "Returns a sequence of maps representing the data from markdown files of pages. Sorts the sequence by post date." [config] - (->> (mapcat + (->> (m/markups) + (mapcat (fn [mu] (->> (find-pages config mu) - (map #(parse-page % config mu)))) - (m/markups)) + (map #(parse-page % config mu))))) (sort-by :page-index))) (defn tag-post @@ -161,7 +161,8 @@ [tags post] (reduce (fn [tags tag] (update-in tags [tag] (fnil conj []) (select-keys post [:uri :title :content :date :enclosure]))) - tags (:tags post))) + tags + (:tags post))) (defn group-by-tags "Maps all the tags with a list of posts that contain each tag" @@ -219,26 +220,26 @@ "When `clean-urls?` is set, appends `/index.html` before spit; otherwise just spits." [file-uri {:keys [clean-urls?]} data] (if clean-urls? - (create-file-recursive (path file-uri "index.html") data) - (create-file file-uri data))) + (cryogen-io/create-file-recursive (cryogen-io/path file-uri "index.html") data) + (cryogen-io/create-file file-uri data))) (defn compile-pages "Compiles all the pages into html and spits them out into the public folder" [{:keys [blog-prefix page-root-uri debug?] :as params} pages] (when-not (empty? pages) (println (blue "compiling pages")) - (create-folder (path "/" blog-prefix page-root-uri)) + (cryogen-io/create-folder (cryogen-io/path "/" blog-prefix page-root-uri)) (doseq [{:keys [uri] :as page} pages] (println "\t-->" (cyan uri)) (when debug? - (println "\t-->" (cyan page))) + (println "\t\tdebug-->" (cyan page))) (write-html uri params (render-file (str "/html/" (:layout page)) (merge params {:active-page "pages" :home false - :servlet-context (path "/" blog-prefix "/") + :servlet-context (cryogen-io/path "/" blog-prefix "/") :page page :uri uri})))))) @@ -247,28 +248,27 @@ [{:keys [blog-prefix post-root-uri disqus-shortname debug?] :as params} posts] (when-not (empty? posts) (println (blue "compiling posts")) - (create-folder (path "/" blog-prefix post-root-uri)) - (doseq [post posts] - (println "\t-->" (cyan (:uri post))) - (println "\t-->" (cyan debug?)) + (cryogen-io/create-folder (cryogen-io/path "/" blog-prefix post-root-uri)) + (doseq [{:keys [uri] :as post} posts] + (println "\t-->" (cyan uri)) (when debug? - (println "\t-->" (cyan post))) - (write-html (:uri post) + (println "\t\tdebug-->" (cyan post))) + (write-html uri params (render-file (str "/html/" (:layout post)) (merge params {:active-page "posts" - :servlet-context (path "/" blog-prefix "/") + :servlet-context (cryogen-io/path "/" blog-prefix "/") :post post :disqus-shortname disqus-shortname - :uri (:uri post)})))))) + :uri uri})))))) (defn compile-tags "Compiles all the tag pages into html and spits them out into the public folder" [{:keys [blog-prefix tag-root-uri] :as params} posts-by-tag] (when-not (empty? posts-by-tag) (println (blue "compiling tags")) - (create-folder (path "/" blog-prefix tag-root-uri)) + (cryogen-io/create-folder (cryogen-io/path "/" blog-prefix tag-root-uri)) (doseq [[tag posts] posts-by-tag] (let [{:keys [name uri]} (tag-info params tag)] (println "\t-->" (cyan uri)) @@ -277,21 +277,22 @@ (render-file "/html/tag.html" (merge params {:active-page "tags" - :servlet-context (path "/" blog-prefix "/") + :servlet-context (cryogen-io/path "/" blog-prefix "/") :name name :posts posts :uri uri}))))))) (defn compile-tags-page [{:keys [blog-prefix] :as params}] + "Compiles a page with links to each tag page. Spits the page into the public folder" (println (blue "compiling tags page")) (let [uri (page-uri "tags.html" params)] (write-html uri params (render-file "/html/tags.html" (merge params - {:active-page "tags" - :servlet-context (path "/" blog-prefix "/") - :uri uri}))))) + {:active-page "tags" + :servlet-context (cryogen-io/path "/" blog-prefix "/") + :uri uri}))))) (defn content-until-more-marker "Returns the content until the special comment, @@ -315,7 +316,7 @@ (defn create-previews "Returns a sequence of vectors, each containing a set of post previews" - [posts-per-page blocks-per-preview posts] + [posts posts-per-page blocks-per-preview] (->> posts (map #(create-preview blocks-per-preview %)) (partition-all posts-per-page) @@ -327,38 +328,41 @@ [previews params] (mapv (fn [[prev target next]] (merge target - {:prev (if prev (page-uri (path "p" (str (:index prev) ".html")) params) nil) - :next (if next (page-uri (path "p" (str (:index next) ".html")) params) nil)})) + {: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)})) (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) - (let [previews (-> (create-previews posts-per-page blocks-per-preview posts) + (let [previews (-> posts + (create-previews posts-per-page blocks-per-preview) (create-preview-links params)) - previews (if (> (count previews) 1) (assoc-in previews [1 :prev] (page-uri "index.html" params)) previews)] - (create-folder (path "/" blog-prefix "p")) + 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")) (doseq [{:keys [index posts prev next]} previews :let [index-page? (= 1 index)]] - (write-html (if index-page? (page-uri "index.html" params) (page-uri (path "p" (str index ".html")) params)) - params - (render-file "/html/previews.html" - (merge params - {:active-page "preview" - :home (when index-page? true) - :servlet-context (path "/" blog-prefix "/") - :posts posts - :prev-uri prev - :next-uri next}))))))) + (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}))))))) (defn compile-index "Compiles the index page into html and spits it out into the public folder" - [{:keys [disqus?] :as params}] + [{:keys [disqus? debug? home-page] :as params}] (println (blue "compiling index")) - (let [uri (page-uri "index.html" params) - debug? (-> params :debug?) - home-page (-> params :home-page) + (let [uri (page-uri "index.html" params) meta {:active-page "home" :home true :disqus? disqus? @@ -366,7 +370,7 @@ :post home-page :page home-page}] (when debug? - (println "\t-->" (cyan meta))) + (println "\t\tdebug-->" (cyan meta))) (write-html uri params (render-file (str "/html/" (:layout home-page)) @@ -382,17 +386,17 @@ params (render-file "/html/archives.html" (merge params - {:active-page "archives" - :archives true - :groups (group-for-archive posts) - :servlet-context (path "/" blog-prefix "/") - :uri uri}))))) + {:active-page "archives" + :archives true + :groups (group-for-archive posts) + :servlet-context (cryogen-io/path "/" blog-prefix "/") + :uri uri}))))) (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")) - (create-folder (path "/" blog-prefix author-root-uri)) + (cryogen-io/create-folder (cryogen-io/path "/" blog-prefix author-root-uri)) ;; if the post author is empty defaults to config's :author (doseq [{:keys [author posts]} (group-for-author posts author)] (let [uri (page-uri (str author ".html") :author-root-uri params)] @@ -403,7 +407,7 @@ (merge params {:author author :groups (group-for-archive posts) - :servlet-context (path "/" blog-prefix "/") + :servlet-context (cryogen-io/path "/" blog-prefix "/") :uri uri})))))) (defn tag-posts @@ -414,11 +418,11 @@ (defn- template-dir? "Checks that the dir exists in the templates directory." [dir] - (.isDirectory (file (str "resources/templates/" dir)))) + (.isDirectory (io/file (str "resources/templates/" dir)))) (defn- markup-entries [post-root page-root] (let [entries (for [mu (m/markups) - t (distinct [post-root page-root])] + t (distinct [post-root page-root])] [(str (m/dir mu) "/" t) t])] (apply concat entries))) @@ -427,7 +431,7 @@ [{:keys [post-root page-root] :as config}] (let [folders (->> (markup-entries post-root page-root) (filter template-dir?))] - (copy-resources + (cryogen-io/copy-resources (merge config {:resources folders :ignored-files (map #(re-pattern-from-ext (m/ext %)) (m/markups))})))) @@ -437,7 +441,7 @@ [] (try (let [config (-> "templates/config.edn" - get-resource + cryogen-io/get-resource slurp read-string (update-in [:blog-prefix] (fnil str "")) @@ -464,42 +468,43 @@ "Generates all the html and copies over resources specified in the config" [] (println (green "compiling assets...")) - (let [{:keys [^String site-url blog-prefix rss-name recent-posts sass-src sass-dest sass-path compass-path keep-files ignored-files previews? clean-urls? debug? author-root-uri] :as config} (read-config) - posts (add-prev-next (read-posts config)) - pages (add-prev-next (read-pages config)) - home-pages (filter #(boolean (:home? %)) pages) + (let [{:keys [^String site-url blog-prefix rss-name recent-posts sass-dest keep-files ignored-files previews? author-root-uri theme] + :as config} (read-config) + posts (add-prev-next (read-posts config)) + pages (add-prev-next (read-pages config)) + home-pages (filter #(boolean (:home? %)) pages) pages-without-home (filter #(boolean (not (:home? %))) pages) [navbar-pages sidebar-pages] (group-pages pages-without-home) - posts-by-tag (group-by-tags posts) - posts (tag-posts posts config) - latest-posts (->> posts (take recent-posts) vec) - params (merge config - {:today (java.util.Date.) - :title (:site-title config) - :active-page "home" - :tags (map (partial tag-info config) (keys posts-by-tag)) - :latest-posts latest-posts - :navbar-pages navbar-pages - :sidebar-pages sidebar-pages - :home-page (if (not-empty home-pages) - (first home-pages) - (merge (first latest-posts) - {:layout "home.html"})) - :archives-uri (page-uri "archives.html" config) - :index-uri (page-uri "index.html" config) - :tags-uri (page-uri "tags.html" config) - :rss-uri (path "/" blog-prefix rss-name) - :site-url (if (.endsWith site-url "/") (.substring site-url 0 (dec (count site-url))) site-url) - :theme-path (str "file:resources/templates/themes/" (:theme config))})] + posts-by-tag (group-by-tags posts) + posts (tag-posts posts config) + latest-posts (->> posts (take recent-posts) vec) + params (merge config + {:today (java.util.Date.) + :title (:site-title config) + :active-page "home" + :tags (map (partial tag-info config) (keys posts-by-tag)) + :latest-posts latest-posts + :navbar-pages navbar-pages + :sidebar-pages sidebar-pages + :home-page (if (not-empty home-pages) + (first home-pages) + (merge (first latest-posts) + {:layout "home.html"})) + :archives-uri (page-uri "archives.html" config) + :index-uri (page-uri "index.html" config) + :tags-uri (page-uri "tags.html" config) + :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) + :theme-path (str "file:resources/templates/themes/" theme)})] (println (blue "debug info")) (println "\t-->" (cyan navbar-pages)) (set-custom-resource-path! (:theme-path params)) - (wipe-public-folder keep-files) + (cryogen-io/wipe-public-folder keep-files) (println (blue "copying theme resources")) - (copy-resources-from-theme config) + (cryogen-io/copy-resources-from-theme config) (println (blue "copying resources")) - (copy-resources config) + (cryogen-io/copy-resources config) (copy-resources-from-markup-folders config) (compile-pages params pages-without-home) (compile-posts params posts) @@ -514,19 +519,16 @@ (println (blue "generating authors views")) (compile-authors params posts)) (println (blue "generating site map")) - (create-file (path "/" blog-prefix "sitemap.xml") (sitemap/generate site-url ignored-files)) + (cryogen-io/create-file (cryogen-io/path "/" blog-prefix "sitemap.xml") (sitemap/generate site-url ignored-files)) (println (blue "generating main rss")) - (create-file (path "/" blog-prefix rss-name) (rss/make-channel config posts)) + (cryogen-io/create-file (cryogen-io/path "/" blog-prefix rss-name) (rss/make-channel config posts)) (println (blue "generating filtered rss")) (rss/make-filtered-channels config posts-by-tag) (println (blue "compiling sass")) (sass/compile-sass->css! - {:path-sass sass-path - :path-compass compass-path - :src-sass sass-src - :dest-sass (path ".." "public" blog-prefix sass-dest) - :ignored-files ignored-files - :base-dir "resources/templates/"}))) + (merge (select-keys config [:sass-path :compass-path :sass-src :ignored-files]) + {:dest-sass (cryogen-io/path ".." "public" blog-prefix sass-dest) + :base-dir "resources/templates/"})))) (defn compile-assets-timed [] (time diff --git a/src/cryogen_core/github.clj b/src/cryogen_core/github.clj deleted file mode 100644 index 44c51ca..0000000 --- a/src/cryogen_core/github.clj +++ /dev/null @@ -1,37 +0,0 @@ -(ns cryogen-core.github - (:require [cheshire.core :as json]) - (:import (org.apache.commons.codec.binary Base64 StringUtils))) - -(defn get-gist [gist-uri] - (let [gist-id (last (clojure.string/split gist-uri #"/+")) ;;just need id for git api - gist-resp (try (slurp (str "https://api.github.com/gists/" gist-id)) - (catch Exception e {:error (.getMessage e)}))] - - (when-not (:error gist-resp) - (if-let [gist (-> (json/parse-string gist-resp) - (get "files") - first ;;todo: optionally get all gist files? - val)] - - {:content (get gist "content") - :language (get gist "language") - :name (get gist "filename") - :id gist-id})))) - -(defn get-src [git-file] - (let [git-re (re-find #"github.com/(.*)/blob/(.+?)/(.+)" git-file) ;;want second and last now (user/repo,file) for git api - git-res (str "https://api.github.com/repos/" (second git-re) "/contents/" (last git-re)) - git-resp (try (slurp git-res) - (catch Exception e {:error (.getMessage e)}))] - (when-not (:error git-resp) - (if-let [git-src (json/parse-string git-resp)] - {:content (String. ^bytes (Base64/decodeBase64 ^String (get git-src "content")) "UTF-8") - :name (get git-src "name") - :uri (get (get git-src "_links") "html")})))) - - -(defn get-gits-ex [] - [(get-gist "https://gist.github.com/viperscape/cec68f0791687f5959f1") - (get-src "https://github.com/viperscape/kuroshio/blob/master/examples/pubsub.clj")]) - -;(prn (get-gits-ex)) diff --git a/src/cryogen_core/markup.clj b/src/cryogen_core/markup.clj index d9c7143..eee6977 100644 --- a/src/cryogen_core/markup.clj +++ b/src/cryogen_core/markup.clj @@ -1,6 +1,5 @@ (ns cryogen-core.markup - (:require [clojure.string :as s]) - (:import java.util.Collections)) + (:require [clojure.string :as s])) (defonce markup-registry (atom [])) @@ -18,7 +17,7 @@ [blog-prefix text] (if (s/blank? blog-prefix) text - (clojure.string/replace text #"href=.?/|src=.?/" #(str (subs % 0 (dec (count %))) blog-prefix "/")))) + (s/replace text #"href=.?/|src=.?/" #(str (subs % 0 (dec (count %))) blog-prefix "/")))) (defn markups "Return a vector of Markup implementations. This is the primary entry point diff --git a/src/cryogen_core/plugins.clj b/src/cryogen_core/plugins.clj index e907745..a85892a 100644 --- a/src/cryogen_core/plugins.clj +++ b/src/cryogen_core/plugins.clj @@ -1,6 +1,5 @@ (ns cryogen-core.plugins - (:require [cryogen-core.compiler :refer [compile-assets-timed]] - [clojure.edn :as edn] + (:require [clojure.edn :as edn] [clojure.string :as s] [text-decoration.core :refer :all])) diff --git a/src/cryogen_core/rss.clj b/src/cryogen_core/rss.clj index f2ffb75..ef28bff 100644 --- a/src/cryogen_core/rss.clj +++ b/src/cryogen_core/rss.clj @@ -1,7 +1,7 @@ (ns cryogen-core.rss (:require [clj-rss.core :as rss] [text-decoration.core :refer :all] - [cryogen-core.io :refer [create-file path]]) + [cryogen-core.io :as cryogen-io]) (:import java.util.Date)) @@ -31,6 +31,6 @@ (defn make-filtered-channels [{:keys [rss-filters blog-prefix] :as config} posts-by-tag] (doseq [filter rss-filters] - (let [uri (path "/" blog-prefix (str (name filter) ".xml"))] + (let [uri (cryogen-io/path "/" blog-prefix (str (name filter) ".xml"))] (println "\t-->" (cyan uri)) - (create-file uri (make-channel config (get posts-by-tag filter)))))) + (cryogen-io/create-file uri (make-channel config (get posts-by-tag filter)))))) diff --git a/src/cryogen_core/sass.clj b/src/cryogen_core/sass.clj index f85bf43..b164081 100644 --- a/src/cryogen_core/sass.clj +++ b/src/cryogen_core/sass.clj @@ -1,8 +1,8 @@ (ns cryogen-core.sass - (:require [clojure.java.shell :as shell] - [clojure.java.io :as io] + (:require [clojure.java.io :as io] + [clojure.java.shell :as shell] [text-decoration.core :refer :all] - [cryogen-core.io :refer [ignore match-re-filter]])) + [cryogen-core.io :as cryogen-io])) (defmacro sh [& args] @@ -11,64 +11,51 @@ (defn sass-installed? "Checks for the installation of Sass." - [path-sass] - (= 0 (:exit (sh path-sass "--version")))) + [sass-path] + (zero? (:exit (sh sass-path "--version")))) (defn compass-installed? "Checks for the installation of Compass." - [path-compass] + [compass-path] (try - (= 0 (:exit (sh path-compass "--version"))) + (zero? (:exit (sh compass-path "--version"))) (catch java.io.IOException _ false))) (defn find-sass-files "Given a Diretory, gets files, Filtered to those having scss or sass - extention. Ignores files matching any ignored regexps." + extention. Ignores files matching any ignored regexps." [base-dir dir ignored-files] - (let [^java.io.FilenameFilter filename-filter (match-re-filter #"(?i:s[ca]ss$)")] + (let [^java.io.FilenameFilter filename-filter (cryogen-io/match-re-filter #"(?i:s[ca]ss$)")] (->> (.listFiles (io/file base-dir dir) filename-filter) (filter #(not (.isDirectory ^java.io.File %))) - (filter (ignore ignored-files)) + (filter (cryogen-io/ignore ignored-files)) (map #(.getName ^java.io.File %))))) (defn compile-sass-file! - "Given a sass file which might be in src-sass directory, - output the resulting css in dest-sass. All error handling is - done by sh / launching the sass command." - [{:keys [src-sass - dest-sass - path-sass - path-compass - base-dir]}] + "Given a sass file which might be in sass-src directory, + output the resulting css in sass-dest. All error handling is + done by sh / launching the sass command." + [{:keys [sass-src sass-dest sass-path compass-path base-dir]}] (shell/with-sh-dir base-dir - (if (compass-installed? path-compass) - (sh path-sass "--compass" "--update" (str src-sass ":" dest-sass)) - (sh path-sass "--update" (str src-sass ":" dest-sass))))) + (if (compass-installed? compass-path) + (sh sass-path "--compass" "--update" (str sass-src ":" sass-dest)) + (sh sass-path "--update" (str sass-src ":" sass-dest))))) (defn compile-sass->css! - "Given a directory src-sass, looks for all sass files and compiles them into -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. " - [{:keys [src-sass - dest-sass - path-sass - ignored-files - base-dir] :as opts}] - (when-let [sass-files (seq (find-sass-files base-dir src-sass ignored-files))] - (if (sass-installed? path-sass) - ;; I found sass files, - ;; If sass is installed + "Given a directory sass-src, looks for all sass files and compiles them into + sass-dest. 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. " + [{:keys [sass-src sass-dest sass-path ignored-files base-dir] :as opts}] + (when (seq (find-sass-files base-dir sass-src ignored-files)) + (if (sass-installed? sass-path) (do - (println "\t" (cyan src-sass) "-->" (cyan dest-sass)) + (println "\t" (cyan sass-src) "-->" (cyan sass-dest)) (let [result (compile-sass-file! opts)] (if (zero? (:exit result)) - ;; no problems in sass compilation (println "Successfully compiled sass files") - ;; else I show the error (println (red (:err result)) (red (:out result)))))) - ;; Else I prompt to install Sass (println "Sass seems not to be installed, but you have scss / sass files in " - src-sass + sass-src " - You might want to install it here: sass-lang.com")))) diff --git a/src/cryogen_core/sitemap.clj b/src/cryogen_core/sitemap.clj index 618828a..edaaf0e 100644 --- a/src/cryogen_core/sitemap.clj +++ b/src/cryogen_core/sitemap.clj @@ -1,6 +1,6 @@ (ns cryogen-core.sitemap (:require [clojure.xml :refer [emit]] - [cryogen-core.io :refer [get-resource find-assets]]) + [cryogen-core.io :as cryogen-io]) (:import java.util.Date)) ;;generate sitemaps using the sitemap spec @@ -19,7 +19,7 @@ {:tag :urlset :attrs {:xmlns "http://www.sitemaps.org/schemas/sitemap/0.9"} :content - (for [^java.io.File f (find-assets "public" ".html" ignored-files)] + (for [^java.io.File f (cryogen-io/find-assets "public" ".html" ignored-files)] {:tag :url :content [{:tag :loc diff --git a/src/cryogen_core/watcher.clj b/src/cryogen_core/watcher.clj index 215d98a..5f0a5ae 100644 --- a/src/cryogen_core/watcher.clj +++ b/src/cryogen_core/watcher.clj @@ -1,20 +1,20 @@ (ns cryogen-core.watcher - (:require [clojure.java.io :refer [file]] - [cryogen-core.io :refer [ignore]] - [pandect.algo.md5 :refer [md5]] + (:require [clojure.java.io :as io] + [clojure.set :as set] [hawk.core :as hawk] - [clojure.set :as set])) + [pandect.algo.md5 :as md5] + [cryogen-core.io :as cryogen-io])) (defn get-assets [path ignored-files] (->> path - file + io/file file-seq (filter #(not (.isDirectory ^java.io.File %))) - (filter (ignore ignored-files)))) + (filter (cryogen-io/ignore ignored-files)))) (defn checksums [path ignored-files] (let [files (get-assets path ignored-files)] - (zipmap (map md5 files) files))) + (zipmap (map md5/md5 files) files))) (defn find-changes [old-sums new-sums] (let [old-sum-set (-> old-sums keys set) diff --git a/test/cryogen_core/compiler_test.clj b/test/cryogen_core/compiler_test.clj index 46a5a55..dcd9525 100644 --- a/test/cryogen_core/compiler_test.clj +++ b/test/cryogen_core/compiler_test.clj @@ -1,9 +1,8 @@ (ns cryogen-core.compiler-test (:require [clojure.test :refer :all] + [me.raynes.fs :as fs] [cryogen-core.compiler :refer :all] - [cryogen-core.io :refer [path]] - [cryogen-core.markup :as m] - [me.raynes.fs :as fs]) + [cryogen-core.markup :as m]) (:import [java.io File])) ; Test that the content-until-more-marker return nil or correct html text. diff --git a/test/cryogen_core/toc_test.clj b/test/cryogen_core/toc_test.clj index 4a608e9..df2809b 100644 --- a/test/cryogen_core/toc_test.clj +++ b/test/cryogen_core/toc_test.clj @@ -1,7 +1,6 @@ (ns cryogen-core.toc-test (:require [clojure.test :refer :all] - [clojure.string :refer [join]] - [clojure.zip :as z] + [clojure.string :as s] [crouton.html :as html] [hiccup.core :as hiccup] [cryogen-core.toc :refer :all])) @@ -9,8 +8,6 @@ ; Reimport private functions (def get-headings #'cryogen-core.toc/get-headings) (def make-toc-entry #'cryogen-core.toc/make-toc-entry) -(def zip-toc-tree-to-insertion-point #'cryogen-core.toc/zip-toc-tree-to-insertion-point) -(def insert-toc-tree-entry #'cryogen-core.toc/insert-toc-tree-entry) (def build-toc-tree #'cryogen-core.toc/build-toc-tree) (def build-toc #'cryogen-core.toc/build-toc) @@ -21,18 +18,18 @@ ; Test that the get-headings function properly filters non-headers (deftest test-get-headings (let [noisy-headers [:div [:h1 "First H1"] - [:p "Ignore..."] - [:h2 "First H2"]]] + [:p "Ignore..."] + [:h2 "First H2"]]] (is (= (parse-to-headings noisy-headers) - [{:tag :h1 :attrs nil :content ["First H1"]} - {:tag :h2 :attrs nil :content ["First H2"]}])))) + [{:tag :h1 :attrs nil :content ["First H1"]} + {:tag :h2 :attrs nil :content ["First H2"]}])))) ; Test that the make-toc-entry ignores invalid input (deftest test-make-toc-entry (is (nil? - (make-toc-entry nil "Text"))) + (make-toc-entry nil "Text"))) (is (nil? - (make-toc-entry "anchor" nil))) + (make-toc-entry "anchor" nil))) (is (= [:li [:a {:href "#anchor"} "Text"]] (make-toc-entry "anchor" "Text")))) @@ -45,65 +42,64 @@ ; * h1 (deftest test-build-toc (let [simplest-header [:div [:h2 [:a {:name "test"}] "Test"]] - no-headers [:div [:p "This is not a header"]] + no-headers [:div [:p "This is not a header"]] + closing-header-larger-than-opening-1 - [:div [:h2 [:a {:name "starting_low"}] - "Starting Low"] - [:h1 [:a {:name "finishing_high"}] - "Finishing High"]] + [:div [:h2 [:a {:name "starting_low"}] + "Starting Low"] + [:h1 [:a {:name "finishing_high"}] + "Finishing High"]] + closing-header-larger-than-opening-2 - [:div [:h2 [:a {:name "starting_low"}] - "Starting Low"] - [:h4 [:a {:name "jumping_in"}] - "Jumping Right In"] - [:h3 [:a {:name "pulling_back"}] - "But then pull back"] - [:h2 [:a {:name "to_the_top"}] - "To the top"]]] + [:div [:h2 [:a {:name "starting_low"}] + "Starting Low"] + [:h4 [:a {:name "jumping_in"}] + "Jumping Right In"] + [:h3 [:a {:name "pulling_back"}] + "But then pull back"] + [:h2 [:a {:name "to_the_top"}] + "To the top"]]] (is (= [:ol.content (seq [[:li [:a {:href "#test"} "Test"]]])] - (-> simplest-header parse-to-headings build-toc-tree + (-> simplest-header + (parse-to-headings) + (build-toc-tree) (build-toc :ol)))) - (is (nil? - (-> no-headers parse-to-headings build-toc-tree - (build-toc :ol)))) + (is (-> no-headers + (parse-to-headings) + (build-toc-tree) + (build-toc :ol) + (nil?))) (is (= [:ol.content (seq [[:li [:a {:href "#starting_low"} "Starting Low"]] [:li [:a {:href "#finishing_high"} "Finishing High"]]])] - (-> closing-header-larger-than-opening-1 - parse-to-headings - build-toc-tree - (build-toc :ol))) + (-> closing-header-larger-than-opening-1 + (parse-to-headings) + (build-toc-tree) + (build-toc :ol))) "No outer header should be less indented than the first header tag.") - (is (= [:ul.content - (seq [ - (seq [ - [:li [:a {:href "#starting_low"} "Starting Low"]] - [:ul - (seq [ - [:li [:a {:href "#jumping_in"} "Jumping Right In"]] - [:li [:a {:href "#pulling_back"} "But then pull back"]] - ]) - ] ]) - [:li [:a {:href "#to_the_top"} "To the top"]] - ])] + (is (= [:ul.content + (seq [(seq [[:li [:a {:href "#starting_low"} "Starting Low"]] + [:ul + (seq [[:li [:a {:href "#jumping_in"} "Jumping Right In"]] + [:li [:a {:href "#pulling_back"} "But then pull back"]]])]]) + [:li [:a {:href "#to_the_top"} "To the top"]]])] (-> closing-header-larger-than-opening-2 - parse-to-headings - build-toc-tree + (parse-to-headings) + (build-toc-tree) (build-toc :ul))) - (join "" ["Inner headers can be more indented, " - "but outer headers cannot be less indented " - "than the original header."])) - )) + (s/join "" ["Inner headers can be more indented, " + "but outer headers cannot be less indented " + "than the original header."])))) (deftest test-generate-toc (let [htmlString "

Test

"] (is (= "
  1. Test
" - (generate-toc htmlString))) + (generate-toc htmlString))) (is (= "
  1. Test
" - (generate-toc htmlString :list-type true))) + (generate-toc htmlString :list-type true))) (is (= "
  1. Test
" - (generate-toc htmlString :list-type :ol))) + (generate-toc htmlString :list-type :ol))) (is (= "" - (generate-toc htmlString :list-type :ul))))) + (generate-toc htmlString :list-type :ul))))) From 1cfb2b17df1b1f1510b2c881e932753c8f008d37 Mon Sep 17 00:00:00 2001 From: Aleksander Madland Stapnes Date: Mon, 16 Jan 2017 18:16:11 -0300 Subject: [PATCH 04/15] Remove crouton dep because enlive does the same thing Almost the same thing; it doesn't insert missing html, head and body tags, but in this case we only care about the stuff in the body. --- project.clj | 1 - src/cryogen_core/toc.clj | 9 +++------ test/cryogen_core/toc_test.clj | 6 ++---- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/project.clj b/project.clj index 7540783..db7df6c 100644 --- a/project.clj +++ b/project.clj @@ -7,7 +7,6 @@ [cheshire "5.6.3"] [clj-rss "0.2.3"] [clj-text-decoration "0.0.3"] - [crouton "0.1.2"] [enlive "1.1.6"] [hawk "0.2.11"] [hiccup "1.0.5"] diff --git a/src/cryogen_core/toc.clj b/src/cryogen_core/toc.clj index 0324c67..3544ba3 100644 --- a/src/cryogen_core/toc.clj +++ b/src/cryogen_core/toc.clj @@ -1,6 +1,6 @@ (ns cryogen-core.toc (:require [clojure.zip :as z] - [crouton.html :as html] + [net.cgrand.enlive-html :as enlive] [hiccup.core :as hiccup])) (def _h [:h1 :h2 :h3 :h4 :h5 :h6]) @@ -102,13 +102,10 @@ :ol and true will result in an ordered list being generated for the table of contents, while :ul will result in an unordered list. The default is an ordered list." - [^String html & {:keys [list-type] :or {list-type :ol}}] + [html & {:keys [list-type] :or {list-type :ol}}] (let [list-type (if (true? list-type) :ol list-type)] (-> html - (.getBytes "UTF-8") - (java.io.ByteArrayInputStream.) - (html/parse) - :content + (enlive/html-snippet) (get-headings) (build-toc-tree) (build-toc list-type) diff --git a/test/cryogen_core/toc_test.clj b/test/cryogen_core/toc_test.clj index df2809b..83bb390 100644 --- a/test/cryogen_core/toc_test.clj +++ b/test/cryogen_core/toc_test.clj @@ -1,7 +1,7 @@ (ns cryogen-core.toc-test (:require [clojure.test :refer :all] [clojure.string :as s] - [crouton.html :as html] + [net.cgrand.enlive-html :as enlive] [hiccup.core :as hiccup] [cryogen-core.toc :refer :all])) @@ -13,7 +13,7 @@ (defn parse-to-headings [hiccup-seq] - (-> hiccup-seq hiccup/html html/parse-string :content get-headings)) + (-> hiccup-seq hiccup/html enlive/html-snippet get-headings)) ; Test that the get-headings function properly filters non-headers (deftest test-get-headings @@ -101,5 +101,3 @@ (generate-toc htmlString :list-type :ol))) (is (= "" (generate-toc htmlString :list-type :ul))))) - - From 9cd50165374bae209d9434ea6b483e88a55fb841 Mon Sep 17 00:00:00 2001 From: Carmen La Date: Mon, 16 Jan 2017 23:12:53 -0500 Subject: [PATCH 05/15] Don't create prev/next links pointing to :home? pages - Also include more metadata in page.prev and page.next params - And some general code cleanup --- src/cryogen_core/compiler.clj | 114 ++++++++++++++++++---------------- 1 file changed, 60 insertions(+), 54 deletions(-) diff --git a/src/cryogen_core/compiler.clj b/src/cryogen_core/compiler.clj index fd92eb6..dea8566 100644 --- a/src/cryogen_core/compiler.clj +++ b/src/cryogen_core/compiler.clj @@ -1,5 +1,6 @@ (ns cryogen-core.compiler (:require [clojure.java.io :as io] + [clojure.pprint :refer [pprint]] [clojure.string :as s] [io.aviso.exception :refer [write-exception]] [net.cgrand.enlive-html :as enlive] @@ -200,13 +201,13 @@ :uri (page-uri (str (name tag) ".html") :tag-root-uri config)}) (defn add-prev-next - "Adds a :prev and :next key to the page/post data containing the title and uri of the prev/next + "Adds a :prev and :next key to the page/post data containing the metadata of the prev/next post/page if it exists" [pages] (map (fn [[prev target next]] (assoc target - :prev (if prev (select-keys prev [:title :uri]) nil) - :next (if next (select-keys next [:title :uri]) nil))) + :prev (if prev (dissoc prev :content) nil) + :next (if next (dissoc next :content) nil))) (partition 3 1 (flatten [nil pages nil])))) (defn group-pages @@ -223,6 +224,10 @@ (cryogen-io/create-file-recursive (cryogen-io/path file-uri "index.html") data) (cryogen-io/create-file file-uri data))) +(defn- print-debug-info [data] + (println "DEBUG:") + (pprint data)) + (defn compile-pages "Compiles all the pages into html and spits them out into the public folder" [{:keys [blog-prefix page-root-uri debug?] :as params} pages] @@ -230,9 +235,9 @@ (println (blue "compiling pages")) (cryogen-io/create-folder (cryogen-io/path "/" blog-prefix page-root-uri)) (doseq [{:keys [uri] :as page} pages] - (println "\t-->" (cyan uri)) + (println "-->" (cyan uri)) (when debug? - (println "\t\tdebug-->" (cyan page))) + (print-debug-info page)) (write-html uri params (render-file (str "/html/" (:layout page)) @@ -250,9 +255,9 @@ (println (blue "compiling posts")) (cryogen-io/create-folder (cryogen-io/path "/" blog-prefix post-root-uri)) (doseq [{:keys [uri] :as post} posts] - (println "\t-->" (cyan uri)) + (println "-->" (cyan uri)) (when debug? - (println "\t\tdebug-->" (cyan post))) + (print-debug-info post)) (write-html uri params (render-file (str "/html/" (:layout post)) @@ -271,7 +276,7 @@ (cryogen-io/create-folder (cryogen-io/path "/" blog-prefix tag-root-uri)) (doseq [[tag posts] posts-by-tag] (let [{:keys [name uri]} (tag-info params tag)] - (println "\t-->" (cyan uri)) + (println "-->" (cyan uri)) (write-html uri params (render-file "/html/tag.html" @@ -362,20 +367,18 @@ "Compiles the index page into html and spits it out into the public folder" [{:keys [disqus? debug? home-page] :as params}] (println (blue "compiling index")) - (let [uri (page-uri "index.html" params) - meta {:active-page "home" - :home true - :disqus? disqus? - :uri uri - :post home-page - :page home-page}] + (let [uri (page-uri "index.html" params)] (when debug? - (println "\t\tdebug-->" (cyan meta))) + (print-debug-info meta)) (write-html uri params - (render-file (str "/html/" (:layout home-page)) + (render-file "/html/home.html" (merge params - meta))))) + {:active-page "home" + :home true + :disqus? disqus? + :uri uri + :post home-page}))))) (defn compile-archives "Compiles the archives page into html and spits it out into the public folder" @@ -400,7 +403,7 @@ ;; if the post author is empty defaults to config's :author (doseq [{:keys [author posts]} (group-for-author posts author)] (let [uri (page-uri (str author ".html") :author-root-uri params)] - (println "\t-->" (cyan uri)) + (println "-->" (cyan uri)) (write-html uri params (render-file "/html/author.html" @@ -470,58 +473,61 @@ (println (green "compiling assets...")) (let [{:keys [^String site-url blog-prefix rss-name recent-posts sass-dest keep-files ignored-files previews? author-root-uri theme] :as config} (read-config) - posts (add-prev-next (read-posts config)) - pages (add-prev-next (read-pages config)) - home-pages (filter #(boolean (:home? %)) pages) - pages-without-home (filter #(boolean (not (:home? %))) pages) - [navbar-pages sidebar-pages] (group-pages pages-without-home) - posts-by-tag (group-by-tags posts) - posts (tag-posts posts config) - latest-posts (->> posts (take recent-posts) vec) - params (merge config - {:today (java.util.Date.) - :title (:site-title config) - :active-page "home" - :tags (map (partial tag-info config) (keys posts-by-tag)) - :latest-posts latest-posts - :navbar-pages navbar-pages - :sidebar-pages sidebar-pages - :home-page (if (not-empty home-pages) - (first home-pages) - (merge (first latest-posts) - {:layout "home.html"})) - :archives-uri (page-uri "archives.html" config) - :index-uri (page-uri "index.html" config) - :tags-uri (page-uri "tags.html" config) - :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) - :theme-path (str "file:resources/templates/themes/" theme)})] + posts (add-prev-next (read-posts config)) + posts-by-tag (group-by-tags posts) + posts (tag-posts posts config) + latest-posts (->> posts (take recent-posts) vec) + pages (read-pages config) + home-page (->> pages + (filter #(boolean (:home? %))) + (first)) + other-pages (->> pages + (remove #{home-page}) + (add-prev-next)) + [navbar-pages + sidebar-pages] (group-pages other-pages) + params (merge + config + {:today (java.util.Date.) + :title (:site-title config) + :active-page "home" + :tags (map (partial tag-info config) (keys posts-by-tag)) + :latest-posts latest-posts + :navbar-pages navbar-pages + :sidebar-pages sidebar-pages + :home-page (if home-page + home-page + (first latest-posts)) + :archives-uri (page-uri "archives.html" config) + :index-uri (page-uri "index.html" config) + :tags-uri (page-uri "tags.html" config) + :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)})] - (println (blue "debug info")) - (println "\t-->" (cyan navbar-pages)) - (set-custom-resource-path! (:theme-path params)) + (set-custom-resource-path! (str "file:resources/templates/themes/" theme)) (cryogen-io/wipe-public-folder keep-files) (println (blue "copying theme resources")) (cryogen-io/copy-resources-from-theme config) (println (blue "copying resources")) (cryogen-io/copy-resources config) (copy-resources-from-markup-folders config) - (compile-pages params pages-without-home) + (compile-pages params other-pages) (compile-posts params posts) (compile-tags params posts-by-tag) (compile-tags-page params) - (when previews? - (compile-preview-pages params posts)) - (when (or (not-empty home-pages) (not previews?)) + (if previews? + (compile-preview-pages params posts) (compile-index params)) (compile-archives params posts) (when author-root-uri (println (blue "generating authors views")) (compile-authors params posts)) (println (blue "generating site map")) - (cryogen-io/create-file (cryogen-io/path "/" blog-prefix "sitemap.xml") (sitemap/generate site-url ignored-files)) + (->> (sitemap/generate site-url ignored-files) + (cryogen-io/create-file (cryogen-io/path "/" blog-prefix "sitemap.xml"))) (println (blue "generating main rss")) - (cryogen-io/create-file (cryogen-io/path "/" blog-prefix rss-name) (rss/make-channel config posts)) + (->> (rss/make-channel config posts) + (cryogen-io/create-file (cryogen-io/path "/" blog-prefix rss-name))) (println (blue "generating filtered rss")) (rss/make-filtered-channels config posts-by-tag) (println (blue "compiling sass")) From 1b7f0fb367f3b851de700bef6e1c50fcd0015ff1 Mon Sep 17 00:00:00 2001 From: Carmen La Date: Mon, 16 Jan 2017 23:29:48 -0500 Subject: [PATCH 06/15] update deps and version number --- project.clj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/project.clj b/project.clj index db7df6c..cd7cd79 100644 --- a/project.clj +++ b/project.clj @@ -1,10 +1,10 @@ -(defproject cryogen-core "0.1.47" +(defproject cryogen-core "0.1.48" :description "Cryogen's compiler" :url "https://github.com/cryogen-project/cryogen-core" :license {:name "Eclipse Public License" :url "http://www.eclipse.org/legal/epl-v10.html"} :dependencies [[org.clojure/clojure "1.8.0"] - [cheshire "5.6.3"] + [cheshire "5.7.0"] [clj-rss "0.2.3"] [clj-text-decoration "0.0.3"] [enlive "1.1.6"] @@ -13,6 +13,6 @@ [io.aviso/pretty "0.1.33"] [me.raynes/fs "1.4.6"] [pandect "0.6.1"] - [selmer "1.10.3"]] + [selmer "1.10.5"]] :deploy-repositories [["snapshots" :clojars] ["releases" :clojars]]) From 6ba76bc7f5cf3f71103e64e08db509d1e3a1280c Mon Sep 17 00:00:00 2001 From: Carmen La Date: Tue, 17 Jan 2017 01:41:04 -0500 Subject: [PATCH 07/15] Fix a regression --- project.clj | 2 +- src/cryogen_core/compiler.clj | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/project.clj b/project.clj index cd7cd79..aafa6fd 100644 --- a/project.clj +++ b/project.clj @@ -1,4 +1,4 @@ -(defproject cryogen-core "0.1.48" +(defproject cryogen-core "0.1.49" :description "Cryogen's compiler" :url "https://github.com/cryogen-project/cryogen-core" :license {:name "Eclipse Public License" diff --git a/src/cryogen_core/compiler.clj b/src/cryogen_core/compiler.clj index dea8566..b9e50a6 100644 --- a/src/cryogen_core/compiler.clj +++ b/src/cryogen_core/compiler.clj @@ -372,7 +372,7 @@ (print-debug-info meta)) (write-html uri params - (render-file "/html/home.html" + (render-file (str "/html/" (:layout home-page)) (merge params {:active-page "home" :home true @@ -497,7 +497,7 @@ :sidebar-pages sidebar-pages :home-page (if home-page home-page - (first latest-posts)) + (assoc (first latest-posts) :layout "home.html")) :archives-uri (page-uri "archives.html" config) :index-uri (page-uri "index.html" config) :tags-uri (page-uri "tags.html" config) From f0cc7353c1797d62a3a533b3d79ddc060bca461c Mon Sep 17 00:00:00 2001 From: Carmen La Date: Tue, 17 Jan 2017 01:56:14 -0500 Subject: [PATCH 08/15] Pass both page/post params to the index template --- project.clj | 2 +- src/cryogen_core/compiler.clj | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/project.clj b/project.clj index aafa6fd..316ad33 100644 --- a/project.clj +++ b/project.clj @@ -1,4 +1,4 @@ -(defproject cryogen-core "0.1.49" +(defproject cryogen-core "0.1.50" :description "Cryogen's compiler" :url "https://github.com/cryogen-project/cryogen-core" :license {:name "Eclipse Public License" diff --git a/src/cryogen_core/compiler.clj b/src/cryogen_core/compiler.clj index b9e50a6..5219e67 100644 --- a/src/cryogen_core/compiler.clj +++ b/src/cryogen_core/compiler.clj @@ -378,7 +378,8 @@ :home true :disqus? disqus? :uri uri - :post home-page}))))) + :post home-page + :page home-page}))))) (defn compile-archives "Compiles the archives page into html and spits it out into the public folder" From 84a933bdcf10be2686bae25f0109246373bbc372 Mon Sep 17 00:00:00 2001 From: Carmen La Date: Tue, 17 Jan 2017 23:44:37 -0500 Subject: [PATCH 09/15] Fix dest-sass/sass-dest key Issue #85 --- project.clj | 2 +- src/cryogen_core/compiler.clj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/project.clj b/project.clj index 316ad33..e29657d 100644 --- a/project.clj +++ b/project.clj @@ -1,4 +1,4 @@ -(defproject cryogen-core "0.1.50" +(defproject cryogen-core "0.1.51" :description "Cryogen's compiler" :url "https://github.com/cryogen-project/cryogen-core" :license {:name "Eclipse Public License" diff --git a/src/cryogen_core/compiler.clj b/src/cryogen_core/compiler.clj index 5219e67..053d1ba 100644 --- a/src/cryogen_core/compiler.clj +++ b/src/cryogen_core/compiler.clj @@ -534,7 +534,7 @@ (println (blue "compiling sass")) (sass/compile-sass->css! (merge (select-keys config [:sass-path :compass-path :sass-src :ignored-files]) - {:dest-sass (cryogen-io/path ".." "public" blog-prefix sass-dest) + {:sass-dest (cryogen-io/path ".." "public" blog-prefix sass-dest) :base-dir "resources/templates/"})))) (defn compile-assets-timed [] From ac52785b19ecc62e391e73e8605f55729b894ce2 Mon Sep 17 00:00:00 2001 From: Aleksander Madland Stapnes Date: Thu, 19 Jan 2017 14:33:38 -0300 Subject: [PATCH 10/15] Automatic klipse integration --- project.clj | 1 + src/cryogen_core/compiler.clj | 7 ++- src/cryogen_core/klipse.clj | 92 +++++++++++++++++++++++++++++++ test/cryogen_core/klipse_test.clj | 43 +++++++++++++++ 4 files changed, 141 insertions(+), 2 deletions(-) create mode 100644 src/cryogen_core/klipse.clj create mode 100644 test/cryogen_core/klipse_test.clj diff --git a/project.clj b/project.clj index e29657d..57d65b7 100644 --- a/project.clj +++ b/project.clj @@ -4,6 +4,7 @@ :license {:name "Eclipse Public License" :url "http://www.eclipse.org/legal/epl-v10.html"} :dependencies [[org.clojure/clojure "1.8.0"] + [camel-snake-kebab "0.4.0"] [cheshire "5.7.0"] [clj-rss "0.2.3"] [clj-text-decoration "0.0.3"] diff --git a/src/cryogen_core/compiler.clj b/src/cryogen_core/compiler.clj index 053d1ba..4729618 100644 --- a/src/cryogen_core/compiler.clj +++ b/src/cryogen_core/compiler.clj @@ -8,6 +8,7 @@ [selmer.util :refer [set-custom-resource-path!]] [text-decoration.core :refer :all] [cryogen-core.io :as cryogen-io] + [cryogen-core.klipse :as klipse] [cryogen-core.markup :as m] [cryogen-core.rss :as rss] [cryogen-core.sass :as sass] @@ -111,7 +112,8 @@ (merge (merge-meta-and-content file-name page-meta content) {:uri (page-uri file-name :page-root-uri config) - :page-index (:page-index page-meta)}))) + :page-index (:page-index page-meta) + :klipse (klipse/emit (:klipse config) (:klipse page-meta))}))) (defn parse-post "Return a map with the given post's information." @@ -128,7 +130,8 @@ :formatted-archive-group formatted-group :parsed-archive-group (.parse archive-fmt formatted-group) :uri (page-uri file-name :post-root-uri config) - :tags (set (:tags page-meta))})))) + :tags (set (:tags page-meta)) + :klipse (klipse/emit (:klipse config) (:klipse page-meta))})))) (defn read-posts "Returns a sequence of maps representing the data from markdown files of posts. diff --git a/src/cryogen_core/klipse.clj b/src/cryogen_core/klipse.clj new file mode 100644 index 0000000..2ea5705 --- /dev/null +++ b/src/cryogen_core/klipse.clj @@ -0,0 +1,92 @@ +(ns cryogen-core.klipse + (:require + [camel-snake-kebab.core :refer [->snake_case_string ->camelCaseString]] + [cheshire.core :as json])) + +;;;;;;;;;;; +;; utils + +(defn map-keys + "Applies f to each key in m" + [f m] + (zipmap (map f (keys m)) (vals m))) + +(defn update-existing + "Like clojure.core/update, but returns m untouched if it doesn't contain k" + [m k f & args] + (if (contains? m k) (apply update m k f args) m)) + +(def map-or-nil? (some-fn map? nil?)) + +(defn deep-merge + "Like clojure.core/merge, but also merges nested maps under the same key." + [& ms] + (apply merge-with + (fn [v1 v2] + (if (and (map-or-nil? v1) (map-or-nil? v2)) + (deep-merge v1 v2) + v2)) + ms)) + +;;;;;;;;;;;; +;; klipse + +(def defaults + {:js-src + {:min "https://storage.googleapis.com/app.klipse.tech/plugin_prod/js/klipse_plugin.min.js" + :non-min "https://storage.googleapis.com/app.klipse.tech/plugin/js/klipse_plugin.js"} + + :css-base "https://storage.googleapis.com/app.klipse.tech/css/codemirror.css"}) + +;; This needs to be updated whenever a new clojure selector is introduced. +;; It should only be necessary for react wrappers and the like, so not very often. +;; When (if?) self hosted cljs becomes compatible with advanced builds +;; this can be removed and we can just always use minified js. +(def clojure-selectors + "A set of selectors that imply clojure evaluation." + #{"selector" "selector_reagent"}) + +(defn clojure-eval? + "Does the configuration include any keys that imply clojure eval?" + [normalized-cfg] + (some clojure-selectors (keys normalized-cfg))) + +(defn normalize-settings + "Transform the keys to the correct snake-case or camelCase strings." + [cfg] + (-> (map-keys ->snake_case_string cfg) + (update-existing "codemirror_options_in" (partial map-keys ->camelCaseString)) + (update-existing "codemirror_options_out" (partial map-keys ->camelCaseString)))) + +(defn merge-configs [global-config post-config] + (when post-config + (let [post-config (if (true? post-config) {} post-config) + merged-config (deep-merge defaults + (update-existing global-config :settings normalize-settings) + (update-existing post-config :settings normalize-settings))] + (when (:settings merged-config) + (if (:js merged-config) + merged-config + (assoc merged-config :js (if (clojure-eval? (:settings merged-config)) + :non-min + :min))))))) + +(defn include-css [href] + (str "")) + +(defn include-js [src] + (str "")) + +(defn emit [global-config post-config] + (when-let [{:keys [settings js-src js css-base css-theme]} + (merge-configs global-config post-config)] + + (assert (#{:min :non-min} js) + (str ":js needs to be one of :min or :non-min but was: " js)) + + (str (include-css css-base) "\n" + (when css-theme (str (include-css css-theme) "\n")) + "\n" + (include-js (js js-src))))) diff --git a/test/cryogen_core/klipse_test.clj b/test/cryogen_core/klipse_test.clj new file mode 100644 index 0000000..5e92a19 --- /dev/null +++ b/test/cryogen_core/klipse_test.clj @@ -0,0 +1,43 @@ +(ns cryogen-core.klipse-test + (:require [cryogen-core.klipse :refer :all] + [clojure.test :refer [deftest testing is are]])) + +(deftest map-keys-test + (is (= {"a" 1 "b" 2} (map-keys name {:a 1 :b 2})))) + +(deftest update-existing-test + (is (= {:a 1 :b 2} (update-existing {:a 1 :b 1} :b inc))) + (is (= {:a 1} (update-existing {:a 1} :b (constantly 2))))) + +(deftest deep-merge-test + (is (= {:a {:b 1 :c 2}} (deep-merge {:a {:b 1}} {:a {:c 2}}))) + (is (= {:a {:b 1}} (deep-merge {:a {:b 1}} {:a nil}))) + (is (= {:a {:b 1 :c 3}} (deep-merge {:a {:b 1 :c 2}} {:a {:c 3}})))) + +(deftest normalize-settings-test + (is (= {"selector_reagent" ".reagent" + "codemirror_options_in" {"lineNumbers" true}} + (normalize-settings + {:selector-reagent ".reagent" + :codemirror-options-in {:line-numbers true}})))) + +(deftest merge-configs-test + (testing "Things are merged correctly, and :js :non-min is inferred from :selector." + (is (= (merge defaults + {:settings {"selector" ".clojure" + "codemirror_options_in" {"lineNumbers" true}} + :js :non-min}) + (merge-configs {:settings {:codemirror-options-in {:line-numbers true}}} + {:settings {:selector ".clojure"}})))) + + (testing "If it's all set up in config.edn, in the post it can be just :klipse true" + (is (= (merge defaults + {:settings {"selector_js" ".javascript"} + :js :min}) + (merge-configs {:settings {:selector-js ".javascript"}} true)))) + + (testing "Returns nil if there's nothing in the blog post" + (is (nil? (merge-configs {:settings {:selector ".clojure"}} nil)))) + + (testing "If there's no :settings, returns nil" + (is (nil? (merge-configs {:css-base "/css/base.css"} {:css-theme "/css/theme.css"}))))) From c5d995b2626c61f33d470b69898e6121b6d77a4e Mon Sep 17 00:00:00 2001 From: Aleksander Madland Stapnes Date: Thu, 19 Jan 2017 20:33:40 -0300 Subject: [PATCH 11/15] Add some docstrings --- src/cryogen_core/klipse.clj | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/cryogen_core/klipse.clj b/src/cryogen_core/klipse.clj index 2ea5705..f997d5f 100644 --- a/src/cryogen_core/klipse.clj +++ b/src/cryogen_core/klipse.clj @@ -58,12 +58,22 @@ (update-existing "codemirror_options_in" (partial map-keys ->camelCaseString)) (update-existing "codemirror_options_out" (partial map-keys ->camelCaseString)))) -(defn merge-configs [global-config post-config] +(defn merge-configs + "Merges the defaults, global config and post config, + transforms lisp-case keywords into snake_case/camelCase strings + and infers whether to use minified or non-minified js + (this can be overridden by supplying a :js key). + If the post config is just true, uses only the global config. + Returns nil if either there's no post-config or if there's no settings after merging." + [global-config post-config] (when post-config (let [post-config (if (true? post-config) {} post-config) merged-config (deep-merge defaults (update-existing global-config :settings normalize-settings) (update-existing post-config :settings normalize-settings))] + ;; It would make more sense to return nil if there's no selector specified + ;; instead of no settings, but that would be too much of a + ;; maintenance burden, as there are new selectors added all the time. (when (:settings merged-config) (if (:js merged-config) merged-config @@ -77,7 +87,10 @@ (defn include-js [src] (str "")) -(defn emit [global-config post-config] +(defn emit + "Takes the :klipse config from config.edn and the :klipse config from the + current post, and returns the html to include on the bottom of the page." + [global-config post-config] (when-let [{:keys [settings js-src js css-base css-theme]} (merge-configs global-config post-config)] From f7f02f74331687ff3779b538e9fd60f629fc34a9 Mon Sep 17 00:00:00 2001 From: Aleksander Madland Stapnes Date: Fri, 20 Jan 2017 16:16:01 -0300 Subject: [PATCH 12/15] Change confusing local names. cfg -> settings --- src/cryogen_core/klipse.clj | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/cryogen_core/klipse.clj b/src/cryogen_core/klipse.clj index f997d5f..18d95bd 100644 --- a/src/cryogen_core/klipse.clj +++ b/src/cryogen_core/klipse.clj @@ -47,14 +47,14 @@ #{"selector" "selector_reagent"}) (defn clojure-eval? - "Does the configuration include any keys that imply clojure eval?" - [normalized-cfg] - (some clojure-selectors (keys normalized-cfg))) + "Do the settings include any keys that imply clojure eval?" + [normalized-settings] + (some clojure-selectors (keys normalized-settings))) (defn normalize-settings "Transform the keys to the correct snake-case or camelCase strings." - [cfg] - (-> (map-keys ->snake_case_string cfg) + [settings] + (-> (map-keys ->snake_case_string settings) (update-existing "codemirror_options_in" (partial map-keys ->camelCaseString)) (update-existing "codemirror_options_out" (partial map-keys ->camelCaseString)))) From 70c95b41d89962f51e486f6fea69b65dc8180aa2 Mon Sep 17 00:00:00 2001 From: Aleksander Madland Stapnes Date: Fri, 27 Jan 2017 02:57:33 -0300 Subject: [PATCH 13/15] Look at the content as well as the config to infer clojure eval Before only the config was looked at to determine whether to include the js minified of not, now look at the html as well. This makes it more convenient to set up all klipse stuff once in config.edn without having to manually specify which js to include. --- src/cryogen_core/compiler.clj | 12 +++-- src/cryogen_core/klipse.clj | 78 +++++++++++++++++++++---------- test/cryogen_core/klipse_test.clj | 56 +++++++++++++++++----- 3 files changed, 105 insertions(+), 41 deletions(-) diff --git a/src/cryogen_core/compiler.clj b/src/cryogen_core/compiler.clj index 4729618..6403cca 100644 --- a/src/cryogen_core/compiler.clj +++ b/src/cryogen_core/compiler.clj @@ -113,7 +113,7 @@ (merge-meta-and-content file-name page-meta content) {:uri (page-uri file-name :page-root-uri config) :page-index (:page-index page-meta) - :klipse (klipse/emit (:klipse config) (:klipse page-meta))}))) + :klipse (klipse/merge-configs (:klipse config) (:klipse page-meta))}))) (defn parse-post "Return a map with the given post's information." @@ -131,7 +131,7 @@ :parsed-archive-group (.parse archive-fmt formatted-group) :uri (page-uri file-name :post-root-uri config) :tags (set (:tags page-meta)) - :klipse (klipse/emit (:klipse config) (:klipse page-meta))})))) + :klipse (klipse/merge-configs (:klipse config) (:klipse page-meta))})))) (defn read-posts "Returns a sequence of maps representing the data from markdown files of posts. @@ -477,11 +477,15 @@ (println (green "compiling assets...")) (let [{:keys [^String site-url blog-prefix rss-name recent-posts sass-dest keep-files ignored-files previews? author-root-uri theme] :as config} (read-config) - posts (add-prev-next (read-posts config)) + posts (map (fn [{:keys [klipse content] :as post}] + (assoc post :klipse (klipse/emit klipse content))) + (add-prev-next (read-posts config))) posts-by-tag (group-by-tags posts) posts (tag-posts posts config) latest-posts (->> posts (take recent-posts) vec) - pages (read-pages config) + pages (map (fn [{:keys [klipse content] :as page}] + (assoc page :klipse (klipse/emit klipse content))) + (read-pages config)) home-page (->> pages (filter #(boolean (:home? %))) (first)) diff --git a/src/cryogen_core/klipse.clj b/src/cryogen_core/klipse.clj index 18d95bd..3735c10 100644 --- a/src/cryogen_core/klipse.clj +++ b/src/cryogen_core/klipse.clj @@ -1,7 +1,8 @@ (ns cryogen-core.klipse - (:require - [camel-snake-kebab.core :refer [->snake_case_string ->camelCaseString]] - [cheshire.core :as json])) + (:require [clojure.string :as str] + [camel-snake-kebab.core :refer [->snake_case_string ->camelCaseString]] + [cheshire.core :as json] + [net.cgrand.enlive-html :as enlive])) ;;;;;;;;;;; ;; utils @@ -28,6 +29,25 @@ v2)) ms)) +(defn filter-html-elems + "Recursively walks a sequence of enlive-style html elements depth first + and returns a flat sequence of the elements where (pred elem)" + [pred html-elems] + (reduce (fn [acc {:keys [content] :as elem}] + (into (if (pred elem) (conj acc elem) acc) + (filter-html-elems pred content))) + [] html-elems)) + +(defn code-block-classes + "Takes a string of html and returns a sequence of + all the classes on all code blocks." + [html] + (->> html + enlive/html-snippet + (filter-html-elems (comp #{:code} :tag)) + (keep (comp :class :attrs)) + (mapcat #(str/split % #" ")))) + ;;;;;;;;;;;; ;; klipse @@ -46,10 +66,19 @@ "A set of selectors that imply clojure evaluation." #{"selector" "selector_reagent"}) -(defn clojure-eval? - "Do the settings include any keys that imply clojure eval?" +(defn clojure-eval-classes + "Takes settings and returns a set of the html classes that imply clojure eval." [normalized-settings] - (some clojure-selectors (keys normalized-settings))) + (reduce (fn [classes selector] + (if-let [klass (get normalized-settings selector)] + (conj classes (->> klass rest (apply str))) ;; Strip the leading . + classes)) + #{} clojure-selectors)) + +(defn clojure-eval? + "Takes settings and html and returns whether there is any clojure eval." + [normalized-settings html] + (boolean (some (clojure-eval-classes normalized-settings) (code-block-classes html)))) (defn normalize-settings "Transform the keys to the correct snake-case or camelCase strings." @@ -61,25 +90,24 @@ (defn merge-configs "Merges the defaults, global config and post config, transforms lisp-case keywords into snake_case/camelCase strings - and infers whether to use minified or non-minified js - (this can be overridden by supplying a :js key). - If the post config is just true, uses only the global config. - Returns nil if either there's no post-config or if there's no settings after merging." + Returns nil if there's no post-config. + A post-config with the value true counts as an empty map." [global-config post-config] (when post-config - (let [post-config (if (true? post-config) {} post-config) - merged-config (deep-merge defaults - (update-existing global-config :settings normalize-settings) - (update-existing post-config :settings normalize-settings))] - ;; It would make more sense to return nil if there's no selector specified - ;; instead of no settings, but that would be too much of a - ;; maintenance burden, as there are new selectors added all the time. - (when (:settings merged-config) - (if (:js merged-config) - merged-config - (assoc merged-config :js (if (clojure-eval? (:settings merged-config)) - :non-min - :min))))))) + (let [post-config (if (true? post-config) {} post-config)] + (deep-merge defaults + (update-existing global-config :settings normalize-settings) + (update-existing post-config :settings normalize-settings))))) + +(defn infer-clojure-eval + "Infers whether there's clojure eval and returns the config with the + appropriate value assoc'd to :js. + Returns the config untouched if :js is already specified." + [config html] + (if (:js config) + config + (assoc config :js + (if (clojure-eval? (:settings config) html) :non-min :min)))) (defn include-css [href] (str "")) @@ -90,9 +118,9 @@ (defn emit "Takes the :klipse config from config.edn and the :klipse config from the current post, and returns the html to include on the bottom of the page." - [global-config post-config] + [config html] (when-let [{:keys [settings js-src js css-base css-theme]} - (merge-configs global-config post-config)] + (infer-clojure-eval config html)] (assert (#{:min :non-min} js) (str ":js needs to be one of :min or :non-min but was: " js)) diff --git a/test/cryogen_core/klipse_test.clj b/test/cryogen_core/klipse_test.clj index 5e92a19..33b15f6 100644 --- a/test/cryogen_core/klipse_test.clj +++ b/test/cryogen_core/klipse_test.clj @@ -14,6 +14,44 @@ (is (= {:a {:b 1}} (deep-merge {:a {:b 1}} {:a nil}))) (is (= {:a {:b 1 :c 3}} (deep-merge {:a {:b 1 :c 2}} {:a {:c 3}})))) +;; For testing convenience. +(defn elt + "Returns an enlive style html element." + ([tag] (elt tag nil)) + ([tag attrs & content] + {:tag tag, :attrs attrs, :content content})) + +(deftest filter-html-elems-test + (is (= [(elt :div {:class "x"} :content [(elt :div {:class "x"} "foo")]) + (elt :div {:class "x"} "foo")]) + (filter-html-elems (comp #{"x"} :class :attrs) + [(elt :h1 {:class "y"} "things!") + (elt :div {:class "x"} (elt :div {:class "x"} "foo"))]))) + +(deftest code-block-classes-test + (is (= ["clojure" "ruby"] + (code-block-classes + "

stuff

+
(def x 42)
+
123
"))))
+
+(deftest clojure-eval-classes-test
+  (is (= #{"eval-cljs" "eval-reagent"}
+         (clojure-eval-classes {"selector" ".eval-cljs"
+                                "selector_reagent" ".eval-reagent"
+                                "selector_eval_ruby" ".eval-ruby"}))))
+
+(deftest clojure-eval?-test
+  (is (clojure-eval? {"selector" ".eval-cljs"}
+                     "

stuff

+
(def x 42)
+
123
"))
+
+  (is (not (clojure-eval? {"selector" ".eval-cljs"
+                           "selector_eval_ruby" ".eval-ruby"}
+                          "

stuff

+
123
"))))
+
 (deftest normalize-settings-test
   (is (= {"selector_reagent" ".reagent"
           "codemirror_options_in" {"lineNumbers" true}}
@@ -22,22 +60,16 @@
            :codemirror-options-in {:line-numbers true}}))))
 
 (deftest merge-configs-test
-  (testing "Things are merged correctly, and :js :non-min is inferred from :selector."
+  (testing "Things are merged correctly"
     (is (= (merge defaults
-                  {:settings {"selector" ".clojure"
-                              "codemirror_options_in" {"lineNumbers" true}}
-                   :js :non-min})
+                  {:settings {"selector" ".clojure-eval"
+                              "codemirror_options_in" {"lineNumbers" true}}})
            (merge-configs {:settings {:codemirror-options-in {:line-numbers true}}}
-                          {:settings {:selector ".clojure"}}))))
+                          {:settings {:selector ".clojure-eval"}}))))
 
   (testing "If it's all set up in config.edn, in the post it can be just :klipse true"
-    (is (= (merge defaults
-                  {:settings {"selector_js" ".javascript"}
-                   :js :min})
+    (is (= (merge defaults {:settings {"selector_js" ".javascript"}})
            (merge-configs {:settings {:selector-js ".javascript"}} true))))
 
   (testing "Returns nil if there's nothing in the blog post"
-    (is (nil? (merge-configs {:settings {:selector ".clojure"}} nil))))
-
-  (testing "If there's no :settings, returns nil"
-    (is (nil? (merge-configs {:css-base "/css/base.css"} {:css-theme "/css/theme.css"})))))
+    (is (nil? (merge-configs {:settings {:selector ".clojure-eval"}} nil)))))

From 60c4ec0054730c72097ba50c8efac05e6e08bddd Mon Sep 17 00:00:00 2001
From: Aleksander Madland Stapnes 
Date: Thu, 2 Feb 2017 00:49:51 -0300
Subject: [PATCH 14/15] Add nohighlight to klipsified code blocks.

---
 src/cryogen_core/compiler.clj | 17 +++++++++++------
 src/cryogen_core/klipse.clj   | 16 ++++++++++++++++
 2 files changed, 27 insertions(+), 6 deletions(-)

diff --git a/src/cryogen_core/compiler.clj b/src/cryogen_core/compiler.clj
index 6403cca..b10f236 100644
--- a/src/cryogen_core/compiler.clj
+++ b/src/cryogen_core/compiler.clj
@@ -471,21 +471,26 @@
     (catch Exception _
       (throw (IllegalArgumentException. "Failed to parse config.edn")))))
 
+(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))))
+
 (defn compile-assets
   "Generates all the html and copies over resources specified in the config"
   []
   (println (green "compiling assets..."))
   (let [{:keys [^String site-url blog-prefix rss-name recent-posts sass-dest keep-files ignored-files previews? author-root-uri theme]
          :as   config} (read-config)
-        posts        (map (fn [{:keys [klipse content] :as post}]
-                            (assoc post :klipse (klipse/emit klipse content)))
-                          (add-prev-next (read-posts config)))
+        posts        (map klipsify (add-prev-next (read-posts config)))
         posts-by-tag (group-by-tags posts)
         posts        (tag-posts posts config)
         latest-posts (->> posts (take recent-posts) vec)
-        pages        (map (fn [{:keys [klipse content] :as page}]
-                            (assoc page :klipse (klipse/emit klipse content)))
-                          (read-pages config))
+        pages        (map klipsify (read-pages config))
         home-page    (->> pages
                           (filter #(boolean (:home? %)))
                           (first))
diff --git a/src/cryogen_core/klipse.clj b/src/cryogen_core/klipse.clj
index 3735c10..e3be3ee 100644
--- a/src/cryogen_core/klipse.clj
+++ b/src/cryogen_core/klipse.clj
@@ -51,6 +51,22 @@
 ;;;;;;;;;;;;
 ;; klipse
 
+(defn eval-classes
+  "Takes the :settings map and returns all values that are css class selectors."
+  [settings]
+  (filter #(str/starts-with? % ".") (vals settings)))
+
+(defn tag-nohighlight
+  "Takes html as a string and a coll of class-selectors and adds
+   nohighlight to all code blocks that includes one of them."
+  [html settings]
+  (letfn [(tag [h clas]
+            (enlive/sniptest h
+              [(keyword (str "code" clas))]
+              (fn [x]
+                (update-in x [:attrs :class] #(str % " nohighlight")))))]
+    (reduce tag html (eval-classes settings))))
+
 (def defaults
   {:js-src
    {:min "https://storage.googleapis.com/app.klipse.tech/plugin_prod/js/klipse_plugin.min.js"

From d502799a9354f70d782bd35d4ff979f08773bfa4 Mon Sep 17 00:00:00 2001
From: Carmen La 
Date: Wed, 1 Feb 2017 23:17:27 -0500
Subject: [PATCH 15/15] Update deps

---
 project.clj | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/project.clj b/project.clj
index 57d65b7..a001dfa 100644
--- a/project.clj
+++ b/project.clj
@@ -1,4 +1,4 @@
-(defproject cryogen-core "0.1.51"
+(defproject cryogen-core "0.1.52"
             :description "Cryogen's compiler"
             :url "https://github.com/cryogen-project/cryogen-core"
             :license {:name "Eclipse Public License"
@@ -14,6 +14,6 @@
                            [io.aviso/pretty "0.1.33"]
                            [me.raynes/fs "1.4.6"]
                            [pandect "0.6.1"]
-                           [selmer "1.10.5"]]
+                           [selmer "1.10.6"]]
             :deploy-repositories [["snapshots" :clojars]
                                   ["releases" :clojars]])