camping 1.2 → 1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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