Automatic klipse integration

This commit is contained in:
Aleksander Madland Stapnes 2017-01-19 14:33:38 -03:00
parent 84a933bdcf
commit ac52785b19
4 changed files with 141 additions and 2 deletions

View file

@ -4,6 +4,7 @@
:license {:name "Eclipse Public License" :license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"} :url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.8.0"] :dependencies [[org.clojure/clojure "1.8.0"]
[camel-snake-kebab "0.4.0"]
[cheshire "5.7.0"] [cheshire "5.7.0"]
[clj-rss "0.2.3"] [clj-rss "0.2.3"]
[clj-text-decoration "0.0.3"] [clj-text-decoration "0.0.3"]

View file

@ -8,6 +8,7 @@
[selmer.util :refer [set-custom-resource-path!]] [selmer.util :refer [set-custom-resource-path!]]
[text-decoration.core :refer :all] [text-decoration.core :refer :all]
[cryogen-core.io :as cryogen-io] [cryogen-core.io :as cryogen-io]
[cryogen-core.klipse :as klipse]
[cryogen-core.markup :as m] [cryogen-core.markup :as m]
[cryogen-core.rss :as rss] [cryogen-core.rss :as rss]
[cryogen-core.sass :as sass] [cryogen-core.sass :as sass]
@ -111,7 +112,8 @@
(merge (merge
(merge-meta-and-content file-name page-meta content) (merge-meta-and-content file-name page-meta content)
{:uri (page-uri file-name :page-root-uri config) {: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 (defn parse-post
"Return a map with the given post's information." "Return a map with the given post's information."
@ -128,7 +130,8 @@
:formatted-archive-group formatted-group :formatted-archive-group formatted-group
:parsed-archive-group (.parse archive-fmt formatted-group) :parsed-archive-group (.parse archive-fmt formatted-group)
:uri (page-uri file-name :post-root-uri config) :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 (defn read-posts
"Returns a sequence of maps representing the data from markdown files of posts. "Returns a sequence of maps representing the data from markdown files of posts.

View file

@ -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 "<link rel=\"stylesheet\" type=\"text/css\" href=" (pr-str href) ">"))
(defn include-js [src]
(str "<script src=" (pr-str src) "></script>"))
(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"))
"<script>\n"
"window.klipse_settings = " (json/generate-string settings {:pretty true}) ";\n"
"</script>\n"
(include-js (js js-src)))))

View file

@ -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"})))))