|
@@ -20,36 +20,84 @@ will checkout the repo to a **$TMPDIR** and call `(coleslaw:main $TMPDIR)`.
|
20
|
20
|
|
21
|
21
|
It is then coleslaw's job to load all of your content, your config and
|
22
|
22
|
templates, and render the content to disk. Deployment is done by
|
23
|
|
-updating a symlink and the default install assumes your webserver will
|
24
|
|
-be configured to serve from that symlink. However, there are plugins
|
25
|
|
-for deploying to Heroku, S3, and Github Pages.
|
|
23
|
+moving the files to a location specified in the config and updating a
|
|
24
|
+symlink. It is assumed a web server is set up to serve from that
|
|
25
|
+symlink. However, there are plugins for deploying to Heroku, S3, and
|
|
26
|
+Github Pages.
|
26
|
27
|
|
27
|
28
|
### Blogs vs Sites
|
28
|
29
|
|
29
|
30
|
**Coleslaw** is blogware. When I designed it, I only cared that it
|
30
|
|
-could replace my server's wordpress install. As a result, the code is
|
31
|
|
-still structured in terms of POSTs and INDEXes. Roughly speaking, a
|
32
|
|
-POST is a blog entry and an INDEX is a collection of POSTs or other
|
33
|
|
-content. An INDEX really only serves to group a set of content objects
|
34
|
|
-on a page, it isn't content itself.
|
|
31
|
+could replace my server's wordpress install. As a result, the code
|
|
32
|
+until very recently was structured in terms of POSTs and
|
|
33
|
+INDEXes. Roughly speaking, a POST is a blog entry and an INDEX is a
|
|
34
|
+collection of POSTs or other content. An INDEX really only serves to
|
|
35
|
+group a set of content objects on a page, it isn't content itself.
|
35
|
36
|
|
36
|
37
|
This isn't ideal if you're looking for a full-on static site
|
37
|
38
|
generator. Content Types were added in 0.8 as a step towards making
|
38
|
39
|
*coleslaw* suitable for more use cases but still have some
|
39
|
|
-limitations. Chiefly, the association between Content Types, their
|
40
|
|
-template, and their inclusion in an INDEX is presently ad-hoc.
|
|
40
|
+limitations. Any subclass of CONTENT that implements the *document
|
|
41
|
+protocol* counts as a content type. However, only POSTs are currently
|
|
42
|
+included on INDEXes since their isn't yet a formal relationship to
|
|
43
|
+determine what content types should be included on which indexes.
|
41
|
44
|
|
42
|
|
-### Current Content Types & Indices
|
|
45
|
+### The Document Protocol
|
43
|
46
|
|
44
|
|
-There are 3 INDEX subclasses at present: TAG-INDEX, DATE-INDEX, and
|
45
|
|
-NUMERIC-INDEX, for grouping content by tags, publishing date, and
|
46
|
|
-reverse chronological order, respectively. Currently, there is only 1
|
47
|
|
-content type: POST, for blog entries.
|
|
47
|
+The *document protocol* was born during a giant refactoring in 0.9.3.
|
|
48
|
+Any object that will be rendered to HTML should adhere to the protocol.
|
|
49
|
+Subclasses of CONTENT (content types) that implement the protocol will
|
|
50
|
+be seamlessly picked up by *coleslaw* and included on the rendered site.
|
|
51
|
+
|
|
52
|
+All current Content Types and Indexes implement the protocol faithfully.
|
|
53
|
+It consists of 2 "class" methods, 2 instance methods, and an invariant.
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+* Class Methods:
|
|
57
|
+
|
|
58
|
+Since Common Lisp doesn't have explicit support for class methods, we
|
|
59
|
+implement them by eql-specializing on the class, e.g.
|
|
60
|
+```lisp
|
|
61
|
+(defmethod foo ((doc-type (eql (find-class 'bar))))
|
|
62
|
+ ... )
|
|
63
|
+```
|
|
64
|
+
|
|
65
|
+- `discover`: Create instances for documents of the class and put them in
|
|
66
|
+ in-memory database with `add-document`. If your class is a subclass of
|
|
67
|
+ CONTENT, there is a default method for this.
|
|
68
|
+- `publish`: Iterate over all objects of the class
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+* Instance Methods:
|
|
72
|
+
|
|
73
|
+- `page-url`: Generate a unique, relative path for the object on the site
|
|
74
|
+ sans file extension. An :around method adds that later. The `slug` slot
|
|
75
|
+ on the object is generally used to hold a portion of the unique
|
|
76
|
+ identifier. i.e. `(format nil "posts/~a" (content-slug object))`.
|
|
77
|
+- `render`: A method that calls the appropriate template with `theme-fn`,
|
|
78
|
+ passing it any needed arguments and returning rendered HTML.
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+* Invariants:
|
|
82
|
+
|
|
83
|
+- Any Content Types (subclasses of CONTENT) are expected to be stored in
|
|
84
|
+ the site's git repo with the lowercased class-name as a file extension,
|
|
85
|
+ i.e. (".post" for POST files).
|
|
86
|
+
|
|
87
|
+### Current Content Types & Indexes
|
|
88
|
+
|
|
89
|
+There are 5 INDEX subclasses at present: TAG-INDEX, MONTH-INDEX,
|
|
90
|
+NUMERIC-INDEX, FEED, and TAG-FEED. Respectively, they support
|
|
91
|
+grouping content by tags, publishing date, and reverse chronological
|
|
92
|
+order. Feeds exist to special case RSS and ATOM generation.
|
|
93
|
+Currently, there is only 1 content type: POST, for blog entries.
|
48
|
94
|
|
49
|
95
|
I'm planning to add a content type PAGE, for static pages. It should
|
50
|
96
|
be a pretty straightforward subclass of CONTENT with the necessary
|
51
|
|
-methods: `render`, `page-url` and `publish`, but will require a small
|
52
|
|
-tweak to prevent showing up in any INDEX.
|
|
97
|
+methods: `render`, `page-url` and `publish`. It could have a `url`
|
|
98
|
+slot with `page-url` as a reader to allow arbitrary layout on the site.
|
|
99
|
+The big question is how to handle templating and how indexes or other
|
|
100
|
+content should link to it.
|
53
|
101
|
|
54
|
102
|
### Templates and Theming
|
55
|
103
|
|
|
@@ -57,41 +105,42 @@ User configs are allowed to specify a theme, otherwise the default is
|
57
|
105
|
used. A theme consists of a directory under "themes/" containing css,
|
58
|
106
|
images, and at least 3 templates: Base, Index, and Post.
|
59
|
107
|
|
60
|
|
-**Coleslaw** exclusively uses
|
|
108
|
+**Coleslaw** uses
|
61
|
109
|
[cl-closure-template](https://github.com/archimag/cl-closure-template)
|
62
|
|
-for templating which is a well documented CL implementation of
|
63
|
|
-Google's Closure Templates. Each template file should be in a
|
64
|
|
-namespace like `coleslaw.theme.theme-name`.
|
|
110
|
+exclusively for templating. **cl-closure-template** is a well
|
|
111
|
+documented CL implementation of Google's Closure Templates. Each
|
|
112
|
+template file should contain a namespace like
|
|
113
|
+`coleslaw.theme.theme-name`.
|
65
|
114
|
|
66
|
115
|
Each template creates a lisp function in the theme's package when
|
67
|
116
|
loaded. These functions take a property list (or plist) as an argument
|
68
|
117
|
and return rendered HTML. **Coleslaw** defines a helper called
|
69
|
|
-`theme-fn` for easy access to the template functions.
|
|
118
|
+`theme-fn` for easy access to the template functions. Additionally,
|
|
119
|
+there are RSS, ATOM, and sitemap templates *coleslaw* uses automatically.
|
|
120
|
+No need for individual themes to reimplement a standard, after all!
|
70
|
121
|
|
|
122
|
+// TODO: Update for changes to compile-blog, indexes refactor, etc.
|
71
|
123
|
### The Lifecycle of a Page
|
72
|
124
|
|
73
|
125
|
- `(load-content)`
|
74
|
126
|
|
75
|
|
-A page starts, obviously, with a file. When
|
76
|
|
-*coleslaw* loads your content, it iterates over a list of content
|
77
|
|
-types (i.e. subclasses of CONTENT). For each content type, it
|
78
|
|
-iterates over all files in the repo with a matching extension,
|
79
|
|
-e.g. ".post" for POSTs. Objects of the appropriate class are created
|
80
|
|
-from each matching file and inserted into the `*content*` hash-table.
|
|
127
|
+A page starts, obviously, with a file. When *coleslaw* loads your
|
|
128
|
+content, it iterates over a list of content types (i.e. subclasses of
|
|
129
|
+CONTENT). For each content type, it iterates over all files in the
|
|
130
|
+repo with a matching extension, e.g. ".post" for POSTs. Objects of the
|
|
131
|
+appropriate class are created from each matching file and inserted
|
|
132
|
+into the an in-memory data store. Then the INDEXes are created by
|
|
133
|
+iterating over the POSTs and inserted into the data store.
|
81
|
134
|
|
82
|
135
|
- `(compile-blog dir)`
|
83
|
136
|
|
84
|
137
|
Compilation starts by ensuring the staging directory (`/tmp/coleslaw/`
|
85
|
138
|
by default) exists, cd'ing there, and copying over any necessary theme
|
86
|
|
-assets. Then *coleslaw* iterates over the content types, calling the
|
87
|
|
-`publish` method on each one. Publish creates any non-INDEX pages for
|
88
|
|
-the objects of that content type by iterating over the objects in an
|
89
|
|
-appropriate fashion, rendering them, and passing the result to
|
90
|
|
-`write-page` (which should probably just be renamed to `write-file`).
|
91
|
|
-
|
92
|
|
-After this, `render-indices` and `render-feeds` are called, and an
|
93
|
|
-'index.html' symlink is created to point to the first reverse
|
94
|
|
-chronological index.
|
|
139
|
+assets. Then *coleslaw* iterates over the content types and index classes,
|
|
140
|
+calling the `publish` method on each one. Publish iterates over the
|
|
141
|
+class instances, rendering each one and writing the result out to disk
|
|
142
|
+with `write-page` (which should probably just be renamed to `write-file`).
|
|
143
|
+After this, an 'index.html' symlink is created to point to the first index.
|
95
|
144
|
|
96
|
145
|
- `(deploy dir)`
|
97
|
146
|
|
|
@@ -102,10 +151,29 @@ freshly built site.
|
102
|
151
|
|
103
|
152
|
## Areas for Improvement
|
104
|
153
|
|
|
154
|
+### Render Function Cleanup
|
|
155
|
+
|
|
156
|
+There are currently 3 render-foo* functions and 3 implementations of the
|
|
157
|
+render method. Only the render-foo* functions call `write-page` so there
|
|
158
|
+should be some room for cleanup here. The render method implementations
|
|
159
|
+are probably necessary unless we want to start storing their arguments
|
|
160
|
+on the models. There may be a different way to abstract the data flow.
|
|
161
|
+
|
|
162
|
+### User-Defined Routing
|
|
163
|
+
|
|
164
|
+There is no reason *coleslaw* should be in charge of the site layout or
|
|
165
|
+should care. If all objects only used the *slug* slot in their `page-url`
|
|
166
|
+methods, there could be a :routing argument in the config containing
|
|
167
|
+a plist of `(:class "~{format string~}")` pairs. A default method could
|
|
168
|
+check the :class key under `(routing *config*)` if no specialized
|
|
169
|
+`page-url` was defined. This would have the additional benefit of
|
|
170
|
+localizing all the site routing in one place. New Content Types would
|
|
171
|
+probably `pushnew` a plist onto the config key in their `enable` function.
|
|
172
|
+
|
105
|
173
|
### Better Content Types
|
106
|
174
|
|
107
|
|
-Creating a new content type should be both straightforward and doable
|
108
|
|
-as a plugin. All that is really required is a subclass of CONTENT with
|
|
175
|
+Creating a new content type is both straightforward and doable as a
|
|
176
|
+plugin. All that is really required is a subclass of CONTENT with
|
109
|
177
|
any needed slots, a template, a `render` method to call the template
|
110
|
178
|
with any needed options, a `page-url` method for layout, and a
|
111
|
179
|
`publish` method.
|
|
@@ -115,10 +183,12 @@ Unfortunately, this does not solve:
|
115
|
183
|
1. The issue of compiling the template at load-time and making sure it
|
116
|
184
|
was installed in the theme package. The plugin would need to do
|
117
|
185
|
this itself or the template would need to be included in 'core'.
|
|
186
|
+ Thankfully, this should be easy with *cl-closure-template*.
|
118
|
187
|
2. More seriously, there is no formal relationship between content
|
119
|
|
- types and indices. Indices include *ALL* objects in the `*content*`
|
120
|
|
- hash table. This may be undesirable and doesn't permit indices
|
121
|
|
- dedicated to particular content types.
|
|
188
|
+ types and indexes. Consequentially, INDEXes include only POST
|
|
189
|
+ objects at the moment. Whether the INDEX should specify what
|
|
190
|
+ Content Types it includes or the CONTENT which indexes it appears
|
|
191
|
+ on is not yet clear.
|
122
|
192
|
|
123
|
193
|
### New Content Type: Shouts!
|
124
|
194
|
|
|
@@ -130,19 +200,10 @@ tabs or stored on twitter's servers. It would be cool to see SHOUTs as
|
130
|
200
|
a plugin, probably with a dedicated SHOUT-INDEX, and some sort of
|
131
|
201
|
oEmbed/embed.ly/noembed support.
|
132
|
202
|
|
133
|
|
-### Layouts and Paths
|
134
|
|
-
|
135
|
|
-Defining a page-url for every content-object and index seems a bit
|
136
|
|
-silly. It also spreads information about the site layout throughout
|
137
|
|
-the codebase, it might be better to have a slot in the config that
|
138
|
|
-defines this information with a key to go with each format string.
|
139
|
|
-Adding a new content-type as a plugin could then provide a default
|
140
|
|
-by banging on the config or specify the path in its `enable` options.
|
141
|
|
-
|
142
|
203
|
### Incremental Compilation
|
143
|
204
|
|
144
|
205
|
Incremental compilation is doable, even straightforward if you ignore
|
145
|
|
-indices. It is also preferable to building the site in parallel as
|
|
206
|
+indexes. It is also preferable to building the site in parallel as
|
146
|
207
|
avoiding work is better than using more workers. Moreover, being
|
147
|
208
|
able to determine (and expose) what files just changed enables new
|
148
|
209
|
functionality such as plugins that cross-post to tumblr.
|
|
@@ -158,6 +219,6 @@ things the existing deployment model would not work as it involves
|
158
|
219
|
rebuilding the entire site. In all likelihood we would want to update
|
159
|
220
|
the site 'in-place'. Atomicity of filesystem operations would be a
|
160
|
221
|
reasonable concern. Also, every numbered INDEX would have to be
|
161
|
|
-regenerated along with any tag or month indices matching the
|
|
222
|
+regenerated along with any tag or month indexes matching the
|
162
|
223
|
modified files. If incremental compilation is a goal, simply
|
163
|
|
-disabling the indices may be appropriate for certain users.
|
|
224
|
+disabling the indexes may be appropriate for certain users.
|