simplecov-simple-html 0.2.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 (55) hide show
  1. data/.gitignore +35 -0
  2. data/.yardopts +2 -0
  3. data/LICENSE +20 -0
  4. data/README.md +11 -0
  5. data/Rakefile +54 -0
  6. data/assets/javascripts/application.js +23 -0
  7. data/assets/javascripts/libraries/jquery-1.6.2.min.js +18 -0
  8. data/assets/javascripts/plugins/highlight.pack.js +1 -0
  9. data/assets/javascripts/plugins/jquery.colorbox.js +952 -0
  10. data/assets/javascripts/plugins/jquery.dataTables.min.js +152 -0
  11. data/assets/javascripts/plugins/jquery.timeago.js +141 -0
  12. data/assets/javascripts/plugins/jquery.url.js +174 -0
  13. data/assets/stylesheets/application.css +3 -0
  14. data/assets/stylesheets/plugins/highlight.css +129 -0
  15. data/assets/stylesheets/plugins/jquery-ui-1.8.4.custom.css +295 -0
  16. data/assets/stylesheets/plugins/jquery.colorbox.css +52 -0
  17. data/assets/stylesheets/reset.css +103 -0
  18. data/assets/stylesheets/screen.css.sass +220 -0
  19. data/lib/simplecov-simple-html.rb +324 -0
  20. data/lib/simplecov-simple-html/version.rb +10 -0
  21. data/public/application.css +799 -0
  22. data/public/application.js +1464 -0
  23. data/public/colorbox/border.png +0 -0
  24. data/public/colorbox/controls.png +0 -0
  25. data/public/colorbox/loading.gif +0 -0
  26. data/public/colorbox/loading_background.png +0 -0
  27. data/public/favicon_green.png +0 -0
  28. data/public/favicon_red.png +0 -0
  29. data/public/favicon_yellow.png +0 -0
  30. data/public/loading.gif +0 -0
  31. data/public/magnify.png +0 -0
  32. data/public/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  33. data/public/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  34. data/public/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  35. data/public/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  36. data/public/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  37. data/public/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  38. data/public/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  39. data/public/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  40. data/public/smoothness/images/ui-icons_222222_256x240.png +0 -0
  41. data/public/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  42. data/public/smoothness/images/ui-icons_454545_256x240.png +0 -0
  43. data/public/smoothness/images/ui-icons_888888_256x240.png +0 -0
  44. data/public/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  45. data/simplecov-simple-html.gemspec +25 -0
  46. data/spec/simple_cov-simple_html_spec.rb +56 -0
  47. data/test/lib/model/model.rb +6 -0
  48. data/test/lib/test.rb +15 -0
  49. data/test/lib/text/text.rb +6 -0
  50. data/test/simple_cov-simple_html_test.rb +12 -0
  51. data/test/test_helper.rb +17 -0
  52. data/test/test_test.rb +23 -0
  53. data/views/index.html.in +70 -0
  54. data/views/source.html.in +35 -0
  55. metadata +148 -0
@@ -0,0 +1,103 @@
1
+ /* -----------------------------------------------------------------------
2
+
3
+
4
+ Blueprint CSS Framework 0.9
5
+ http://blueprintcss.org
6
+
7
+ * Copyright (c) 2007-Present. See LICENSE for more info.
8
+ * See README for instructions on how to use Blueprint.
9
+ * For credits and origins, see AUTHORS.
10
+ * This is a compressed file. See the sources in the 'src' directory.
11
+
12
+ ----------------------------------------------------------------------- */
13
+
14
+ /* reset.css */
15
+ html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, code, del, dfn, em, img, q, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, dialog, figure, footer, header, hgroup, nav, section {margin:0;padding:0;border:0;font-weight:inherit;font-style:inherit;font-size:100%;font-family:inherit;vertical-align:baseline;}
16
+ article, aside, dialog, figure, footer, header, hgroup, nav, section {display:block;}
17
+ body {line-height:1.5;}
18
+ table {border-collapse:separate;border-spacing:0;}
19
+ caption, th, td {text-align:left;font-weight:normal;}
20
+ table, td, th {vertical-align:middle;}
21
+ blockquote:before, blockquote:after, q:before, q:after {content:"";}
22
+ blockquote, q {quotes:"" "";}
23
+ a img {border:none;}
24
+
25
+ /* typography.css */
26
+ html {font-size:100.01%;}
27
+ body {font-size:82%;color:#222;background:#fff;font-family:"Helvetica Neue", Arial, Helvetica, sans-serif;}
28
+ h1, h2, h3, h4, h5, h6 {font-weight:normal;color:#111;}
29
+ h1 {font-size:3em;line-height:1;margin-bottom:0.5em;}
30
+ h2 {font-size:2em;margin-bottom:0.75em;}
31
+ h3 {font-size:1.5em;line-height:1;margin-bottom:1em;}
32
+ h4 {font-size:1.2em;line-height:1.25;margin-bottom:1.25em;}
33
+ h5 {font-size:1em;font-weight:bold;margin-bottom:1.5em;}
34
+ h6 {font-size:1em;font-weight:bold;}
35
+ h1 img, h2 img, h3 img, h4 img, h5 img, h6 img {margin:0;}
36
+ p {margin:0 0 1.5em;}
37
+ p img.left {float:left;margin:1.5em 1.5em 1.5em 0;padding:0;}
38
+ p img.right {float:right;margin:1.5em 0 1.5em 1.5em;}
39
+ a:focus, a:hover {color:#000;}
40
+ a {color:#009;text-decoration:underline;}
41
+ blockquote {margin:1.5em;color:#666;font-style:italic;}
42
+ strong {font-weight:bold;}
43
+ em, dfn {font-style:italic;}
44
+ dfn {font-weight:bold;}
45
+ sup, sub {line-height:0;}
46
+ abbr, acronym {border-bottom:1px dotted #666;}
47
+ address {margin:0 0 1.5em;font-style:italic;}
48
+ del {color:#666;}
49
+ pre {margin:1.5em 0;white-space:pre;}
50
+ pre, code, tt {font:1em 'andale mono', 'lucida console', monospace;line-height:1.5;}
51
+ li ul, li ol {margin:0;}
52
+ ul, ol {margin:0 1.5em 1.5em 0;padding-left:3.333em;}
53
+ ul {list-style-type:disc;}
54
+ ol {list-style-type:decimal;}
55
+ dl {margin:0 0 1.5em 0;}
56
+ dl dt {font-weight:bold;}
57
+ dd {margin-left:1.5em;}
58
+ table {margin-bottom:1.4em;width:100%;}
59
+ th {font-weight:bold;}
60
+ thead th {background:#c3d9ff;}
61
+ th, td, caption {padding:4px 10px 4px 5px;}
62
+ tr.even td {background:#efefef;}
63
+ tfoot {font-style:italic;}
64
+ caption {background:#eee;}
65
+ .small {font-size:.8em;margin-bottom:1.875em;line-height:1.875em;}
66
+ .large {font-size:1.2em;line-height:2.5em;margin-bottom:1.25em;}
67
+ .hide {display:none;}
68
+ .quiet {color:#666;}
69
+ .loud {color:#000;}
70
+ .highlight {background:#ff0;}
71
+ .added {background:#060;color:#fff;}
72
+ .removed {background:#900;color:#fff;}
73
+ .first {margin-left:0;padding-left:0;}
74
+ .last {margin-right:0;padding-right:0;}
75
+ .top {margin-top:0;padding-top:0;}
76
+ .bottom {margin-bottom:0;padding-bottom:0;}
77
+
78
+ /* forms.css */
79
+ label {font-weight:bold;}
80
+ fieldset {padding:1.4em;margin:0 0 1.5em 0;border:1px solid #ccc;}
81
+ legend {font-weight:bold;font-size:1.2em;}
82
+ input[type=text], input[type=password], input.text, input.title, textarea, select {background-color:#fff;border:1px solid #bbb;}
83
+ input[type=text]:focus, input[type=password]:focus, input.text:focus, input.title:focus, textarea:focus, select:focus {border-color:#666;}
84
+ input[type=text], input[type=password], input.text, input.title, textarea, select {margin:0.5em 0;}
85
+ input.text, input.title {width:300px;padding:5px;}
86
+ input.title {font-size:1.5em;}
87
+ textarea {width:390px;height:250px;padding:5px;}
88
+ input[type=checkbox], input[type=radio], input.checkbox, input.radio {position:relative;top:.25em;}
89
+ form.inline {line-height:3;}
90
+ form.inline p {margin-bottom:0;}
91
+ .error, .notice, .success {padding:.8em;margin-bottom:1em;border:2px solid #ddd;}
92
+ .error {background:#FBE3E4;color:#8a1f11;border-color:#FBC2C4;}
93
+ .notice {background:#FFF6BF;color:#514721;border-color:#FFD324;}
94
+ .success {background:#E6EFC2;color:#264409;border-color:#C6D880;}
95
+ .error a {color:#8a1f11;}
96
+ .notice a {color:#514721;}
97
+ .success a {color:#264409;}
98
+ .box {padding:1.5em;margin-bottom:1.5em;background:#E5ECF9;}
99
+ hr {background:#ddd;color:#ddd;clear:both;float:none;width:100%;height:.1em;margin:0 0 1.45em;border:none;}
100
+ hr.space {background:#fff;color:#fff;visibility:hidden;}
101
+ .clearfix:after, .container:after {content:"\0020";display:block;height:0;clear:both;visibility:hidden;overflow:hidden;}
102
+ .clearfix, .container {display:block;}
103
+ .clear {clear:both;}
@@ -0,0 +1,220 @@
1
+ #loading
2
+ position: fixed
3
+ left: 40%
4
+ top: 50%
5
+
6
+ a
7
+ color: #333
8
+ text-decoration: none
9
+ &:hover
10
+ color: #000
11
+ text-decoration: underline
12
+
13
+ body
14
+ font-family: "Lucida Grande", Helvetica, "Helvetica Neue", Arial, sans-serif
15
+ padding: 12px
16
+ background-color: #333
17
+
18
+ h1, h2, h3, h4
19
+ color: #1C2324
20
+ margin: 0
21
+ padding: 0
22
+ margin-bottom: 12px
23
+
24
+ table
25
+ width: 100%
26
+
27
+ #content
28
+ clear: left
29
+ background-color: white
30
+ border: 2px solid #ddd
31
+ border-top: 8px solid #ddd
32
+ padding: 18px
33
+ -webkit-border-bottom-left-radius: 5px
34
+ -webkit-border-bottom-right-radius: 5px
35
+ -webkit-border-top-right-radius: 5px
36
+ -moz-border-radius-bottomleft: 5px
37
+ -moz-border-radius-bottomright: 5px
38
+ -moz-border-radius-topright: 5px
39
+ border-bottom-left-radius: 5px
40
+ border-bottom-right-radius: 5px
41
+ border-top-right-radius: 5px
42
+
43
+ .dataTables_filter, .dataTables_info
44
+ padding: 2px 6px
45
+
46
+ abbr.timeago
47
+ text-decoration: none
48
+ border: none
49
+ font-weight: bold
50
+
51
+ .timestamp
52
+ float: right
53
+ color: #ddd
54
+
55
+ .group_tabs
56
+ list-style: none
57
+ float: left
58
+ margin: 0
59
+ padding: 0
60
+ li
61
+ display: inline
62
+ float: left
63
+ a
64
+ font-family: Helvetica, Arial, sans-serif
65
+ display: block
66
+ float: left
67
+ text-decoration: none
68
+ padding: 4px 8px
69
+ background-color: #aaa
70
+ background: -webkit-gradient(linear, 0 0, 0 bottom, from(#dddddd), to(#aaaaaa))
71
+ background: -moz-linear-gradient(#dddddd, #aaaaaa)
72
+ background: linear-gradient(#dddddd, #aaaaaa)
73
+ text-shadow: #e5e5e5 1px 1px 0px
74
+ border-bottom: none
75
+ color: #333
76
+ font-weight: bold
77
+ margin-right: 8px
78
+ border-top: 1px solid #efefef
79
+ -webkit-border-top-left-radius: 2px
80
+ -webkit-border-top-right-radius: 2px
81
+ -moz-border-radius-topleft: 2px
82
+ -moz-border-radius-topright: 2px
83
+ border-top-left-radius: 2px
84
+ border-top-right-radius: 2px
85
+ &:hover
86
+ background-color: #ccc
87
+ background: -webkit-gradient(linear, 0 0, 0 bottom, from(#eeeeee), to(#aaaaaa))
88
+ background: -moz-linear-gradient(#eeeeee, #aaaaaa)
89
+ background: linear-gradient(#eeeeee, #aaaaaa)
90
+ &:active
91
+ padding-top: 5px
92
+ padding-bottom: 3px
93
+ &.active a
94
+ color: black
95
+ text-shadow: #fff 1px 1px 0px
96
+ background-color: #ddd
97
+ background: -webkit-gradient(linear, 0 0, 0 bottom, from(white), to(#dddddd))
98
+ background: -moz-linear-gradient(white, #dddddd)
99
+ background: linear-gradient(white, #dddddd)
100
+
101
+ .file_list
102
+ margin-bottom: 18px
103
+
104
+ a.src_link
105
+ background: url('./magnify.png') no-repeat left 50%
106
+ padding-left: 18px
107
+
108
+ tr, td
109
+ margin: 0
110
+ padding: 0
111
+
112
+ th
113
+ white-space: nowrap
114
+ &.ui-state-default
115
+ cursor: pointer
116
+ span.ui-icon
117
+ float: left
118
+
119
+ td
120
+ padding: 4px 8px
121
+ &.strong
122
+ font-weight: bold
123
+
124
+ .source_table
125
+ h3, h4
126
+ padding: 0
127
+ margin: 0
128
+ margin-bottom: 4px
129
+ .header
130
+ padding: 10px
131
+ pre
132
+ margin: 0
133
+ padding: 0
134
+ white-space: normal
135
+ color: #000
136
+ font-family: "Monaco", "Inconsolata", "Consolas", monospace
137
+ code
138
+ color: #000
139
+ font-family: "Monaco", "Inconsolata", "Consolas", monospace
140
+ pre
141
+ background-color: #333
142
+ ol
143
+ margin: 0px
144
+ padding: 0px
145
+ margin-left: 45px
146
+ font-size: 12px
147
+ color: white
148
+ li
149
+ margin: 0px
150
+ padding: 2px 6px
151
+ border-left: 5px solid white
152
+ code
153
+ white-space: pre
154
+ white-space: pre-wrap
155
+ .hits
156
+ float: right
157
+ margin-left: 10px
158
+ padding: 2px 4px
159
+ background-color: #444
160
+ background: -webkit-gradient(linear, 0 0, 0 bottom, from(#222222), to(#666666))
161
+ background: -moz-linear-gradient(#222222, #666666)
162
+ background: linear-gradient(#222222, #666666)
163
+ color: white
164
+ font-family: Helvetica, "Helvetica Neue", Arial, sans-serif
165
+ font-size: 10px
166
+ font-weight: bold
167
+ text-align: center
168
+ border-radius: 6px
169
+
170
+ #footer
171
+ color: #ddd
172
+ font-size: 12px
173
+ font-weight: bold
174
+ margin-top: 12px
175
+ text-align: right
176
+ a
177
+ color: #eee
178
+ text-decoration: underline
179
+ &:hover
180
+ color: #fff
181
+ text-decoration: none
182
+
183
+ .green
184
+ color: #090
185
+
186
+ .red
187
+ color: #900
188
+
189
+ .yellow
190
+ color: #da0
191
+
192
+ .source_table
193
+ .covered
194
+ border-color: #090
195
+ .missed
196
+ border-color: #900
197
+ .never
198
+ border-color: black
199
+ .skipped
200
+ border-color: #fc0
201
+ .covered
202
+ &:nth-child(odd)
203
+ background-color: #CDF2CD
204
+ &:nth-child(even)
205
+ background-color: #DBF2DB
206
+ .missed
207
+ &:nth-child(odd)
208
+ background-color: #F7C0C0
209
+ &:nth-child(even)
210
+ background-color: #F7CFCF
211
+ .never
212
+ &:nth-child(odd)
213
+ background-color: #efefef
214
+ &:nth-child(even)
215
+ background-color: #f4f4f4
216
+ .skipped
217
+ &:nth-child(odd)
218
+ background-color: #FBF0C0
219
+ &:nth-child(even)
220
+ background-color: #FBFfCf
@@ -0,0 +1,324 @@
1
+ # encodeing: utf-8
2
+ require 'rexml/xpath'
3
+ require 'rexml/document'
4
+ require 'fileutils'
5
+
6
+ require 'simplecov-simple-html/version'
7
+
8
+ # Ensure we are using a compatible version of SimpleCov
9
+ if Gem::Version.new(SimpleCov::VERSION) < Gem::Version.new("0.7.1")
10
+ raise RuntimeError, "The version of SimpleCov you are using is too old. Please update with `gem install simplecov` or `bundle update simplecov`"
11
+ end
12
+
13
+ # A simple HTML formater for SimpleCov
14
+ # There a coverage file created for each ruby file tested
15
+ class SimpleCov::Formatter::SimpleHTMLFormatter
16
+ include REXML
17
+ # fixup the path
18
+ # @param [REXML::Document] source_doc
19
+ # @return [void]
20
+ def fixup_path(source_doc)
21
+ source_doc.each_element('//link') do |e|
22
+ e.add_attribute('href', e.attribute('href').to_s.sub('VERSION', SimpleCov::Formatter::SimpleHTMLFormatter::VERSION))
23
+ end
24
+ source_doc.each_element('//script') do |e|
25
+ e.add_attribute('src', e.attribute('src').to_s.sub('VERSION', SimpleCov::Formatter::SimpleHTMLFormatter::VERSION))
26
+ end
27
+ nil
28
+ end
29
+ # Format the coverage results
30
+ # @param [SimpleCov::Result] result The SimpleCov::Result
31
+ # @return [void]
32
+ # @note Creates a directory and serveral files
33
+ def format(result)
34
+ Dir[File.join(File.dirname(__FILE__), '../public/*')].each do |path|
35
+ FileUtils.cp_r(path, asset_output_path)
36
+ end
37
+ File.open(File.join(File.dirname(__FILE__), '../views/source.html.in'), "r") do |ifile|
38
+ source_doc = REXML::Document.new ifile
39
+ fixup_path(source_doc)
40
+ result.source_files.each do |source_file|
41
+ doc = source_doc.deep_clone
42
+ doc.each_recursive do |e|
43
+ case e.attribute('class').to_s
44
+ when 'filename'
45
+ e.text = shortened_filename source_file.filename
46
+ when 'covered_percent'
47
+ e.text = source_file.covered_percent.round(2).to_s
48
+ e.parent.attributes['style'] = "color: #{ coverage_css_class(source_file.covered_percent) };"
49
+ when 'lines_of_code'
50
+ e.text = source_file.lines_of_code
51
+ when 'covered_lines'
52
+ e.text = source_file.covered_lines.size
53
+ when 'missed_lines'
54
+ e.text = source_file.missed_lines.size
55
+ end
56
+ end
57
+ ol = doc.get_elements('//div/pre/ol')[0]
58
+ li = doc.get_elements('//div/pre/ol/li')[0]
59
+ ol.delete_element(li)
60
+ source_file.lines.each_with_index do |line|
61
+ nli = li.deep_clone
62
+ nli.add_attribute("class", line.status)
63
+ nli.add_attribute("data-linenumber", line.number)
64
+ nli.add_attribute("data-hits", line.coverage ? line.coverage : '')
65
+
66
+ nli.get_elements('code')[0].text = line.src
67
+ if line.covered?
68
+ nli.get_elements('span')[0].text = line.coverage
69
+ elsif line.skipped?
70
+ nli.get_elements('span')[0].text = line.coverage
71
+ else
72
+ nli.delete_element(nli.get_elements('span')[0])
73
+ end
74
+ ol << nli
75
+ end
76
+ filename = File.join(output_path, shortened_filename(source_file.filename).gsub('/', '_') + '.html')
77
+ FileUtils.mkdir_p(File.dirname(filename))
78
+ File.open(filename, 'w') do |ofile|
79
+ ofile.puts doc.to_s
80
+ end
81
+ end
82
+ end
83
+ groups = [ "All Files" ] + result.groups.each_key.to_a
84
+ a = Array.new
85
+ a = a.push [ "All Files", result.source_files ]
86
+ a += result.groups.to_a
87
+ groups_hash = Hash[ a ]
88
+
89
+ File.open(File.join(File.dirname(__FILE__), '../views/index.html.in'), "r") do |ifile|
90
+ data = ifile.read
91
+ groups.each_with_index do |name, i|
92
+ doc = REXML::Document.new data
93
+ source_files = groups_hash[name]
94
+ fixup_path(doc)
95
+ doc.xpath
96
+ body = doc.root.elements['body/div']
97
+ XPath.each(body, '//*[@class="source_files_covered_percent"]') do |element|
98
+ element.text = source_files.covered_percent.round(2)
99
+ element.parent.attributes['class'] = coverage_css_class(source_files.covered_percent)
100
+ end
101
+ XPath.each(body, '//*/span[@class="covered_strength_value"]') do |x|
102
+ x.text = source_files.covered_strength.round(2)
103
+ x.parent.attributes['class'] = strength_css_class(source_files.covered_strength)
104
+ end
105
+ XPath.each(body, '//*/span[@class="files_total"]') do |x|
106
+ x.text = source_files.size
107
+ end
108
+ XPath.each(body, '//*/span[@class="file_lines"]') do |x|
109
+ x.text = source_files.lines_of_code
110
+ end
111
+ XPath.each(body, '//*/span[@class="covered_lines"]') do |x|
112
+ x.text = source_files.covered_lines
113
+ end
114
+ XPath.each(body, '//*/span[@class="missed_lines"]') do |x|
115
+ x.text = source_files.missed_lines
116
+ end
117
+ XPath.each(body, '//*/ul[@class="group_tabs"]').each do |x|
118
+ #p x.to_s
119
+ end
120
+ body.each_element do |body_element|
121
+ if body_element.attribute('class')
122
+ case body_element.attribute('class').to_s
123
+ when 'timestamp'
124
+ body_element.each_element do |e2|
125
+ case e2.name.to_s
126
+ when 'abbr'
127
+ time = Time.now
128
+ e2.add_attribute('title', time.iso8601)
129
+ e2.text = time.iso8601
130
+ end
131
+ end
132
+ when 'group_tabs'
133
+ fli = nil
134
+ body_element.to_a.each do |li|
135
+ case li
136
+ when REXML::Element
137
+ fli = li.dup unless fli
138
+ body_element.delete_element li
139
+ when REXML::Text
140
+ body_element.delete li
141
+ else
142
+ raise 'unknown'
143
+ end
144
+ end
145
+ groups.each_with_index do |g, gi|
146
+ g_source_files = groups_hash[g]
147
+ nli = fli.deep_clone
148
+ if g == name
149
+ nli.attributes['class'] = 'active'
150
+ end
151
+ nli.each_element('a/span[@class="tab_group_name"]') do |x|
152
+ x.text = g
153
+ end
154
+ nli.each_element('a/span[@class="color"]') do |x|
155
+ x.attributes['class'] = coverage_css_class(g_source_files.covered_percent)
156
+ end
157
+ nli.each_element('a/span/span[@class="tab_coverage"]') do |x|
158
+ x.text = g_source_files.covered_percent.round(2)
159
+ end
160
+ nli.each_element('a') do |x|
161
+ if gi > 0
162
+ x.attributes['href'] = 'index%d.html' % gi
163
+ else
164
+ x.attributes['href'] = 'index.html'
165
+ end
166
+ end
167
+ body_element.add_element nli
168
+ end
169
+ end
170
+ end
171
+ if body_element.attribute('id')
172
+ case body_element.attribute('id').to_s
173
+ when 'content'
174
+ file_list_container = body_element.get_elements("//div[@class='file_list_container']")[0]
175
+ file_list_container.add_attribute('id', 'AllFiles')
176
+ # x = file_list_container.deep_clone
177
+ x = file_list_container
178
+ x.each_element do |e1|
179
+ case e1.name
180
+ when 'h2'
181
+ e1.each_recursive do |e2|
182
+ case e2.attribute('class').to_s
183
+ when 'group_name'
184
+ e2.text = name
185
+ end
186
+ end
187
+ when 'table'
188
+ tbody = e1.get_elements('//tbody')[0]
189
+ body_element.each_element('//tbody/tr') do |tr|
190
+ tbody.delete_element tr
191
+ source_files.each do |source_file|
192
+ ntr = tr.deep_clone
193
+ x = ntr.get_elements('//td')
194
+ filename = x[0].get_elements('a')[0]
195
+ filename.text = shortened_filename source_file.filename
196
+ filename.add_attribute('href', shortened_filename(source_file.filename).gsub('/', '_') + '.html')
197
+ x[1].add_attribute('class', coverage_css_class(source_file.covered_percent))
198
+ x[1].text = source_file.covered_percent.round(2)
199
+ x[2].text = source_file.lines.count
200
+ x[3].text = source_file.covered_lines.size + source_file.missed_lines.count
201
+ x[4].text = source_file.covered_lines.size
202
+ x[5].text = source_file.missed_lines.size
203
+ x[6].text = source_file.covered_strength
204
+ tbody << ntr
205
+ end
206
+ end
207
+ else
208
+ #puts e
209
+ end
210
+ end
211
+ when 'footer'
212
+ body_element.each_element do |e|
213
+ case body_element.attribute('id').to_s
214
+ when 'simplecov_version'
215
+ body_element.text = SimpleCov::VERSION
216
+ when 'result.command_name'
217
+ body_element.text = result.command_name
218
+ else
219
+ #puts body_element
220
+ end
221
+ end
222
+ else
223
+ puts "Id #{ body_element.attribute('id').to_s }"
224
+ end
225
+ end
226
+ end
227
+ if i == 0
228
+ ofilename = 'index.html'
229
+ else
230
+ ofilename = "index#{i}.html"
231
+ end
232
+ File.open(File.join(output_path, ofilename), "w+") do |ofile|
233
+ ofile.puts doc.to_s
234
+ end
235
+ end
236
+ end
237
+ puts output_message(result)
238
+ nil
239
+ end
240
+
241
+ # Generate the coverage report text
242
+ # @param [SimpleCov::Result] result The SimpleCov::Result
243
+ # @return [String] the coverage report
244
+ def output_message(result)
245
+ "Coverage report generated for #{result.command_name} to #{output_path}. #{result.covered_lines} / #{result.total_lines} LOC (#{result.covered_percent.round(2)}%) covered."
246
+ end
247
+
248
+ private
249
+
250
+ # Returns the an erb instance for the template of given name
251
+ # @deprecated
252
+ def template(name)
253
+ raise "template(#{name})"
254
+ end
255
+
256
+ # @return [String] the path where the coverage report will be generated
257
+ def output_path
258
+ SimpleCov.coverage_path
259
+ end
260
+
261
+ # @return [String] the path where the assests are stored
262
+ def asset_output_path
263
+ return @asset_output_path if defined? @asset_output_path and @asset_output_path
264
+ @asset_output_path = File.join(output_path, 'assets', SimpleCov::Formatter::SimpleHTMLFormatter::VERSION)
265
+ FileUtils.mkdir_p(@asset_output_path)
266
+ @asset_output_path
267
+ end
268
+
269
+ # @return [String] the path to a particular asset
270
+ def assets_path(name)
271
+ File.join('./assets', SimpleCov::Formatter::SimpleHTMLFormatter::VERSION, name)
272
+ end
273
+
274
+ # Returns the html for the given source_file
275
+ def formatted_source_file(source_file)
276
+ template('source_file').result(binding)
277
+ end
278
+
279
+ # Returns a table containing the given source files
280
+ def formatted_file_list(title, source_files)
281
+ title_id = title.gsub(/^[^a-zA-Z]+/, '').gsub(/[^a-zA-Z0-9\-\_]/, '')
282
+ title_id # Ruby will give a warning when we do not use this except via the binding :( FIXME
283
+ template('file_list').result(binding)
284
+ end
285
+
286
+ def coverage_css_class(covered_percent)
287
+ if covered_percent > 90
288
+ 'green'
289
+ elsif covered_percent > 80
290
+ 'yellow'
291
+ else
292
+ 'red'
293
+ end
294
+ end
295
+
296
+ def strength_css_class(covered_strength)
297
+ if covered_strength > 1
298
+ 'green'
299
+ elsif covered_strength == 1
300
+ 'yellow'
301
+ else
302
+ 'red'
303
+ end
304
+ end
305
+
306
+ # Return a (kind of) unique id for the source file given. Uses SHA1 on path for the id
307
+ # @return [String] Digest::SHA1.hexdigest of the source_file
308
+ def id(source_file)
309
+ Digest::SHA1.hexdigest(source_file.filename)
310
+ end
311
+
312
+ def timeago(time)
313
+ "<abbr class=\"timeago\" title=\"#{time.iso8601}\">#{time.iso8601}</abbr>"
314
+ end
315
+
316
+ def shortened_filename(source_file_name)
317
+ source_file_name.gsub(SimpleCov.root, '.').gsub(/^\.\//, '')
318
+ end
319
+
320
+ def link_to_source_file(source_file)
321
+ %Q(<a href="##{id source_file}" class="src_link" title="#{shortened_filename source_file}">#{shortened_filename source_file}</a>)
322
+ end
323
+ end
324
+