needle 1.2.0 → 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. data/doc/manual-html/chapter-1.html +138 -78
  2. data/doc/manual-html/chapter-2.html +180 -99
  3. data/doc/manual-html/chapter-3.html +111 -75
  4. data/doc/manual-html/chapter-4.html +80 -48
  5. data/doc/manual-html/chapter-5.html +106 -56
  6. data/doc/manual-html/chapter-6.html +82 -34
  7. data/doc/manual-html/chapter-7.html +74 -38
  8. data/doc/manual-html/chapter-8.html +70 -41
  9. data/doc/manual-html/chapter-9.html +88 -63
  10. data/doc/manual-html/index.html +6 -6
  11. data/doc/manual-html/needle.png +0 -0
  12. data/doc/manual-html/{manual.css → stylesheets/manual.css} +83 -10
  13. data/doc/manual-html/stylesheets/ruby.css +17 -0
  14. data/doc/manual/chapter.erb +20 -0
  15. data/doc/manual/img/Needle.ai +0 -0
  16. data/doc/manual/img/needle.png +0 -0
  17. data/doc/manual/manual.rb +80 -5
  18. data/doc/manual/manual.yml +3 -3
  19. data/doc/manual/page.erb +1 -1
  20. data/doc/manual/parts/01_use_cases.txt +70 -70
  21. data/doc/manual/parts/02_creating.txt +19 -19
  22. data/doc/manual/parts/02_namespaces.txt +29 -29
  23. data/doc/manual/parts/02_services.txt +40 -41
  24. data/doc/manual/parts/03_conventional.txt +20 -20
  25. data/doc/manual/parts/03_locator.txt +44 -44
  26. data/doc/manual/parts/04_overview.txt +1 -1
  27. data/doc/manual/parts/04_setup.txt +32 -32
  28. data/doc/manual/parts/customizing_contexts.txt +14 -14
  29. data/doc/manual/parts/customizing_interceptors.txt +25 -25
  30. data/doc/manual/parts/customizing_namespaces.txt +12 -12
  31. data/doc/manual/parts/interceptors_attaching.txt +29 -30
  32. data/doc/manual/parts/interceptors_custom.txt +16 -16
  33. data/doc/manual/parts/interceptors_ordering.txt +5 -5
  34. data/doc/manual/parts/libraries_creating.txt +18 -18
  35. data/doc/manual/parts/libraries_using.txt +19 -19
  36. data/doc/manual/parts/logging_configuration.txt +13 -13
  37. data/doc/manual/parts/logging_logfactory.txt +21 -22
  38. data/doc/manual/parts/models_models.txt +8 -8
  39. data/doc/manual/parts/models_overview.txt +1 -1
  40. data/doc/manual/parts/models_pipelines.txt +22 -22
  41. data/doc/manual/{manual.css → stylesheets/manual.css} +83 -10
  42. data/doc/manual/stylesheets/ruby.css +17 -0
  43. data/lib/needle/definition-context.rb +3 -2
  44. data/lib/needle/lifecycle/proxy.rb +1 -1
  45. data/lib/needle/version.rb +1 -1
  46. metadata +94 -85
@@ -1,7 +1,7 @@
1
1
  <html>
2
2
  <head>
3
3
  <title>Needle Manual :: Chapter 9: Customizing Needle</title>
4
- <link type="text/css" rel="stylesheet" href="manual.css" />
4
+ <link type="text/css" rel="stylesheet" href="stylesheets/manual.css" />
5
5
  </head>
6
6
 
7
7
  <body>
@@ -14,8 +14,8 @@
14
14
  </div>
15
15
  </td><td valign='middle' align='right'>
16
16
  <div class="info">
17
- Needle Version: <strong>1.2.0</strong><br />
18
- Manual Last Updated: <strong>2004-11-18 15:36 GMT</strong>
17
+ Needle Version: <strong>1.2.1</strong><br />
18
+ Manual Last Updated: <strong>2005-07-27 05:49 UTC</strong>
19
19
  </div>
20
20
  </td></tr>
21
21
  </table>
@@ -208,7 +208,15 @@
208
208
 
209
209
  <div id="content">
210
210
 
211
- <h1>9. Customizing Needle</h1>
211
+ <div class="top"><div class="prevnext">
212
+
213
+ <a href="chapter-8.html">Previous (8. Service Libraries)</a> |
214
+
215
+ <a href="index.html">Up</a>
216
+
217
+ </div></div>
218
+
219
+ <h1>9. Customizing Needle</h1>
212
220
 
213
221
 
214
222
 
@@ -222,27 +230,31 @@
222
230
  <div class="section">
223
231
  <p>By default, when you create a namespace in Needle, the namespace is registered as a service. The type of the service is determined by the <code>:namespace_impl_factory</code> service, which (by default) returns the <code>Needle::Container</code> class.</p>
224
232
 
233
+
225
234
  <p>You can specify your own custom implementation for namespaces by registering your own <code>:namespace_impl_factory</code> service. In fact, each namespace can have its own implementation of subnamespaces&#8212;just register a <code>:namespace_impl_factory</code> in each one that you want to be specialized.</p>
226
235
 
236
+
227
237
  <p>Here&#8217;s a contrived example. Suppose you want each namespace to keep track of the precise time that it was created.</p>
228
238
 
229
239
 
230
- <pre>
231
- class TimeTrackerNamespace &lt; Needle::Container
232
- attr_reader :birth_date
240
+ <div class='figure'>
241
+ <span class='caption'>Custom namespace implementations [ruby]</span>
242
+ <div class='body'><table border='0' cellpadding='0' cellspacing='0'><tr><td class='lineno'>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br /></td><td width='100%'><link rel='stylesheet' type='text/css' href='stylesheets/ruby.css' /><div class='ruby'><pre><span class="keyword">class </span><span class="class">TimeTrackerNamespace</span> <span class="punct">&lt;</span> <span class="constant">Needle</span><span class="punct">::</span><span class="constant">Container</span>
243
+ <span class="ident">attr_reader</span> <span class="symbol">:birth_date</span>
244
+
245
+ <span class="keyword">def </span><span class="method">initialize</span><span class="punct">(</span> <span class="punct">*</span><span class="ident">args</span> <span class="punct">)</span>
246
+ <span class="keyword">super</span>
247
+ <span class="attribute">@birth_date</span> <span class="punct">=</span> <span class="constant">Time</span><span class="punct">.</span><span class="ident">now</span>
248
+ <span class="keyword">end</span>
249
+ <span class="keyword">end</span>
233
250
 
234
- def initialize( *args )
235
- super
236
- @birth_date = Time.now
237
- end
238
- end
251
+ <span class="ident">reg</span> <span class="punct">=</span> <span class="constant">Needle</span><span class="punct">::</span><span class="constant">Registry</span><span class="punct">.</span><span class="ident">new</span>
252
+ <span class="ident">reg</span><span class="punct">.</span><span class="ident">register</span><span class="punct">(</span> <span class="symbol">:namespace_impl_factory</span> <span class="punct">)</span> <span class="punct">{</span> <span class="constant">TimeTrackerNamespace</span> <span class="punct">}</span>
253
+
254
+ <span class="ident">reg</span><span class="punct">.</span><span class="ident">namespace</span> <span class="symbol">:hello</span>
255
+ <span class="ident">p</span> <span class="ident">reg</span><span class="punct">.</span><span class="ident">hello</span><span class="punct">.</span><span class="ident">birth_date</span></pre></div></td></tr></table></div></div>
239
256
 
240
- reg = Needle::Registry.new
241
- reg.register( :namespace_impl_factory ) { TimeTrackerNamespace }
242
257
 
243
- reg.namespace :hello
244
- p reg.hello.birth_date
245
- </pre>
246
258
  <p>In general, you&#8217;ll be better off having your custom implementation extend <code>Needle::Container</code>, although the only <em>real</em> requirement is that your implementation publish the same interface as the default namespace implementation.</p>
247
259
  </div>
248
260
 
@@ -258,43 +270,46 @@
258
270
  <div class="section">
259
271
  <p>When you attach an interceptor to a service, that new interceptor is wrapped in a definition object that includes various metadata about the interceptor, including its implementation, its priority, its name, and so forth. The implementation of this interceptor definition is determined by the value of the <code>:interceptor_impl_factory</code> service, which by default returns <code>Needle::Interceptor</code>.</p>
260
272
 
273
+
261
274
  <p>It is this wrapper object that allows interceptor definitions to be done using method chaining:</p>
262
275
 
263
276
 
264
- <pre>
265
- reg.intercept( :foo ).with { ... }.with_options(...)
266
- </pre>
277
+ <div class='figure'>
278
+ <span class='caption'>Configuring an interceptor [ruby]</span>
279
+ <div class='body'><link rel='stylesheet' type='text/css' href='stylesheets/ruby.css' /><div class='ruby'><pre><span class="ident">reg</span><span class="punct">.</span><span class="ident">intercept</span><span class="punct">(</span> <span class="symbol">:foo</span> <span class="punct">).</span><span class="ident">with</span> <span class="punct">{</span> <span class="punct">...</span> <span class="punct">}.</span><span class="ident">with_options</span><span class="punct">(...)</span></pre></div></div></div>
280
+
281
+
267
282
  <p>If you wish to add custom, domain-specific functionality to the interceptor wrapper, you can register your own implementation of the <code>:interceptor_impl_factory</code>. Consider the following contrived example, where an &#8220;only_if&#8221; clause is given to determine when the interceptor should be invoked.</p>
268
283
 
269
284
 
270
- <pre>
271
- class OnlyIfInterceptor &lt; Needle::Interceptor
272
- def only_if( &#38;block )
273
- @only_if = block
274
- self
275
- end
276
-
277
- def action
278
- action_proc = super
279
- lambda do |chain,ctx|
280
- if @only_if.call( chain, ctx )
281
- action_proc.call( chain, ctx )
282
- else
283
- chain.process_next( ctx )
284
- end
285
- end
286
- end
287
- end
288
-
289
- reg = Needle::Registry.new
290
- reg.register( :interceptor_impl_factory ) { OnlyIfInterceptor }
291
- reg.register( :foo ) { Bar.new }
292
-
293
- reg.intercept( :foo ).
294
- with { |c| c.logging_interceptor }.
295
- only_if { |ch,ctx| something_is_true( ch, ctx ) }.
296
- with_options(...)
297
- </pre>
285
+ <div class='figure'>
286
+ <span class='caption'>Advanced configuration of an interceptor [ruby]</span>
287
+ <div class='body'><table border='0' cellpadding='0' cellspacing='0'><tr><td class='lineno'>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br /></td><td width='100%'><link rel='stylesheet' type='text/css' href='stylesheets/ruby.css' /><div class='ruby'><pre><span class="keyword">class </span><span class="class">OnlyIfInterceptor</span> <span class="punct">&lt;</span> <span class="constant">Needle</span><span class="punct">::</span><span class="constant">Interceptor</span>
288
+ <span class="keyword">def </span><span class="method">only_if</span><span class="punct">(</span> <span class="punct">&amp;</span><span class="ident">block</span> <span class="punct">)</span>
289
+ <span class="attribute">@only_if</span> <span class="punct">=</span> <span class="ident">block</span>
290
+ <span class="constant">self</span>
291
+ <span class="keyword">end</span>
292
+
293
+ <span class="keyword">def </span><span class="method">action</span>
294
+ <span class="ident">action_proc</span> <span class="punct">=</span> <span class="keyword">super</span>
295
+ <span class="ident">lambda</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">chain</span><span class="punct">,</span><span class="ident">ctx</span><span class="punct">|</span>
296
+ <span class="keyword">if</span> <span class="attribute">@only_if</span><span class="punct">.</span><span class="ident">call</span><span class="punct">(</span> <span class="ident">chain</span><span class="punct">,</span> <span class="ident">ctx</span> <span class="punct">)</span>
297
+ <span class="ident">action_proc</span><span class="punct">.</span><span class="ident">call</span><span class="punct">(</span> <span class="ident">chain</span><span class="punct">,</span> <span class="ident">ctx</span> <span class="punct">)</span>
298
+ <span class="keyword">else</span>
299
+ <span class="ident">chain</span><span class="punct">.</span><span class="ident">process_next</span><span class="punct">(</span> <span class="ident">ctx</span> <span class="punct">)</span>
300
+ <span class="keyword">end</span>
301
+ <span class="keyword">end</span>
302
+ <span class="keyword">end</span>
303
+ <span class="keyword">end</span>
304
+
305
+ <span class="ident">reg</span> <span class="punct">=</span> <span class="constant">Needle</span><span class="punct">::</span><span class="constant">Registry</span><span class="punct">.</span><span class="ident">new</span>
306
+ <span class="ident">reg</span><span class="punct">.</span><span class="ident">register</span><span class="punct">(</span> <span class="symbol">:interceptor_impl_factory</span> <span class="punct">)</span> <span class="punct">{</span> <span class="constant">OnlyIfInterceptor</span> <span class="punct">}</span>
307
+ <span class="ident">reg</span><span class="punct">.</span><span class="ident">register</span><span class="punct">(</span> <span class="symbol">:foo</span> <span class="punct">)</span> <span class="punct">{</span> <span class="constant">Bar</span><span class="punct">.</span><span class="ident">new</span> <span class="punct">}</span>
308
+
309
+ <span class="ident">reg</span><span class="punct">.</span><span class="ident">intercept</span><span class="punct">(</span> <span class="symbol">:foo</span> <span class="punct">).</span>
310
+ <span class="ident">with</span> <span class="punct">{</span> <span class="punct">|</span><span class="ident">c</span><span class="punct">|</span> <span class="ident">c</span><span class="punct">.</span><span class="ident">logging_interceptor</span> <span class="punct">}.</span>
311
+ <span class="ident">only_if</span> <span class="punct">{</span> <span class="punct">|</span><span class="ident">ch</span><span class="punct">,</span><span class="ident">ctx</span><span class="punct">|</span> <span class="ident">something_is_true</span><span class="punct">(</span> <span class="ident">ch</span><span class="punct">,</span> <span class="ident">ctx</span> <span class="punct">)</span> <span class="punct">}.</span>
312
+ <span class="ident">with_options</span><span class="punct">(...)</span></pre></div></td></tr></table></div></div>
298
313
  </div>
299
314
 
300
315
 
@@ -309,33 +324,43 @@
309
324
  <div class="section">
310
325
  <p>A <em>definition context</em> is used when registering services using any of the <code>#define</code> interfaces. For example, <code>Container#define</code> yields an instance of a definition context to the given block, and <code>Container#define!</code> uses the block in an <code>instance_eval</code> on a definition context.</p>
311
326
 
327
+
312
328
  <p>The default implementation used for definition contexts is defined by the <code>:definition_context_factory</code> service. By default, this service returns <code>Needle::DefinitionContext</code>, but you can specify your own definition context implementations by overriding this service. In fact, each namespace could have its own definition context implementation, if needed.</p>
313
329
 
330
+
314
331
  <p>Consider the following contrived example, where you want to provide a convenient way to register services of type Hash.</p>
315
332
 
316
333
 
317
- <pre>
318
- class MyDefinitionContext &lt; Needle::DefinitionContext
319
- def register_hash( name, opts={} )
320
- this_container.register( name, opts ) { Hash.new }
321
- end
322
- end
334
+ <div class='figure'>
335
+ <span class='caption'>Custom DefinitionContext example [ruby]</span>
336
+ <div class='body'><table border='0' cellpadding='0' cellspacing='0'><tr><td class='lineno'>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br /></td><td width='100%'><link rel='stylesheet' type='text/css' href='stylesheets/ruby.css' /><div class='ruby'><pre><span class="keyword">class </span><span class="class">MyDefinitionContext</span> <span class="punct">&lt;</span> <span class="constant">Needle</span><span class="punct">::</span><span class="constant">DefinitionContext</span>
337
+ <span class="keyword">def </span><span class="method">register_hash</span><span class="punct">(</span> <span class="ident">name</span><span class="punct">,</span> <span class="ident">opts</span><span class="punct">={}</span> <span class="punct">)</span>
338
+ <span class="ident">this_container</span><span class="punct">.</span><span class="ident">register</span><span class="punct">(</span> <span class="ident">name</span><span class="punct">,</span> <span class="ident">opts</span> <span class="punct">)</span> <span class="punct">{</span> <span class="constant">Hash</span><span class="punct">.</span><span class="ident">new</span> <span class="punct">}</span>
339
+ <span class="keyword">end</span>
340
+ <span class="keyword">end</span>
323
341
 
324
- reg = Needle::Registry.new
325
- reg.register( :definition_context_factory ) { MyDefinitionContext }
342
+ <span class="ident">reg</span> <span class="punct">=</span> <span class="constant">Needle</span><span class="punct">::</span><span class="constant">Registry</span><span class="punct">.</span><span class="ident">new</span>
343
+ <span class="ident">reg</span><span class="punct">.</span><span class="ident">register</span><span class="punct">(</span> <span class="symbol">:definition_context_factory</span> <span class="punct">)</span> <span class="punct">{</span> <span class="constant">MyDefinitionContext</span> <span class="punct">}</span>
326
344
 
327
- reg.define do |b|
328
- b.register_hash( :test1 )
329
- b.register_hash( :test2 )
330
- end
345
+ <span class="ident">reg</span><span class="punct">.</span><span class="ident">define</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">b</span><span class="punct">|</span>
346
+ <span class="ident">b</span><span class="punct">.</span><span class="ident">register_hash</span><span class="punct">(</span> <span class="symbol">:test1</span> <span class="punct">)</span>
347
+ <span class="ident">b</span><span class="punct">.</span><span class="ident">register_hash</span><span class="punct">(</span> <span class="symbol">:test2</span> <span class="punct">)</span>
348
+ <span class="keyword">end</span>
331
349
 
332
- reg.test1[:key] = "value"
333
- reg.test2[:foo] = "bar"
334
- </pre>
350
+ <span class="ident">reg</span><span class="punct">.</span><span class="ident">test1</span><span class="punct">[</span><span class="symbol">:key</span><span class="punct">]</span> <span class="punct">=</span> <span class="punct">&quot;</span><span class="string">value</span><span class="punct">&quot;</span>
351
+ <span class="ident">reg</span><span class="punct">.</span><span class="ident">test2</span><span class="punct">[</span><span class="symbol">:foo</span><span class="punct">]</span> <span class="punct">=</span> <span class="punct">&quot;</span><span class="string">bar</span><span class="punct">&quot;</span></pre></div></td></tr></table></div></div>
335
352
  </div>
336
353
 
337
354
 
338
355
 
356
+ <div class="bottom"><div class="prevnext">
357
+
358
+ <a href="chapter-8.html">Previous (8. Service Libraries)</a> |
359
+
360
+ <a href="index.html">Up</a>
361
+
362
+ </div></div>
363
+
339
364
 
340
365
  </div>
341
366
 
@@ -1,7 +1,7 @@
1
1
  <html>
2
2
  <head>
3
3
  <title>Needle Manual</title>
4
- <link type="text/css" rel="stylesheet" href="manual.css" />
4
+ <link type="text/css" rel="stylesheet" href="stylesheets/manual.css" />
5
5
  </head>
6
6
 
7
7
  <body>
@@ -14,8 +14,8 @@
14
14
  </div>
15
15
  </td><td valign='middle' align='right'>
16
16
  <div class="info">
17
- Needle Version: <strong>1.2.0</strong><br />
18
- Manual Last Updated: <strong>2004-11-18 15:36 GMT</strong>
17
+ Needle Version: <strong>1.2.1</strong><br />
18
+ Manual Last Updated: <strong>2005-07-27 05:49 UTC</strong>
19
19
  </div>
20
20
  </td></tr>
21
21
  </table>
@@ -211,7 +211,7 @@
211
211
  <p class="product-manual">Product Manual</p>
212
212
 
213
213
  <p align="center">
214
- <img src=""
214
+ <img src="needle.png"
215
215
  alt="Needle: to the point -->" />
216
216
  </p>
217
217
 
@@ -234,9 +234,9 @@
234
234
  <table border='0' cellpadding='0' cellspacing='0' align='center'><tr><td>
235
235
  <ul>
236
236
 
237
- <li>Described parameterized services</li>
237
+ <li>Added Needle graphic (thanks to Bruce Williams)</li>
238
238
 
239
- <li>Added multiton service models to list of available models</li>
239
+ <li>Added syntax highlighting to code blocks</li>
240
240
 
241
241
  </ul>
242
242
  </table>
@@ -87,8 +87,8 @@ a:hover {
87
87
  }
88
88
 
89
89
  #navigation ul, #navigation ol {
90
- margin-left: 1.5em;
91
- padding-left: 1.5em;
90
+ margin-left: 1.2em;
91
+ padding-left: 1.2em;
92
92
  }
93
93
 
94
94
  #navigation .license {
@@ -107,12 +107,6 @@ a:hover {
107
107
  text-align: justify;
108
108
  }
109
109
 
110
- #content pre {
111
- background: #FFE;
112
- border: 1px dotted #AAA;
113
- padding: 1em;
114
- }
115
-
116
110
  #content h1 {
117
111
  background: #005;
118
112
  color: #FFF;
@@ -186,7 +180,86 @@ a:hover {
186
180
  text-align: center;
187
181
  }
188
182
 
189
- table.list td {
190
- border-bottom: 1px dotted #005;
183
+ table.list {
184
+ margin: 2em;
185
+ border: 1px solid black;
186
+ background: #FFD;
187
+ padding: 0px;
188
+ border-spacing: 0px;
189
+ }
190
+
191
+ table.list th {
192
+ border-bottom: 1px solid #005;
191
193
  padding-bottom: 5px;
194
+ background: #008;
195
+ color: white;
196
+ padding: 0.5em;
197
+ text-align: left;
198
+ }
199
+
200
+ table.list td {
201
+ padding: 0.2em;
202
+ text-align: left;
203
+ vertical-align: top;
204
+ border-bottom: 1px solid;
205
+ }
206
+
207
+ .prevnext {
208
+ padding: 0.5em 1em 0.5em 1em;
209
+ background: #557;
210
+ color: #FFF;
211
+ font-size: small;
212
+ font-weight: bold;
213
+ border: 1px solid #000;
214
+ }
215
+
216
+ .prevnext a {
217
+ color: #FF0;
218
+ }
219
+
220
+ .top .prevnext {
221
+ margin: 0 0 1em 0;
222
+ text-align: left;
223
+ }
224
+
225
+ .bottom .prevnext {
226
+ margin: 1em 0 0 0;
227
+ text-align: right;
228
+ }
229
+
230
+ .figure {
231
+ border: 1px solid black;
232
+ line-height: normal;
233
+ background: #FFD;
234
+ margin: 2em;
235
+ }
236
+
237
+ .figure .caption {
238
+ background: #008;
239
+ color: white;
240
+ font-weight: bold;
241
+ font-size: small;
242
+ padding: 4px 24px 4px 8px;
243
+ margin-left: -4px;
244
+ border: 1px dotted #77F;
245
+ }
246
+
247
+ .figure .body {
248
+ padding-left: 1em;
249
+ }
250
+
251
+ .figure pre {
252
+ padding: 0px;
253
+ background: transparent;
254
+ border: none;
255
+ font-size: small;
256
+ font-family: mono;
257
+ }
258
+
259
+ .figure .lineno {
260
+ text-align: right;
261
+ color: #B00;
262
+ font-family: mono;
263
+ font-size: small;
264
+ padding-right: 1em;
192
265
  }
@@ -0,0 +1,17 @@
1
+ .ruby .normal {}
2
+ .ruby .comment { color: #005; font-style: italic; }
3
+ .ruby .keyword { color: #A00; font-weight: bold; }
4
+ .ruby .method { color: #077; }
5
+ .ruby .class { color: #074; }
6
+ .ruby .module { color: #050; }
7
+ .ruby .punct { color: #447; font-weight: bold; }
8
+ .ruby .symbol { color: #099; }
9
+ .ruby .string { color: #944; }
10
+ .ruby .char { color: #F07; }
11
+ .ruby .ident { color: #004; }
12
+ .ruby .constant { color: #07F; }
13
+ .ruby .regex { color: #B66; }
14
+ .ruby .number { color: #D55; }
15
+ .ruby .attribute { color: #377; }
16
+ .ruby .global { color: #3B7; }
17
+ .ruby .expr { color: #227; }
@@ -1,3 +1,13 @@
1
+ <div class="top"><div class="prevnext">
2
+ <% if previous_chapter %>
3
+ <a href="chapter-<%= previous_chapter.index %>.html">Previous (<%= previous_chapter.index %>. <%= previous_chapter.title %>)</a> |
4
+ <% end %>
5
+ <a href="index.html">Up</a>
6
+ <% if next_chapter %>
7
+ | <a href="chapter-<%= next_chapter.index %>.html">Next (<%= next_chapter.index %>. <%= next_chapter.title %>)</a>
8
+ <% end %>
9
+ </div></div>
10
+
1
11
  <h1><%= object.index %>. <%= object.title %></h1>
2
12
 
3
13
  <% object.sections.each do |section|
@@ -16,3 +26,13 @@
16
26
  </div>
17
27
 
18
28
  <% end %>
29
+
30
+ <div class="bottom"><div class="prevnext">
31
+ <% if previous_chapter %>
32
+ <a href="chapter-<%= previous_chapter.index %>.html">Previous (<%= previous_chapter.index %>. <%= previous_chapter.title %>)</a> |
33
+ <% end %>
34
+ <a href="index.html">Up</a>
35
+ <% if next_chapter %>
36
+ | <a href="chapter-<%= next_chapter.index %>.html">Next (<%= next_chapter.index %>. <%= next_chapter.title %>)</a>
37
+ <% end %>
38
+ </div></div>
Binary file
Binary file
@@ -11,6 +11,7 @@ require 'erb'
11
11
  require 'fileutils'
12
12
  require 'yaml'
13
13
  require 'redcloth'
14
+ require 'syntax/convertors/html'
14
15
 
15
16
  module Needle
16
17
  module Manual
@@ -100,10 +101,79 @@ module Needle
100
101
  def initialize( index, title, content )
101
102
  @index = index
102
103
  @title = RedCloth.new( title ).to_html.gsub( %r{</?p>}, "" ) if title
103
- @content = RedCloth.new( content || "" )
104
+ @content = FigureContainer.new( content || "" )
104
105
  end
105
106
  end
106
107
 
108
+ class FigureContainer
109
+ def initialize( content )
110
+ @content = content
111
+ @html = nil
112
+ end
113
+
114
+ def to_html
115
+ return @html if @html
116
+ extract_figures
117
+ convert_to_html
118
+ replace_figures
119
+ @html
120
+ end
121
+
122
+ private
123
+
124
+ Figure = Struct.new( :opts, :body )
125
+
126
+ def extract_figures
127
+ @figures = []
128
+ @content.gsub!( /^\{\{\{(.*?)?\n(.*?)\n\}\}\}$/m ) do
129
+ body = $2.strip
130
+ opts = Hash[*$1.strip.split(/,/).map{|p| p.split(/=/)}.flatten]
131
+ @figures << Figure.new( opts, body )
132
+ "====#{@figures.length-1}===="
133
+ end
134
+ end
135
+
136
+ def convert_to_html
137
+ @html = ( @content.length < 1 ? "" :
138
+ RedCloth.new( @content ).to_html )
139
+ end
140
+
141
+ def replace_figures
142
+ @html.gsub!( /<p>====(.*?)====<\/p>/ ) do
143
+ figure = @figures[$1.to_i]
144
+ lang = figure.opts["lang"]
145
+ caption = figure.opts["caption"] || "Figure"
146
+ caption << " [#{lang}]" if lang
147
+
148
+ body = figure.body
149
+
150
+ if lang
151
+ convertor = Syntax::Convertors::HTML.for_syntax( lang )
152
+
153
+ body = "<link rel='stylesheet' type='text/css' " +
154
+ "href='stylesheets/#{lang}.css' />" +
155
+ "<div class='#{lang}'>" +
156
+ convertor.convert( body ) +
157
+ "</div>"
158
+ end
159
+
160
+ if figure.opts["number"] && eval(figure.opts["number"])
161
+ line = 1
162
+ numbers = ""
163
+ body.each_line { numbers << "#{line}<br />"; line += 1 }
164
+ body = "<table border='0' cellpadding='0' cellspacing='0'>" +
165
+ "<tr><td class='lineno'>#{numbers}</td>" +
166
+ "<td width='100%'>#{body}</td></tr></table>"
167
+ end
168
+
169
+ "<div class='figure'>\n" +
170
+ "<span class='caption'>#{caption}</span>\n" +
171
+ "<div class='body'>#{body}</div>" +
172
+ "</div>"
173
+ end
174
+ end
175
+ end
176
+
107
177
  YAML.add_private_type( 'file' ) { |type_id, value| File.read( value ) rescue "" }
108
178
  YAML.add_private_type( 'eval' ) { |type_id, value| eval( value ) }
109
179
 
@@ -200,11 +270,15 @@ if __FILE__ == $0
200
270
  template = File.open( "chapter.erb" ) { |file| ERB.new( file.read ) }
201
271
  template.filename = "chapter.erb"
202
272
 
203
- manual.chapters.each do |object|
273
+ manual.chapters.each_with_index do |object, index|
204
274
  log_action "Processing chapter ##{object.index}..."
275
+
276
+ previous_chapter = ( index < 1 ? nil : manual.chapters[index-1] )
277
+ next_chapter = manual.chapters[index+1]
278
+
205
279
  File.open( File.join( output_path, "chapter-#{object.index}.html" ), "w" ) do |file|
206
- guts = template.result
207
- file << page.result
280
+ guts = template.result( binding )
281
+ file << page.result( binding )
208
282
  end
209
283
  end
210
284
 
@@ -231,10 +305,11 @@ if __FILE__ == $0
231
305
  # end
232
306
 
233
307
  log_action "Copying style sheets..."
234
- FileUtils.cp Dir["*.css"], output_path
308
+ FileUtils.cp_r "stylesheets", output_path
235
309
 
236
310
  log_action "Copying images..."
237
311
  FileUtils.cp Dir["img/*.jpg"], output_path
312
+ FileUtils.cp Dir["img/*.png"], output_path
238
313
 
239
314
  log_action "Done!"
240
315
  end