josh-rack-cache 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,112 @@
1
+ Configuration
2
+ =============
3
+
4
+ __Rack::Cache__ includes a configuration system that can be used to specify
5
+ fairly sophisticated cache policy on a global or per-request basis.
6
+
7
+ <a id='setopt'></a>
8
+
9
+ Setting Cache Options
10
+ ---------------------
11
+
12
+ Cache options can be set when the __Rack::Cache__ object is created,
13
+ or by setting a `rack-cache.<option>` variable in __Rack__'s
14
+ __Environment__.
15
+
16
+ When the __Rack::Cache__ object is instantiated:
17
+
18
+ use Rack::Cache,
19
+ :verbose => true,
20
+ :metastore => 'memcached://localhost:11211/',
21
+ :entitystore => 'file:/var/cache/rack'
22
+
23
+ Using __Rack__'s __Environment__:
24
+
25
+ env.merge!(
26
+ 'rack-cache.verbose' => true,
27
+ 'rack-cache.metastore' => 'memcached://localhost:11211/',
28
+ 'rack-cache.entitystore' => 'file:/var/cache/rack'
29
+ )
30
+
31
+ <a id='options'></a>
32
+
33
+ Cache Option Reference
34
+ ----------------------
35
+
36
+ Use the following options to customize __Rack::Cache__:
37
+
38
+ ### `verbose`
39
+
40
+ Boolean specifying whether verbose trace logging is enabled. This option is
41
+ currently enabled (`true`) by default but is likely to be disabled (`false`) in
42
+ a future release. All log output is written to the `rack.errors` stream, which
43
+ is typically set to `STDERR`.
44
+
45
+ The `trace`, `info`, `warn`, and `error` methods can be used within the
46
+ configuration context to write messages to the errors stream.
47
+
48
+ ### `default_ttl`
49
+
50
+ An integer specifying the number of seconds a cached object should be considered
51
+ "fresh" when no explicit freshness information is provided in a response.
52
+ Explicit `Cache-Control` or `Expires` response headers always override this
53
+ value. The `default_ttl` option defaults to `0`, meaning responses without
54
+ explicit freshness information are considered immediately "stale" and will not
55
+ be served from cache without validation.
56
+
57
+ ### `metastore`
58
+
59
+ A URI specifying the __MetaStore__ implementation used to store request/response
60
+ meta information. See the [Rack::Cache Storage Documentation](storage.html)
61
+ for detailed information on different storage implementations.
62
+
63
+ If no metastore is specified, the `heap:/` store is assumed. This implementation
64
+ has significant draw-backs so explicit configuration is recommended.
65
+
66
+ ### `entitystore`
67
+
68
+ A URI specifying the __EntityStore__ implementation used to store
69
+ response bodies. See the [Rack::Cache Storage Documentation](storage.html)
70
+ for detailed information on different storage implementations.
71
+
72
+ If no entitystore is specified, the `heap:/` store is assumed. This
73
+ implementation has significant draw-backs so explicit configuration is
74
+ recommended.
75
+
76
+ ### `private_headers`
77
+
78
+ An array of request header names that cause the response to be treated with
79
+ private cache control semantics. The default value is `['Authorization', 'Cookie']`.
80
+ If any of these headers are present in the request, the response is considered
81
+ private and will not be cached _unless_ the response is explicitly marked public
82
+ (e.g., `Cache-Control: public`).
83
+
84
+ ### `allow_reload`
85
+
86
+ A boolean specifying whether reload requests sent by the client should be
87
+ honored by the cache. When this option is enabled (`rack-cache.allow_reload`
88
+ is `true`), requests that include a `Cache-Control: no-cache` header cause
89
+ the cache to discard anything it has stored for the request and ask that the
90
+ response be fully generated.
91
+
92
+ Most browsers include a `Cache-Control: no-cache` header when the user performs
93
+ a "hard refresh" (e.g., holding `Shift` while clicking the "Refresh" button).
94
+
95
+ *IMPORTANT: Enabling this option globally allows all clients to break your cache.*
96
+
97
+ ### `allow_revalidate`
98
+
99
+ A boolean specifying whether revalidate requests sent by the client should be
100
+ honored by the cache. When this option is enabled (`rack-cache.allow_revalidate`
101
+ is `true`), requests that include a `Cache-Control: max-age=0` header cause the
102
+ cache to assume its copy of the response is stale, resulting in a conditional
103
+ GET / validation request to be sent to the server.
104
+
105
+ Most browsers include a `Cache-Control: max-age=0` header when the user performs
106
+ a refresh (e.g., clicking the "Refresh" button).
107
+
108
+ *IMPORTANT: Enabling this option globally allows all clients to break your cache.*
109
+
110
+ ### `cache_key`
111
+
112
+ TODO: Document custom cache keys
@@ -0,0 +1,141 @@
1
+ Frequently Asked Questions
2
+ ==========================
3
+
4
+ <p class='intro'>
5
+ <strong>NOTE:</strong> This is a work in progress. Please send questions, comments, or
6
+ suggestions to <a href="mailto:r@tomayko.com">r@tomayko.com</a>.
7
+ </p>
8
+
9
+ General
10
+ -------
11
+
12
+
13
+ <a class='hash' id='rails' href='#rails'>#</a>
14
+
15
+ ### Q: Can I use Rack::Cache with Rails?
16
+
17
+ Rack::Cache can be used with Rails 2.3 or above. Documentation and a
18
+ sample application is forthcoming; in the mean time, see
19
+ [this example of using Rack::Cache with Rails 2.3](http://snippets.aktagon.com/snippets/302-How-to-setup-and-use-Rack-Cache-with-Rails-2-3-0-RC-1).
20
+
21
+ <a class='hash' id='why-not-squid' href='#why-not-squid'>#</a>
22
+
23
+ ### Q: Why Rack::Cache? Why not Squid, Varnish, Perlbol, etc.?
24
+
25
+ __Rack::Cache__ is often easier to setup as part of your existing Ruby
26
+ application than a separate caching system. __Rack::Cache__ runs entirely inside
27
+ your backend application processes - no separate / external process is required.
28
+ This lets __Rack::Cache__ scale down to development environments and simple
29
+ deployments very easily while not sacrificing the benefits of a standards-based
30
+ approach to caching.
31
+
32
+
33
+ <a class='hash' id='why-not-rails' href='#why-not-rails'>#</a>
34
+
35
+ ### Q: Why Rack::Cache? Why not use Rails/Merb/FrameworkX's caching system?
36
+
37
+ __Rack::Cache__ takes a standards-based approach to caching that provides some
38
+ benefits over framework-integrated systems. It uses standard HTTP headers
39
+ (`Expires`, `Cache-Control`, `Etag`, `Last-Modified`, etc.) to determine
40
+ what/when to cache. Designing applications to support these standard HTTP
41
+ mechanisms gives the benefit of being able to switch to a different HTTP
42
+ cache implementation in the future.
43
+
44
+ In addition, using a standards-based approach to caching creates a clear
45
+ separation between application and caching logic. The application need only
46
+ specify a basic set of information about the response and all decisions
47
+ regarding how and when to cache is moved into the caching layer.
48
+
49
+
50
+ <a class='hash' id='scale' href='#scale'>#</a>
51
+
52
+ ### Q: Will Rack::Cache make my app scale?
53
+
54
+ No. Your design is the only thing that can make your app scale.
55
+
56
+ Also, __Rack::Cache__ is not overly optimized for performance. The main goal of
57
+ the project is to provide a portable, easy-to-configure, and standards-based
58
+ caching solution for small to medium sized deployments. More sophisticated /
59
+ performant caching systems (e.g., [Varnish][v], [Squid][s],
60
+ [httpd/mod-cache][h]) may be more appropriate for large deployments with
61
+ crazy-land throughput requirements.
62
+
63
+ [v]: http://varnish.projects.linpro.no/
64
+ [s]: http://www.squid-cache.org/
65
+ [h]: http://httpd.apache.org/docs/2.0/mod/mod_cache.html
66
+
67
+
68
+ Features
69
+ --------
70
+
71
+
72
+ <a class='hash' id='validation' href='#validation'>#</a>
73
+
74
+ ### Q: Does Rack::Cache support validation?
75
+
76
+ Yes. Both freshness and validation-based caching is supported. A response
77
+ will be cached if it has a freshness lifetime (e.g., `Expires` or
78
+ `Cache-Control: max-age=N` headers) and/or includes a validator (e.g.,
79
+ `Last-Modified` or `ETag` headers). When the cache hits and the response is
80
+ fresh, it's delivered immediately without talking to the backend application;
81
+ when the cache is stale, the cached response is validated using a conditional
82
+ GET request.
83
+
84
+
85
+ <a class='hash' id='fragments' href='#fragments'>#</a>
86
+
87
+ ### Q: Does Rack::Cache support fragment caching?
88
+
89
+ Not really. __Rack::Cache__ deals with entire responses and doesn't know
90
+ anything about how your application constructs them.
91
+
92
+ However, something like [ESI](http://www.w3.org/TR/esi-lang) may be implemented
93
+ in the future (likely as a separate Rack middleware component that could be
94
+ situated upstream from Rack::Cache), which would allow applications to compose
95
+ responses based on several "fragment resources". Each fragment would have its
96
+ own cache policy.
97
+
98
+
99
+ <a class='hash' id='manual-purge' href='#manual-purge'>#</a>
100
+
101
+ ### Q: How do I manually purge or expire a cached entry?
102
+
103
+ Although planned, there is currently no mechanism for manually purging
104
+ an entry stored in the cache.
105
+
106
+ Note that using an `Expires` or `Cache-Control: max-age=N` header and relying on
107
+ manual purge to invalidate cached entry can often be implemented more simply
108
+ using efficient validation based caching (`Last-Modified`, `Etag`). Many web
109
+ frameworks are based entirely on manual purge and do not support validation at
110
+ the cache level.
111
+
112
+
113
+ <a class='hash' id='efficient-validation' href='#efficient-validation'>#</a>
114
+
115
+ ### Q: What does "Efficient Validation" mean?
116
+
117
+ It means that your application performs only the processing necessary to
118
+ determine if a response is valid before sending a `304 Not Modified` in response
119
+ to a conditional GET request. Many applications that perform validation do so
120
+ only after the entire response has been generated, which provides bandwidth
121
+ savings but results in no CPU/IO savings. Implementing validation efficiently
122
+ can increase backend application throughput significantly when fronted by a
123
+ validating caching system (like __Rack::Cache__).
124
+
125
+ [Here's an example Rack application](http://gist.github.com/9395) that performs
126
+ efficient validation.
127
+
128
+
129
+ <a class='hash' id='orly' href='#orly'>#</a>
130
+
131
+ ### Q: Did you just make that up?
132
+
133
+ Yes.
134
+
135
+
136
+ <a class='hash' id='https' href='#https'>#</a>
137
+
138
+ ### Q: Can I do HTTPS with Rack::Cache?
139
+
140
+ Sure. HTTPS is typically managed by a front-end web server so this isn't really
141
+ relevant to Rack::Cache.
@@ -0,0 +1,121 @@
1
+ __Rack::Cache__ is suitable as a quick drop-in component to enable HTTP caching
2
+ for [Rack][]-based applications that produce freshness (`Expires`,
3
+ `Cache-Control`) and/or validation (`Last-Modified`, `ETag`) information.
4
+
5
+ * Standards-based (see [RFC 2616][rfc] / [Section 13][s13]).
6
+ * Freshness/expiration based caching
7
+ * Validation
8
+ * Vary support
9
+ * Portable: 100% Ruby / works with any [Rack][]-enabled framework.
10
+ * Disk, memcached, and heap memory [storage backends][storage].
11
+
12
+ News
13
+ ----
14
+
15
+ * Rack::Cache 0.5 was released on May 25, 2009. See the
16
+ [`CHANGES`](http://github.com/rtomayko/rack-cache/blob/0.5.0/CHANGES) file
17
+ for details.
18
+ * [How to use Rack::Cache with Rails 2.3](http://snippets.aktagon.com/snippets/302-How-to-setup-and-use-Rack-Cache-with-Rails-2-3-0-RC-1) - it's really easy.
19
+ * [RailsLab's Advanced HTTP Caching Screencast](http://railslab.newrelic.com/2009/02/26/episode-11-advanced-http-caching)
20
+ is a really great review of HTTP caching concepts and shows how to
21
+ use Rack::Cache with Rails.
22
+
23
+ Installation
24
+ ------------
25
+
26
+ $ sudo gem install rack-cache
27
+
28
+ Or, from a local working copy:
29
+
30
+ $ git clone git://github.com/rtomayko/rack-cache.git
31
+ $ rake package && sudo rake install
32
+
33
+ Basic Usage
34
+ -----------
35
+
36
+ __Rack::Cache__ is implemented as a piece of [Rack][] middleware and can be used
37
+ with any __Rack__-based application. If your application includes a rackup
38
+ (`.ru`) file or uses __Rack::Builder__ to construct the application pipeline,
39
+ simply `require` and `use` as follows:
40
+
41
+ require 'rack/cache'
42
+
43
+ use Rack::Cache,
44
+ :verbose => true,
45
+ :metastore => 'file:/var/cache/rack/meta'
46
+ :entitystore => 'file:/var/cache/rack/body'
47
+
48
+ run app
49
+
50
+ Assuming you've designed your backend application to take advantage of HTTP's
51
+ caching features, no further code or configuration is required for basic
52
+ caching.
53
+
54
+ More
55
+ ----
56
+
57
+ * [Configuration Options][config] - how to set cache options.
58
+
59
+ * [Cache Storage Documentation][storage] - detailed information on the various
60
+ storage implementations available in __Rack::Cache__ and how to choose the one
61
+ that's best for your application.
62
+
63
+ * [Things Caches Do][things] - an illustrated guide to how HTTP gateway
64
+ caches work with pointers to other useful resources on HTTP caching.
65
+
66
+ * [GitHub Repository](http://github.com/rtomayko/rack-cache/) - get your
67
+ fork on.
68
+
69
+ * [Mailing List](http://groups.google.com/group/rack-cache) - for hackers
70
+ and users (`rack-cache@groups.google.com`).
71
+
72
+ * [FAQ](./faq) - Frequently Asked Questions about __Rack::Cache__.
73
+
74
+ * [RDoc API Documentation](./api/) - Mostly worthless if you just want to use
75
+ __Rack::Cache__ in your application but mildly insightful if you'd like to
76
+ get a feel for how the system has been put together; I recommend
77
+ [reading the source](http://github.com/rtomayko/rack-cache/master/lib/rack/cache).
78
+
79
+
80
+ See Also
81
+ --------
82
+
83
+ The overall design of __Rack::Cache__ is based largely on the work of the
84
+ internet standards community. The following resources provide a good starting
85
+ point for exploring the basic concepts of HTTP caching:
86
+
87
+ * Mark Nottingham's [Caching Tutorial](http://www.mnot.net/cache_docs/),
88
+ especially the short section on
89
+ [How Web Caches Work](http://www.mnot.net/cache_docs/#WORK)
90
+
91
+ * Joe Gregorio's [Doing HTTP Caching Right](http://www.xml.com/lpt/a/1642)
92
+
93
+ * [RFC 2616](http://www.ietf.org/rfc/rfc2616.txt), especially
94
+ [Section 13, "Caching in HTTP"](http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html)
95
+
96
+ __Rack::Cache__ takes (_liberally_) various concepts from
97
+ [Varnish](http://varnish.projects.linpro.no/) and
98
+ [Django's cache framework](http://docs.djangoproject.com/en/dev/topics/cache/).
99
+
100
+ License
101
+ -------
102
+
103
+ __Rack::Cache__ is Copyright &copy; 2008
104
+ by [Ryan Tomayko](http://tomayko.com/about)
105
+ and is provided under [the MIT license](./license)
106
+
107
+ [config]: ./configuration "Rack::Cache Configuration Language Documentation"
108
+ [storage]: ./storage "Rack::Cache Storage Documentation"
109
+ [things]: http://tomayko.com/writings/things-caches-do
110
+
111
+ [rfc]: http://tools.ietf.org/html/rfc2616
112
+ "RFC 2616 - Hypertext Transfer Protocol -- HTTP/1.1 [ietf.org]"
113
+
114
+ [s13]: http://tools.ietf.org/html/rfc2616#section-13
115
+ "RFC 2616 / Section 13 Caching in HTTP"
116
+
117
+ [rack]: http://rack.rubyforge.org/
118
+ "Rack: a Ruby Webserver Interface"
119
+
120
+ [vcl]: http://tomayko.com/man/vcl
121
+ "VCL(7) -- Varnish Configuration Language Manual Page"
@@ -0,0 +1,34 @@
1
+ <!DOCTYPE html>
2
+ <html lang='en'>
3
+ <head>
4
+ <meta http-equiv='Content-Type' content='text/html;charset=utf-8'>
5
+ <title>Rack::Cache <%= title %></title>
6
+ <link rel='stylesheet' href='rack-cache.css' type='text/css' media='all'>
7
+ <script type='text/javascript' src='http://code.jquery.com/jquery-1.2.3.js'></script>
8
+ <script type='text/javascript' src='http://tomayko.com/js/tomayko.js'></script>
9
+ </head>
10
+ <body>
11
+ <div id='container'>
12
+ <div id='header'>
13
+ <h1><a href="./">rack-cache</a></h1>
14
+ <p>
15
+ <a href="./configuration" title='Configuration Language Documentation'>Config</a> |
16
+ <a href="./storage" title='Cache Storage Documentation'>Storage</a> |
17
+ <a href="http://tomayko.com/writings/things-caches-do" title="Things Caches Do">Things</a> |
18
+ <a href="./faq" title='Frequently Asked Questions'>FAQ</a> |
19
+ <a href="./api/" title='Fucking Sucks.'>RDoc</a>
20
+ </p>
21
+ </div>
22
+ <div id='content'><%= content %></div>
23
+ <div id='footer'>
24
+ <p class='rights'>
25
+ Copyright
26
+ <a href="./license" rel="license">&copy;</a>
27
+ 2003-2008
28
+ by
29
+ <a href='http://tomayko.com/about' rel='me author'>Ryan Tomayko</a>
30
+ </p>
31
+ </div>
32
+ </div>
33
+ </body>
34
+ </html>
@@ -0,0 +1,24 @@
1
+ License (MIT)
2
+ =============
3
+
4
+ __Rack::Cache__ is Copyright &copy; 2008
5
+ by [Ryan Tomayko](http://tomayko.com/about)
6
+
7
+ <pre class='license'>
8
+ Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ of this software and associated documentation files (the "Software"), to
10
+ deal in the Software without restriction, including without limitation the
11
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
12
+ sell copies of the Software, and to permit persons to whom the Software is
13
+ furnished to do so, subject to the following conditions:
14
+
15
+ The above copyright notice and this permission notice shall be included in
16
+ all copies or substantial portions of the Software.
17
+
18
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21
+ THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
22
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
+ </pre>
@@ -0,0 +1,362 @@
1
+ /* rack-cache.css
2
+ *---------------------------------------------------------------------------
3
+ * Copyright (C) 2005-08 Ryan Tomayko <r@tomayko.com>
4
+ */
5
+
6
+
7
+ /* 18px base font size / 25px baseline */
8
+ body {
9
+ font-size:112.5%; /* 18px (probably) */
10
+ line-height:1.3888; /* 25px */
11
+ letter-spacing:-0.02em;
12
+ margin:0 10px;
13
+ font-family: 'lucida sans unicode', 'lucida grande',
14
+ helvetica, 'bitstream vera sans', sans-serif;
15
+ color:#556;
16
+ background-color:#fff;
17
+ }
18
+
19
+ #container {
20
+ max-width:45em;
21
+ margin:0 auto;
22
+ }
23
+
24
+ h1, h2, h3 {
25
+ font-family:georgia, 'bitstream vera sans serif', 'lucida grande',
26
+ helvetica, verdana, sans-serif;
27
+ font-weight:normal;
28
+ letter-spacing:-0.05em;
29
+ color:#000;
30
+ }
31
+ i, em {
32
+ font-style:italic;
33
+ }
34
+ b, strong {
35
+ font-weight:normal;
36
+ color:#000;
37
+ }
38
+ blockquote {
39
+ color:#555;
40
+ }
41
+ blockquote em {
42
+ color:#333;
43
+ font-style:italic;
44
+ }
45
+ blockquote strong {
46
+ color:#333;
47
+ font-weight: normal;
48
+ }
49
+ dt {
50
+ font-weight:bold;
51
+ color:#000;
52
+ }
53
+ tt, pre, code, samp, kbd {
54
+ font-family: consolas, 'lucida console', 'bitstream vera sans mono',
55
+ 'courier new', monospace;
56
+ color: #000;
57
+ }
58
+ pre {
59
+ color:#333;
60
+ background-color:#f9f9f9;
61
+ }
62
+ code {
63
+ color:#007A00;
64
+ }
65
+ pre code {
66
+ color:#333;
67
+ }
68
+ pre.license {
69
+ border:0;
70
+ background:#fff;
71
+ padding:0;
72
+ font-size:1.1em;
73
+ }
74
+ a, a:link {
75
+ color:#023;
76
+ background:#eef;
77
+ }
78
+ a:visited {
79
+ color:#345;
80
+ background:#fff;
81
+ }
82
+ a:hover {
83
+ background:#ccf;
84
+ color:#000;
85
+ text-decoration:none;
86
+ }
87
+
88
+
89
+ /* TYPOGRAPHY */
90
+
91
+ p, ul, ol, dl, pre, blockquote, table, form {
92
+ margin:1em 0;
93
+ }
94
+ dl {
95
+ margin-left:2em;
96
+ }
97
+ hr {
98
+ color:#eee;
99
+ background-color:#ccc;
100
+ border:0;
101
+ height:1px;
102
+ margin:1.5em 0;
103
+ }
104
+ blockquote {
105
+ font-size:0.83333em; /* 15px */
106
+ line-height:1.66666; /* 25px */
107
+ margin:1.2em 3em;
108
+ padding:0;
109
+ }
110
+ tt, pre, code, samp, kbd {
111
+ font-size: 16px;
112
+ line-height:1.1;
113
+ }
114
+ pre {
115
+ margin:1.5em 0;
116
+ padding:6px 4px 4px 6px;
117
+ border:1px solid #eee;
118
+ border-left-width:20px;
119
+ overflow:auto;
120
+ }
121
+ h1 {
122
+ font-size:2.3333em; /* 42px */
123
+ line-height:1.1904; /* 50px */
124
+ margin:0.5952em 0; /* 25px */
125
+ }
126
+ h2 {
127
+ font-size:1.66666667em; /* 30px */
128
+ line-height:1.2; /* 36px */
129
+ margin:1em 0;
130
+ }
131
+ h3 {
132
+ font-size:1.33333333em; /* 22px */
133
+ line-height:1.13636363; /* 25px */
134
+ margin:1em 0;
135
+ }
136
+ h3 code{
137
+ font-size:0.95em;
138
+ color:#000;
139
+ }
140
+ h4 {
141
+ font-size:1em;
142
+ font-weight:bold;
143
+ line-height:1.5;
144
+ margin:1em 0;
145
+ }
146
+ p small {
147
+ font-size:0.8333; /* 15px */
148
+ line-height:1.2;
149
+ }
150
+
151
+ /* Tables
152
+ --------------------------------------------------------------------------- */
153
+
154
+ table {
155
+ width:100%;
156
+ border-style:none;
157
+ border-color:#ddd;
158
+ padding:0;
159
+ }
160
+
161
+ th, td {
162
+ padding: 4px 10px 4px 5px;
163
+ border-style:solid;
164
+ border-color:#fff;
165
+ }
166
+
167
+ th {
168
+ font-weight: bold;
169
+ background: #eef;
170
+ }
171
+
172
+ td {
173
+ background: #f9f9f9;
174
+ }
175
+
176
+ tfoot {
177
+ font-style: italic;
178
+ }
179
+
180
+ caption {
181
+ background: #eee;
182
+ }
183
+
184
+ /* Header / Titling
185
+ --------------------------------------------------------------------------- */
186
+
187
+ #header {
188
+ text-align:left;
189
+ margin:1.5em auto 2em;
190
+ float:left;
191
+ width:100%;
192
+ padding-bottom:1.5em;
193
+ border-bottom:1px solid #777;
194
+ }
195
+ #header h1 {
196
+ font-family: 'lucida sans unicode', 'lucida grande',
197
+ helvetica, 'bitstream vera sans', sans-serif;
198
+ font-size:5em;
199
+ font-weight:bold;
200
+ line-height:1;
201
+ margin:0;
202
+ float:left;
203
+ color:#000;
204
+ letter-spacing:-0.08em;
205
+ }
206
+ #header h1 a, #header h1 a:link, #header h1 a:visited, #header h1 a:hover {
207
+ color:#000;
208
+ text-decoration:none;
209
+ background:transparent;
210
+ }
211
+ #header p {
212
+ margin: 0;
213
+ line-height:1.8;
214
+ color: #777;
215
+ text-transform:capitalize;
216
+ font-variant:small-caps;
217
+ float:right;
218
+ }
219
+ #header a, #header a:link, #header a:visited {
220
+ color:#445;
221
+ background:#fff;
222
+ }
223
+ #header a:hover {
224
+ background:#ccf;
225
+ color:#000;
226
+ text-decoration:none;
227
+ }
228
+ #content {
229
+ clear:both;
230
+ }
231
+
232
+ /* FOOTER */
233
+
234
+ #footer {
235
+ clear:both;
236
+ color:#555;
237
+ font-size:0.88888888em;
238
+ line-height:1.5625;
239
+ border-top:1px solid #ddd;
240
+ padding:19px 0 0 0;
241
+ margin:40px 0 20px 0;
242
+ text-align:center;
243
+ }
244
+ #footer p {
245
+ margin:0;
246
+ }
247
+ #footer form {
248
+ float:right;
249
+ }
250
+ #footer input{
251
+ font-size:10px;
252
+ }
253
+
254
+ /* MISC HELPER STYLES */
255
+
256
+ ul.clean, ol.clean {
257
+ list-style-type: none;
258
+ padding-left: 0;
259
+ }
260
+ .caps {
261
+ font-variant:small-caps;
262
+ }
263
+ .clear {
264
+ clear:both;
265
+ }
266
+ .left{
267
+ float:left;
268
+ }
269
+ .right{
270
+ float:right;
271
+ }
272
+ .center{
273
+ text-align:center;
274
+ }
275
+ .intro {
276
+ font-size:0.833333em; /* 15px */
277
+ line-height:1.666667; /* 25px */
278
+ border:1px solid #ccc;
279
+ padding:0.5em;
280
+ font-style:italic;
281
+ color:#555;
282
+ }
283
+ a.hash,
284
+ a.hash:link,
285
+ a.hash:visited {
286
+ display:block;
287
+ float:right;
288
+ background:#fff;
289
+ font-size:0.8em;
290
+ text-decoration:none;
291
+ line-height:2;
292
+ color:#999;
293
+ }
294
+ a.hash:hover {
295
+ color:MediumOrchid;
296
+ }
297
+
298
+ /* PRINT */
299
+
300
+ @media print {
301
+ html, body, #container {
302
+ margin:0;
303
+ }
304
+ #container {
305
+ width:100%;
306
+ max-width:100%;
307
+ }
308
+ #header {
309
+ margin-top:0;
310
+ }
311
+ #header p {
312
+ display:none;
313
+ }
314
+ #footer {
315
+ display:none;
316
+ }
317
+ a, a:link, a:visited {
318
+ color:#000;
319
+ background:#fff;
320
+ text-decoration:none;
321
+ }
322
+ pre.license {
323
+ font-size:0.95em;
324
+ }
325
+ @page {
326
+ size:8.5in 11in;
327
+ }
328
+ }
329
+
330
+ /* PRETTIFICATION OF SOURCE CODE */
331
+
332
+ .str { color: #181; font-style:italic; }
333
+ .kwd { color: #369; }
334
+ .com { color: #666; }
335
+ .typ { color: #c40; }
336
+ .lit { color: #900; }
337
+ .pun { color: #000; font-weight: bold; }
338
+ .pln { color: #333; }
339
+ .tag { color: #369; font-weight: bold; }
340
+ .atn { color: #939; font-weight: bold }
341
+ .atv { color: #181; }
342
+ .dec { color: #606; }
343
+
344
+ @media print {
345
+ .str { color: #060; }
346
+ .kwd { color: #006; font-weight: bold; }
347
+ .com { color: #600; font-style: italic; }
348
+ .typ { color: #404; font-weight: bold; }
349
+ .lit { color: #044; }
350
+ .pun { color: #440; }
351
+ .pln { color: #000; }
352
+ .tag { color: #006; font-weight: bold; }
353
+ .atn { color: #404; }
354
+ .atv { color: #060; }
355
+ }
356
+
357
+ /* FUCKING IE */
358
+
359
+ * html body{width:40em}
360
+ * html div.index{width:34.5em}
361
+
362
+ /* vim: set ft=css ts=4 sw=4 noexpandtab: */