BuildMaster 0.7.0 → 0.8.0

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.
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
+ }