camping 1.2 → 1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,18 +1,24 @@
1
1
  #!/usr/bin/env ruby
2
+ RAILS_CONNECTION_ADAPTERS = %w[sqlite]
3
+
2
4
  #
3
5
  # Serves all examples, mounted into Webrick.
4
6
  #
7
+ $:.unshift File.expand_path(File.dirname(__FILE__) + "/../lib")
5
8
  require 'stringio'
6
9
  require 'webrick/httpserver'
10
+ require 'camping'
11
+
12
+ # All applications share a single database
13
+ Camping::Models::Base.establish_connection :adapter => 'sqlite3', :database => 'serve.db'
14
+ Camping::Models::Base.logger = Logger.new('camping.log')
7
15
 
8
- dir = Dir.pwd
16
+ # Find the working applications
9
17
  apps =
10
18
  Dir['*'].select do |d|
11
- Dir.chdir(dir)
12
- if File.exists? "#{d}/#{d}.rb"
19
+ if File.directory? "#{d}"
13
20
  begin
14
- Dir.chdir("#{dir}/#{d}")
15
- load "#{d}.rb"
21
+ load "#{d}/#{d}.rb"
16
22
  true
17
23
  rescue Exception => e
18
24
  puts "Camping app `#{d}' will not load: #{e.class} #{e.message}"
@@ -20,37 +26,82 @@ apps =
20
26
  end
21
27
  end
22
28
  apps.map! do |app|
23
- [app, (Object.const_get(Object.constants.grep(/^#{app}$/i)[0]) rescue nil)]
29
+ begin
30
+ klass = Object.const_get(Object.constants.grep(/^#{app}$/i)[0])
31
+ klass.create if klass.respond_to? :create
32
+ [app, klass]
33
+ rescue Exception => e
34
+ puts "Camping app `#{app}' will not load: #{e.class} #{e.message}"
35
+ end
24
36
  end
37
+ apps.compact!
25
38
 
26
39
  s = WEBrick::HTTPServer.new(:BindAddress => '0.0.0.0', :Port => 3301)
27
- apps.each do |app, klass|
28
- s.mount_proc("/#{app}") do |req, resp|
29
- Object.instance_eval do
30
- remove_const :ENV
31
- const_set :ENV, req.meta_vars
40
+
41
+ # Root mount displays applications mounted
42
+ s.mount_proc("/") do |req, resp|
43
+ welcome = "Welcome to the Camping Example Server"
44
+ b = Markaby::Builder.new({}, {})
45
+ b = b.instance_eval do
46
+ html do
47
+ head do
48
+ title welcome
49
+ style <<-END, :type => 'text/css'
50
+ body {
51
+ font-family: verdana, arial, sans-serif;
52
+ padding: 10px 40px;
53
+ margin: 0;
54
+ }
55
+ h1, h2, h3, h4, h5, h6 {
56
+ font-family: utopia, georgia, serif;
57
+ }
58
+ END
59
+ end
60
+ body do
61
+ h1 welcome
62
+ p %{
63
+ Good day. These are the Camping sample applications. The code
64
+ for each of these applications is available in its own folder
65
+ under examples. A link to the application's source code is
66
+ also given next to each one.
67
+ }
68
+ p %{Well, click on the application's name to give a try.}
69
+ ul do
70
+ apps.each do |app, klass|
71
+ li do
72
+ h3(:style => "display: inline") { a app, :href => "/#{app}" }
73
+ small { text " / " ; a "View Source", :href => "/code/#{app}" }
74
+ end
75
+ end
76
+ end
77
+ end
32
78
  end
33
- def resp.<<(data)
34
- raw_header, body = "#{data}".split(/^[\xd\xa]+/on, 2)
79
+ end
80
+ resp.body = b.to_s
81
+ end
35
82
 
36
- begin
37
- header = WEBrick::HTTPUtils::parse_header(raw_header)
38
- if /^(\d+)/ =~ header['status'][0]
39
- self.status = $1.to_i
40
- header.delete('status')
41
- end
42
- header.each{|key, val| self[key] = val.join(", ") }
43
- rescue => ex
44
- raise WEBrick::HTTPStatus::InternalServerError, ex.message
83
+ # Mount which handles each application
84
+ apps.each do |app, klass|
85
+ # Mount for view source
86
+ s.mount_proc("/code/#{app}") do |req, resp|
87
+ resp.header['Content-Type'] = 'text/plain'
88
+ resp.body = File.read("#{app}/#{app}.rb")
89
+ end
90
+
91
+ s.mount_proc("/#{app}") do |req, resp|
92
+ controller = klass.run((req.body and StringIO.new(req.body)), req.meta_vars)
93
+ resp.status = controller.status
94
+ controller.headers.each do |k, v|
95
+ [*v].each do |vi|
96
+ resp[k] = vi
45
97
  end
46
- self.body = body
47
98
  end
48
- Dir.chdir("#{dir}/#{app}")
49
- klass.run((req.body and StringIO.new(req.body)), resp)
50
- Dir.chdir(dir)
99
+ resp.body = controller.body
51
100
  nil
52
101
  end
53
102
  end
103
+
104
+ # Server up
54
105
  trap(:INT) do
55
106
  s.shutdown
56
107
  end
@@ -19,7 +19,7 @@ module Tepee::Models
19
19
  end
20
20
 
21
21
  Tepee::Models.schema do
22
- create_table :pages, :force => true do |t|
22
+ create_table :tepee_pages, :force => true do |t|
23
23
  t.column :title, :string, :limit => 255
24
24
  t.column :body, :text
25
25
  end
@@ -127,11 +127,16 @@ module Tepee::Views
127
127
  end
128
128
  end
129
129
 
130
- db_exists = File.exists?('tepee.db')
131
- Tepee::Models::Base.establish_connection :adapter => 'sqlite3', :database => 'tepee.db'
132
- Tepee::Models::Base.logger = Logger.new('camping.log')
133
- ActiveRecord::Schema.define(&Tepee::Models.schema) unless db_exists
130
+ def Tepee.create
131
+ unless Tepee::Models::Page.table_exists?
132
+ ActiveRecord::Schema.define(&Tepee::Models.schema)
133
+ Tepee::Models::Page.reset_column_information
134
+ end
135
+ end
134
136
 
135
137
  if __FILE__ == $0
136
- Tepee.run
138
+ Tepee::Models::Base.establish_connection :adapter => 'sqlite3', :database => 'tepee.db'
139
+ Tepee::Models::Base.logger = Logger.new('camping.log')
140
+ Tepee.create
141
+ puts Tepee.run
137
142
  end
Binary file
@@ -0,0 +1,480 @@
1
+ CAMPING_EXTRAS_DIR = File.expand_path(File.dirname(__FILE__))
2
+
3
+ module Generators
4
+ class HTMLGenerator
5
+ def generate_html
6
+ @files_and_classes = {
7
+ 'allfiles' => gen_into_index(@files),
8
+ 'allclasses' => gen_into_index(@classes),
9
+ "initial_page" => main_url,
10
+ 'title' => CGI.escapeHTML(@options.title),
11
+ 'charset' => @options.charset
12
+ }
13
+
14
+ # the individual descriptions for files and classes
15
+ gen_into(@files)
16
+ gen_into(@classes)
17
+ gen_main_index
18
+
19
+ # this method is defined in the template file
20
+ write_extra_pages if defined? write_extra_pages
21
+ end
22
+
23
+ def gen_into(list)
24
+ hsh = @files_and_classes.dup
25
+ list.each do |item|
26
+ if item.document_self
27
+ op_file = item.path
28
+ hsh['root'] = item.path.split("/").map { ".." }[1..-1].join("/")
29
+ item.instance_variable_set("@values", hsh)
30
+ File.makedirs(File.dirname(op_file))
31
+ File.open(op_file, "w") { |file| item.write_on(file) }
32
+ end
33
+ end
34
+ end
35
+
36
+ def gen_into_index(list)
37
+ res = []
38
+ list.each do |item|
39
+ hsh = item.value_hash
40
+ hsh['href'] = item.path
41
+ hsh['name'] = item.index_name
42
+ res << hsh
43
+ end
44
+ res
45
+ end
46
+
47
+ def gen_main_index
48
+ template = TemplatePage.new(RDoc::Page::INDEX)
49
+ File.open("index.html", "w") do |f|
50
+ values = @files_and_classes.dup
51
+ if @options.inline_source
52
+ values['inline_source'] = true
53
+ end
54
+ template.write_html_on(f, values)
55
+ end
56
+ camping_gif = File.join(CAMPING_EXTRAS_DIR, 'Camping.gif')
57
+ File.copy(camping_gif, 'Camping.gif')
58
+ end
59
+ end
60
+ end
61
+
62
+
63
+ module RDoc
64
+ module Page
65
+ ######################################################################
66
+ #
67
+ # The following is used for the -1 option
68
+ #
69
+
70
+ FONTS = "verdana,arial,'Bitstream Vera Sans',helvetica,sans-serif"
71
+
72
+ STYLE = %{
73
+ body, th, td {
74
+ font: normal 14px verdana,arial,'Bitstream Vera Sans',helvetica,sans-serif;
75
+ line-height: 160%;
76
+ padding: 0; margin: 0;
77
+ margin-bottom: 30px;
78
+ /* background-color: #402; */
79
+ background-color: #694;
80
+ }
81
+ h1, h2, h3, h4 {
82
+ font-family: Utopia, Georgia, serif;
83
+ font-weight: bold;
84
+ letter-spacing: -0.018em;
85
+ }
86
+ h1 { font-size: 24px; margin: .15em 1em 0 0 }
87
+ h2 { font-size: 24px }
88
+ h3 { font-size: 19px }
89
+ h4 { font-size: 17px; font-weight: normal; }
90
+ h4.ruled { border-bottom: solid 1px #CC9; }
91
+ h2.ruled { padding-top: 35px; border-top: solid 1px #AA5; }
92
+
93
+ /* Link styles */
94
+ :link, :visited {
95
+ color: #00b;
96
+ }
97
+ :link:hover, :visited:hover {
98
+ background-color: #eee;
99
+ color: #B22;
100
+ }
101
+ #fullpage {
102
+ width: 720px;
103
+ margin: 0 auto;
104
+ }
105
+ .page_shade, .page {
106
+ padding: 0px 5px 5px 0px;
107
+ background-color: #fcfcf9;
108
+ border: solid 1px #983;
109
+ }
110
+ .page {
111
+ margin-left: -5px;
112
+ margin-top: -5px;
113
+ padding: 20px 35px;
114
+ }
115
+ .page .header {
116
+ float: right;
117
+ color: #777;
118
+ font-size: 10px;
119
+ }
120
+ .page h1, .page h2, .page h3 {
121
+ clear: both;
122
+ text-align: center;
123
+ }
124
+ #pager {
125
+ padding: 10px 4px;
126
+ color: white;
127
+ font-size: 11px;
128
+ }
129
+ #pager :link, #pager :visited {
130
+ color: #bfb;
131
+ padding: 0px 5px;
132
+ }
133
+ #pager :link:hover, #pager :visited:hover {
134
+ background-color: #262;
135
+ color: white;
136
+ }
137
+ #logo { float: left; }
138
+ #menu { background-color: #dfa; padding: 4px 12px; margin: 0; }
139
+ #menu h3 { padding: 0; margin: 0; }
140
+ #menu #links { float: right; }
141
+ .dyn-source { background-color: #f3f3e5; border: solid 1px #99C; padding: 4px 8px; margin: 0; display: none; }
142
+ .dyn-source pre { font-size: 8pt; }
143
+ .source-link { text-align: right; font-size: 8pt; }
144
+ .ruby-comment { color: green; font-style: italic }
145
+ .ruby-constant { color: #4433aa; font-weight: bold; }
146
+ .ruby-identifier { color: #222222; }
147
+ .ruby-ivar { color: #2233dd; }
148
+ .ruby-keyword { color: #3333FF; font-weight: bold }
149
+ .ruby-node { color: #777777; }
150
+ .ruby-operator { color: #111111; }
151
+ .ruby-regexp { color: #662222; }
152
+ .ruby-value { color: #662222; font-style: italic }
153
+ .kw { color: #3333FF; font-weight: bold }
154
+ .cmt { color: green; font-style: italic }
155
+ .str { color: #662222; font-style: italic }
156
+ .re { color: #662222; }
157
+ }
158
+
159
+ CONTENTS_XML = %{
160
+ IF:description
161
+ %description%
162
+ ENDIF:description
163
+
164
+ IF:requires
165
+ <h4>Requires:</h4>
166
+ <ul>
167
+ START:requires
168
+ IF:aref
169
+ <li><a href="%aref%">%name%</a></li>
170
+ ENDIF:aref
171
+ IFNOT:aref
172
+ <li>%name%</li>
173
+ ENDIF:aref
174
+ END:requires
175
+ </ul>
176
+ ENDIF:requires
177
+
178
+ IF:attributes
179
+ <h4>Attributes</h4>
180
+ <table>
181
+ START:attributes
182
+ <tr><td>%name%</td><td>%rw%</td><td>%a_desc%</td></tr>
183
+ END:attributes
184
+ </table>
185
+ ENDIF:attributes
186
+
187
+ IF:includes
188
+ <h4>Includes</h4>
189
+ <ul>
190
+ START:includes
191
+ IF:aref
192
+ <li><a href="%aref%">%name%</a></li>
193
+ ENDIF:aref
194
+ IFNOT:aref
195
+ <li>%name%</li>
196
+ ENDIF:aref
197
+ END:includes
198
+ </ul>
199
+ ENDIF:includes
200
+
201
+ START:sections
202
+ IF:method_list
203
+ <h2 class="ruled">Methods</h2>
204
+ START:method_list
205
+ IF:methods
206
+ START:methods
207
+ <h4 class="ruled">%type% %category% method:
208
+ IF:callseq
209
+ <strong><a name="%aref%">%callseq%</a></strong>
210
+ ENDIF:callseq
211
+ IFNOT:callseq
212
+ <strong><a name="%aref%">%name%%params%</a></strong></h4>
213
+ ENDIF:callseq
214
+
215
+ IF:m_desc
216
+ %m_desc%
217
+ ENDIF:m_desc
218
+
219
+ IF:sourcecode
220
+ <div class="sourcecode">
221
+ <p class="source-link">[ <a href="javascript:toggleSource('%aref%_source')" id="l_%aref%_source">show source</a> ]</p>
222
+ <div id="%aref%_source" class="dyn-source">
223
+ <pre>
224
+ %sourcecode%
225
+ </pre>
226
+ </div>
227
+ </div>
228
+ ENDIF:sourcecode
229
+ END:methods
230
+ ENDIF:methods
231
+ END:method_list
232
+ ENDIF:method_list
233
+ END:sections
234
+ }
235
+
236
+ ############################################################################
237
+
238
+
239
+ BODY = %{
240
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
241
+ <html>
242
+ <head>
243
+ <title>%title%</title>
244
+ <meta http-equiv="Content-Type" content="text/html; charset=%charset%" />
245
+ <link rel="stylesheet" href="%style_url%" type="text/css" media="screen" />
246
+ <script language="JavaScript" type="text/javascript">
247
+ // <![CDATA[
248
+
249
+ function toggleSource( id )
250
+ {
251
+ var elem
252
+ var link
253
+
254
+ if( document.getElementById )
255
+ {
256
+ elem = document.getElementById( id )
257
+ link = document.getElementById( "l_" + id )
258
+ }
259
+ else if ( document.all )
260
+ {
261
+ elem = eval( "document.all." + id )
262
+ link = eval( "document.all.l_" + id )
263
+ }
264
+ else
265
+ return false;
266
+
267
+ if( elem.style.display == "block" )
268
+ {
269
+ elem.style.display = "none"
270
+ link.innerHTML = "show source"
271
+ }
272
+ else
273
+ {
274
+ elem.style.display = "block"
275
+ link.innerHTML = "hide source"
276
+ }
277
+ }
278
+
279
+ function openCode( url )
280
+ {
281
+ window.open( url, "SOURCE_CODE", "width=400,height=400,scrollbars=yes" )
282
+ }
283
+ // ]]>
284
+ </script>
285
+ </head>
286
+ <body>
287
+ <div id="menu">
288
+ <div id="links">
289
+ <a href="http://redhanded.hobix.com/bits/campingAMicroframework.html">backstory</a> |
290
+ <a href="http://code.whytheluckystiff.net/camping/">wiki</a> |
291
+ <a href="http://code.whytheluckystiff.net/camping/newticket">bugs</a> |
292
+ <a href="http://code.whytheluckystiff.net/svn/camping/">svn</a>
293
+ </div>
294
+ <h3 class="title">%title%</h3>
295
+ </div>
296
+ <div id="fullpage">
297
+ <div id="logo"><img src="%root%/Camping.gif" /></div>
298
+ <div id="pager">
299
+ <strong>Files:</strong>
300
+ START:allfiles
301
+ <a href="%root%/%href%" value="%title%">%name%</a>
302
+ END:allfiles
303
+ IF:allclasses
304
+ |
305
+ <strong>classes:</strong>
306
+ START:allclasses
307
+ <a href="%root%/%href%" title="%title%">%name%</a>
308
+ END:allclasses
309
+ ENDIF:allclasses
310
+ </ul>
311
+ </div>
312
+
313
+ !INCLUDE!
314
+
315
+ </div>
316
+ </body>
317
+ </html>
318
+ }
319
+
320
+ ###############################################################################
321
+
322
+ FILE_PAGE = <<_FILE_PAGE_
323
+ <div id="%full_path%" class="page_shade">
324
+ <div class="page">
325
+ <div class="header">
326
+ <div class="path">%full_path% / %dtm_modified%</div>
327
+ </div>
328
+ #{CONTENTS_XML}
329
+ </div>
330
+ </div>
331
+ _FILE_PAGE_
332
+
333
+ ###################################################################
334
+
335
+ CLASS_PAGE = %{
336
+ <div id="%full_name%" class="page_shade">
337
+ <div class="page">
338
+ IF:parent
339
+ <h3>%classmod% %full_name% &lt; HREF:par_url:parent:</h3>
340
+ ENDIF:parent
341
+ IFNOT:parent
342
+ <h3>%classmod% %full_name%</h3>
343
+ ENDIF:parent
344
+
345
+ IF:infiles
346
+ (in files
347
+ START:infiles
348
+ HREF:full_path_url:full_path:
349
+ END:infiles
350
+ )
351
+ ENDIF:infiles
352
+ } + CONTENTS_XML + %{
353
+ </div>
354
+ </div>
355
+ }
356
+
357
+ ###################################################################
358
+
359
+ METHOD_LIST = %{
360
+ IF:includes
361
+ <div class="tablesubsubtitle">Included modules</div><br>
362
+ <div class="name-list">
363
+ START:includes
364
+ <span class="method-name">HREF:aref:name:</span>
365
+ END:includes
366
+ </div>
367
+ ENDIF:includes
368
+
369
+ IF:method_list
370
+ START:method_list
371
+ IF:methods
372
+ <table cellpadding=5 width="100%">
373
+ <tr><td class="tablesubtitle">%type% %category% methods</td></tr>
374
+ </table>
375
+ START:methods
376
+ <table width="100%" cellspacing = 0 cellpadding=5 border=0>
377
+ <tr><td class="methodtitle">
378
+ <a name="%aref%">
379
+ IF:callseq
380
+ <b>%callseq%</b>
381
+ ENDIF:callseq
382
+ IFNOT:callseq
383
+ <b>%name%</b>%params%
384
+ ENDIF:callseq
385
+ IF:codeurl
386
+ <a href="%codeurl%" target="source" class="srclink">src</a>
387
+ ENDIF:codeurl
388
+ </a></td></tr>
389
+ </table>
390
+ IF:m_desc
391
+ <div class="description">
392
+ %m_desc%
393
+ </div>
394
+ ENDIF:m_desc
395
+ IF:aka
396
+ <div class="aka">
397
+ This method is also aliased as
398
+ START:aka
399
+ <a href="%aref%">%name%</a>
400
+ END:aka
401
+ </div>
402
+ ENDIF:aka
403
+ IF:sourcecode
404
+ <div class="sourcecode">
405
+ <p class="source-link">[ <a href="javascript:toggleSource('%aref%_source')" id="l_%aref%_source">show source</a> ]</p>
406
+ <div id="%aref%_source" class="dyn-source">
407
+ <pre>
408
+ %sourcecode%
409
+ </pre>
410
+ </div>
411
+ </div>
412
+ ENDIF:sourcecode
413
+ END:methods
414
+ ENDIF:methods
415
+ END:method_list
416
+ ENDIF:method_list
417
+ }
418
+
419
+
420
+ ########################## Index ################################
421
+
422
+ FR_INDEX_BODY = %{
423
+ !INCLUDE!
424
+ }
425
+
426
+ FILE_INDEX = %{
427
+ <html>
428
+ <head>
429
+ <meta http-equiv="Content-Type" content="text/html; charset=%charset%">
430
+ <style>
431
+ <!--
432
+ body {
433
+ background-color: #ddddff;
434
+ font-family: #{FONTS};
435
+ font-size: 11px;
436
+ font-style: normal;
437
+ line-height: 14px;
438
+ color: #000040;
439
+ }
440
+ div.banner {
441
+ background: #0000aa;
442
+ color: white;
443
+ padding: 1;
444
+ margin: 0;
445
+ font-size: 90%;
446
+ font-weight: bold;
447
+ line-height: 1.1;
448
+ text-align: center;
449
+ width: 100%;
450
+ }
451
+
452
+ -->
453
+ </style>
454
+ <base target="docwin">
455
+ </head>
456
+ <body>
457
+ <div class="banner">%list_title%</div>
458
+ START:entries
459
+ <a href="%href%">%name%</a><br>
460
+ END:entries
461
+ </body></html>
462
+ }
463
+
464
+ CLASS_INDEX = FILE_INDEX
465
+ METHOD_INDEX = FILE_INDEX
466
+
467
+ INDEX = %{
468
+ <HTML>
469
+ <HEAD>
470
+ <META HTTP-EQUIV="refresh" content="0;URL=%initial_page%">
471
+ <TITLE>%title%</TITLE>
472
+ </HEAD>
473
+ <BODY>
474
+ Click <a href="%initial_page%">here</a> to open the Camping docs.
475
+ </BODY>
476
+ </HTML>
477
+ }
478
+
479
+ end
480
+ end