BuildMaster 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data/README +26 -0
  2. data/lib/buildmaster.rb +2 -1
  3. data/lib/buildmaster/build_number_file.rb +27 -0
  4. data/lib/buildmaster/buildnumber +1 -0
  5. data/lib/buildmaster/file_processor.rb +114 -25
  6. data/lib/buildmaster/java_manifest.rb +4 -0
  7. data/lib/buildmaster/{site.rb → site/site.rb} +11 -46
  8. data/lib/buildmaster/site/template/buildmaster.css +340 -0
  9. data/lib/buildmaster/site/template/buildmaster_template.xml +130 -0
  10. data/lib/buildmaster/site/template_builder.rb +276 -0
  11. data/lib/buildmaster/site_server.rb +33 -0
  12. data/lib/buildmaster/site_spec.rb +74 -22
  13. data/lib/buildmaster/site_tester.rb +14 -2
  14. data/lib/buildmaster/source_content.rb +11 -0
  15. data/lib/buildmaster/source_file_handler.rb +7 -2
  16. data/lib/buildmaster/svn_driver.rb +23 -11
  17. data/lib/buildmaster/template_exception.rb +8 -0
  18. data/lib/buildmaster/template_runner.rb +19 -86
  19. data/lib/buildmaster/templatelets.rb +23 -0
  20. data/lib/buildmaster/templatelets/attribute.rb +16 -0
  21. data/lib/buildmaster/templatelets/each.rb +43 -0
  22. data/lib/buildmaster/templatelets/href.rb +39 -0
  23. data/lib/buildmaster/templatelets/include.rb +30 -0
  24. data/lib/buildmaster/templatelets/link.rb +41 -0
  25. data/lib/buildmaster/templatelets/text.rb +14 -0
  26. data/lib/buildmaster/templatelets/when.rb +24 -0
  27. data/lib/buildmaster/tree_to_object.rb +76 -0
  28. data/lib/buildmaster/xtemplate.rb +10 -11
  29. data/test/buildmaster/manifest.mf +1 -1
  30. data/test/buildmaster/{content → site/content}/index.html +0 -0
  31. data/test/buildmaster/site/content/markdown.markdown +0 -0
  32. data/test/buildmaster/site/content/textile.textile +0 -0
  33. data/test/buildmaster/{tc_site.rb → site/tc_site.rb} +1 -1
  34. data/test/buildmaster/site/tc_template_builder.rb +128 -0
  35. data/test/buildmaster/tc_build_number_file.rb +31 -0
  36. data/test/buildmaster/tc_file_processor.rb +81 -14
  37. data/test/buildmaster/tc_site_spec.rb +26 -42
  38. data/test/buildmaster/tc_source_file_handler.rb +55 -0
  39. data/test/buildmaster/tc_template_runner.rb +42 -1
  40. data/test/buildmaster/tc_tree_to_object.rb +120 -0
  41. data/test/buildmaster/tc_xtemplate.rb +13 -233
  42. data/test/buildmaster/templatelets/common_templatelet_test.rb +27 -0
  43. data/test/buildmaster/templatelets/tc_attribute.rb +57 -0
  44. data/test/buildmaster/templatelets/tc_each.rb +69 -0
  45. data/test/buildmaster/templatelets/tc_href.rb +48 -0
  46. data/test/buildmaster/templatelets/tc_include.rb +34 -0
  47. data/test/buildmaster/templatelets/tc_link.rb +70 -0
  48. data/test/buildmaster/templatelets/tc_text.rb +36 -0
  49. data/test/buildmaster/templatelets/tc_when.rb +59 -0
  50. data/test/buildmaster/ts_site.rb +4 -0
  51. data/test/buildmaster/ts_templatelets.rb +10 -0
  52. data/test/tmp/output/index.html +8 -0
  53. data/test/tmp/output/markdown.html +8 -0
  54. data/test/tmp/output/textile.html +8 -0
  55. data/test/ts_buildmaster.rb +15 -3
  56. metadata +102 -53
data/README CHANGED
@@ -23,3 +23,29 @@ and decrorating the content pages with a skin.
23
23
  The supported content sources are <a href="http://www.w3.org/TR/xhtml11/">XHTML</a> and <a href="http://hobix.com/textile/">Textile</a>.
24
24
 
25
25
 
26
+ == Task List
27
+
28
+ * Use RDoc engine (rdoc/template, TemplatePage) to generate template (page
29
+ 255)
30
+ * Use RDoc format for content
31
+
32
+ require 'rdoc/template'
33
+ HTML = %{Hello, %name%.
34
+ <p>
35
+ The reasons you gave were:
36
+ <ul>
37
+ START:reasons
38
+ <li>%reason_name% (%rank%)
39
+ END:reasons
40
+ </ul>
41
+ }
42
+ data = {
43
+ 'name' => 'Dave Thomas',
44
+ 'reasons' => [
45
+ { 'reason_name' => 'flexible', 'rank' => '87' },
46
+ { 'reason_name' => 'transparent', 'rank' => '76' },
47
+ { 'reason_name' => 'fun', 'rank' => '94' },
48
+ ]
49
+ }
50
+ t = TemplatePage.new(HTML)
51
+ t.write_html_on(STDOUT, data)
data/lib/buildmaster.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  $:.unshift(File.dirname(__FILE__))
2
2
 
3
+ require 'buildmaster/build_number_file'
3
4
  require 'buildmaster/java_manifest'
4
5
  require 'buildmaster/shell_command'
5
6
  require 'buildmaster/release_control'
@@ -7,5 +8,5 @@ require 'buildmaster/ant_driver'
7
8
  require 'buildmaster/cvs_driver'
8
9
  require 'buildmaster/svn_driver'
9
10
  require 'buildmaster/site_spec'
10
- require 'buildmaster/site'
11
+ require 'buildmaster/site/site'
11
12
  require 'buildmaster/xtemplate'
@@ -0,0 +1,27 @@
1
+
2
+ module BuildMaster
3
+ class BuildNumberFile
4
+ attr_reader :number
5
+
6
+ def initialize(path)
7
+ @path = path
8
+ @number = load_content().chomp!.to_i
9
+ end
10
+
11
+ def increase_build
12
+ @number = @number + 1
13
+ save_content
14
+ end
15
+
16
+ private
17
+ def load_content()
18
+ content = nil
19
+ File.open(@path, 'r') {|file| content = file.gets}
20
+ return content
21
+ end
22
+
23
+ def save_content
24
+ File.open(@path, 'w') {|file| file.puts @number}
25
+ end
26
+ end
27
+ end
@@ -0,0 +1 @@
1
+ 9
@@ -1,26 +1,118 @@
1
1
  $:.unshift File.dirname(__FILE__)
2
2
 
3
+ require 'site_spec'
4
+ require 'source_content'
5
+ require 'pathname'
6
+
3
7
  module BuildMaster
4
8
 
5
9
  class FileProcessor
6
- def initialize(template, content_path, evaluator)
10
+ #todo match only beginning of the file
11
+ @@TEXTILE_REGX = /---(-)*\n(.*)\n(-)*---\n/
12
+
13
+ def FileProcessor::join(from, path)
14
+ result = from
15
+ path.each_filename do |name|
16
+ result = File.join(result, name)
17
+ end
18
+ return result
19
+ end
20
+
21
+ attr_reader :path_to_content_file, :path_to_target_file
22
+
23
+ def initialize(template, path_to_content_file, sitespec)
7
24
  @template = template
8
- @content_path = content_path
9
- @evaluator = evaluator
25
+ @path_to_content_file = path_to_content_file
26
+ @sitespec = sitespec
27
+ extension = File.extname(path_to_content_file)
28
+ if (extension == '.html')
29
+ @convert_method = 'process_html'
30
+ elsif (extension == '.textile')
31
+ @convert_method = 'process_textile'
32
+ elsif (extension == '.markdown')
33
+ @convert_method = 'process_markdown'
34
+ end
35
+ if @convert_method
36
+ basename = File.basename(path_to_content_file, extension).to_s
37
+ @path = sitespec.relative_to_root(path_to_content_file).parent.join("#{basename}.html")
38
+ @path_to_target_file = FileProcessor.join(sitespec.output_dir, @path)
39
+ else
40
+ @path_to_target_file = FileProcessor.join(sitespec.output_dir, sitespec.relative_to_root(path_to_content_file))
41
+ end
42
+ end
43
+
44
+ def FileProcessor::for_request_path(request_path, site_spec)
45
+ template = site_spec.load_template
46
+ relative_to_root = Pathname.new("#{request_path}")
47
+ dir = relative_to_root.parent
48
+ extension = relative_to_root.extname.to_s
49
+ result = nil
50
+ path_to_content = nil
51
+ if (extension == '.html')
52
+ basename = relative_to_root.basename(extension).to_s
53
+ source_directory = join(site_spec.content_dir, dir)
54
+ ['textile', 'markdown', 'html'].find do |extension_candidate|
55
+ filename = "#{basename}.#{extension_candidate}"
56
+ candidate = File.join(source_directory, filename)
57
+ if (FileTest.file? candidate)
58
+ path_to_content = candidate
59
+ true
60
+ else
61
+ false
62
+ end
63
+ end
64
+ end
65
+ if (not path_to_content)
66
+ path_to_content = join(site_spec.content_dir, relative_to_root)
67
+ end
68
+ return FileProcessor.new(template, path_to_content, site_spec)
69
+ end
70
+
71
+ def is_html?
72
+ return File.extname(path_to_target_file) == '.html'
73
+ end
74
+
75
+ def write_to_target
76
+ document = generate_document
77
+ if (document)
78
+ File.open(path_to_target_file, 'w') do |file|
79
+ document.write(file, 0, false, true)
80
+ end
81
+ else
82
+ FileUtils.cp path_to_content_file, path_to_target_file
83
+ end
84
+ end
85
+
86
+ def generate_document
87
+ send(@convert_method, load_content()) if (@convert_method)
88
+ end
89
+
90
+
91
+ def load_content
92
+ return IO.read(path_to_content_file)
93
+ end
94
+
95
+ def process_textile(textile_content)
96
+ require 'redcloth'
97
+ return process_content_with_title(textile_content) {|content| RedCloth.new(content).to_html}
98
+ end
99
+
100
+ def process_markdown(markdown_content)
101
+ require 'bluecloth'
102
+ return process_content_with_title(markdown_content) {|content| BlueCloth.new(content).to_html}
10
103
  end
11
104
 
12
- def process_textile()
13
- textile_content = IO.read(@content_path)
14
- match_result = TEXTILE_REGX.match(textile_content)
105
+ def process_content_with_title(full_content)
106
+ match_result = @@TEXTILE_REGX.match(full_content)
15
107
  title = ''
16
- if match_result != nil
17
- title = match_result[2]
18
- textile_content = match_result.post_match
19
- end
20
- html_body = RedCloth.new(textile_content).to_html
21
- html_content = <<HTML
22
- <!DOCTYPE html
23
- PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
108
+ body_content = full_content
109
+ if match_result != nil
110
+ title = match_result[2]
111
+ body_content = match_result.post_match
112
+ end
113
+ html_body = yield body_content
114
+ html_content = <<HTML
115
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
24
116
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
25
117
  <html xmlns="http://www.w3.org/1999/xhtml">
26
118
  <head>
@@ -31,18 +123,15 @@ class FileProcessor
31
123
  </body>
32
124
  </html>
33
125
  HTML
34
- return process_html_content(html_content)
35
- end
36
-
37
- def process_html()
38
- return process_html_content(File.open(@content_path))
39
- end
126
+ return process_html(html_content)
127
+ end
128
+
129
+ def process_html(html_content)
130
+ source = SourceContent.new(@path, REXML::Document.new(html_content))
131
+ document_with_skin = @template.process(source)
132
+ return document_with_skin
133
+ end
40
134
 
41
- def process_html_content(source)
42
- document_with_skin = @template.process(source) {|message| @evaluator.evaluate(message, @content_path)}
43
- return document_with_skin
44
- end
45
-
46
135
  end
47
136
 
48
137
  end
@@ -4,6 +4,10 @@ class JavaManifest
4
4
  @manifest_file = manifest_file
5
5
  end
6
6
 
7
+ def JavaManifest::from_file(manifest_file)
8
+ return JavaManifest.new(manifest_file)
9
+ end
10
+
7
11
  def version
8
12
  number = nil
9
13
  build = nil
@@ -1,15 +1,10 @@
1
- $:.unshift File.dirname(__FILE__)
1
+ $:.unshift File.join(File.dirname(__FILE__), '..')
2
2
 
3
3
  require 'fileutils'
4
- require 'redcloth'
5
- require 'source_file_handler'
6
4
  require 'file_processor'
7
5
  require 'site_spec'
8
6
 
9
7
  module BuildMaster
10
- #todo match only beginning of the file
11
- TEXTILE_REGX = /---(-)*\n(.*)\n(-)*---/
12
-
13
8
  class NullLogger
14
9
  def << message
15
10
  puts "IGNORED: #{message}"
@@ -38,23 +33,10 @@ TEXTILE_REGX = /---(-)*\n(.*)\n(-)*---/
38
33
  puts "Generated file count: #{@count}"
39
34
  end
40
35
 
41
- def server(port_number=2000, log_file=$stdout, level=WEBrick::Log::INFO, access_log=nil)
42
- require 'webrick'
43
- mime_types = WEBrick::HTTPUtils::DefaultMimeTypes.update(
44
- {"textile" => "text/plain"}
45
- )
46
- @server = WEBrick::HTTPServer.new(
47
- :Port => port_number,
48
- :Logger => WEBrick::Log.new(log_file, level),
49
- :MimeTypes => mime_types,
50
- :AccessLog => access_log
51
- )
52
- @server.mount('/', SourceFileHandler, @spec)
53
- @server.mount('/source', WEBrick::HTTPServlet::FileHandler, @spec.content_dir, true)
54
- ['INT', 'TERM'].each { |signal|
55
- trap(signal){ @server.shutdown}
56
- }
57
- @server.start
36
+ def server(*args)
37
+ require 'site_server'
38
+ @server = SiteServer.new(*args)
39
+ @server.start(@spec)
58
40
  end
59
41
 
60
42
  def test(port_number=2000)
@@ -71,6 +53,7 @@ require 'webrick'
71
53
  require 'buildmaster/site_tester'
72
54
  Thread.new() {server(port_number, NullLogger.new, 0, NullLogger.new)}
73
55
  begin
56
+ sleep(2)
74
57
  yield port_number
75
58
  ensure
76
59
  @server.stop
@@ -99,30 +82,12 @@ require 'buildmaster/site_tester'
99
82
  end
100
83
  end
101
84
 
102
- def process_file(content_path, out_dir, content_dir, item)
103
- print ">> #{content_path}"
104
- extension = File.extname(content_path)
85
+ def process_file(path_to_content, out_dir, content_dir, item)
86
+ print ">> #{path_to_content}\n"
87
+ extension = File.extname(path_to_content)
105
88
  isIndex = @current_file_name =~ /^index/
106
- file_processor = FileProcessor.new(@template, content_path, @spec)
107
- if (extension.casecmp('.textile') == 0)
108
- base_name = File.basename(item, extension)
109
- output_file = File.join(out_dir, base_name + '.html')
110
- write(output_file, file_processor.process_textile())
111
- elsif (extension.casecmp('.html') == 0)
112
- output_file = File.join(out_dir, item)
113
- write(output_file, file_processor.process_html())
114
- else
115
- output_file = File.join(out_dir, item)
116
- puts " ==> #{output_file}"
117
- FileUtils.cp content_path, output_file
118
- end
119
- end
120
-
121
- def write(target_file, xhtml)
122
- puts " ==> #{target_file}"
123
- File.open(target_file, "w") do |file|
124
- xhtml.write(file, 0, false, true)
125
- end
89
+ file_processor = FileProcessor.new(@template, path_to_content, @spec)
90
+ file_processor.write_to_target
126
91
  end
127
92
 
128
93
  end
@@ -0,0 +1,340 @@
1
+ body {
2
+ padding: 0px;
3
+ margin: 0px;
4
+ border: 0px;
5
+ font-family: helvetica, arial, sans-serif;
6
+ background-color: white;
7
+ color: black;
8
+ }
9
+
10
+ h1, h2, h3, h4, h5, h6 {
11
+ margin: 0px;
12
+ border: 0px;
13
+ padding: 0px;
14
+ font-weight: normal;
15
+ }
16
+
17
+ a:link { color: #00a; }
18
+ a:active { color: red; }
19
+ a:hover { color: darkred; }
20
+ a:visited { color: black; }
21
+
22
+ img {
23
+ border: 0px;
24
+ padding: 0px;
25
+ margin: 0px;
26
+ }
27
+
28
+ p {
29
+ border: 0px;
30
+ padding: 0px;
31
+ margin: 0px;
32
+ margin-bottom: 10px;
33
+ }
34
+
35
+ blockquote {
36
+ margin-bottom: 10px;
37
+ }
38
+
39
+ td {
40
+ padding: 2px;
41
+ }
42
+
43
+ th {
44
+ font-weight: bold;
45
+ white-space: nowrap;
46
+ padding: 2px;
47
+ }
48
+
49
+ th.Row {
50
+ text-align: left;
51
+ vertical-align: top;
52
+ }
53
+
54
+ ul, ol {
55
+ border: 0px;
56
+ padding: 0px;
57
+ margin-top: 0px;
58
+ margin-bottom: 12px;
59
+ margin-left: 20px;
60
+ }
61
+
62
+ div.header {
63
+ top: 0px;
64
+ left: 0px;
65
+ right: 0px;
66
+ width: 100%;
67
+ height: 86px;
68
+ margin: 0px;
69
+ border: 0px;
70
+ background-color: #e0e0f0;
71
+ border-bottom: 1px solid #aaf;
72
+ padding-left,padding-right,padding-top: 0px;
73
+ padding-bottom: 4px;
74
+ }
75
+
76
+ h1.header {
77
+ padding:0;
78
+ margin:0;
79
+ }
80
+
81
+ a.header { border: 0px; text-decoration: none;}
82
+ a.header:visited { color: #00a; }
83
+ a.header:hover { color: red; }
84
+ a.header:active { color: red; }
85
+
86
+ div.left {
87
+ float:left;
88
+ width:180px;
89
+ background-color: white;
90
+ padding: 8px;
91
+ font-size: small;
92
+ font-style: normal;
93
+ margin-top: 16px;
94
+ }
95
+
96
+ div.left h1{
97
+ margin: 0px;
98
+ border: 0px;
99
+ padding: 4px;
100
+ color: #006;
101
+ font-size: small;
102
+ font-weight: bold;
103
+ }
104
+
105
+ div.MenuGroup a { text-decoration: none; }
106
+ div.MenuGroup a:link { color: #006; }
107
+ div.MenuGroup a:visited { color: #006; }
108
+ div.MenuGroup a:active { color: red; }
109
+ div.MenuGroup a:hover { color: white; background-color:#006;width:160px;}
110
+ div.current {background-color:#006;width=160px;color:white;}
111
+ /*---------------------------------------------------------------------------
112
+ * Menus
113
+ */
114
+ .MenuGroup {
115
+ border-left: 1px solid #aaf;
116
+ border-top: 1px solid #aaf;
117
+ border-bottom: 1px solid white; /* IE work-around */
118
+
119
+ margin-bottom: 8px;
120
+ background-color: white;
121
+ color: #006;
122
+ }
123
+
124
+ .MenuGroup ul {
125
+ margin: 0px;
126
+ padding-left: 4px;
127
+ list-style-type: none;
128
+ }
129
+
130
+ .MenuGroup li {
131
+ padding: 2px;
132
+ }
133
+
134
+ .More {
135
+ width: 100%;
136
+ text-align: right;
137
+ }
138
+ /*------------------------------------------------------------------------------*/
139
+
140
+ /*-------------------------------------------------
141
+ * Right Panel
142
+ */
143
+ div.right {
144
+ float:right;
145
+ width:184px;
146
+ margin:0;
147
+ background-color: white;
148
+ padding: 8px;
149
+ font-size: small;
150
+ font-style: normal;
151
+ margin-top: 16px;
152
+ }
153
+
154
+ div.right h1{
155
+ margin: 0px;
156
+ border: 0px;
157
+ padding: 4px;
158
+ color: #006;
159
+ font-size: small;
160
+ font-weight: bold;
161
+ }
162
+
163
+ div.right a { text-decoration: none; }
164
+ div.right a:link { color: #006; }
165
+ div.right a:visited { color: #006; }
166
+ div.right a:active { color: red; }
167
+ div.right a:hover { color: red; }
168
+
169
+
170
+ /*---------------------------------------------------------------------------
171
+ * News panel
172
+ */
173
+ .NewsGroup {
174
+ border-left: 1px solid #aaf;
175
+ border-top: 1px solid #aaf;
176
+ border-bottom: 1px solid white; /* IE workaround */
177
+ margin-bottom: 8px;
178
+
179
+ color: #006;
180
+ }
181
+ .NewsItem {
182
+ margin: 4px;
183
+ }
184
+ .NewsTitle {
185
+ font-weight: bold;
186
+ margin: 0px;
187
+ padding: 0px;
188
+ }
189
+ .NewsDate {
190
+ margin: 0px;
191
+ padding: 0px;
192
+ font-size: smaller;
193
+ }
194
+ .NewsText {
195
+ padding: 0px;
196
+ margin: 0px;
197
+ margin-bottom: 8px;
198
+ }
199
+ .NewsText a { text-decoration: underline; }
200
+ .NewsText a:link { color: #006; }
201
+ .NewsText a:visited { color: #006; }
202
+ .NewsText a:active { color: red; }
203
+ .NewsText a:hover { color: red; }
204
+ .NewsMore {
205
+ font-size: small;
206
+ margin: 4px;
207
+ margin-top: 12px;
208
+ text-align: left;
209
+ }
210
+ .NewsGroup td {
211
+ font-size: 12px;
212
+ }
213
+
214
+ /*-------------------------------------------------------------------------*/
215
+
216
+ /*---------------------------------------------------------------------------
217
+ * Document meta-information
218
+ */
219
+
220
+ .Meta {
221
+ margin-top: 64px;
222
+ font-size: smaller;
223
+ color: #C0C0C0;
224
+ text-align: right;
225
+ }
226
+
227
+ .Meta a { text-decoration: underline; }
228
+ .Meta a:link { color: #C0C0C0; }
229
+ .Meta a:visited { color: #C0C0C0; }
230
+ .Meta a:active { color: red; }
231
+ .Meta a:hover { color: red; }
232
+ /*--------------------------------------------------------------------------*/
233
+
234
+ div.Content3Column {
235
+ margin-left:200px;
236
+ margin-right:216px;
237
+ }
238
+
239
+ div.Content2Column {
240
+ margin-left:200px;
241
+ margin-right:16px;
242
+ }
243
+
244
+ div.content h1 {
245
+ width: 100%;
246
+ font-size: Larger;
247
+ background-color: #006;
248
+ color: white;
249
+ padding: 2px;
250
+ padding-left: 6px;
251
+ margin-top: 24px;
252
+ margin-bottom: 12px;
253
+ }
254
+
255
+ div.content a { text-decoration: underline; }
256
+ div.content a:link { color: #006; }
257
+ div.content a:visited { color: #006; }
258
+ div.content a:active { color: green; }
259
+ div.content a:hover { color: red; }
260
+ div.content h2 {
261
+ margin-top: 24px;
262
+ margin-bottom: 16px;
263
+ font-weight: bold;
264
+ font-size: Larger;
265
+ }
266
+
267
+ div.content li {
268
+ margin-bottom: 6px;
269
+ }
270
+ div.content th {
271
+ background-color: #aaf;
272
+ }
273
+ div.content td {
274
+ background-color: #ddf;
275
+ }
276
+
277
+ div.Shaded pre {
278
+ padding: 4px;
279
+ font-family: courier new, monospace;
280
+ font-size: smaller;
281
+ border: 1px solid #008;
282
+ background-color: #ccf;
283
+ color: black;
284
+ width: 100%;
285
+ }
286
+
287
+ div.Shaded:before {
288
+ margin: 0px;
289
+ padding: 0px;
290
+ border: 0px;
291
+ font-size: inherit;
292
+ line-spacing: 100%;
293
+ }
294
+
295
+ div.footer {
296
+ color: #006;
297
+ padding:0.5em;
298
+ clear:both;
299
+ text-align:center;
300
+ font-size:75%;
301
+ }
302
+
303
+ div.footer a {
304
+ color:#006;
305
+ font-size:inherit;
306
+ }
307
+
308
+ div.bottomshadow {
309
+ width=100%;
310
+ height: 12px;
311
+ background-image: url("border_bottom.gif");
312
+ background-repeat: repeat-x;
313
+ padding: 12px;
314
+ }
315
+
316
+ div#content .Float {
317
+ float: right;
318
+ margin-left: 8px;
319
+ margin-right: 0px;
320
+ margin-top: 8px;
321
+ margin-bottom: 8px;
322
+ }
323
+
324
+ div#content .Diagram {
325
+ display: block;
326
+ margin-left: auto;
327
+ margin-right: auto;
328
+ margin-top: 8px;
329
+ margin-bottom: 8px;
330
+ }
331
+
332
+ div#content .Inline {
333
+ display: inline;
334
+ }
335
+
336
+ .source {
337
+ width: 100%;
338
+ text-align: right;
339
+ font-size: 90%;
340
+ }