Created
April 10, 2016 06:35
-
-
Save shaunlebron/2165eff75ed6bab4f402b2f5d66f0b6b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns sitegen.markdown | |
(:require | |
[clojure.string :as string] | |
[planck.core :refer [file-seq slurp]] | |
[clojure.walk :refer [keywordize-keys]])) | |
(def ^:dynamic *filename*) | |
(defn error [msg] | |
(throw (str "markdown metadata error: " msg " - " *filename*))) | |
(defn meta-boundary? [line] | |
(= "---" line)) | |
(defn find-content-start [lines] | |
(if (meta-boundary? (first lines)) | |
(let [i (->> (map-indexed vector lines) | |
(rest) | |
(filter (comp meta-boundary? second)) | |
(first) | |
(first))] | |
(when i ;; if closing boundary found, content starts on next line | |
(inc i))) | |
0)) | |
(defn clean-value | |
[value] | |
(let [value (string/trim value) | |
dequoted (or (second (re-find #"^\"(.*)\"$" value)) | |
(second (re-find #"^'(.*)'$" value)))] | |
(if dequoted | |
(string/trim dequoted) | |
value))) | |
(defn parse-meta-line [line] | |
(let [pattern #"^([a-zA-Z-_]+):(.*)" | |
[match key value] (re-find pattern line)] | |
(when-not match | |
(error (str "key/value line must follow pattern: " pattern))) | |
[key (clean-value value)])) | |
(defn parse-meta-lines [lines] | |
(reduce | |
(fn [result line] | |
(let [[key value] (parse-meta-line line)] | |
(when (contains? result key) | |
(error (str "duplicate key '" key))) | |
(assoc result key value))) | |
{} lines)) | |
(defn get-meta [text] | |
(let [lines (string/split-lines text) | |
start-i (find-content-start lines)] | |
(when-not start-i | |
(error "metadata never closed")) | |
(if (zero? start-i) | |
{:text text} | |
{:meta (parse-meta-lines (subvec lines 1 (dec start-i))) | |
:text (string/join "\n" (subvec lines start-i))}))) | |
(defn -main [] | |
(doseq [f (file-seq "news")] | |
(when (string/ends-with? (:path f) ".md") | |
(let [filename (subs (:path f) (count "news/")) | |
{:keys [meta text]} (binding [*filename* filename] | |
(get-meta (slurp f)))] | |
(-> meta | |
keywordize-keys | |
(assoc :filename filename) | |
prn))))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment