Implement clean URLs feature (Issue #89)
When `clean-urls?` is set in config, emit pages as subdirectories `prefix/root/page-name/index.html` instead of `prefix/root/page-name.html`. Links in emitted HTML then point to `prefix/root/page-name/`. When `clean-urls?` not set, behaves as before. Refactor most URI generation into a new `page-uri` function. `page-uri` replaces most calls* to `path`, all calls to `post-uri` and all calls to the old `page-uri`. Introduce function `create-file-recursive`. Function creates file parent if not exists. Introduce function `write-html`. When `clean-urls?` is set, spits emitted HTML into subdirectories as described above; otherwise behaves like `create-file`. Replaces most* calls to `create-file` Calls `create-file` or `create-file-recursive`. * Exceptions made for sitemap XML and RSS feed XML pages
This commit is contained in:
parent
b3bdba2804
commit
c18c3d60f2
2 changed files with 104 additions and 83 deletions
|
@ -11,7 +11,7 @@
|
||||||
[cryogen-core.sass :as sass]
|
[cryogen-core.sass :as sass]
|
||||||
[cryogen-core.markup :as m]
|
[cryogen-core.markup :as m]
|
||||||
[cryogen-core.io :refer
|
[cryogen-core.io :refer
|
||||||
[get-resource find-assets create-folder create-file wipe-public-folder
|
[get-resource find-assets create-folder create-file-recursive create-file wipe-public-folder
|
||||||
copy-resources copy-resources-from-theme path]]
|
copy-resources copy-resources-from-theme path]]
|
||||||
[cryogen-core.sitemap :as sitemap]
|
[cryogen-core.sitemap :as sitemap]
|
||||||
[cryogen-core.rss :as rss])
|
[cryogen-core.rss :as rss])
|
||||||
|
@ -47,15 +47,14 @@
|
||||||
(let [fmt (java.text.SimpleDateFormat. date-fmt)]
|
(let [fmt (java.text.SimpleDateFormat. date-fmt)]
|
||||||
(.parse fmt (.substring file-name 0 10))))
|
(.parse fmt (.substring file-name 0 10))))
|
||||||
|
|
||||||
(defn post-uri
|
|
||||||
"Creates a post uri from the post file name"
|
|
||||||
[file-name {:keys [blog-prefix post-root-uri]} mu]
|
|
||||||
(path "/" blog-prefix post-root-uri (s/replace file-name (re-pattern-from-ext (m/ext mu)) ".html")))
|
|
||||||
|
|
||||||
(defn page-uri
|
(defn page-uri
|
||||||
"Creates a page uri from the page file name"
|
"Creates a URI from file name. `uri-type` is any of the uri types specified in config, e.g., `:post-root-uri`."
|
||||||
[page-name {:keys [blog-prefix page-root-uri]} mu]
|
([file-name params]
|
||||||
(path "/" blog-prefix page-root-uri (s/replace page-name (re-pattern-from-ext (m/ext mu)) ".html")))
|
(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))))
|
||||||
|
|
||||||
(defn read-page-meta
|
(defn read-page-meta
|
||||||
"Returns the clojure map from the top of a markdown page/post"
|
"Returns the clojure map from the top of a markdown page/post"
|
||||||
|
@ -94,7 +93,7 @@
|
||||||
(let [{:keys [file-name page-meta content]} (page-content page config markup)]
|
(let [{:keys [file-name page-meta content]} (page-content page config markup)]
|
||||||
(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 config markup)
|
{:uri (page-uri file-name :page-root-uri config)
|
||||||
:page-index (:page-index page-meta)})))
|
:page-index (:page-index page-meta)})))
|
||||||
|
|
||||||
(defn parse-post
|
(defn parse-post
|
||||||
|
@ -111,7 +110,7 @@
|
||||||
{:date date
|
{:date date
|
||||||
: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 (post-uri file-name config markup)
|
:uri (page-uri file-name :post-root-uri config)
|
||||||
:tags (set (:tags page-meta))}))))
|
:tags (set (:tags page-meta))}))))
|
||||||
|
|
||||||
(defn read-posts
|
(defn read-posts
|
||||||
|
@ -178,9 +177,9 @@
|
||||||
|
|
||||||
(defn tag-info
|
(defn tag-info
|
||||||
"Returns a map containing the name and uri of the specified tag"
|
"Returns a map containing the name and uri of the specified tag"
|
||||||
[{:keys [blog-prefix tag-root-uri]} tag]
|
[config tag]
|
||||||
{:name (name tag)
|
{:name (name tag)
|
||||||
:uri (path "/" blog-prefix tag-root-uri (str (name tag) ".html"))})
|
:uri (page-uri (str (name tag) ".html") :tag-root-uri config)})
|
||||||
|
|
||||||
(defn add-prev-next
|
(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 title and uri of the prev/next
|
||||||
|
@ -199,6 +198,13 @@
|
||||||
sidebar-pages false} (group-by #(boolean (:navbar? %)) pages)]
|
sidebar-pages false} (group-by #(boolean (:navbar? %)) pages)]
|
||||||
(map (partial sort-by :page-index) [navbar-pages sidebar-pages])))
|
(map (partial sort-by :page-index) [navbar-pages sidebar-pages])))
|
||||||
|
|
||||||
|
(defn write-html
|
||||||
|
"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)))
|
||||||
|
|
||||||
(defn compile-pages
|
(defn compile-pages
|
||||||
"Compiles all the pages into html and spits them out into the public folder"
|
"Compiles all the pages into html and spits them out into the public folder"
|
||||||
[{:keys [blog-prefix page-root-uri] :as params} pages]
|
[{:keys [blog-prefix page-root-uri] :as params} pages]
|
||||||
|
@ -207,7 +213,8 @@
|
||||||
(create-folder (path "/" blog-prefix page-root-uri))
|
(create-folder (path "/" blog-prefix page-root-uri))
|
||||||
(doseq [{:keys [uri] :as page} pages]
|
(doseq [{:keys [uri] :as page} pages]
|
||||||
(println "\t-->" (cyan uri))
|
(println "\t-->" (cyan uri))
|
||||||
(create-file uri
|
(write-html uri
|
||||||
|
params
|
||||||
(render-file (str "/html/" (:layout page))
|
(render-file (str "/html/" (:layout page))
|
||||||
(merge params
|
(merge params
|
||||||
{:active-page "pages"
|
{:active-page "pages"
|
||||||
|
@ -223,7 +230,8 @@
|
||||||
(create-folder (path "/" blog-prefix post-root-uri))
|
(create-folder (path "/" blog-prefix post-root-uri))
|
||||||
(doseq [post posts]
|
(doseq [post posts]
|
||||||
(println "\t-->" (cyan (:uri post)))
|
(println "\t-->" (cyan (:uri post)))
|
||||||
(create-file (:uri post)
|
(write-html (:uri post)
|
||||||
|
params
|
||||||
(render-file (str "/html/" (:layout post))
|
(render-file (str "/html/" (:layout post))
|
||||||
(merge params
|
(merge params
|
||||||
{:active-page "posts"
|
{:active-page "posts"
|
||||||
|
@ -241,7 +249,8 @@
|
||||||
(doseq [[tag posts] posts-by-tag]
|
(doseq [[tag posts] posts-by-tag]
|
||||||
(let [{:keys [name uri]} (tag-info params tag)]
|
(let [{:keys [name uri]} (tag-info params tag)]
|
||||||
(println "\t-->" (cyan uri))
|
(println "\t-->" (cyan uri))
|
||||||
(create-file uri
|
(write-html uri
|
||||||
|
params
|
||||||
(render-file "/html/tag.html"
|
(render-file "/html/tag.html"
|
||||||
(merge params
|
(merge params
|
||||||
{:active-page "tags"
|
{:active-page "tags"
|
||||||
|
@ -252,11 +261,13 @@
|
||||||
|
|
||||||
(defn compile-tags-page [{:keys [blog-prefix] :as params}]
|
(defn compile-tags-page [{:keys [blog-prefix] :as params}]
|
||||||
(println (blue "compiling tags page"))
|
(println (blue "compiling tags page"))
|
||||||
(create-file (path "/" blog-prefix "tags.html")
|
(let [uri (page-uri "tags.html" params)]
|
||||||
|
(write-html uri
|
||||||
|
params
|
||||||
(render-file "/html/tags.html"
|
(render-file "/html/tags.html"
|
||||||
(merge params
|
(merge params
|
||||||
{:active-page "tags"
|
{:active-page "tags"
|
||||||
:uri (path "/" blog-prefix "tags.html")}))))
|
:uri uri})))))
|
||||||
|
|
||||||
(defn content-until-more-marker
|
(defn content-until-more-marker
|
||||||
[^String content]
|
[^String content]
|
||||||
|
@ -288,11 +299,11 @@
|
||||||
(defn create-preview-links
|
(defn create-preview-links
|
||||||
"Turn each vector of previews into a map with :prev and :next keys that contain the uri of the
|
"Turn each vector of previews into a map with :prev and :next keys that contain the uri of the
|
||||||
prev/next preview page"
|
prev/next preview page"
|
||||||
[previews blog-prefix]
|
[previews params]
|
||||||
(mapv (fn [[prev target next]]
|
(mapv (fn [[prev target next]]
|
||||||
(merge target
|
(merge target
|
||||||
{:prev (if prev (path "/" blog-prefix "p" (str (:index prev) ".html")) nil)
|
{:prev (if prev (page-uri (path "p" (str (:index prev) ".html")) params) nil)
|
||||||
:next (if next (path "/" blog-prefix "p" (str (:index next) ".html")) nil)}))
|
:next (if next (page-uri (path "p" (str (:index next) ".html")) params) nil)}))
|
||||||
(partition 3 1 (flatten [nil previews nil]))))
|
(partition 3 1 (flatten [nil previews nil]))))
|
||||||
|
|
||||||
(defn compile-preview-pages
|
(defn compile-preview-pages
|
||||||
|
@ -300,12 +311,13 @@
|
||||||
[{:keys [blog-prefix posts-per-page blocks-per-preview] :as params} posts]
|
[{:keys [blog-prefix posts-per-page blocks-per-preview] :as params} posts]
|
||||||
(when-not (empty? posts)
|
(when-not (empty? posts)
|
||||||
(let [previews (-> (create-previews posts-per-page blocks-per-preview posts)
|
(let [previews (-> (create-previews posts-per-page blocks-per-preview posts)
|
||||||
(create-preview-links blog-prefix))
|
(create-preview-links params))
|
||||||
previews (if (> (count previews) 1) (assoc-in previews [1 :prev] (path "/" blog-prefix "index.html")) previews)]
|
previews (if (> (count previews) 1) (assoc-in previews [1 :prev] (page-uri "index.html" params)) previews)]
|
||||||
(create-folder (path "/" blog-prefix "p"))
|
(create-folder (path "/" blog-prefix "p"))
|
||||||
(doseq [{:keys [index posts prev next]} previews
|
(doseq [{:keys [index posts prev next]} previews
|
||||||
:let [index-page? (= 1 index)]]
|
:let [index-page? (= 1 index)]]
|
||||||
(create-file (if index-page? (path "/" blog-prefix "index.html") (path "/" blog-prefix "p" (str index ".html")))
|
(write-html (if index-page? (page-uri "index.html" params) (page-uri (path "p" (str index ".html")) params))
|
||||||
|
params
|
||||||
(render-file "/html/previews.html"
|
(render-file "/html/previews.html"
|
||||||
(merge params
|
(merge params
|
||||||
{:active-page "preview"
|
{:active-page "preview"
|
||||||
|
@ -319,26 +331,30 @@
|
||||||
"Compiles the index page into html and spits it out into the public folder"
|
"Compiles the index page into html and spits it out into the public folder"
|
||||||
[{:keys [blog-prefix disqus?] :as params}]
|
[{:keys [blog-prefix disqus?] :as params}]
|
||||||
(println (blue "compiling index"))
|
(println (blue "compiling index"))
|
||||||
(create-file (path "/" blog-prefix "index.html")
|
(let [uri (page-uri "index.html" params)]
|
||||||
|
(write-html uri
|
||||||
|
params
|
||||||
(render-file "/html/home.html"
|
(render-file "/html/home.html"
|
||||||
(merge params
|
(merge params
|
||||||
{:active-page "home"
|
{:active-page "home"
|
||||||
:home true
|
:home true
|
||||||
:disqus? disqus?
|
:disqus? disqus?
|
||||||
:post (get-in params [:latest-posts 0])
|
:post (get-in params [:latest-posts 0])
|
||||||
:uri (path "/" blog-prefix "index.html")}))))
|
:uri uri})))))
|
||||||
|
|
||||||
(defn compile-archives
|
(defn compile-archives
|
||||||
"Compiles the archives page into html and spits it out into the public folder"
|
"Compiles the archives page into html and spits it out into the public folder"
|
||||||
[{:keys [blog-prefix] :as params} posts]
|
[{:keys [blog-prefix] :as params} posts]
|
||||||
(println (blue "compiling archives"))
|
(println (blue "compiling archives"))
|
||||||
(create-file (path "/" blog-prefix "archives.html")
|
(let [uri (page-uri "archives.html" params)]
|
||||||
|
(write-html uri
|
||||||
|
params
|
||||||
(render-file "/html/archives.html"
|
(render-file "/html/archives.html"
|
||||||
(merge params
|
(merge params
|
||||||
{:active-page "archives"
|
{:active-page "archives"
|
||||||
:archives true
|
:archives true
|
||||||
:groups (group-for-archive posts)
|
:groups (group-for-archive posts)
|
||||||
:uri (path "/" blog-prefix "/archives.html")}))))
|
:uri uri})))))
|
||||||
|
|
||||||
(defn compile-authors
|
(defn compile-authors
|
||||||
"For each author, creates a page with filtered posts."
|
"For each author, creates a page with filtered posts."
|
||||||
|
@ -347,9 +363,10 @@
|
||||||
(create-folder (path "/" blog-prefix author-root-uri))
|
(create-folder (path "/" blog-prefix author-root-uri))
|
||||||
;; if the post author is empty defaults to config's :author
|
;; if the post author is empty defaults to config's :author
|
||||||
(doseq [{:keys [author posts]} (group-for-author posts author)]
|
(doseq [{:keys [author posts]} (group-for-author posts author)]
|
||||||
(let [uri (path "/" blog-prefix author-root-uri (str author ".html"))]
|
(let [uri (page-uri (str author ".html") :author-root-uri params)]
|
||||||
(println "\t-->" (cyan uri))
|
(println "\t-->" (cyan uri))
|
||||||
(create-file uri
|
(write-html uri
|
||||||
|
params
|
||||||
(render-file "/html/author.html"
|
(render-file "/html/author.html"
|
||||||
(merge params
|
(merge params
|
||||||
{:author author
|
{:author author
|
||||||
|
@ -414,9 +431,9 @@
|
||||||
:latest-posts (->> posts (take recent-posts) vec)
|
:latest-posts (->> posts (take recent-posts) vec)
|
||||||
:navbar-pages navbar-pages
|
:navbar-pages navbar-pages
|
||||||
:sidebar-pages sidebar-pages
|
:sidebar-pages sidebar-pages
|
||||||
:archives-uri (path "/" blog-prefix "archives.html")
|
:archives-uri (page-uri "archives.html" config)
|
||||||
:index-uri (path "/" blog-prefix "index.html")
|
:index-uri (page-uri "index.html" config)
|
||||||
:tags-uri (path "/" blog-prefix "tags.html")
|
:tags-uri (page-uri "tags.html" config)
|
||||||
:rss-uri (path "/" blog-prefix rss-name)
|
:rss-uri (path "/" blog-prefix rss-name)
|
||||||
:site-url (if (.endsWith site-url "/") (.substring site-url 0 (dec (count site-url))) site-url)
|
: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))})]
|
:theme-path (str "file:resources/templates/themes/" (:theme config))})]
|
||||||
|
|
|
@ -45,12 +45,16 @@
|
||||||
[]))
|
[]))
|
||||||
|
|
||||||
(defn create-folder [folder]
|
(defn create-folder [folder]
|
||||||
(let [loc (io/file (str public folder))]
|
(let [loc (io/file (path public folder))]
|
||||||
(when-not (.exists loc)
|
(when-not (.exists loc)
|
||||||
(.mkdirs loc))))
|
(.mkdirs loc))))
|
||||||
|
|
||||||
(defn create-file [file data]
|
(defn create-file [file data]
|
||||||
(spit (str public file) data))
|
(spit (path public file) data))
|
||||||
|
|
||||||
|
(defn create-file-recursive [file data]
|
||||||
|
(create-folder (.getParent (io/file file)))
|
||||||
|
(create-file file data))
|
||||||
|
|
||||||
(defn wipe-public-folder [keep-files]
|
(defn wipe-public-folder [keep-files]
|
||||||
(let [filenamefilter (reify java.io.FilenameFilter (accept [this _ filename] (not (some #{filename} keep-files))))]
|
(let [filenamefilter (reify java.io.FilenameFilter (accept [this _ filename] (not (some #{filename} keep-files))))]
|
||||||
|
|
Loading…
Reference in a new issue