sitefuel 0.0.0a

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. data/README +86 -0
  2. data/RELEASE_NOTES +7 -0
  3. data/bin/sitefuel +162 -0
  4. data/lib/sitefuel/Configuration.rb +35 -0
  5. data/lib/sitefuel/SiteFuelLogger.rb +128 -0
  6. data/lib/sitefuel/SiteFuelRuntime.rb +293 -0
  7. data/lib/sitefuel/extensions/ArrayComparisons.rb +34 -0
  8. data/lib/sitefuel/extensions/DynamicClassMethods.rb +19 -0
  9. data/lib/sitefuel/extensions/FileComparison.rb +24 -0
  10. data/lib/sitefuel/extensions/Silently.rb +27 -0
  11. data/lib/sitefuel/extensions/StringFormatting.rb +75 -0
  12. data/lib/sitefuel/extensions/SymbolComparison.rb +13 -0
  13. data/lib/sitefuel/external/AbstractExternalProgram.rb +616 -0
  14. data/lib/sitefuel/external/ExternalProgramTestCase.rb +67 -0
  15. data/lib/sitefuel/external/GIT.rb +9 -0
  16. data/lib/sitefuel/external/JPEGTran.rb +68 -0
  17. data/lib/sitefuel/external/PNGCrush.rb +66 -0
  18. data/lib/sitefuel/processors/AbstractExternalProgramProcessor.rb +72 -0
  19. data/lib/sitefuel/processors/AbstractProcessor.rb +378 -0
  20. data/lib/sitefuel/processors/AbstractStringBasedProcessor.rb +88 -0
  21. data/lib/sitefuel/processors/CSSProcessor.rb +84 -0
  22. data/lib/sitefuel/processors/HAMLProcessor.rb +52 -0
  23. data/lib/sitefuel/processors/HTMLProcessor.rb +211 -0
  24. data/lib/sitefuel/processors/JavaScriptProcessor.rb +57 -0
  25. data/lib/sitefuel/processors/PHPProcessor.rb +32 -0
  26. data/lib/sitefuel/processors/PNGProcessor.rb +80 -0
  27. data/lib/sitefuel/processors/RHTMLProcessor.rb +25 -0
  28. data/lib/sitefuel/processors/SASSProcessor.rb +50 -0
  29. data/test/processor_listing.rb +28 -0
  30. data/test/test_AbstractExternalProgram.rb +186 -0
  31. data/test/test_AbstractProcessor.rb +237 -0
  32. data/test/test_AbstractStringBasedProcessor.rb +48 -0
  33. data/test/test_AllProcessors.rb +65 -0
  34. data/test/test_ArrayComparisons.rb +32 -0
  35. data/test/test_CSSProcessor.rb +120 -0
  36. data/test/test_FileComparisons.rb +42 -0
  37. data/test/test_HAMLProcessor.rb.rb +60 -0
  38. data/test/test_HTMLProcessor.rb +186 -0
  39. data/test/test_JPEGTran.rb +40 -0
  40. data/test/test_JavaScriptProcessor.rb +63 -0
  41. data/test/test_PHPProcessor.rb +51 -0
  42. data/test/test_PNGCrush.rb +58 -0
  43. data/test/test_PNGProcessor.rb +32 -0
  44. data/test/test_RHTMLProcessor.rb +62 -0
  45. data/test/test_SASSProcessor.rb +68 -0
  46. data/test/test_SiteFuelLogging.rb +79 -0
  47. data/test/test_SiteFuelRuntime.rb +96 -0
  48. data/test/test_StringFormatting.rb +51 -0
  49. data/test/test_SymbolComparison.rb +27 -0
  50. data/test/test_images/sample_jpg01.jpg +0 -0
  51. data/test/test_images/sample_png01.png +0 -0
  52. data/test/test_programs/versioning.rb +26 -0
  53. data/test/test_sites/simplehtml/deployment.yml +22 -0
  54. data/test/test_sites/simplehtml/index.html +66 -0
  55. data/test/test_sites/simplehtml/style.css +40 -0
  56. data/test/ts_all.rb +39 -0
  57. metadata +165 -0
@@ -0,0 +1,84 @@
1
+ #
2
+ # File:: CSSProcessor.rb
3
+ # Author:: wkm
4
+ # Copyright:: 2009
5
+ # License:: GPL
6
+ #
7
+ # Rather lightweight CSS processor; primarily intended to minify CSS, but has
8
+ # basic support for beautifcation as well
9
+ #
10
+
11
+ module SiteFuel
12
+ module Processor
13
+
14
+ require 'cssmin'
15
+
16
+ require 'sitefuel/processors/AbstractStringBasedProcessor'
17
+
18
+ class CSSProcessor < AbstractStringBasedProcessor
19
+
20
+ # file patterns for CSS
21
+ def self.file_patterns
22
+ [".css"]
23
+ end
24
+
25
+ #
26
+ # FILTER SETS
27
+ #
28
+
29
+ # gives the default filterset to run
30
+ def self.default_filterset
31
+ :minify
32
+ end
33
+
34
+ # gives the minify filter to run
35
+ def self.filterset_minify
36
+ [:minify]
37
+ end
38
+
39
+ # beautifies the source
40
+ def self.filterset_beautify
41
+ [:beautify]
42
+ end
43
+
44
+
45
+
46
+ #
47
+ # FILTERS
48
+ #
49
+
50
+ # strips comments out of CSS using Regexp
51
+ def filter_strip_comments
52
+ @document.gsub!(/\/\/.*?$/m, '')
53
+ @document.gsub!(/\*(.*?)\*/m, '')
54
+ end
55
+
56
+ # lightweight minification by removing excess whitespace
57
+ def filter_clean_whitespace
58
+ @document.gsub!(/(\s\s+)/) do |text_block|
59
+ # if there's a newline we keep it. This is necessary for comments.
60
+ # in general, however, this filter should really be run after the
61
+ # strip_comments filter because it's silly to clip whitespace but
62
+ # not comments....
63
+ if text_block.count("\n") > 0
64
+ "\n"
65
+ else
66
+ text_block[0..0]
67
+ end
68
+ end
69
+ end
70
+
71
+ # lightweight beautifier that works through Regexp, adds whitespace above
72
+ # line comments, puts each declaration on it's own line. etc.
73
+ def filter_beautify
74
+ @document
75
+ end
76
+
77
+ # uses the CSSMin gem to minify a CSS document using regular expressions
78
+ def filter_minify
79
+ @document = CSSMin.minify(document)
80
+ end
81
+
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,52 @@
1
+ #
2
+ # File:: HAMLProcessor.rb
3
+ # Author:: wkm
4
+ # Copyright:: 2009
5
+ # License:: GPL
6
+ #
7
+ # processes .haml source files to generate the associated HTML
8
+ #
9
+
10
+ module SiteFuel
11
+ module Processor
12
+
13
+ require 'sitefuel/extensions/Silently'
14
+
15
+ # since the haml gem gives exec() warnings, we temporarily lower the verbosity
16
+ # (last tested with 2.2.14, this might not be needed with a future version)
17
+ silently { require 'haml' }
18
+
19
+ require 'sitefuel/processors/AbstractStringBasedProcessor'
20
+ require 'sitefuel/processors/HTMLProcessor'
21
+
22
+ class HAMLProcessor < AbstractStringBasedProcessor
23
+
24
+ def self.file_patterns
25
+ ['.haml']
26
+ end
27
+
28
+ def self.default_filterset
29
+ :generate
30
+ end
31
+
32
+ def self.filterset_generate
33
+ [:generate, :minify]
34
+ end
35
+
36
+ # generate the raw .html file from a .haml file
37
+ def filter_generate
38
+ # to silence instance variable not initialized warnings from haml
39
+ silently {
40
+ engine = Haml::Engine.new(document)
41
+ @document = engine.render
42
+ }
43
+ end
44
+
45
+ # run the HTMLProcessor's whitespace filter
46
+ def filter_minify
47
+ @document = HTMLProcessor.filter_string(:whitespace, document)
48
+ end
49
+
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,211 @@
1
+ #
2
+ # File:: HTMLProcessor.rb
3
+ # Author:: wkm
4
+ # Copyright:: 2009
5
+ # License:: GPL
6
+ #
7
+ # Defines an HTMLProcessor class that is used to compress and cleanup HTML
8
+ # files for deployment with sitefuel. Uses hpricot to process the HTML.
9
+ #
10
+
11
+ module SiteFuel
12
+ module Processor
13
+
14
+ require 'hpricot'
15
+
16
+ require 'sitefuel/processors/AbstractStringBasedProcessor'
17
+ require 'sitefuel/processors/CSSProcessor'
18
+ require 'sitefuel/processors/JavaScriptProcessor'
19
+
20
+ class HTMLProcessor < AbstractStringBasedProcessor
21
+
22
+ #
23
+ # HTML ENTITIES
24
+ #
25
+
26
+ # quotes
27
+ SINGLE_QUOTE_OPEN = '&#8216;'.freeze
28
+ SINGLE_QUOTE_CLOSE = '&#8217;'.freeze
29
+ DOUBLE_QUOTE_OPEN = '&#8220;'.freeze
30
+ DOUBLE_QUOTE_CLOSE = '&#8221;'.freeze
31
+
32
+ # dashes
33
+ EN_DASH = '&#8211;'.freeze
34
+ EM_DASH = '&#8212;'.freeze
35
+
36
+ # signs
37
+ ELLIPSIS = '&#8230;'.freeze
38
+ COPYRIGHT = '&#169;'.freeze
39
+ TRADEMARK = '&#8482;'.freeze
40
+ REGISTERED = '&#174;'.freeze
41
+
42
+ # arrows
43
+ ARROW_LEFTWARD = '&#8592;'.freeze
44
+ ARROW_RIGHTWARD = '&#8594;'.freeze
45
+ ARROW_LEFTRIGHT = '&#8596;'.freeze
46
+ ARROW_DOUBLE_LEFTWARD = '&#8656;'.freeze
47
+ ARROW_DOUBLE_RIGHTWARD = '&#8658;'.freeze
48
+ ARROW_DOUBLE_LEFTRIGHT = '&#8660;'.freeze
49
+
50
+ # math operators
51
+ MULTIPLICATION_SIGN = '&#215;'.freeze
52
+
53
+
54
+ # list of tags which have proper text items inside them
55
+ TEXTUAL_TAGS = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6',
56
+ 'p', 'b', 'i', 'ul', 'a', 'li', 'td',
57
+ 'th'].freeze
58
+
59
+ # filter for use with XPath searches
60
+ TEXTUAL_TAGS_FILTER = TEXTUAL_TAGS.join('|').freeze
61
+
62
+
63
+
64
+ # gives the file patterns which this processor will match
65
+ def self.file_patterns
66
+ [
67
+ # plain html
68
+ ".html", ".htm"
69
+ ]
70
+ end
71
+
72
+ def self.default_filterset
73
+ :minify
74
+ end
75
+
76
+ def self.filterset_minify
77
+ [:whitespace, :minify_javascript, :minify_styles]
78
+ end
79
+
80
+ def self.filterset_beautify
81
+ [:beautify_quotes, :beautify_dashes, :beautify_arrows, :beautify_symbols]
82
+ end
83
+
84
+
85
+ #
86
+ # FILTERS
87
+ #
88
+
89
+ # before any filters are run parse the document with hpricot
90
+ def setup_filters
91
+ @htmlstruc = Hpricot.parse(document)
92
+ end
93
+
94
+ # after all the filters are run dump the HTML as a string and do a
95
+ # tiny bit of post processing
96
+ def finish_filters
97
+ # do a last minute, ugly +br+ cleanup
98
+ @document = @htmlstruc.to_s.gsub('<br />', '<br>')
99
+ end
100
+
101
+ def traverse(patterns = TEXTUAL_TAGS_FILTER, &block)
102
+ (@htmlstruc/patterns).each do |tag|
103
+ tag.traverse_text do |txt|
104
+ block.call(tag.pathname, txt)
105
+ end
106
+ end
107
+ end
108
+
109
+ # strips excess whitespace in most HTML tags. Notably, +pre+ tags are
110
+ # left alone.
111
+ def filter_whitespace
112
+ @htmlstruc.traverse_text do |txt|
113
+ if /\A\s+\z/ =~ txt.content then
114
+ txt.content = ''
115
+ else
116
+ txt.content = txt.content.gsub(/\s+/m, ' ')
117
+ end
118
+ end
119
+ end
120
+
121
+ # minifies embedded JavaScript code using the JavaScriptProcessor
122
+ def filter_minify_javascript
123
+ # TODO check the language attribute to make sure it's javascript
124
+ traverse('script') do |tag,txt|
125
+ txt.content = JavaScriptProcessor.process_string(
126
+ txt.content,
127
+ {:resource_name => resource_name+'<embedded_JS>'}
128
+ )
129
+ end
130
+ end
131
+
132
+ # minifies embedded CSS styles using the CSSProcessor
133
+ def filter_minify_styles
134
+ traverse('style') do |tag,txt|
135
+ txt.content = CSSProcessor.process_string(
136
+ txt.content,
137
+ :resource_name => resource_name+'<embedded_CSS>'
138
+ )
139
+ end
140
+ end
141
+
142
+ # cleans up double and single quotes in textual objects
143
+ # <pre>"hello world" => &#8220; hello world&#8221;</pre>
144
+ def filter_beautify_quotes
145
+ traverse do |tag,txt|
146
+ txt.content = txt.content.
147
+ # apostrophes
148
+ gsub(/(\S)'(s)/i, '\1%s\2' % SINGLE_QUOTE_CLOSE).
149
+ gsub(/(\Ss)'(\s)/i, '\1%s\2' % SINGLE_QUOTE_CLOSE).
150
+
151
+ # double quotes
152
+ gsub(/"(\S.*?\S)"/, '%s\1%s' % [DOUBLE_QUOTE_OPEN, DOUBLE_QUOTE_CLOSE]).
153
+
154
+ # single quotes
155
+ gsub(/'(\S.*?\S)'/, '%s\1%s' % [SINGLE_QUOTE_OPEN, SINGLE_QUOTE_CLOSE])
156
+ end
157
+ end
158
+
159
+ # cleans up the various dash forms:
160
+ # <pre>12--13 => 12&#8211;13</pre>
161
+ # <pre>the car---it was red---was destroyed => ...&#8212;it was red&#8212;...</pre>
162
+ def filter_beautify_dashes
163
+ traverse do |tag,txt|
164
+ txt.content = txt.content.
165
+ # between two numbers we have an en dash
166
+ # this would be a bit cleaner with (negative) lookbehind
167
+ gsub(/(\d)--(\d)/, "\\1#{EN_DASH}\\2").
168
+
169
+ # we can also have multiple en-dashes
170
+ gsub(/\b(--(--)+)(\b|\z|\s)/) do ||
171
+ EN_DASH * ($1.length / 2) + $3
172
+ end.
173
+
174
+ # three dashes in general are an em dash
175
+ gsub(/(\s|\b)---(\s|\b)/, "\\1#{EM_DASH}\\2")
176
+ end
177
+ end
178
+
179
+ # convert basic arrow forms to unicode characters
180
+ def filter_beautify_arrows
181
+ traverse do |tag,txt|
182
+ txt.content = txt.content.
183
+ gsub(/(\s|\b)-->(\s|\b)/, "\\1#{ARROW_RIGHTWARD}\\2").
184
+ gsub(/(\s|\b)<--(\s|\b)/, "\\1#{ARROW_LEFTWARD}\\2").
185
+ gsub(/(\s|\b)<->(\s|\b)/, "\\1#{ARROW_LEFTRIGHT}\\2").
186
+ gsub(/(\s|\b)==>(\s|\b)/, "\\1#{ARROW_DOUBLE_RIGHTWARD}\\2").
187
+ gsub(/(\s|\b)<==(\s|\b)/, "\\1#{ARROW_DOUBLE_LEFTWARD}\\2").
188
+ gsub(/(\s|\b)<=>(\s|\b)/, "\\1#{ARROW_DOUBLE_LEFTRIGHT}\\2")
189
+ end
190
+ end
191
+
192
+ # converts 'x' signs between numbers into the unicode symbol
193
+ def filter_beautify_math
194
+
195
+ end
196
+
197
+ # convert a few shorthands like (c), (tm) to their unicode symbols
198
+ def filter_beautify_symbols
199
+ traverse do |tag,txt|
200
+ txt.content = txt.content.
201
+ gsub(/\(tm\)/i, TRADEMARK).
202
+ gsub(/\(c\)/i, COPYRIGHT).
203
+ gsub(/\(r\)/i, REGISTERED).
204
+ gsub(/(\b| )\.\.\.(\.)?/, "\\1#{ELLIPSIS}\\2")
205
+
206
+ end
207
+ end
208
+
209
+ end
210
+ end
211
+ end
@@ -0,0 +1,57 @@
1
+ #
2
+ # File:: JavaScriptProcessor.rb
3
+ # Author:: wkm
4
+ # Copyright:: 2009
5
+ # License:: GPL
6
+ #
7
+
8
+ module SiteFuel
9
+ module Processor
10
+
11
+ require 'jsmin'
12
+
13
+ require 'sitefuel/processors/AbstractStringBasedProcessor'
14
+
15
+ class JavaScriptProcessor < AbstractStringBasedProcessor
16
+
17
+ def self.file_patterns
18
+ ['.js']
19
+ end
20
+
21
+ # override AbstractProcessor#processor_name so output shows up as +JS+
22
+ # instead of +JavaScript+.
23
+ def self.processor_name
24
+ "JS"
25
+ end
26
+
27
+ def self.default_filterset
28
+ :minify
29
+ end
30
+
31
+ def self.filterset_minify
32
+ [:minify]
33
+ end
34
+
35
+ CDATA_START = '//<![CDATA['
36
+ CDATA_END = '//]]>'
37
+ def filter_minify
38
+ return nil if @document == nil
39
+ return nil if @document.length == 0
40
+
41
+ # JSMin doesn't like having files without any newlines
42
+ @document << "\n"
43
+
44
+ # put in CDATA placeholders
45
+ @document.gsub!(CDATA_START, '[[CDATA_START]]')
46
+ @document.gsub!(CDATA_END, '[[CDATA_END]]')
47
+
48
+ # run the minification
49
+ @document = JSMin.minify(@document).strip
50
+
51
+ # put back CDATA
52
+ @document.gsub!('[[CDATA_START]]', CDATA_START)
53
+ @document.gsub!('[[CDATA_END]]', CDATA_END)
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,32 @@
1
+ #
2
+ # File:: PHPProcessor.rb
3
+ # Author:: wkm
4
+ # Copyright:: 2009
5
+ # License:: GPL
6
+ #
7
+ # Defines a PHPProcessor class; but it's really a very lightweight alias
8
+ # around the HTMLProcessor
9
+ #
10
+
11
+
12
+ module SiteFuel
13
+ module Processor
14
+
15
+ require 'sitefuel/processors/HTMLProcessor'
16
+
17
+ # An alias for the HTMLProcessor; there is nothing PHP specific
18
+ # sitefuel can do at the moment.
19
+ class PHPProcessor < HTMLProcessor
20
+
21
+ # PHP specific file patterns
22
+ def self.file_patterns
23
+ # it doesn't really make sense to handle phps files, so we're leaving
24
+ # them alone. It might make sense to have a dummy empty processor for
25
+ # the files so it's clear we recognize them.
26
+ ['.php', '.phtml', '.php5']
27
+ end
28
+
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,80 @@
1
+ #
2
+ # File:: PNGProcessor.rb
3
+ # Author:: wkm
4
+ # Copyright:: 2009
5
+ # License:: GPL
6
+ #
7
+ # Interfaces with the rbcrush library that's wrapped around pngcrush
8
+ #
9
+
10
+ module SiteFuel
11
+ module Processor
12
+
13
+ require 'sitefuel/processors/AbstractExternalProgramProcessor'
14
+ require 'sitefuel/external/PNGCrush'
15
+
16
+ include External
17
+
18
+ # processor for handling Portable Network Graphics images
19
+ # currently operates as a lightweight wrapper around 'pngcrush'
20
+ class PNGProcessor < AbstractExternalProgramProcessor
21
+ def self.file_patterns
22
+ ['.png']
23
+ end
24
+
25
+ #
26
+ # External Program Handling
27
+ #
28
+
29
+ # gives the name of the pngcrush binary
30
+ def self.program_binary
31
+ 'pngcrush'
32
+ end
33
+
34
+ def self.program_version_option
35
+ '-version'
36
+ end
37
+
38
+ # we've only tested 1.5.10; but we're not using pngcrush
39
+ # in any special way
40
+ def self.appropriate_program_versions
41
+ "> 1.5.0"
42
+ end
43
+
44
+
45
+ #
46
+ # FILTERS AND FILTERSETS
47
+ #
48
+
49
+ def self.default_filterset
50
+ :max
51
+ end
52
+
53
+ def self.filterset_quick
54
+ [:quick]
55
+ end
56
+
57
+ def self.filterset_max
58
+ [:brute_chainsaw]
59
+ end
60
+
61
+
62
+ #
63
+ # FILTERS
64
+ #
65
+
66
+ def filter_brute
67
+ SiteFuel::External::PNGCrush.brute(resource_name, output_filename)
68
+ end
69
+
70
+ def filter_quick
71
+ SiteFuel::External::PNGCrush.quick(resource_name, output_filename)
72
+ end
73
+
74
+ def filter_brute_chainsaw
75
+ SiteFuel::External::PNGCrush.chainsaw(resource_name, output_filename)
76
+ end
77
+ end
78
+
79
+ end
80
+ end
@@ -0,0 +1,25 @@
1
+ #
2
+ # File:: RHTMLProcessor.rb
3
+ # Author:: wkm
4
+ # Copyright:: 2009
5
+ # License:: GPL
6
+ #
7
+ # Defines the RHTMLProcessor class. This is a lightweight wrapper
8
+ # around the HTMLProcessor class
9
+ #
10
+
11
+ module SiteFuel
12
+ module Processor
13
+ require 'sitefuel/processors/HTMLProcessor'
14
+
15
+ class RHTMLProcessor < HTMLProcessor
16
+
17
+ def self.file_patterns
18
+ ['.rhtml', '.erb']
19
+ end
20
+
21
+
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,50 @@
1
+ #
2
+ # File:: SASSProcessor.rb
3
+ # Author:: wkm
4
+ # Copyright:: 2009
5
+ # License:: GPL
6
+ #
7
+ # processes .sass stylesheets to generate the associated CSS
8
+ #
9
+
10
+ module SiteFuel
11
+ module Processor
12
+ require 'sitefuel/extensions/Silently'
13
+
14
+ # since the haml gem gives exec() warnings, we temporarily lower the verbosity
15
+ # (last tested with 2.2.14, this might not be needed with a future version)
16
+ silently { require 'sass' }
17
+
18
+ require 'sitefuel/processors/AbstractStringBasedProcessor'
19
+ require 'sitefuel/processors/CSSProcessor'
20
+
21
+ class SASSProcessor < AbstractStringBasedProcessor
22
+
23
+ def self.file_patterns
24
+ ['.sass']
25
+ end
26
+
27
+ def self.default_filterset
28
+ :generate
29
+ end
30
+
31
+ def self.filterset_generate
32
+ [:generate, :minify]
33
+ end
34
+
35
+ # generates the raw .css file from a .sass file
36
+ #
37
+ # TODO it's very important that generate be the first filter run
38
+ def filter_generate
39
+ engine = Sass::Engine.new(document)
40
+ @document = engine.render
41
+ end
42
+
43
+ # runs the CSSProcessor's minify filter
44
+ def filter_minify
45
+ @document = CSSProcessor.filter_string(:minify, document)
46
+ end
47
+
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/ruby
2
+ #
3
+ # File:: processor_listing.rb
4
+ # Author:: wkm
5
+ # Copyright:: 2009
6
+ # License:: GPL
7
+ #
8
+ # Lists all the processors in SiteFuel with their file patterns
9
+ #
10
+
11
+ $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
12
+
13
+ require 'sitefuel/SiteFuelRuntime'
14
+ include SiteFuel
15
+
16
+ SiteFuelRuntime.load_processors
17
+ processors = SiteFuelRuntime.find_processors
18
+ processors = processors.delete_if do |proc|
19
+ proc.processor_name =~ /Abstract.*/
20
+ end
21
+ processors.each do |proc|
22
+ puts ' | %s | %s | %s | '%
23
+ [
24
+ proc.processor_name.ljust(10),
25
+ proc.file_patterns.join(', ').ljust(30),
26
+ proc.processor_type.ljust(8)
27
+ ]
28
+ end