epic 0.0.3 → 0.0.4

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.
@@ -1,3 +1,10 @@
1
+ == 0.0.4 2010-01-30
2
+ * major enhancements
3
+ * compression and validation performed by instances rather the class
4
+ * minor enhancements
5
+ * don't growl and raise errors on validation, just display errors
6
+ * internal refactoring
7
+
1
8
  == 0.0.3 2010-01-25
2
9
  * major enhancements
3
10
  * added YUI compressor to compress JavaScript and CSS
data/Rakefile CHANGED
@@ -30,6 +30,7 @@ end
30
30
  Spec::Rake::SpecTask.new(:rcov) do |spec|
31
31
  spec.libs << 'lib' << 'spec'
32
32
  spec.pattern = 'spec/**/*_spec.rb'
33
+ spec.rcov_opts = ['--exclude', '.gem,Library,spec', '--sort', 'coverage']
33
34
  spec.rcov = true
34
35
  end
35
36
 
@@ -52,3 +53,8 @@ Rake::RDocTask.new do |rdoc|
52
53
  rdoc.rdoc_files.include('README*')
53
54
  rdoc.rdoc_files.include('lib/**/*.rb')
54
55
  end
56
+
57
+ require 'cucumber/rake/task'
58
+ Cucumber::Rake::Task.new do |t|
59
+ t.cucumber_opts = "--format pretty"
60
+ end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.3
1
+ 0.0.4
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{epic}
8
- s.version = "0.0.3"
8
+ s.version = "0.0.4"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Jeff Coleman"]
12
- s.date = %q{2010-01-25}
12
+ s.date = %q{2010-01-30}
13
13
  s.default_executable = %q{epic}
14
14
  s.description = %q{Epic validator, wraps validation for HTML, JavaScript and CSS.}
15
15
  s.email = %q{progressions@gmail.com}
@@ -29,15 +29,36 @@ Gem::Specification.new do |s|
29
29
  "VERSION",
30
30
  "bin/epic",
31
31
  "epic.gemspec",
32
+ "features/compressor.feature",
33
+ "features/data/html/invalid.html",
34
+ "features/data/html/valid.html",
35
+ "features/data/javascripts/invalid.js",
36
+ "features/data/javascripts/invalid_uncompressed.js",
37
+ "features/data/javascripts/pre_compressed.js",
38
+ "features/data/javascripts/pre_compressed.js.min",
39
+ "features/data/javascripts/valid.js",
40
+ "features/data/javascripts/valid_uncompressed.js",
41
+ "features/data/stylesheets/valid.css",
42
+ "features/step_definitions/compressor_steps.rb",
43
+ "features/step_definitions/file_steps.rb",
44
+ "features/step_definitions/validator_steps.rb",
45
+ "features/support/env.rb",
46
+ "features/validator.feature",
32
47
  "lib/epic.rb",
33
48
  "lib/epic/base.rb",
34
49
  "lib/epic/compressor.rb",
50
+ "lib/epic/errors.rb",
35
51
  "lib/epic/validator.rb",
52
+ "lib/epic/validator/base.rb",
53
+ "lib/epic/validator/html.rb",
54
+ "lib/epic/validator/javascript.rb",
55
+ "lib/epic/validator/json.rb",
56
+ "lib/epic/validator/stylesheet.rb",
36
57
  "spec/compressor_spec.rb",
37
- "spec/epic_spec.rb",
38
58
  "spec/spec.opts",
39
59
  "spec/spec_helper.rb",
40
60
  "spec/stubs.rb",
61
+ "spec/validator_spec.rb",
41
62
  "vendor/ext/js.jar",
42
63
  "vendor/ext/jslint.js",
43
64
  "vendor/ext/yuicompressor-2.4.2.jar"
@@ -49,9 +70,9 @@ Gem::Specification.new do |s|
49
70
  s.summary = %q{Epic validation of HTML, JavaScript and CSS}
50
71
  s.test_files = [
51
72
  "spec/compressor_spec.rb",
52
- "spec/epic_spec.rb",
53
73
  "spec/spec_helper.rb",
54
- "spec/stubs.rb"
74
+ "spec/stubs.rb",
75
+ "spec/validator_spec.rb"
55
76
  ]
56
77
 
57
78
  if s.respond_to? :specification_version then
@@ -0,0 +1,29 @@
1
+
2
+ Feature: Compress JavaScript and Stylesheet files
3
+
4
+ Background:
5
+ Given I configure Epic::Base
6
+
7
+ Scenario: Compress a valid JavaScript file
8
+ Given I compress the file "javascripts/valid_uncompressed.js"
9
+ And I open the file "javascripts/valid_uncompressed.js.min"
10
+ Then I should see "var hello\=function\(a\)"
11
+ And no exceptions should have been raised
12
+ And I remove the file "javascripts/valid_uncompressed.js.min"
13
+
14
+ Scenario: Compress an invalid JavaScript file
15
+ Given I compress the file "javascripts/invalid_uncompressed.js"
16
+ Then an exception should have been raised with the message "JavaScript errors"
17
+
18
+ Scenario: Don't re-compress if compressed file exists
19
+ Given I compress the file "javascripts/pre_compressed.js"
20
+ And I open the file "javascripts/pre_compressed.js.min"
21
+ Then I should see "function alreadyCompressed\(b\)"
22
+
23
+ Scenario: Raise an error if the original file doesn't exist
24
+ Given I compress the file "javascripts/nonexistent.js"
25
+ Then an exception should have been raised with the message "No such file or directory"
26
+
27
+
28
+
29
+
@@ -0,0 +1,12 @@
1
+ <html>
2
+ <head>
3
+ <title>Title of valid HTML file</title>
4
+ </head>
5
+
6
+ <body>
7
+ <p>Hello</p>
8
+ <span>
9
+ <div>This div is inside a span</div>
10
+ </span>
11
+ </body>
12
+ </html>
@@ -0,0 +1,9 @@
1
+ <html>
2
+ <head>
3
+ <title>Title of valid HTML file</title>
4
+ </head>
5
+
6
+ <body>
7
+ <p>Hello</p>
8
+ </body>
9
+ </html>
@@ -0,0 +1 @@
1
+ alert("hello")
@@ -0,0 +1,3 @@
1
+ var hello = function() {
2
+ alert("My name is" name)
3
+ };
@@ -0,0 +1,3 @@
1
+ function preCompressed(name) {
2
+ alert("I'm precompressed " + name);
3
+ };
@@ -0,0 +1 @@
1
+ function alreadyCompressed(b){alert("I'm precompressed "+a);}
@@ -0,0 +1 @@
1
+ alert("hello");
@@ -0,0 +1,3 @@
1
+ var hello = function(name) {
2
+ alert("My name is" + name);
3
+ };
@@ -0,0 +1,3 @@
1
+ p {
2
+ color: red;
3
+ }
@@ -0,0 +1,9 @@
1
+ Given %r{I compress the file "([^\"]*)"} do |filename|
2
+ path = "#{BASE_PATH}/#{filename}"
3
+
4
+ begin
5
+ Epic::Compressor.new(path).compress
6
+ rescue StandardError => e
7
+ @exceptions << e.message
8
+ end
9
+ end
@@ -0,0 +1,25 @@
1
+ Given %r{the file "([^\"]*)" exists with "([^\"]*)"} do |filename, content|
2
+ content.gsub!("\\n", "\n")
3
+ File.open("#{BASE_PATH}/#{filename}", "w") do |f|
4
+ content.split("\n").each do |line|
5
+ f.puts line
6
+ end
7
+ end
8
+ @files << "#{BASE_PATH}/#{filename}"
9
+ end
10
+
11
+ And %r{I remove the file "([^\"]*)"} do |filename|
12
+ system "rm #{BASE_PATH}/#{filename}"
13
+ end
14
+
15
+ When %r{I open the file "([^\"]*)"} do |filename|
16
+ @current_file = File.read("#{BASE_PATH}/#{filename}")
17
+ end
18
+
19
+ Then %r{I should see "([^\"]*)"} do |content|
20
+ @current_file.should match(Regexp.new(content))
21
+ end
22
+
23
+ Then %r{I should not see "([^\"]*)"} do |content|
24
+ @current_file.should_not match(Regexp.new(content))
25
+ end
@@ -0,0 +1,38 @@
1
+ Given %r{I configure Epic::Base} do
2
+ Epic::Base.configure do |config|
3
+ config.base_path = "#{BASE_PATH}"
4
+ end
5
+ end
6
+
7
+ Given %r{the file "([^\"]*)" should be valid} do |filename|
8
+ if filename =~ /\.html$/
9
+ @validator = Epic::Validator::HTML.new
10
+ elsif filename =~ /\.js$/
11
+ @validator = Epic::Validator::JavaScript.new
12
+ end
13
+ @validator.validate("#{BASE_PATH}/#{filename}").should be_true
14
+ end
15
+
16
+ Given %r{the file "([^\"]*)" should not be valid} do |filename|
17
+ if filename =~ /\.html$/
18
+ @validator = Epic::Validator::HTML.new
19
+ @validator.validate("#{BASE_PATH}/#{filename}").should be_false
20
+ elsif filename =~ /\.js$/
21
+ @validator = Epic::Validator::JavaScript.new
22
+ @validator.validate("#{BASE_PATH}/#{filename}").should be_false
23
+ end
24
+ end
25
+
26
+ Then /^an exception should have been raised with the message "([^\"]*)"$/ do |message|
27
+ found_exception = false
28
+ puts @exceptions.inspect
29
+ @exceptions.each do |exception|
30
+ found_exception ||= exception =~ Regexp.new(message)
31
+ end
32
+ found_exception.should be_true
33
+ end
34
+
35
+ Then %r{no exceptions should have been raised} do
36
+ @exceptions.should be_empty
37
+ end
38
+
@@ -0,0 +1,31 @@
1
+ require 'vendor/gems/environment'
2
+ Bundler.require_env :cucumber
3
+
4
+ require 'spec/expectations'
5
+ require 'spec/mocks'
6
+
7
+ require 'lib/epic'
8
+
9
+ require 'spec/stubs'
10
+
11
+ Before do
12
+ unless defined?(BASE_PATH)
13
+ BASE_PATH = File.expand_path("./features/data")
14
+ end
15
+
16
+ @exceptions = []
17
+ @files = []
18
+
19
+ $rspec_mocks ||= Spec::Mocks::Space.new
20
+
21
+ stub_growl
22
+ end
23
+
24
+ After do
25
+ @files.each do |file|
26
+ system "rm #{file}"
27
+ end
28
+
29
+ system "rm -rf #{BASE_PATH}/tmp"
30
+ system "mkdir #{BASE_PATH}/tmp"
31
+ end
@@ -0,0 +1,17 @@
1
+ Feature: Test the validator
2
+
3
+ Background:
4
+ Given I configure Epic::Base
5
+
6
+ Scenario: Validate a valid HTML file
7
+ Given the file "html/valid.html" should be valid
8
+
9
+ Scenario: Validate an invalid HTML file
10
+ Given the file "html/invalid.html" should not be valid
11
+
12
+ Scenario: Validate a valid JavaScript file
13
+ Given the file "javascripts/valid.js" should be valid
14
+
15
+ Scenario: Validate an invalid JavaScript file
16
+ Given the file "javascripts/invalid.js" should not be valid
17
+
@@ -1,5 +1,6 @@
1
1
  dir = File.dirname(__FILE__)
2
2
  $LOAD_PATH.unshift dir unless $LOAD_PATH.include?(dir)
3
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), 'epic'))
3
4
 
4
5
  require 'rubygems'
5
6
  require 'f'
@@ -8,5 +9,6 @@ require 'active_support'
8
9
  require 'w3c_validators'
9
10
 
10
11
  require 'epic/base'
12
+ require 'epic/errors'
11
13
  require 'epic/validator'
12
- require 'epic/compressor'
14
+ require 'compressor'
@@ -6,36 +6,25 @@ module Epic #:nodoc
6
6
  class Base
7
7
  class << self
8
8
  def configuration
9
- @@configuration ||= Epic::Configuration.new
9
+ @configuration ||= Epic::Configuration.new
10
10
  end
11
11
 
12
12
  def configure
13
13
  yield configuration
14
14
  end
15
-
16
- # Parses out the <tt>base_path</tt> setting from a path to display it in a
17
- # less verbose way.
18
- #
19
- def display_path(path)
20
- path = File.expand_path(path)
21
- path.gsub(base_path.to_s, "")
22
- end
23
-
24
- def base_path
25
- configuration.base_path
26
- end
27
15
  end
28
16
 
29
17
  def configuration
30
- self.class.configuration
18
+ Epic::Base.configuration
31
19
  end
32
20
 
33
21
  # Parses out the <tt>base_path</tt> setting from a path to display it in a
34
22
  # less verbose way.
35
23
  #
36
- def display_path(path)
37
- path = File.expand_path(path)
38
- path.gsub(base_path.to_s, "")
24
+ def display_path(filename=nil)
25
+ filename ||= path
26
+ display_path = File.expand_path(filename)
27
+ display_path.gsub(base_path.to_s, "")
39
28
  end
40
29
 
41
30
  def base_path
@@ -43,7 +32,7 @@ module Epic #:nodoc
43
32
  end
44
33
 
45
34
  def tmp_path
46
- configuration.tmp_path || ""
35
+ configuration.tmp_path || "#{base_path}/tmp" || ""
47
36
  end
48
37
  end
49
38
  end
@@ -1,126 +1,139 @@
1
1
  module Epic #:nodoc:
2
- module Compressor #:nodoc:
3
- # Compresses a file using the specified compressor/minifier (currently YUI Compressor 2.4.2).
4
- #
5
- # === Usage
6
- #
7
- # Epic::Compressor::Base.compress("filename.js", "type" => "js")
8
- #
9
- # Epic::Compressor::Base.compress("filename.css", "type" => "css")
10
- #
11
- # Outputs the compressed file to <tt>_path_.min.</tt>
12
- #
13
- # === Options
14
- #
15
- # "type":: "js" or "css". Identifies the file type.
16
- #
17
- # "obfuscate":: true or false. Change internal variable names within the code.
18
- #
19
- # "verbose":: true or false. Output warnings about code quality.
20
- #
21
- # "preserve_semi":: true or false. Preserve unnecessary semicolons.
22
- #
23
- # TODO: Make it support multiple compressors.
24
- #
25
- # TODO: Convert it to an object, so you instantiate the Compressor class and then call it
26
- # on a file or a string.
27
- #
28
- # TODO: Get some stringify_keys! action going so you can send in symbols or strings.
2
+ # Compresses a file using the specified compressor/minifier (currently YUI Compressor 2.4.2).
3
+ #
4
+ # === Usage
5
+ #
6
+ # Epic::Compressor.compress("filename.js")
7
+ #
8
+ # Epic::Compressor.compress("filename.css")
9
+ #
10
+ # Outputs the compressed file to <tt>_path_.min.</tt>
11
+ #
12
+ # === Options
13
+ #
14
+ # "type" "js" or "css". Identifies the file type. Only needed if the file does
15
+ # not have a standard extension.
16
+ #
17
+ # "obfuscate" true or false. Change internal variable names within the code.
18
+ #
19
+ # "verbose" true or false. Output warnings about code quality.
20
+ #
21
+ # "preserve_semi" true or false. Preserve unnecessary semicolons.
22
+ #
23
+ # TODO: Make it support multiple compressors.
24
+ #
25
+ class Compressor < Epic::Base
26
+ include Epic::Errors
27
+
28
+ # The path of the original file being compressed.
29
+ #
30
+ attr_accessor :path
31
+
32
+ # The type of file, whether :js or :css.
29
33
  #
30
- class Base < Epic::Base
31
- def self.compress(path, options={})
32
- options.stringify_keys!
33
- compressed_display_path = display_path(path)
34
- compressed_path = "#{path}.min"
34
+ attr_accessor :type
35
+
36
+ def initialize(path)
37
+ @path = path
38
+ if path =~ /\.js$/
39
+ @type = :js
40
+ elsif path =~ /\.css$/
41
+ @type = :css
42
+ end
43
+ @errors = []
44
+ end
45
+
46
+ def compress(params={})
47
+ # if the compressed_file exists, don't create it again
48
+ #
49
+ compress_path(params) unless File.exists?(compressed_path)
35
50
 
36
- options["type"] ||= "js"
37
- options["type"] = options["type"].to_s
38
-
39
- # if the compressed_file exists, don't create it again
40
- #
41
- unless File.exists?(compressed_path)
42
- $stdout.print " #{compressed_display_path} compressing . . . "
43
- compressed = ''
44
-
45
- # set options and defaults
46
- #
47
- if options.delete("obfuscate")
48
- options["nomunge"] = ""
49
- end
50
- if options.delete("verbose")
51
- options["verbose"] = ""
52
- end
53
- options["charset"] = "utf-8"
54
-
55
- if options["type"].to_s == "js" && !options["preserve_semi"]
56
- options["preserve-semi"] = ""
57
- end
58
-
59
- # join the options together for appending to the command line
60
- #
61
- options_string = options.map {|k,v| "--#{k} #{v}"}.join(" ")
51
+ File.read(compressed_path)
52
+ end
53
+
54
+ def compressed_path
55
+ @compressed_path ||= "#{path}.min"
56
+ end
57
+
58
+ def compressed_display_path
59
+ @compressed_display_path ||= display_path(path)
60
+ end
61
+
62
+ def compress_path(params)
63
+ params.stringify_keys!
62
64
 
63
- # call the compressor
64
- #
65
- compressor_path = File.expand_path("#{File.dirname(__FILE__)}/../../vendor/ext/yuicompressor-2.4.2.jar")
66
- raise "#{compressor_path} does not exist" unless File.exists?(compressor_path)
67
-
68
- command = "java -jar #{compressor_path} #{options_string} #{path} -o #{compressed_path} 2>&1"
69
- result = F.execute(command, :return => true)
70
-
71
- result.split("\n").each do |line|
72
- if line =~ /\[ERROR\] (\d+):(\d+):(.*)/
73
- line_number = $1.to_i
74
- error = "Error at #{compressed_display_path} line #{line_number} character #{$2}: #{$3}"
75
- error += F.get_line_from_file(path, line_number)
76
-
77
- $stdout.puts error
78
- g(error)
79
- end
80
- end
81
-
82
- if result =~ /ERROR/
83
- raise "JavaScript errors in #{compressed_display_path}"
84
- else
85
- $stdout.puts "OK"
86
- end
87
- end
88
-
89
- # The compressed file should exist now. If it does, use it. If not, raise an error.
90
- #
91
- if File.exists?(compressed_path)
92
- compressed = File.read(compressed_path)
93
- else
94
- raise "File does not exist: #{compressed_display_path}"
95
- end
65
+ $stdout.print " #{compressed_display_path} compressing . . . "
66
+ compressed = ''
96
67
 
97
- compressed
98
- end
68
+ options_string = convert_params_to_string(params)
69
+
70
+ result = execute_compressor(options_string)
71
+
72
+ parse_errors(result)
73
+
74
+ if valid?
75
+ $stdout.puts "OK"
76
+ else
77
+ display_errors
78
+ raise "JavaScript errors in #{compressed_display_path}"
79
+ end
99
80
  end
100
81
 
101
- # Compresses a CSS file using the specified compressor/minifier (currently YUI Compressor 2.4.2).
102
- #
103
- # === Usage
82
+ # call the compressor
104
83
  #
105
- # Epic::Compressor::Stylesheet.compress("filename.css")
106
- #
107
- class Stylesheet < Base
108
- def self.compress(path)
109
- super(path, "type" => "css")
110
- end
84
+ def execute_compressor(options_string)
85
+ command = "java -jar #{compressor_path} #{options_string} #{path} -o #{compressed_path} 2>&1"
86
+ result = F.execute(command, :return => true)
111
87
  end
112
88
 
113
- # Compresses a JavaScript file using the specified compressor/minifier (currently YUI Compressor 2.4.2).
114
- #
115
- # === Usage
89
+ def parse_errors(result="")
90
+ result.to_s.split("\n").each do |line|
91
+ if line =~ /\[ERROR\] (\d+):(\d+):(.*)/
92
+ line_number = $1.to_i
93
+ error = "Error at #{compressed_display_path} line #{line_number} character #{$2}: #{$3}"
94
+ error += F.get_line_from_file(path, line_number)
95
+
96
+ errors << error
97
+ end
98
+ end
99
+ end
100
+
101
+ # join the options together for appending to the command line
116
102
  #
117
- # Epic::Compressor::JavaScript.compress("filename.js")
103
+ def convert_params_to_string(params)
104
+ options = parse_options(params)
105
+ options.map {|k,v| "--#{k} #{v}"}.join(" ")
106
+ end
107
+
108
+ # set options and defaults
118
109
  #
119
- class JavaScript < Base
120
- # TODO: Add options hash
121
- def self.compress(filename)
122
- super(filename, "type" => "js")
110
+ def parse_options(options)
111
+ options["type"] ||= type
112
+ options["type"] = options["type"].to_s
113
+
114
+ if options.delete("obfuscate")
115
+ options["nomunge"] = ""
116
+ end
117
+ if options.delete("verbose")
118
+ options["verbose"] = ""
123
119
  end
120
+ options["charset"] = "utf-8"
121
+
122
+ if options["type"].to_s == "js" && !options["preserve_semi"]
123
+ options["preserve-semi"] = ""
124
+ end
125
+
126
+ options
127
+ end
128
+
129
+ def compressor_path
130
+ compressor_path = File.expand_path("#{vendor_path}/ext/yuicompressor-2.4.2.jar")
131
+ raise "#{compressor_path} does not exist" unless File.exists?(compressor_path)
132
+ compressor_path
133
+ end
134
+
135
+ def vendor_path
136
+ File.join(File.dirname(__FILE__), "..", "..", "vendor")
124
137
  end
125
138
  end
126
139
  end
@@ -0,0 +1,18 @@
1
+ module Epic #:nodoc:
2
+ module Errors #:nodoc:
3
+ def errors
4
+ @errors ||= []
5
+ end
6
+
7
+ def valid?
8
+ errors.empty?
9
+ end
10
+
11
+ def display_errors
12
+ errors.each do |err|
13
+ $stdout.puts
14
+ $stdout.puts err.to_s
15
+ end
16
+ end
17
+ end
18
+ end
@@ -1,118 +1,5 @@
1
- require 'epic/base'
2
-
3
- module Epic
4
- module Validator
5
- class HTML < Epic::Base
6
- def validator
7
- @validator ||= W3CValidators::MarkupValidator.new
8
- end
9
-
10
- def validate(path)
11
- $stdout.print " #{path} validating . . . "
12
-
13
- doctype = configuration.doctype || "HTML 4.01 Transitional"
14
- validator.set_doctype!(doctype)
15
-
16
- results = validator.validate_file(path)
17
-
18
- valid = results.errors.length <= 0
19
-
20
- if valid
21
- $stdout.puts "OK"
22
- else
23
- $stdout.puts "validation errors"
24
- results.errors.each do |err|
25
- $stdout.puts
26
- $stdout.puts err.to_s
27
- end
28
- end
29
-
30
- valid
31
- end
32
- end
33
-
34
- class JavaScript < Base
35
- def use_jslint_settings?
36
- !jslint_settings.blank?
37
- end
38
-
39
- def jslint_settings
40
- configuration.jslint_settings
41
- end
42
-
43
- def jslint_settings_count
44
- jslint_settings.to_s.split("\n").size
45
- end
46
-
47
- def pre_process(content)
48
- content
49
- end
50
-
51
- def validate(path)
52
- display = display_path(path)
53
- $stdout.print " #{display} validating . . . "
54
- output = ""
55
-
56
- File.open(path) do |f|
57
- output = f.read
58
- end
59
-
60
- output = pre_process(output)
61
-
62
- FileUtils.mkdir_p(tmp_path)
63
-
64
- js_fragment_path = File.expand_path("#{tmp_path}/#{File.basename(path)}_fragment")
65
- fragment_display_path = display_path(js_fragment_path)
66
-
67
- if File.exists?(js_fragment_path)
68
- puts "That already exists?"
69
- else
70
- File.open(js_fragment_path,'w') do |f|
71
- f.puts jslint_settings if use_jslint_settings?
72
- f.puts output
73
- end
74
-
75
- jslint_path = File.expand_path("#{File.dirname(__FILE__)}/../../vendor/ext/jslint.js")
76
- raise "#{jslint_path} does not exist" unless File.exists?(jslint_path)
77
- rhino_path = File.expand_path("#{File.dirname(__FILE__)}/../../vendor/ext/js.jar")
78
- raise "#{rhino_path} does not exist" unless File.exists?(rhino_path)
79
-
80
- results = F.execute("java -jar #{rhino_path} #{jslint_path} #{js_fragment_path}", :return => true)
81
-
82
- if results =~ /jslint: No problems found/
83
- $stdout.puts "OK"
84
- else
85
- $stdout.puts "errors found!"
86
- results.split("\n").each do |result|
87
- if result =~ /line (\d+) character (\d+): (.*)/
88
- line_number = $1.to_i
89
- error = "Error at #{fragment_display_path} line #{line_number-jslint_settings_count} character #{$2}: #{$3}"
90
- error += F.get_line_from_file(js_fragment_path, line_number)
91
-
92
- $stdout.puts error
93
- end
94
- end
95
- message = "JavaScript Errors embedded in #{display}"
96
- g(message)
97
- raise message
98
- end
99
- end
100
- end
101
- end
102
-
103
- class JSON < JavaScript
104
- def pre_process(output)
105
- output
106
- end
107
-
108
- def jslint_settings
109
- end
110
- end
111
-
112
- class Stylesheet < Base
113
- def validate(filename)
114
- true
115
- end
116
- end
117
- end
118
- end
1
+ require 'validator/base'
2
+ require 'validator/html'
3
+ require 'validator/javascript'
4
+ require 'validator/json'
5
+ require 'validator/stylesheet'
@@ -0,0 +1,14 @@
1
+ module Epic #:nodoc:
2
+ module Validator #:nodoc:
3
+ class Base < Epic::Base
4
+ include Epic::Errors
5
+
6
+ attr_accessor :path, :errors
7
+
8
+ def initialize(path=nil)
9
+ @path = path
10
+ @errors = []
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,33 @@
1
+ module Epic #:nodoc:
2
+ module Validator #:nodoc:
3
+ class HTML < Epic::Validator::Base
4
+ def validator
5
+ @validator ||= W3CValidators::MarkupValidator.new
6
+ end
7
+
8
+ def doctype
9
+ configuration.doctype || "HTML 4.01 Transitional"
10
+ end
11
+
12
+ def validate(filename=nil)
13
+ @path = filename || path
14
+ $stdout.print " #{display_path} validating . . . "
15
+
16
+ validator.set_doctype!(doctype)
17
+
18
+ results = validator.validate_file(path)
19
+
20
+ @errors = results.errors
21
+
22
+ if valid?
23
+ $stdout.puts "OK"
24
+ else
25
+ $stdout.puts "validation errors"
26
+ display_errors
27
+ end
28
+
29
+ valid?
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,82 @@
1
+ module Epic #:nodoc:
2
+ module Validator #:nodoc
3
+ class JavaScript < Epic::Validator::Base
4
+ def jslint_settings
5
+ configuration.jslint_settings.to_s
6
+ end
7
+
8
+ def jslint_settings_count
9
+ jslint_settings.split("\n").size
10
+ end
11
+
12
+ def pre_process(content)
13
+ jslint_settings + content
14
+ end
15
+
16
+ def js_fragment_path
17
+ File.expand_path("#{tmp_path}/#{File.basename(path)}_fragment")
18
+ end
19
+
20
+ def jslint_path
21
+ jslint_path = File.expand_path("#{vendor_path}/ext/jslint.js")
22
+ raise "#{jslint_path} does not exist" unless File.exists?(jslint_path)
23
+ jslint_path
24
+ end
25
+
26
+ def rhino_path
27
+ rhino_path = File.expand_path("#{vendor_path}/ext/js.jar")
28
+ raise "#{rhino_path} does not exist" unless File.exists?(rhino_path)
29
+ rhino_path
30
+ end
31
+
32
+ def vendor_path
33
+ File.join(File.dirname(__FILE__), "..", "..", "..", "vendor")
34
+ end
35
+
36
+ def valid_results?(results)
37
+ fragment_display_path = display_path(js_fragment_path)
38
+ unless results =~ /jslint: No problems found/
39
+ results.split("\n").each do |result|
40
+ if result =~ /line (\d+) character (\d+): (.*)/
41
+ line_number = $1.to_i
42
+ error = "Error at #{fragment_display_path} line #{line_number-jslint_settings_count} character #{$2}: #{$3}"
43
+ error += F.get_line_from_file(js_fragment_path, line_number)
44
+
45
+ errors << error
46
+ end
47
+ end
48
+ end
49
+ errors.length <= 0
50
+ end
51
+
52
+ def validate_path
53
+ raw_output = File.read(path)
54
+ output = pre_process(raw_output)
55
+
56
+ FileUtils.mkdir_p(tmp_path)
57
+
58
+ File.open(js_fragment_path,'w') do |f|
59
+ f.puts output
60
+ end
61
+
62
+ F.execute("java -jar #{rhino_path} #{jslint_path} #{js_fragment_path}", :return => true)
63
+ end
64
+
65
+ def validate(filename=nil)
66
+ @path = filename || path
67
+ $stdout.print " #{display_path} validating . . . "
68
+
69
+ results = validate_path
70
+
71
+ if valid_results?(results)
72
+ $stdout.puts "OK"
73
+ else
74
+ $stdout.puts "errors found!"
75
+ display_errors
76
+ end
77
+
78
+ errors.length <= 0
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,13 @@
1
+ module Epic #:nodoc:
2
+ module Validator #:nodoc
3
+ class JSON < JavaScript
4
+ def pre_process(output)
5
+ output
6
+ end
7
+
8
+ def jslint_settings
9
+ ""
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,9 @@
1
+ module Epic #:nodoc:
2
+ module Validator #:nodoc
3
+ class Stylesheet < Base
4
+ def validate(path=nil)
5
+ true
6
+ end
7
+ end
8
+ end
9
+ end
@@ -11,7 +11,7 @@ describe "Compressor" do
11
11
  File.stub!(:exists?).with(/file.js/).and_return(true)
12
12
  @file = "compressed file"
13
13
  File.stub(:read).and_return(@file)
14
- Epic::Compressor::Base.compress("file.js", "type" => "js").should == @file
14
+ Epic::Compressor.new("file.js").compress.should == @file
15
15
  end
16
16
 
17
17
  describe "generate a compressed file if one doesn't exist" do
@@ -22,47 +22,47 @@ describe "Compressor" do
22
22
 
23
23
  it "should log what it's doing" do
24
24
  $stdout.should_receive(:print).with(/file.js compressing . . ./)
25
- Epic::Compressor::Base.compress("file.js", "type" => "js")
25
+ Epic::Compressor.new("file.js").compress
26
26
  end
27
27
 
28
28
  it "should run the compressor" do
29
29
  F.should_receive(:execute).with(/yuicompressor/, :return => true).and_return("")
30
- Epic::Compressor::Base.compress("file.js", "type" => "js")
30
+ Epic::Compressor.new("file.js").compress
31
31
  end
32
32
 
33
33
  describe "options" do
34
34
  it "should set nomunge" do
35
35
  F.should_receive(:execute).with(/nomunge/, :return => true).and_return("")
36
- Epic::Compressor::Base.compress("file.js", "type" => "js", "obfuscate" => true)
36
+ Epic::Compressor.new("file.js").compress("obfuscate" => true)
37
37
  end
38
38
 
39
39
  it "should not set nomunge" do
40
40
  F.stub!(:execute).with(/yuicompressor/, :return => true).and_return("")
41
41
  F.should_not_receive(:execute).with(/nomunge/, :return => true).and_return("")
42
- Epic::Compressor::Base.compress("file.js", "type" => "js", "obfuscate" => false)
42
+ Epic::Compressor.new("file.js").compress("obfuscate" => false)
43
43
  end
44
44
 
45
45
  it "should set verbose" do
46
46
  F.should_receive(:execute).with(/verbose/, :return => true).and_return("")
47
- Epic::Compressor::Base.compress("file.js", "type" => "js", "verbose" => true)
47
+ Epic::Compressor.new("file.js").compress("verbose" => true)
48
48
  end
49
49
 
50
50
  it "should not set verbose" do
51
51
  F.stub!(:execute).with(/yuicompressor/, :return => true).and_return("")
52
52
  F.should_not_receive(:execute).with(/verbose/, :return => true).and_return("")
53
- Epic::Compressor::Base.compress("file.js", "type" => "js", "verbose" => false)
53
+ Epic::Compressor.new("file.js").compress("verbose" => false)
54
54
  end
55
55
 
56
56
  it "should set preserve-semi on javascript" do
57
57
  F.should_receive(:execute).with(/preserve-semi/, :return => true).and_return("")
58
- Epic::Compressor::Base.compress("file.js", "type" => "js")
58
+ Epic::Compressor.new("file.js").compress
59
59
  end
60
60
 
61
61
  it "should not set preserve-semi on css" do
62
62
  File.stub!(:exists?).with(/file.css/).and_return(true)
63
63
  F.stub!(:execute).with(/yuicompressor/, :return => true).and_return("")
64
64
  F.should_not_receive(:execute).with(/preserve-semi/, :return => true).and_return("")
65
- Epic::Compressor::Base.compress("file.css", "type" => "css")
65
+ Epic::Compressor.new("file.css").compress
66
66
  end
67
67
  end
68
68
 
@@ -73,55 +73,22 @@ describe "Compressor" do
73
73
 
74
74
  it "should raise an exception" do
75
75
  lambda {
76
- Epic::Compressor::Base.compress("file.js", "type" => "js")
77
- }.should raise_error(/JavaScript errors/)
78
- end
79
-
80
- it "should growl" do
81
- @g.should_receive(:notify)
82
- lambda {
83
- Epic::Compressor::Base.compress("file.js", "type" => "js")
76
+ Epic::Compressor.new("file.js").compress
84
77
  }.should raise_error(/JavaScript errors/)
85
78
  end
86
79
 
87
80
  it "should show the source code" do
88
81
  F.should_receive(:get_line_from_file).with("file.js", 12).and_return("")
89
82
  lambda {
90
- Epic::Compressor::Base.compress("file.js", "type" => "js")
83
+ Epic::Compressor.new("file.js").compress
91
84
  }.should raise_error(/JavaScript errors/)
92
85
  end
93
86
  end
94
87
 
95
88
  it "should report OK" do
96
89
  $stdout.should_receive(:puts).with("OK")
97
- Epic::Compressor::Base.compress("file.js", "type" => "js")
90
+ Epic::Compressor.new("file.js").compress
98
91
  end
99
-
100
- it "should raise an error if the compressed file doesn't exist" do
101
- # File.stub!(:exists?).with(/file.js/).and_return(true)
102
- # File.stub!(:exists?).with(/file.js.min/).and_return(false)
103
- # lambda {
104
- Epic::Compressor::Base.compress("file.js", "type" => "js")
105
- # }.should raise_error(/File does not exist/)
106
- end
107
- end
108
- end
109
-
110
- describe "JavaScript" do
111
- it "should call Base with type js" do
112
- File.stub(:exists?).with(/file.js/).and_return(true)
113
- @file = "compressed file"
114
- File.stub(:read).and_return(@file)
115
- Epic::Compressor::JavaScript.compress("file.js").should == @file
116
- end
117
- end
118
-
119
- describe "Stylesheet" do
120
- it "should call Base with type css" do
121
- File.stub(:exists?).with(/file.css/).and_return(true)
122
- @file = "compressed file"
123
- File.stub(:read).and_return(@file)
124
- Epic::Compressor::Stylesheet.compress("file.css").should == @file
125
92
  end
126
93
  end
127
94
  end
@@ -40,6 +40,18 @@ describe "Validator" do
40
40
  Epic::Validator::HTML.new.validate("path")
41
41
  end
42
42
 
43
+ describe "new syntax" do
44
+ it "should call validator" do
45
+ W3CValidators::MarkupValidator.should_receive(:new).and_return(@validator)
46
+ Epic::Validator::HTML.new("path").validate
47
+ end
48
+
49
+ it "should print OK" do
50
+ $stdout.should_receive(:puts).with(/OK/)
51
+ Epic::Validator::HTML.new("path").validate
52
+ end
53
+ end
54
+
43
55
  describe "errors" do
44
56
  before(:each) do
45
57
  class ResultsMock
@@ -70,6 +82,17 @@ describe "Validator" do
70
82
  $stdout.should_receive(:puts).with("validation errors")
71
83
  Epic::Validator::HTML.new.validate("path")
72
84
  end
85
+
86
+ describe "new syntax" do
87
+ it "should be false" do
88
+ Epic::Validator::HTML.new("path").validate.should be_false
89
+ end
90
+
91
+ it "should output a message" do
92
+ $stdout.should_receive(:puts).with("validation errors")
93
+ Epic::Validator::HTML.new("path").validate
94
+ end
95
+ end
73
96
  end
74
97
  end
75
98
 
@@ -91,6 +114,20 @@ describe "Validator" do
91
114
  @file.should_receive(:puts).with(@jslint_settings)
92
115
  Epic::Validator::JavaScript.new.validate("path")
93
116
  end
117
+
118
+ describe "new syntax" do
119
+ it "should set jslint settings" do
120
+ Epic::Base.configure do |config|
121
+ config.jslint_settings = @jslint_settings
122
+ end
123
+ Epic::Validator::JavaScript.new("path").jslint_settings.should == @jslint_settings
124
+ end
125
+
126
+ it "should put jslint settings in the file" do
127
+ @file.should_receive(:puts).with(@jslint_settings)
128
+ Epic::Validator::JavaScript.new("path").validate
129
+ end
130
+ end
94
131
  end
95
132
 
96
133
  describe "valid" do
@@ -115,25 +152,14 @@ describe "Validator" do
115
152
  F.stub!(:get_line_from_file).with(anything, 5)
116
153
  end
117
154
 
118
- it "should growl" do
119
- @g.should_receive(:notify).with(anything, anything, /JavaScript Errors/, anything, anything)
120
- lambda {
121
- Epic::Validator::JavaScript.new.validate("path")
122
- }.should raise_error
123
- end
124
-
125
155
  it "should output errors" do
126
156
  $stdout.should_receive(:puts).with(/Unnecessary semicolon/)
127
157
  $stdout.should_receive(:puts).with(/Unknown thingamajig/)
128
- lambda {
129
- Epic::Validator::JavaScript.new.validate("path")
130
- }.should raise_error
158
+ Epic::Validator::JavaScript.new.validate("path").should be_false
131
159
  end
132
160
 
133
- it "should raise error" do
134
- lambda {
135
- Epic::Validator::JavaScript.new.validate("path")
136
- }.should raise_error(/JavaScript Errors/)
161
+ it "should be false" do
162
+ Epic::Validator::JavaScript.new.validate("path").should be_false
137
163
  end
138
164
  end
139
165
  end
@@ -161,25 +187,14 @@ describe "Validator" do
161
187
  F.stub!(:get_line_from_file).with(anything, 5)
162
188
  end
163
189
 
164
- it "should growl" do
165
- @g.should_receive(:notify).with(anything, anything, /JavaScript Errors/, anything, anything)
166
- lambda {
167
- Epic::Validator::JSON.new.validate("path")
168
- }.should raise_error
169
- end
170
-
171
190
  it "should output errors" do
172
191
  $stdout.should_receive(:puts).with(/Unnecessary semicolon/)
173
192
  $stdout.should_receive(:puts).with(/Unknown thingamajig/)
174
- lambda {
175
- Epic::Validator::JSON.new.validate("path")
176
- }.should raise_error
193
+ Epic::Validator::JSON.new.validate("path").should be_false
177
194
  end
178
195
 
179
- it "should raise error" do
180
- lambda {
181
- Epic::Validator::JSON.new.validate("path")
182
- }.should raise_error(/JavaScript Errors/)
196
+ it "should return false" do
197
+ Epic::Validator::JSON.new.validate("path").should be_false
183
198
  end
184
199
  end
185
200
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: epic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeff Coleman
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-01-25 00:00:00 -06:00
12
+ date: 2010-01-30 00:00:00 -06:00
13
13
  default_executable: epic
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -62,15 +62,36 @@ files:
62
62
  - VERSION
63
63
  - bin/epic
64
64
  - epic.gemspec
65
+ - features/compressor.feature
66
+ - features/data/html/invalid.html
67
+ - features/data/html/valid.html
68
+ - features/data/javascripts/invalid.js
69
+ - features/data/javascripts/invalid_uncompressed.js
70
+ - features/data/javascripts/pre_compressed.js
71
+ - features/data/javascripts/pre_compressed.js.min
72
+ - features/data/javascripts/valid.js
73
+ - features/data/javascripts/valid_uncompressed.js
74
+ - features/data/stylesheets/valid.css
75
+ - features/step_definitions/compressor_steps.rb
76
+ - features/step_definitions/file_steps.rb
77
+ - features/step_definitions/validator_steps.rb
78
+ - features/support/env.rb
79
+ - features/validator.feature
65
80
  - lib/epic.rb
66
81
  - lib/epic/base.rb
67
82
  - lib/epic/compressor.rb
83
+ - lib/epic/errors.rb
68
84
  - lib/epic/validator.rb
85
+ - lib/epic/validator/base.rb
86
+ - lib/epic/validator/html.rb
87
+ - lib/epic/validator/javascript.rb
88
+ - lib/epic/validator/json.rb
89
+ - lib/epic/validator/stylesheet.rb
69
90
  - spec/compressor_spec.rb
70
- - spec/epic_spec.rb
71
91
  - spec/spec.opts
72
92
  - spec/spec_helper.rb
73
93
  - spec/stubs.rb
94
+ - spec/validator_spec.rb
74
95
  - vendor/ext/js.jar
75
96
  - vendor/ext/jslint.js
76
97
  - vendor/ext/yuicompressor-2.4.2.jar
@@ -104,6 +125,6 @@ specification_version: 3
104
125
  summary: Epic validation of HTML, JavaScript and CSS
105
126
  test_files:
106
127
  - spec/compressor_spec.rb
107
- - spec/epic_spec.rb
108
128
  - spec/spec_helper.rb
109
129
  - spec/stubs.rb
130
+ - spec/validator_spec.rb