diff --git a/src/cryogen_core/compiler.clj b/src/cryogen_core/compiler.clj
index b089e29..e2a00dc 100644
--- a/src/cryogen_core/compiler.clj
+++ b/src/cryogen_core/compiler.clj
@@ -9,10 +9,9 @@
[clojure.java.io :refer [copy file reader writer]]
[clojure.string :as s]
[text-decoration.core :refer :all]
- [markdown.core :refer [md-to-html-string]]
- [markdown.transformers :refer [transformer-vector]]
[cryogen-core.toc :refer [generate-toc]]
- [cryogen-core.sass :as sass]))
+ [cryogen-core.sass :as sass]
+ [cryogen-core.markup :as m]))
(cache-off!)
@@ -31,13 +30,13 @@
(defn find-posts
"Returns a list of markdown files representing posts under the post root in templates/md"
- [{:keys [post-root ignored-files]}]
- (find-assets (str "templates/md" post-root) ".md" ignored-files))
+ [{:keys [post-root ignored-files]} mu]
+ (find-assets (str "templates/" (m/dir mu) post-root) (m/ext mu) ignored-files))
(defn find-pages
"Returns a list of markdown files representing pages under the page root in templates/md"
- [{:keys [page-root ignored-files]}]
- (find-assets (str "templates/md" page-root) ".md" ignored-files))
+ [{:keys [page-root ignored-files]} mu]
+ (find-assets (str "templates/" (m/dir mu) page-root) (m/ext mu) ignored-files))
(defn parse-post-date
"Parses the post date from the post's file name and returns the corresponding java date object"
@@ -47,13 +46,13 @@
(defn post-uri
"Creates a post uri from the post file name"
- [file-name {:keys [blog-prefix post-root]}]
- (str blog-prefix post-root (s/replace file-name #".md" ".html")))
+ [file-name {:keys [blog-prefix post-root]} mu]
+ (str blog-prefix post-root (s/replace file-name (re-pattern (m/ext mu)) ".html")))
(defn page-uri
"Creates a page uri from the page file name"
- [page-name {:keys [blog-prefix page-root]}]
- (str blog-prefix page-root (s/replace page-name #".md" ".html")))
+ [page-name {:keys [blog-prefix page-root]} mu]
+ (str blog-prefix page-root (s/replace page-name (re-pattern (m/ext mu)) ".html")))
(defn read-page-meta
"Returns the clojure map from the top of a markdown page/post"
@@ -63,65 +62,76 @@
(catch Exception _
(throw (IllegalArgumentException. (str "Malformed metadata on page: " page))))))
-(defn rewrite-hrefs
- "Injects the blog prefix in front of any local links
+(defn page-content
+ "Returns a map with the given page's file-name, metadata and content parsed from
+ the file with the given markup."
+ [page config markup]
+ (with-open [rdr (java.io.PushbackReader. (reader page))]
+ (let [page-name (.getName page)
+ file-name (s/replace page-name (re-pattern (m/ext markup)) ".html")
+ page-meta (read-page-meta page-name rdr)
+ content ((m/render-fn markup) rdr config)]
+ {:file-name file-name
+ :page-meta page-meta
+ :content content})))
- ex. becomes "
- [{:keys [blog-prefix]} text state]
- [(clojure.string/replace text #"href=.?/|src=.?/" #(str (subs % 0 (dec (count %))) blog-prefix "/"))
- state])
-
-(defn parse-content
- "Parses the markdown content in a post/page into html"
- [rdr config]
- (md-to-html-string
- (->> (java.io.BufferedReader. rdr)
- (line-seq)
- (s/join "\n"))
- :reference-links? true
- :heading-anchors true
- :replacement-transformers (conj transformer-vector (partial rewrite-hrefs config))))
+(defn merge-meta-and-content
+ "Merges the page metadata and content maps, adding :toc if necessary."
+ [file-name page-meta content]
+ (merge
+ (update-in page-meta [:layout] #(str (name %) ".html"))
+ {:file-name file-name
+ :content content
+ :toc (if (:toc page-meta) (generate-toc content))}))
(defn parse-page
"Parses a page/post and returns a map of the content, uri, date etc."
- [is-post? page config]
- (with-open [rdr (java.io.PushbackReader. (reader page))]
- (let [page-name (.getName page)
- file-name (s/replace page-name #".md" ".html")
- page-meta (read-page-meta page-name rdr)
- content (parse-content rdr config)]
- (merge
- (update-in page-meta [:layout] #(str (name %) ".html"))
- {:file-name file-name
- :content content
- :toc (if (:toc page-meta) (generate-toc content))}
- (if is-post?
- (let [date (parse-post-date file-name (:post-date-format config))
- archive-fmt (java.text.SimpleDateFormat. "yyyy MMMM" (java.util.Locale. "en"))
- formatted-group (.format archive-fmt date)]
- {:date date
- :formatted-archive-group formatted-group
- :parsed-archive-group (.parse archive-fmt formatted-group)
- :uri (post-uri file-name config)
- :tags (set (:tags page-meta))})
- {:uri (page-uri file-name config)
- :page-index (:page-index page-meta)})))))
+ [page config markup]
+ (let [{:keys [file-name page-meta content]} (page-content page config markup)]
+ (merge
+ (merge-meta-and-content file-name page-meta content)
+ {:uri (page-uri file-name config markup)
+ :page-index (:page-index page-meta)})))
+
+(defn parse-post
+ "Return a map with the given post's information."
+ [page config markup]
+ (let [{:keys [file-name page-meta content]} (page-content page config markup)]
+ (merge
+ (merge-meta-and-content file-name page-meta content)
+ (let [date (parse-post-date file-name (:post-date-format config))
+ archive-fmt (java.text.SimpleDateFormat. "yyyy MMMM" (java.util.Locale. "en"))
+ formatted-group (.format archive-fmt date)]
+ {:date date
+ :formatted-archive-group formatted-group
+ :parsed-archive-group (.parse archive-fmt formatted-group)
+ :uri (post-uri file-name config markup)
+ :tags (set (:tags page-meta))})
+ )))
(defn read-posts
"Returns a sequence of maps representing the data from markdown files of posts.
Sorts the sequence by post date."
[config]
- (->> (find-posts config)
- (map #(parse-page true % config))
+ (->> (mapcat
+ (fn [mu]
+ (->>
+ (find-posts config mu)
+ (map #(parse-post % config mu))))
+ (m/markups))
(sort-by :date)
reverse))
(defn read-pages
"Returns a sequence of maps representing the data from markdown files of pages.
- Sorts the sequence by post date."
+ Sorts the sequence by post date."
[config]
- (->> (find-pages config)
- (map #(parse-page false % config))
+ (->> (mapcat
+ (fn [mu]
+ (->>
+ (find-pages config mu)
+ (map #(parse-page % config mu))))
+ (m/markups))
(sort-by :page-index)))
(defn tag-post
diff --git a/src/cryogen_core/markup.clj b/src/cryogen_core/markup.clj
index f769ce8..d9f60b6 100644
--- a/src/cryogen_core/markup.clj
+++ b/src/cryogen_core/markup.clj
@@ -1,37 +1,63 @@
(ns cryogen-core.markup
(:require [markdown.core :refer [md-to-html-string]]
+ [markdown.transformers :refer [transformer-vector]]
[clojure.string :as s])
(:import org.asciidoctor.Asciidoctor$Factory
java.util.Collections))
(defprotocol Markup
+ "A markup engine comprising a dir(ectory) containing markup files,
+ an ext(ension) for finding markup file names, and a render-fn that returns
+ a fn with the signature [java.io.Reader config] -> String (HTML)."
(dir [this])
(ext [this])
(render-fn [this]))
-(defn- markdown []
+(defn- rewrite-hrefs
+ "Injects the blog prefix in front of any local links
+
+ ex. becomes "
+ [{:keys [blog-prefix]} text state]
+ [(clojure.string/replace text #"href=.?/|src=.?/" #(str (subs % 0 (dec (count %))) blog-prefix "/"))
+ state])
+
+(defn- markdown
+ "Returns a Markdown (https://daringfireball.net/projects/markdown/)
+ implementation of the Markup protocol."
+ []
(reify Markup
(dir [this] "md")
(ext [this] ".md")
(render-fn [this]
- (fn [rdr]
+ (fn [rdr config]
(md-to-html-string
- (->> (java.io.BufferedReader. rdr)
- (line-seq)
- (s/join "\n"))
- :heading-anchors true)))))
+ (->> (java.io.BufferedReader. rdr)
+ (line-seq)
+ (s/join "\n"))
+ :reference-links? true
+ :heading-anchors true
+ :replacement-transformers (conj transformer-vector (partial rewrite-hrefs config)))))))
-(defn- asciidoc []
+(defn- asciidoc
+ "Returns an Asciidoc (http://asciidoc.org/) implementation of the
+ Markup protocol."
+ []
(reify Markup
(dir [this] "asc")
(ext [this] ".asc")
(render-fn [this]
- (fn [rdr]
- (.convert (Asciidoctor$Factory/create)
- (->> (java.io.BufferedReader. rdr)
- (line-seq)
- (s/join "\n"))
- (Collections/emptyMap))))))
+ (let [attributes (java.util.HashMap. {"toc" "macro"})
+ options (java.util.HashMap. {"attributes" attributes})]
+ (fn [rdr _]
+ (.convert (Asciidoctor$Factory/create)
+ (->> (java.io.BufferedReader. rdr)
+ (line-seq)
+ (s/join "\n"))
+ options))))))
-(defn markups []
+(defn markups
+ "Return a vector of Markup implementations. This is the primary entry point
+ for a client of this ns. This vector should be used to iterate over supported
+ Markups."
+ []
[(markdown) (asciidoc)])