Permalink
Browse files

Major documentation update.

Started documenting the way templates work, how they're assembled, and
what parts they need, how the whole thing plays together.

So far, the majority of this task is done, archives, feeds and the
index page are left, and perhaps some spicing up in the end.

Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
  • Loading branch information...
1 parent 6617266 commit f519422a578b65d20eba957330985f062326241f @algernon committed Aug 5, 2012
View
@@ -1,5 +1,10 @@
(ns madness.blog
- "Post & page loading functions."
+ "## Load blog posts & pages
+
+ To build a whole site, madness will first load all the posts and
+ pages, and turn them into data structures that are easy to work
+ with. This is far from efficient, but even for a moderately sized
+ site, neither speed nor memory requirements are particularly bad."
^{:author "Gergely Nagy <algernon@madhouse-project.org>"
:copyright "Copyright (C) 2012 Gergely Nagy <algernon@madhouse-project.org>"
@@ -23,16 +28,22 @@
(FileUtils/listFiles d (into-array ["html"]) true)) [] )))
(defn load-posts
- "Load all posts for the blog. Returns a sequence of processed
- blog posts."
+ "Load all posts for the blog. Returns a sequence of processed blog
+ posts. See the [blog.post][1] namespace for more information about
+ how a processed post looks like.
+
+ [1]: #madness.blog.post"
[]
(map blog-post/read-post (list-files (cfg/dirs :posts))))
(defn load-pages
"Load all pages for the blog. Returns a sequence of processed blog
- pages."
+ pages. See the [blog.page][1] namespace for more information about
+ how a processed page looks like.
+
+ [1]: #madness.blog.page"
[]
View
@@ -1,4 +1,12 @@
(ns madness.blog.nav
+ "## Building blocks for navigation
+
+ All HTML pages of the generated site will contain some common
+ navigation items: a sidebar with recent items, and the list of all
+ available tags.
+
+ The functions herein implement the recent item & tag lists on the
+ sidebar."
^{:author "Gergely Nagy <algernon@madhouse-project.org>"
:copyright "Copyright (C) 2012 Gergely Nagy <algernon@madhouse-project.org>"
@@ -9,24 +17,52 @@
[madness.config :as cfg]
[madness.utils :as utils]))
+;; The sidebar must have a part with the id of `#nav-recent-posts`,
+;; under which must be an unordered list (with only one item in the
+;; template). The single item of that list will be used as the
+;; template snippet for displaying recent items on the sidebar.
+;;
+;; The list item itself, must contain an anchor, whose `href` and
+;; content this snippet will change to the URL and title of the post,
+;; respectively.
(h/defsnippet recent-item (cfg/template) [:#nav-recent-posts :ul :li]
[title url]
[:a] (utils/rewrite-link url title))
+;; Similarly to recent items, the sidebar must also contain a
+;; `#nav-tags` item, also with an unordered list beneath it, where the
+;; single element of the template must also have an anchor.
+;;
+;; The anchor's `href` and textual content will be rewritten by this
+;; snippet to the URL for the tag archive, and the name of the tag
+;; itself.
(h/defsnippet tag-item (cfg/template) [:#nav-tags :ul :li]
[tag]
[:a] (utils/rewrite-link (utils/tag-to-url tag) tag))
+;; To render all recent posts, we simply clone the snippet above for
+;; every recent post we should display. How many are displayed, is
+;; controlled by the configuration.
(defn recent-posts
[all-posts]
(h/clone-for [post (take (cfg/recent-posts :total) all-posts)]
(h/substitute (recent-item (:title post) (:url post)))))
+;; And to display all tags, we also clone the `tag-item` snippet above
+;; for each and every unique tag.
(defn all-tags
[all-posts]
(h/clone-for [tag (utils/tags all-posts)]
(h/substitute (tag-item tag))))
+
+;; These last two functions - `recent-posts` and `all-tags` - will be
+;; used by the various page rendering templates in [blog.archive][1],
+;; [blog.post][2], and [blog.page][3].
+;;
+;; [1]: #madness.blog.archive
+;; [2]: #madness.blog.post
+;; [3]: #madness.blog.page
View
@@ -1,4 +1,15 @@
(ns madness.blog.page
+ "## Loading & rendering of individual static pages
+
+ For the sake of ease, static pages are fully loaded first, and
+ turned into a structure that is easy to work with. This namespace
+ implements the low-level loading, restructuring and rendering of
+ individual static pages.
+
+ Static pages are under `resources/pages` by default, and their path
+ below that will be reused as-is for the URL of the generated
+ page. That is, `resources/pages/foo/bar/index.html` becomes
+ `/foo/bar/index.html`."
^{:author "Gergely Nagy <algernon@madhouse-project.org>"
:copyright "Copyright (C) 2012 Gergely Nagy <algernon@madhouse-project.org>"
@@ -12,20 +23,40 @@
[clojure.string :as str]
[clj-time.format :as time-format]))
+(defn- page-url
+ "Given a file path, strips the pages directory, and returns the
+ result, which will be used as the URL for a given page."
+ [path]
+
+ (second (first (re-seq (re-pattern (str ".*" (cfg/dirs :pages) "(.*)"))
+ path))))
+
(defn- enabled?
+ "A very dumb little helper function, that merely checks if a value
+ is set or not - it's mostly here to make some of the code below
+ clearer."
[value]
(if (nil? value)
false
true))
-(defn- page-url
- [path]
+(defn read-page
+ "Read a static page from a while, and restructure it into a
+ representation that is easy to work with.
- (second (first (re-seq (re-pattern (str ".*" (cfg/dirs :pages) "(.*)"))
- path))))
+ Each static page must have an `article` element, where the only
+ required child is the `title`. It can also - optionally - have a
+ `comments` property, which, when set, will enable commenting on the
+ particular page.
-(defn read-page
+ Apart from the `article` element, only a `section` element is
+ required, whose contents will be used as the main content of the
+ static page.
+
+ The structure this function generates, should be pretty clear by
+ glancing over the code here."
+
[file]
(let [page (h/html-resource file)]
@@ -34,17 +65,38 @@
:comments (-> (first (h/select page [:article])) :attrs :comments enabled?),
:content (h/select page [:section])}))
+;; ### Static page templates
+
+;; The first thing about a page, is its header, the `h1` element of
+;; the `hero-unit` in the template.
+;;
+;; This snippet uses that element as the title template, replacing the
+;; `title` attribute of it, and its textual content with the title of
+;; the page itself.
(h/defsnippet blog-page-title (cfg/template) [:.hero-unit :h1]
[title]
[:h1] (h/do->
(h/content title)
(h/set-attr :title title)))
+;; If commenting is enabled for a post, the `#disqus` element should
+;; be left intact, as-is. Otherwise, it will be removed, that is all
+;; this snippet does.
(h/defsnippet blog-page-disqus (cfg/template) [:#disqus]
[page]
[:#disqus] (when (:comments page) identity))
+;; #### Putting it all together
+;;
+;; To put a full page together, we alter the page title, disable the
+;; recent and archived post areas, along with the `#post-neighbours`,
+;; as pages do not have those. We also rearrange the `hero-unit`, and
+;; last but not least, fill out the sidebar, using the tools provided
+;; by [blog.nav][1].
+;;
+;; [1]: #madness.blog.nav
+;;
(h/deftemplate blog-page (cfg/template)
[page all-posts]
View
@@ -1,4 +1,15 @@
(ns madness.blog.post
+ "## Loading & rendering individual blog posts
+
+ For the sake of ease, blog posts are fully loaded first, and turned
+ into a structure that is easy to work with. This namespace
+ implements the low-level loading, restructuring and rendering of
+ individual blog posts.
+
+ Blog posts are under `resources/posts` by default, and they all must
+ have a filename that starts with a date (in YYYY-MM-DD format),
+ followed by the short title of the post, that will be used for the
+ URL."
^{:author "Gergely Nagy <algernon@madhouse-project.org>"
:copyright "Copyright (C) 2012 Gergely Nagy <algernon@madhouse-project.org>"
@@ -12,23 +23,56 @@
[clojure.string :as str]
[clj-time.format :as time-format]))
-(defn- enabled?
- [value]
-
- (if (nil? value)
- false
- true))
-
+;; The date format used within blog files. Note that this is not the
+;; format we render dates as, but the format we expect them to be
+;; within blog posts!
(def blog-date-format ^{:private true}
(time-format/formatter "yyyy-MM-dd HH:mm"))
(defn- post-url
+ "Given a parsed date and a source filename, return the URI for the blog post.
+
+ The source filenames will be stripped of the date part, and the date
+ within the post itself will be used to construct the final URL of
+ the form `/blog/yyyy/MM/dd/title/`."
+
[date fn]
(str "/blog/" (time-format/unparse (time-format/formatter "yyyy/MM/dd") date)
"/" (second (first (re-seq #"....-..-..-(.*).html" fn))) "/"))
+(defn- enabled?
+ "A very dumb little helper function, that merely checks if a value
+ is set or not - it's mostly here to make some of the code below
+ clearer."
+ [value]
+
+ (if (nil? value)
+ false
+ true))
+
(defn read-post
+ "Read a blog post from a file, and restructure it into a
+ representation that is easy to work with.
+
+ Each blog post must have an `article` element, which must also have
+ `title`, `date`, and `tags` children - all of their purpose should
+ already be clear. The `article` element may also have a `comments`
+ propery, which, when set, will enable commenting on the particular
+ post.
+
+ A blog post must also have a `summary` element, the contents of
+ which will be used when rendering the post for the purposes of
+ recent posts, or as the summary on the main index page. The summary
+ is also part of the blog post, and when viewing the entire post, it
+ will start with the summary.
+
+ Following that, the entire contents of the `section` element of the
+ blog post will be displayed.
+
+ The structure this function generates, should be pretty clear by
+ glancing over the code here."
+
[file]
(let [post (h/html-resource file)
@@ -41,12 +85,31 @@
:comments (-> (first (h/select post [:article])) :attrs :comments enabled?),
:content (h/select post [:section])}))
+;; ### Blog post templates
+;;
+;; Blog posts are almost entirely contained within a `hero-unit`
+;; class, with only the previous/next links outside of it.
+
+;; One of the first things one sees about a post, is its title, which
+;; is the `h1` element of the `hero-unit` in the template.
+;;
+;; This snippet uses that element as the title template, replacing the
+;; `title` attribute of it, and its textual content with the title of
+;; the post itself.
(h/defsnippet blog-post-title (cfg/template) [:.hero-unit :h1]
[title]
[:h1] (h/do->
(h/content title)
(h/set-attr :title title)))
+;; #### Full article footer
+;;
+;; Posts, when viewed in full, and not only their summary, have a
+;; footer, which holds their tags and the date they were posted on,
+;; these all live under the `#full-article-footer` element.
+
+;; The full article footer has only a single link in the template: the
+;; snippet that we'll use to render a single tag.
(h/defsnippet blog-post-tag (cfg/template) [:#full-article-footer :a]
[tag]
@@ -55,6 +118,9 @@
(h/after " "))
[:a :span] (h/substitute tag))
+;; The full footer contains a date, the `#post-date` element, and
+;; we'll also render the tags there too. Both the `#post-date` and the
+;; `#full-article-footer` ids will be removed.
(h/defsnippet blog-post-footer (cfg/template) [:#full-article-footer]
[post]
@@ -65,6 +131,21 @@
(h/remove-attr :id))
[:#full-article-footer] (h/remove-attr :id))
+;; #### Post navigation
+;;
+;; To ease navigating between posts, previous and next posts (if
+;; available) will be shown outside of the `hero-unit`. These we'll
+;; call `#post-neighbours`, and this element must have two children:
+;; one with a `pull-left` class (for the next post), and another with
+;; `pull-right` (for the previous post).
+;;
+;; Both of these need to have an `a` element, whose `href` will be
+;; rewritten, and that element must have a `span` child, to be
+;; replaced by the title of the previous or next post.
+;;
+;; The `#post-neighbours` id will be removed from the final rendering,
+;; as it is only used to easily identify the snippet within the full
+;; template.
(h/defsnippet blog-post-neighbours (cfg/template) [:#post-neighbours]
[neighbours]
@@ -81,11 +162,26 @@
identity)
[:#post-neighbours] (h/remove-attr :id))
+;; #### Commenting
+;;
+;; If commenting is enabled for a post, the `#disqus` element should
+;; be left intact, as-is. Otherwise, it will be removed, that is all
+;; this snippet does.
(h/defsnippet blog-post-disqus (cfg/template) [:#disqus]
[post]
[:#disqus] (when (:comments post) identity))
+;; #### Putting it all together
+;;
+;; To put a full blog post together, we alter the page title, disable
+;; the recent and archived post areas, rearrange the `hero-unit`, pull
+;; in the next/prev links into `#post-neighbours`, and last but not
+;; least, fill out the sidebar, using the tools provided by
+;; [blog.nav][1].
+;;
+;; [1]: #madness.blog.nav
+;;
(h/deftemplate blog-post (cfg/template)
[post all-posts]
Oops, something went wrong.

0 comments on commit f519422

Please sign in to comment.